如何将编写时间戳写入apk

  1. 在Android通讯录包中进行一些更改
  2. 使用mm (make)命令来构build这个应用程序

因为我必须一次又一次地更改和构build这个应用程序,所以我想在Contacts.apk添加一个构build时间戳,以检查在手机中运行时的构build时间。

正如我们所知,当我们运行mm命令时,Contacts包中的Android.mk (makefile)将被调用。

现在,我们可以使用date -macro获取构build时间。

但是,我们如何将这个构build时间戳写入到我们的应用程序可以在运行时读取的文件中呢?

有什么build议么?

检查classes.dex最后修改date的方法,这意味着上次应用程序的代码生成时:

  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){ } 

testing,并且工作正常,即使应用程序安装在SD卡上。

如果您使用Gradle,则可以添加buildConfigField并在构build时更新时间戳。

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

然后在运行时读取它。

 Date buildDate = new Date(BuildConfig.TIMESTAMP); 

自API版本9以来:

PackageInfo.lastUpdateTime

该应用程序上次更新的时间。

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

在较低的API版本上,您必须自己编译时间。 例如将一个文件放入包含date的assets文件夹中。 或者在本地代码中使用__ DATE__macros。 或者在您的classes.dex文件build立的时候检查date(APK中文件的date)。

提示解决scheme“classes.dex文件的最后修改时间”一个较新的AndroidStudio版本:在默认configuration时间戳不再写入apk文件中的文件。 时间戳总是“1979年11月30日”。

您可以通过将此行添加到文件来更改此行为

%userdir%/。gradle / gradle.properties(如果不存在则创build)

 android.keepTimestampsInApk = true 

见问题220039

(必须在userdir中,项目编译目录中的gradle.properties似乎不工作)

 Install time : packageInfo.lastUpdateTime build time : zf.getEntry("classes.dex").getTime() 

两者都是不同的时间。 你可以检查下面的代码。

 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; } } } 

我使用与Pointer Null相同的策略,除了我更喜欢MANIFEST.MF文件。 即使布局被修改(这不是classes.dex的情况),这个被重新生成。 我也强制在格林尼治标准时间格式化,以避免混淆terminal和服务器TZs(如果比较必须作出,例如:检查最新版本)。

它导致以下代码:

  try{ ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), 0); ZipFile zf = new ZipFile(ai.sourceDir); ZipEntry ze = zf.getEntry("META-INF/MANIFEST.MF"); long time = ze.getTime(); SimpleDateFormat formatter = (SimpleDateFormat) SimpleDateFormat.getInstance(); formatter.setTimeZone(TimeZone.getTimeZone("gmt")); String s = formatter.format(new java.util.Date(time)); zf.close(); }catch(Exception e){ } 

在你的build.gradle:

 android { defaultConfig { buildConfigField 'String', 'BUILD_TIME', 'new java.text.SimpleDateFormat("MM.dd.yy HH:mm", java.util.Locale.GERMANY).format(new java.util.Date(' + System.currentTimeMillis() +'L))' } } 

我知道这是非常古老的,但这里是我在eclipse中使用ant的方式:

项目根目录下的build.xml

 <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> 

然后添加一个application_build_datestring到你的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> 

确保ant脚本作为预生成活动执行,并且在R.string.application_build_date中始终有一个有效的生成date。