2012-11-20 196 views
108

如何从AndroidManifest.xml文件以编程方式从AndroidManifest.xml文件以编程方式获得版本代码或版本名称,并且无需安装。获取Android .apk文件版本名或版本代码无需安装apk

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

比如我要在设备上安装它来检查是否有新版本后,关于我的IIS服务中上传的,如果没有一个新的版本,我不想安装它。

+0

检查此问题http://stackoverflow.com/a/4761689/1109425 – nandeesh

+0

你有没有想过什么?我面临同样的问题。谢谢! – Mathieu

+0

顺便说一句,我希望没有人认为一个好的解决方案是下载文件,然后*然后*检查是否需要 - 第一句话的含义是什么。大概你会想要在你的服务器上运行*的代码,并用可用的版本号来响应。 – ToolmakerSteve

回答

4

我现在可以成功从其二进制XML数据中检索APK文件的版本。

这个话题,我拿到了钥匙给我的答案(我还加我的版本的日博的代码): 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) 注:此代码是从下面的主题启发: 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; 
} 

我希望这会有所帮助。

+0

为什么你的代码看起来缩小了? – forresthopkinsa

+0

您是否升级到新的Gradle或Android Studio?这是否仍然有效? Robio代码无法再为我解压缩XML。 –

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

这是最好的答案,应该被接受。 –

+1

这对我无效 – gian1200

+3

如何在不安装应用程序的情况下阅读'apk'内容**? @PatrickCho – talha06

279

继为我工作的命令行:

aapt dump badging myapp.apk 

注:aapt.exe在SDK的build-tools子文件夹中找到。例如:

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

这工作完美,是一个非常简单的解决方案。谢谢! – NateJC

+21

工作正常,这应该被标记为正确答案,对于信息,'aapt'在sdk中的* build-tools/XX *中。 –

+0

是aapt命令的一部分工具还是平台工具? – 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

这不是对这个问题的回答。这是在正在运行的应用程序中获取一些版本信息并显示它的代码。问题是如何从APK文件中获取这些信息,*而不安装应用程序*。 – ToolmakerSteve

2

对于升级方案具体的替代方法可能是有,可提供当前版本号的Web服务和检查而不是下载整个APK只是为了检查其版本。它会节省一些带宽,性能会更高一些(如果大多数时候不需要整个apk,下载速度比apk快很多),并且实现起来要简单得多。

在你可以有你的服务器上的一个简单的文本文件最简单的形式... http://some-place.com/current-app-version.txt

内部的文本文件中有这样的事

3.1.4 

,然后下载该文件,并检查对当前安装的版本。

建立一个更先进的解决方案,这将是实现适当的Web服务,必须在发布的API调用,它可以返回一些JSON,即http://api.some-place.com/versionCheck

{ 
    "current_version": "3.1.4" 
} 
+0

你在正确的轨道 - 不应该下载文件,只是为了得到它的版本。我只想提一下,我不会建议手动创建文本文件 - 太容易让它与实际的apk文件不匹配。相反,编写一个脚本(使用其他答案之一)来查看apk内部,查看它的版本,将其存储在文件或数据库中,以便用您讨论的方法进行检索。 – ToolmakerSteve

+0

是的,在这种情况下,情况并不是它需要完全匹配APK,只是最新的版本号是公开可访问的。 – grego

24

如果使用的是版本2。2及以上Android Studio然后在Android Studio中使用Build分析APK然后选择AndroidManifest.xml文件。

+2

OP问如何通过编程获得它[ – forresthopkinsa

+1

]因为他不知道像这样的工具是在Android Studio中构建的。他还问*没有安装apk *。 – vovahost

+1

当然,他并不知道,因为在问这个问题时,Android Studio不存在。另外,即使这样做,这也不能解决他的问题 - 他希望他的设备能够以编程方式检查他的IIS服务器的更新,就像他在问题中所说的那样。 Patrick Cho的答案解释了如何在没有安装的情况下通过编程来完成。 – forresthopkinsa