2012-11-20 18 views
108

Come è possibile ottenere a livello di codice il codice di versione o il nome di versione di apk dal file AndroidManifest.xml dopo il download e senza installarlo.Scarica il file .apk di Android VersionName o VersionCode SENZA installazione di apk

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="xxx.xx.xxx" 
    android:versionCode="1" 
    android:versionName="1.1" > 

Per esempio voglio verificare se una nuova versione è caricato il mio servizio IIS dopo che installarlo sul dispositivo, se non una nuova versione che non voglio installarlo.

+0

controlla questo http://stackoverflow.com/a/4761689/1109425 – nandeesh

+0

Hai scoperto qualcosa dopo tutto? Sto affrontando lo stesso problema. Grazie! – Mathieu

+0

BTW, spero che nessuno pensi che una buona soluzione sia quella di scaricare il file, e * quindi * verificare se è necessario - che è quello che suggerisce la prima frase. Presumibilmente, preferiresti il ​​codice che viene eseguito * sul tuo server * e risponde con il numero di versione disponibile. – ToolmakerSteve

risposta

4

Ora riesco a recuperare la versione di un file APK dai suoi dati XML binari.

Questo argomento è dove ho avuto la chiave per la mia risposta (ho aggiunto anche la mia versione di codice di Ribo): How to parse the AndroidManifest.xml file inside an .apk package

Inoltre, ecco il codice parsing XML che ho scritto, in particolare per andare a prendere la versione:

XML Analisi

/** 
* Verifies at Conductor APK path if package version if newer 
* 
* @return True if package found is newer, false otherwise 
*/ 
public static boolean checkIsNewVersion(String conductorApkPath) { 

    boolean newVersionExists = false; 

    // Decompress found APK's Manifest XML 
    // Source: https://stackoverflow.com/questions/2097813/how-to-parse-the-androidmanifest-xml-file-inside-an-apk-package/4761689#4761689 
    try { 

     if ((new File(conductorApkPath).exists())) { 

      JarFile jf = new JarFile(conductorApkPath); 
      InputStream is = jf.getInputStream(jf.getEntry("AndroidManifest.xml")); 
      byte[] xml = new byte[is.available()]; 
      int br = is.read(xml); 

      //Tree tr = TrunkFactory.newTree(); 
      String xmlResult = SystemPackageTools.decompressXML(xml); 
      //prt("XML\n"+tr.list()); 

      if (!xmlResult.isEmpty()) { 

       InputStream in = new ByteArrayInputStream(xmlResult.getBytes()); 

       // Source: http://developer.android.com/training/basics/network-ops/xml.html 
       XmlPullParser parser = Xml.newPullParser(); 
       parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); 

       parser.setInput(in, null); 
       parser.nextTag(); 

       String name = parser.getName(); 
       if (name.equalsIgnoreCase("Manifest")) { 

        String pakVersion = parser.getAttributeValue(null, "versionName"); 
          //NOTE: This is specific to my project. Replace with whatever is relevant on your side to fetch your project's version 
        String curVersion = SharedData.getPlayerVersion(); 

        int isNewer = SystemPackageTools.compareVersions(pakVersion, curVersion); 

        newVersionExists = (isNewer == 1); 
       } 

      } 
     } 

    } catch (Exception ex) { 
     android.util.Log.e(TAG, "getIntents, ex: "+ex); 
     ex.printStackTrace(); 
    } 

    return newVersionExists; 
} 

Confronto tra versioni (visto come SystemPackageTools.compareVersions nel frammento precedente) NOTA: Questo codice è ispirato dal seguente argomento: Efficient way to compare version strings in Java

/** 
* Compare 2 version strings and tell if the first is higher, equal or lower 
* Source: https://stackoverflow.com/questions/6701948/efficient-way-to-compare-version-strings-in-java 
* 
* @param ver1 Reference version 
* @param ver2 Comparison version 
* 
* @return 1 if ver1 is higher, 0 if equal, -1 if ver1 is lower 
*/ 
public static final int compareVersions(String ver1, String ver2) { 

    String[] vals1 = ver1.split("\\."); 
    String[] vals2 = ver2.split("\\."); 
    int i=0; 
    while(i<vals1.length&&i<vals2.length&&vals1[i].equals(vals2[i])) { 
     i++; 
    } 

    if (i<vals1.length&&i<vals2.length) { 
     int diff = Integer.valueOf(vals1[i]).compareTo(Integer.valueOf(vals2[i])); 
     return diff<0?-1:diff==0?0:1; 
    } 

    return vals1.length<vals2.length?-1:vals1.length==vals2.length?0:1; 
} 

Spero che questo aiuti.

+0

Perché il tuo codice sembra minimizzato? – forresthopkinsa

+0

Hai eseguito l'upgrade al nuovo Gradle o Android Studio? Funziona ancora? Il codice Robio non funziona più per decomprimere XML per me. –

67
final PackageManager pm = getPackageManager(); 
String apkName = "example.apk"; 
String fullPath = Environment.getExternalStorageDirectory() + "/" + apkName;   
PackageInfo info = pm.getPackageArchiveInfo(fullPath, 0); 
Toast.makeText(this, "VersionCode : " + info.versionCode + ", VersionName : " + info.versionName , Toast.LENGTH_LONG).show(); 
+7

Questa è la migliore risposta e dovrebbe essere accettata. –

+1

Questo non ha funzionato per me – gian1200

+3

come posso leggere il contenuto di 'apk' ** senza installare ** l'applicazione? @PatrickCho – talha06

279

In seguito ha lavorato per me dalla riga di comando:

aapt dump badging myapp.apk 

NOTA: aapt.exe si trova in un build-tools sottocartella di SDK. Per esempio:

<sdk_path>/build-tools/23.0.2/aapt.exe 
+0

Questo ha funzionato perfettamente ed è stata una soluzione molto semplice. Grazie! – NateJC

+21

Funziona bene, questo dovrebbe essere contrassegnato come la risposta corretta, per informazioni, 'aapt' è in * build-tools/XX * nel sdk. –

+0

è parte del comando aapt di strumenti o strumenti di piattaforma? – gmuhammad

3
EditText ET1 = (EditText) findViewById(R.id.editText1); 

    PackageInfo pinfo; 
    try { 
     pinfo = getPackageManager().getPackageInfo(getPackageName(), 0); 
     String versionName = pinfo.versionName; 
     ET1.setText(versionName); 
     //ET2.setText(versionNumber); 
    } catch (NameNotFoundException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
+5

Questa non è una risposta alla domanda. Questo è il codice che, all'interno di un'applicazione in esecuzione, ottiene alcune informazioni sulla versione e la visualizza. La domanda è come ottenere queste informazioni da un file APK, * senza installare l'app *. – ToolmakerSteve

2

Per lo scenario di aggiornamento specificamente un approccio alternativo potrebbe essere quello di avere un servizio web che fornisce il numero di versione corrente e verificare che, invece di scaricare l'intero apk solo per verificare la sua versione. Risparmierebbe un po 'di larghezza di banda, sarebbe un po' più performante (molto più veloce da scaricare rispetto a un apk se l'intero apk non è necessario la maggior parte del tempo) e molto più semplice da implementare.

Nella forma più semplice si potrebbe avere un semplice file di testo sul vostro server ... http://some-place.com/current-app-version.txt

All'interno di tale file di testo avere qualcosa di simile

3.1.4 

e quindi scaricare il file e verificare contro il versione attualmente installata.

Costruire una soluzione più avanzata per che sarebbe di implementare un servizio web corretta e hanno una chiamata API al momento del lancio, che potrebbe tornare un po 'di JSON, cioè http://api.some-place.com/versionCheck:

{ 
    "current_version": "3.1.4" 
} 
+0

Sei sulla strada giusta - non devi scaricare il file, solo per ottenere la sua versione. Voglio solo ricordare che non consiglierei di creare il file di testo MANUALMENTE - troppo facile per non farlo corrispondere al vero file apk. Invece, scrivi uno script (che usa una delle altre risposte) per guardare all'interno dell'apk per vedere quale sia la sua versione, memorizzandola nel file o nel database, per essere recuperata con il mezzo che discuti. – ToolmakerSteve

+0

Sì, in questo scenario il caso non è che debba corrispondere all'APK, ma solo che l'ultimo numero di versione è accessibile pubblicamente. – grego

24

Se si utilizza versione 2.2 e al di sopra diAndroid Studio poi in Android Studio usare CorporaturaAnalizzare APK quindi selezionare AndroidManifest.xml file.

+2

OP ha chiesto come ottenerlo 'programmaticamente' – forresthopkinsa

+1

Perché non sapeva che uno strumento come questo è stato creato in Android Studio. Ha anche chiesto * senza installare l'apk *. – vovahost

+1

Ovviamente non lo sapeva, perché Android Studio non esisteva quando è stata posta questa domanda. Inoltre, anche se fosse così, questo non risolve il suo problema: vuole che il suo dispositivo * controlli * programmaticamente gli aggiornamenti dal suo server IIS, come ha affermato nella domanda. La risposta di Patrick Cho spiega come farlo a livello di codice senza installare. – forresthopkinsa

Problemi correlati