Get Android .apk file VersionName or VersionCode WITHOUT installing apk

前端 未结 9 2573
鱼传尺愫
鱼传尺愫 2020-11-28 17:32

How can I get programmatically get the version code or version name of my apk from the AndroidManifest.xml file after downloading it and without installing it.



        
相关标签:
9条回答
  • 2020-11-28 18:05

    For the upgrade scenario specifically an alternative approach might be to have a web service that delivers the current version number and check that instead of downloading the entire apk just to check its version. It would save some bandwidth, be a little more performant (much faster to download than an apk if the whole apk isn't needed most of the time) and much simpler to implement.

    In the simplest form you could have a simple text file on your server... http://some-place.com/current-app-version.txt

    Inside of that text file have something like

    3.1.4
    

    and then download that file and check against the currently installed version.

    Building a more advanced solution to that would be to implement a proper web service and have an api call at launch which could return some json, i.e. http://api.some-place.com/versionCheck:

    {
        "current_version": "3.1.4"
    }
    
    0 讨论(0)
  • 2020-11-28 18:08

    Following worked for me from the command line:

    aapt dump badging myapp.apk
    

    NOTE: aapt.exe is found in a build-tools sub-folder of SDK. For example:

    <sdk_path>/build-tools/23.0.2/aapt.exe
    
    0 讨论(0)
  • 2020-11-28 18:17

    At the moment, this can be done as follows

    $ANDROID_HOME/build-tools/28.0.3/aapt dump badging /<path to>/<app name>.apk
    

    In General, it will be:

    $ANDROID_HOME/build-tools/<version_of_build_tools>/aapt dump badging /<path to>/<app name>.apk
    
    0 讨论(0)
  • 2020-11-28 18:21

    If you are using version 2.2 and above of Android Studio then in Android Studio use Build Analyze APK then select AndroidManifest.xml file.

    0 讨论(0)
  • 2020-11-28 18:22
    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();
    
    0 讨论(0)
  • 2020-11-28 18:23

    I can now successfully retrieve the version of an APK file from its binary XML data.

    This topic is where I got the key to my answer (I also added my version of Ribo's code): How to parse the AndroidManifest.xml file inside an .apk package

    Additionally, here's the XML parsing code I wrote, specifically to fetch the version:

    XML Parsing

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

    Version Comparison (seen as SystemPackageTools.compareVersions in previous snippet) NOTE: This code is inspired from the following topic: 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;
    }
    

    I hope this helps.

    0 讨论(0)
提交回复
热议问题