your programing

빌드 타임 스탬프를 APK에 쓰는 방법

lovepro 2020. 12. 31. 23:10
반응형

빌드 타임 스탬프를 APK에 쓰는 방법


  1. Android 연락처 패키지에서 일부 변경
  2. 사용 mm(메이크업) 명령은이 응용 프로그램을 구축

이 앱을 몇 번이고 변경하고 빌드해야하기 때문에 Contacts.apk핸드셋에서 실행할 때 빌드 시간을 확인하기 위해 에 빌드 타임 스탬프를 추가하고 싶습니다 .

아시다시피 mm명령 을 실행하면 Android.mkContacts 패키지 (makefile)이 호출됩니다.

이제 date-macro를 사용하여 빌드 시간을 얻을 수 있습니다 .

하지만이 빌드 타임 스탬프를 애플리케이션이 런타임에 읽을 수있는 파일에 어떻게 쓸 수 있을까요?

어떤 제안?


Gradle을 사용하는 경우 buildConfigField빌드시 업데이트 된 타임 스탬프를 추가 할 수 있습니다 .

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

그런 다음 런타임에 읽으십시오.

Date buildDate = new Date(BuildConfig.TIMESTAMP);

classes.dex의 마지막 수정 날짜를 확인하는 메서드로, 앱의 코드가 마지막으로 빌드 된 시간을 의미합니다.

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

앱이 SD 카드에 설치되어 있어도 테스트를 거쳐 제대로 작동합니다.


API 버전 9부터 다음이 있습니다.

PackageInfo.lastUpdateTime

앱이 마지막으로 업데이트 된 시간입니다.

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

낮은 API 버전에서는 빌드 시간을 직접 만들어야합니다. 예를 들어 날짜가 포함 된 자산 폴더에 파일을 넣습니다. 또는 네이티브 코드에서 __ DATE__ 매크로를 사용합니다. 또는 classes.dex가 빌드 된 날짜 (APK의 파일 날짜)를 확인합니다.


새로운 AndroidStudio 버전 인 "class.dex 파일의 마지막 수정 시간"솔루션에 대한 힌트 : 기본 구성에서 타임 스탬프는 더 이상 apk 파일의 파일에 기록되지 않습니다. 타임 스탬프는 항상 '1979 년 11 월 30 일'입니다.

이 행을 파일에 추가하여이 동작을 변경할 수 있습니다.

% userdir % /. gradle / gradle.properties (존재하지 않는 경우 생성)

android.keepTimestampsInApk = true

문제 220039 참조

(userdir에 있어야하며 프로젝트 빌드 디렉토리의 gradle.properties가 작동하지 않는 것 같습니다)


build.gradle에서 :

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

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

    }
}

MANIFEST.MF 파일을 선호한다는 점을 제외하고는 Pointer Null과 동일한 전략을 사용합니다. 이것은 레이아웃이 수정 되더라도 다시 생성됩니다 (class.dex의 경우는 아님). 또한 터미널과 서버 TZ 간의 혼동을 피하기 위해 날짜를 GMT 형식으로 지정합니다 (비교해야하는 경우 예 : 최신 버전 확인).

다음 코드가 생성됩니다.

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

그런 다음 strings.xml에 application_build_date 문자열을 추가하십시오.

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


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")
    }
  }
}
...

In your app code, you can access the properties as follows:

...
Log.i(TAG, BuildConfig.BUILD_TIME);
Log.i(TAG, getString(R.string.build_time));

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


For time stamping and versioning, build.gradle/android/defaultConfig:

def buildDateStamp = new Date().format("yyyyMMdd").toInteger()
versionCode buildDateStamp
versionName "$buildDateStamp"
buildConfigField "String", "BUILD_DATE_STAMP", "\"$buildDateStamp\""

Usage in code: BuildConfig.BUILD_DATE_STAMP

resValue "string", "build_date_stamp", "$buildDateStamp"

Usage in xml: "@string/build_date_stamp"

Caveat: adding HHmm will cause errors (probably integer overflow)

ReferenceURL : https://stackoverflow.com/questions/7607165/how-to-write-build-time-stamp-into-apk

반응형