2011-09-30 8 views
47
  1. Fare alcuni cambiamenti in Contatti Android pacchetto
  2. Utilizzando mm (fare) il comando per costruire questa applicazione

Perché devo cambiare e costruire di nuovo questa applicazione e ancora una volta, quindi voglio aggiungere un timestamp nel Contacts.apk per controllare il tempo di costruzione quando lo eseguiamo nel telefono.Come scrivere costruire timestamp in apk

Come sappiamo, quando eseguiamo il comando mm, verrà chiamato lo Android.mk (makefile) nel pacchetto Contatti.

E ora, è possibile ottenere il tempo di compilazione utilizzando date -macro.

Ma come possiamo scrivere questo timestamp in un file che la nostra applicazione può leggere in fase di runtime?

Qualche suggerimento?

+0

Vuoi aggiungere il timestamp di build all'apk stesso? quindi diventa 'MyApp-201109302359.apk'? – Jimmy

+0

Grazie, ho raggiunto questo obiettivo. come MyApp-201109302359.apk, ma come sapete, devo costruire questa app molte volte. Se lo faccio, ci saranno molti MyApp - *. Apk nella cartella * system/app, non è quello che voglio. – FallingRain

+0

Voglio scrivere il timestamp della build in un file che il mio apk può leggere e visualizzarlo in Activity al runtime. – FallingRain

risposta

22

Dal API versione 9 non c'è:

PackageInfo.lastUpdateTime

L'ora in cui l'applicazione è stata aggiornata.

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

Sulle versioni API inferiori è necessario rendere tempo di costruzione da soli. Ad esempio inserendo un file nella cartella delle risorse contenente la data. O usando la macro __ DATE__ nel codice nativo. Oppure verifica la data in cui è stato creato il tuo classes.dex (la data del file nel tuo APK).

+0

Grazie mille, il tuo consiglio è così prezioso.^_^Sto verificando il metodo usando PackageInfo.lastUpdateTime ... – FallingRain

+0

Come verificare la data dell'ultima modifica data mia propria classes.dex nel codice java della mia applicazione? E quel che è peggio, trovo che classes.dex non viene aggiornato quando ricostruisco la mia applicazione. – FallingRain

+0

PackageInfo.lastUpdate non funziona per me, poiché il suo valore è sempre "2000-01-01". – FallingRain

95

metodo che controlla la data di ultima modifica di classes.dex, questo significa che l'ultima volta in cui il codice della tua app è stata costruita:

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

testato e funziona bene, anche se l'applicazione è installata su scheda SD.

+1

Sì, ora lo uso anche nella finestra di dialogo Informazioni :) –

+11

ma non dimenticare di chiamare ** zf.close() ** dopo aver letto – Sash0k

+0

come posso aggiungere "String s" al nome .apk? – hariszaman

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

Entrambe sono tempi diversi. Puoi controllare con il codice qui sotto.

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

So che questo è molto vecchio, ma ecco come ho fatto usando formica all'interno di Eclipse:

build.xml nella root del progetto

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

Quindi aggiungere una stringa application_build_date sulle tue corde .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> 

Verificare lo script ant viene eseguito come attività pre-compilazione e si vuole avere sempre una data di compilazione valida disponibile in R.string.application_build_date.

+0

Forse è un po 'vecchio, ma molto utile. Puoi aiutarmi come farlo con gradle? –

+0

quindi in realtà ho appena implementato questo stesso script in gradle, ma con il senno di poi avrei dovuto usare la soluzione @AleksejsMjaliks. Il suo approccio lo integrerebbe direttamente in BuildConfig che è ancora più interessante perché hai tipo di build, flavor, testo di versione e codice di versione sono già nascosti all'interno di esso. – ShellDude

+0

ma per rispondere alla tua domanda, metterlo nella root della cartella del progetto, aggiornare il percorso a strings.xml (deve essere location = "./src/main/res/values ​​/ strings.xml" in Android Studio) e quindi importalo semplicemente in grade usando ant.importBuild 'build.xml' nella parte superiore del tuo file gradle.build. È quindi possibile aggiungerlo come attività dipendente alle attività di assemblaggio. – ShellDude

5

Io uso la stessa strategia di Pointer Null tranne che preferisco il file MANIFEST.MF. Questo viene rigenerato anche se viene modificato un layout (che non è il caso di classes.dex). Forzo anche la data da formulare in GMT per evitare confusione tra terminale e server TZ (se è necessario effettuare un confronto, es: controlla l'ultima versione).

Esso risulta nel codice seguente:

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

Se si utilizza Gradle, è possibile aggiungere buildConfigField con data e ora aggiornato al momento della compilazione.

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

Quindi leggerlo in fase di esecuzione.

Date buildDate = new Date(BuildConfig.TIMESTAMP); 
+2

Trovo che questa sia l'opzione migliore se si utilizza Gradle –

+1

Grazie, stavo cercando un po 'di tempo per qualcosa di così facile – Seltsam

+3

Questa dovrebbe essere considerata la migliore risposta. – pepan

5

nel 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))' 
    } 
} 
9

Un suggerimento per soluzione "ora della modifica ultimo dei file di classes.dex" un più recenti versioni Android Studio: Nella configurazione di default il timestamp non è scritto più a file nel file apk. Il timestamp è sempre "30 nov 1979".

È possibile modificare questo comportamento aggiungendo questa riga al file

% userdir% /. Gradle/gradle.properties (creare se non esistenti)

android.keepTimestampsInApk = true 

Vedi Issue 220039

(Must essere in userdir, gradle.properties nella dir di costruzione del progetto sembra non funzionare)