如何将编写时间戳写入apk
- 在Android通讯录包中进行一些更改
- 使用
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="(<string name="application_build_date">)\d+(</string>)" replace="<string name="application_build_date">${DSTAMP}</string>" /> </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。