获取已安装或未安装的apk签名

出处: http://lynen.iteye.com/blog/1700126

某些时候需要获取已安装的apk或者是未安装的apk的签名信息,以下代码片段将会很有用。

1.通过app的packageName获取已安装的apk的签名信息

 

Java代码   收藏代码
  1. public Signature getPackageSignature(Context context, String packageName){  
  2.         PackageManager pm = context.getPackageManager();  
  3.         List<PackageInfo> apps = pm.getInstalledPackages(PackageManager.GET_SIGNATURES);  
  4.         Iterator<PackageInfo> it = apps.iterator();  
  5.         while(it.hasNext()){  
  6.             PackageInfo info = it.next();  
  7.             if(info.packageName.equals(packageName)){  
  8.                 return info.signatures[0];  
  9.             }  
  10.         }  
  11.         return null;  
  12.     }  

 

2.根据文件路径获取未安装的apk的签名信息

由于android平台本身的一个小bug,使用PackageManager方式获取未安装的apk文件的签名会稍微费事一点。

(android平台的这个小bug有些狗血,是因为PackageManager的的getPackageArchiveInfo中少了如下代码的原因导致)

缺少的代码:

 

Java代码   收藏代码
  1. if ((flags & GET_SIGNATURES) != 0)  
  2.             packageParser.collectCertificates(pkg, 0);  

问题的详细信息可以查看以下链接:

https://code.google.com/p/android/issues/detail?id=9151#c8

https://android-review.googlesource.com/#/c/18769/1/core/java/android/content/pm/PackageManager.java

 

这样一来,获取apk文件的签名方式将会变得稍微啰嗦一点

(1)首先自定义一个getPackageArchiveInfo函数,如下:

Java代码   收藏代码
  1. @SuppressWarnings("unchecked")  
  2.     public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags){  
  3.         // Workaround for https://code.google.com/p/android/issues/detail?id=9151#c8  
  4.         try{  
  5.             Class packageParserClass = Class.forName(  
  6.                     "android.content.pm.PackageParser");  
  7.             Class[] innerClasses = packageParserClass.getDeclaredClasses();  
  8.             Class packageParserPackageClass = null;  
  9.             for (Class innerClass : innerClasses){  
  10.                 if (0 == innerClass.getName().compareTo("android.content.pm.PackageParser$Package")){  
  11.                     packageParserPackageClass = innerClass;  
  12.                     break;  
  13.                 }  
  14.             }  
  15.             Constructor packageParserConstructor = packageParserClass.getConstructor(  
  16.                     String.class);  
  17.             Method parsePackageMethod = packageParserClass.getDeclaredMethod(  
  18.                     "parsePackage", File.class, String.class, DisplayMetrics.classint.class);  
  19.             Method collectCertificatesMethod = packageParserClass.getDeclaredMethod(  
  20.                     "collectCertificates", packageParserPackageClass, int.class);  
  21.             Method generatePackageInfoMethod = packageParserClass.getDeclaredMethod(  
  22.                     "generatePackageInfo", packageParserPackageClass, int[].classint.classlong.classlong.class);  
  23.             packageParserConstructor.setAccessible(true);  
  24.             parsePackageMethod.setAccessible(true);  
  25.             collectCertificatesMethod.setAccessible(true);  
  26.             generatePackageInfoMethod.setAccessible(true);  
  27.               
  28.             Object packageParser = packageParserConstructor.newInstance(archiveFilePath);  
  29.       
  30.             DisplayMetrics metrics = new DisplayMetrics();  
  31.             metrics.setToDefaults();  
  32.               
  33.             final File sourceFile = new File(archiveFilePath);  
  34.   
  35.             Object pkg = parsePackageMethod.invoke(  
  36.                     packageParser,  
  37.                     sourceFile,  
  38.                     archiveFilePath,  
  39.                     metrics,  
  40.                     0);  
  41.             if (pkg == null){  
  42.                 return null;  
  43.             }  
  44.       
  45.             if ((flags & android.content.pm.PackageManager.GET_SIGNATURES) != 0){  
  46.                 collectCertificatesMethod.invoke(packageParser, pkg, 0);  
  47.             }  
  48.       
  49.             return (PackageInfo)generatePackageInfoMethod.invoke(null, pkg, null, flags, 00);  
  50.         }  
  51.         catch (Exception e)  
  52.         {  
  53.             Log.e("Signature Monitor",  
  54.                 "android.content.pm.PackageParser reflection failed: " + e.toString());  
  55.         }  
  56.   
  57.         return null;  
  58.     }  

 (2)使用自定义的getPackageArchiveInfo函数获取PackageInfo,从而获取签名信息,如下:

Java代码   收藏代码
  1. /** 
  2.      *  
  3.      * @param context 
  4.      * @param apkFile 文件的全路径信息(包括apk文件的名称),如果是无效的apk文件,返回值为null 
  5.      * @return 
  6.      */  
  7.     public Signature getApkSignatureByFilePath(Context context, String apkFile){  
  8.         PackageInfo newInfo = getPackageArchiveInfo(apkFile, PackageManager.GET_ACTIVITIES | PackageManager.GET_SIGNATURES);  
  9.         if(newInfo != null){  
  10.             if(newInfo.signatures != null && newInfo.signatures.length >0){  
  11.                 return newInfo.signatures[0];  
  12.             }  
  13.         }  
  14.         return null;  
  15.     }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值