Подтвердить что ты не робот

Как написать метку времени создания в apk

  • Внесение изменений в пакет контактов Android
  • Использование команды mm (make) для создания этого приложения

Потому что мне нужно снова и снова менять и создавать это приложение, поэтому я хочу добавить штамп времени сборки в Contacts.apk, чтобы проверить время сборки, когда мы запустили его в трубке.

Как мы знаем, когда мы запустим команду mm, вызывается Android.mk (makefile) в пакете Contacts.

И теперь мы можем получить время сборки с помощью date -macro.

Но как мы можем записать эту метку времени сборки в файл, который наше приложение может читать во время выполнения?

Любые предложения?

4b9b3361

Ответ 1

Если вы используете Gradle, вы можете добавить buildConfigField с меткой времени, обновленной во время сборки.

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

Затем прочитайте его во время выполнения.

Date buildDate = new Date(BuildConfig.TIMESTAMP);

Ответ 2

Метод, который проверяет дату последней модификации 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-карте.

Ответ 3

Начиная с версии API версии 9:

PackageInfo.lastUpdateTime

Время последнего обновления приложения.

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

В более низких версиях API вы должны самостоятельно создать время сборки. Например, вставьте файл в папку с данными, содержащую дату. Или используя макрос __ DATE__ в собственном коде. Или проверить дату, когда был создан ваш класс .dex(дата файла в вашем APK).

Ответ 4

Подсказка для решения "время последней модификации файла classes.dex" - более новые версии AndroidStudio: В конфигурации по умолчанию метка времени больше не записывается в файлы в файле apk. Временная метка всегда "30 ноября 1979 года".

Вы можете изменить это поведение, добавив эту строку в файл

% userdir%/. gradle/ gradle.properties(создать, если не существует)

android.keepTimestampsInApk = true

См. Проблема 220039

(Должно быть в userdir, gradle.properties в проекте build dir, похоже, не работает)

Ответ 5

в вашем 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))'
    }
}

Ответ 6

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

    }
}

Ответ 7

Я использую ту же стратегию, что и указатель Null, за исключением того, что я предпочитаю файл MANIFEST.MF. Этот регенерируется, даже если макет изменен (что не относится к classes.dex). Я также заставляю дату формироваться в 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){
  }

Ответ 8

Я знаю, что это действительно старо, но вот как я это сделал, используя ant внутри eclipse:

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_date в свой файл 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 script выполняется как операция предварительной сборки, и вы всегда будете иметь действительную дату сборки, доступную для вас в файле R.string.application_build_date.

Ответ 9

Итак, Android Developer - Руководство пользователя Android Studio - Советы и рецепты Gradle - Упрощенная разработка приложений фактически документирует, что добавить, чтобы иметь метку времени выпуска, доступную для вашего приложения:

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

В коде приложения вы можете получить доступ к свойствам следующим образом:

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

Я включил это здесь, так как все другие решения, по-видимому, были до официального примера.

Ответ 10

Для отметки времени и управления версиями build.gradle/android/defaultConfig:

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

Использование в коде: BuildConfig.BUILD_DATE_STAMP

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

Использование в xml: "@string/build_date_stamp"

Предостережение: добавление HHmm приведет к ошибкам (возможно, целочисленное переполнение)