211

ダウンロードした後、インストールせずに AndroidManifest.xml ファイルから apk のバージョン コードまたはバージョン名をプログラムで取得するにはどうすればよいですか。

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

たとえば、IIS サービスに新しいバージョンがアップロードされているかどうかを確認したいのですが、デバイスにインストールした後、新しいバージョンでない場合はインストールしたくありません。

4

11 に答える 11

97
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();
于 2013-06-15T00:02:47.887 に答える
51

バージョン 2.2 以降Android Studioを使用している場合は、Android Studio でBuild →を使用Analyze APKし、AndroidManifest.xml ファイルを選択します。

于 2016-06-27T10:06:39.797 に答える
5

バイナリ XML データから APK ファイルのバージョンを正常に取得できるようになりました。

このトピックは、私が答えの鍵を得た場所です (Ribo のコードのバージョンも追加しました): How to parse the AndroidManifest.xml file inside an .apk package

さらに、特にバージョンを取得するために、私が書いた XML 解析コードを次に示します。

XML 解析

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

バージョン比較 (前のスニペットでは SystemPackageTools.compareVersions として表示) 注: このコードは、次のトピックから着想を得ています: 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;
}

これが役立つことを願っています。

于 2013-02-11T14:46:12.223 に答える
4

アップグレード シナリオの場合、具体的には、バージョンを確認するためだけに apk 全体をダウンロードする代わりに、現在のバージョン番号を提供する Web サービスを用意し、それを確認する代替アプローチが考えられます。これにより、帯域幅が節約され、パフォーマンスが少し向上し (ほとんどの場合 apk 全体が必要ない場合は、apk よりもダウンロードがはるかに高速になります)、実装がはるかに簡単になります。

最も単純な形式では、サーバー上に単純なテキスト ファイルを配置できます...http://some-place.com/current-app-version.txt

そのテキストファイルの中に次のようなものがあります

3.1.4

次に、そのファイルをダウンロードして、現在インストールされているバージョンと照合します。

それに対するより高度なソリューションを構築するには、適切な Web サービスを実装し、起動時に json を返す可能性のある API 呼び出しを行う必要がありますhttp://api.some-place.com/versionCheck

{
    "current_version": "3.1.4"
}
于 2016-01-05T23:10:53.160 に答える
3

それを使用apkanalyzerすることは、次の一部になりましたcmdline-tools

$ apkanalyzer manifest version-code my_app.apk
1
$ apkanalyzer manifest version-name my_app.apk
1.2.3.4
于 2021-02-10T20:04:44.143 に答える
0
    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();
    }
于 2014-09-15T02:40:29.727 に答える