How to write build time stamp into apk

2019-01-07 05:42发布

  1. Making some changes in Android Contacts package
  2. Using mm (make) command to build this application

Because I have to change and build this app again and again, so I want to add a build time stamp in the Contacts.apk to check the build time when we runn it in the handset.

As we know, when we run mm command, the Android.mk (makefile) in Contacts package will be called.

And now, we can get the build time using date-macro.

But how we can write this build time stamp into a file that our application can read at runtime?

Any suggestions?

9条回答
冷血范
2楼-- · 2019-01-07 05:58

Method which checks date of last modification of classes.dex, this means last time when your app's code was built:

  try{
     ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), 0);
     ZipFile zf = new ZipFile(ai.sourceDir);
     ZipEntry ze = zf.getEntry("classes.dex");
     long time = ze.getTime();
     String s = SimpleDateFormat.getInstance().format(new java.util.Date(time));
     zf.close();
  }catch(Exception e){
  }

Tested, and works fine, even if app is installed on SD card.

查看更多
淡お忘
3楼-- · 2019-01-07 05:59
Install time : packageInfo.lastUpdateTime
build time   : zf.getEntry("classes.dex").getTime()

Both are differnet time. You can check with the code below.

public class BuildInfoActivity extends Activity {

    private static final String TAG = BuildInfoActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        try {

            PackageManager pm = getPackageManager();
            PackageInfo packageInfo = null;
            try {
                packageInfo = pm.getPackageInfo(getPackageName(), 0);
            } catch (NameNotFoundException e) {
                e.printStackTrace();
            }

            // install datetime
            String appInstallDate = DateUtils.getDate(
                    "yyyy/MM/dd hh:mm:ss.SSS", packageInfo.lastUpdateTime);

            // build datetime
            String appBuildDate = DateUtils.getDate("yyyy/MM/dd hh:mm:ss.SSS",
                    DateUtils.getBuildDate(this));

            Log.i(TAG, "appBuildDate = " + appBuildDate);
            Log.i(TAG, "appInstallDate = " + appInstallDate);

        } catch (Exception e) {
        }

    }

    static class DateUtils {

        public static String getDate(String dateFormat) {
            Calendar calendar = Calendar.getInstance();
            return new SimpleDateFormat(dateFormat, Locale.getDefault())
                    .format(calendar.getTime());
        }

        public static String getDate(String dateFormat, long currenttimemillis) {
            return new SimpleDateFormat(dateFormat, Locale.getDefault())
                    .format(currenttimemillis);
        }

        public static long getBuildDate(Context context) {

            try {
                ApplicationInfo ai = context.getPackageManager()
                        .getApplicationInfo(context.getPackageName(), 0);
                ZipFile zf = new ZipFile(ai.sourceDir);
                ZipEntry ze = zf.getEntry("classes.dex");
                long time = ze.getTime();

                return time;

            } catch (Exception e) {
            }

            return 0l;
        }

    }
}
查看更多
走好不送
4楼-- · 2019-01-07 06:00

So Android Developer - Android Studio User Guide - Gradle Tips and Recipes - Simplify App Development actually documents what to add in order to have a release timestamp available to your app:

android {
  ...
  buildTypes {
    release {
      // These values are defined only for the release build, which
      // is typically used for full builds and continuous builds.
      buildConfigField("String", "BUILD_TIME", "\"${minutesSinceEpoch}\"")
      resValue("string", "build_time", "${minutesSinceEpoch}")
      ...
    }
    debug {
      // Use static values for incremental builds to ensure that
      // resource files and BuildConfig aren't rebuilt with each run.
      // If they were dynamic, they would prevent certain benefits of
      // Instant Run as well as Gradle UP-TO-DATE checks.
      buildConfigField("String", "BUILD_TIME", "\"0\"")
      resValue("string", "build_time", "0")
    }
  }
}
...

I'm including this here since all of the other solutions appear to be from before the official example.

查看更多
我欲成王,谁敢阻挡
5楼-- · 2019-01-07 06:01

If you use Gradle, you can add buildConfigField with timestamp updated at build time.

android {
    defaultConfig {
        buildConfigField "long", "TIMESTAMP", System.currentTimeMillis() + "L"
    }
}

Then read it at runtime.

Date buildDate = new Date(BuildConfig.TIMESTAMP);
查看更多
做个烂人
6楼-- · 2019-01-07 06:02

I know this is really old, but here's how I did it using ant within eclipse:

build.xml in project root

<project name="set_strings_application_build_date" default="set_build_date" basedir=".">
    <description>
        This ant script updates strings.xml application_build_date to the current date
    </description>

    <!-- set global properties for this build -->
    <property name="strings.xml"  location="./res/values/strings.xml"/>

    <target name="init">
        <!-- Create the time stamp -->
        <tstamp/>
    </target>

    <target name="set_build_date" depends="init" description="sets the build date" >

        <replaceregexp file="${strings.xml}"
            match="(&lt;string name=&quot;application_build_date&quot;&gt;)\d+(&lt;/string&gt;)"
            replace="&lt;string name=&quot;application_build_date&quot;&gt;${DSTAMP}&lt;/string&gt;" />

    </target>
</project>

Then add an application_build_date string to your strings.xml

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <string name="app_name">your app name</string>
    <string name="application_build_date">20140101</string>
    ...
</resources>

Ensure the ant script is executed as a pre-build activity and you will always have a valid build date available to you within R.string.application_build_date.

查看更多
The star\"
7楼-- · 2019-01-07 06:07

Since API version 9 there's:

PackageInfo.lastUpdateTime

The time at which the app was last updated.

try {
    PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
    //TODO use packageInfo.lastUpdateTime
} catch (PackageManager.NameNotFoundException e) {
    e.printStackTrace();
}

On lower API versions you must make build time yourself. For example putting a file into assets folder containing the date. Or using __ DATE__ macro in native code. Or checking date when your classes.dex was built (date of file in your APK).

查看更多
登录 后发表回答