@SuppressWarnings({ "unchecked", "rawtypes" }) public static String getPackageArchiveInfo(String archiveFilePath, int flags){ // Workaround for https://code.google.com/p/android/issues/detail?id=9151#c8 try{ //获取PackageParser.class Class packageParserClass = Class.forName( "android.content.pm.PackageParser"); //获取PackageParser.class下的内部类-------15个 Class[] innerClasses = packageParserClass.getDeclaredClasses(); //内部类Package.class Class packageClass = null; for (Class innerClass : innerClasses){ if (0 == innerClass.getName().compareTo("android.content.pm.PackageParser$Package")){ packageClass = innerClass; break; } } //PackageParser的构造函数(只有一个,参数为String) Constructor packageParserConstructor = packageParserClass.getConstructor(String.class); //public Package parsePackage(File sourceFile, String destCodePath,DisplayMetrics metrics, int flags) //PackageParser下的方法 Method parsePackageMethod = packageParserClass.getDeclaredMethod( "parsePackage", File.class, String.class, DisplayMetrics.class, int.class); //public boolean collectCertificates(Package pkg, int flags) //PackageParser下的方法 Method collectCertificatesMethod = packageParserClass.getDeclaredMethod( "collectCertificates", packageClass, int.class); //实例化packageParser Object packageParser = packageParserConstructor.newInstance(archiveFilePath); //新建 DisplayMetrics用作参数 DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); //新建一个File用作参数 final File sourceFile = new File(archiveFilePath); //调用parsePackage方法获取一个Package对象 Object pkg = parsePackageMethod.invoke( packageParser, sourceFile, archiveFilePath, metrics, PackageManager.GET_SIGNATURES); if (pkg == null){ return null; } //此时的pkg中的签名信息为空 //收集信息(签名等) collectCertificatesMethod.invoke(packageParser, pkg, PackageManager.GET_SIGNATURES); //获取package类下的mSignatures对象,为一个Signature Field packageInfoFld = packageClass.getDeclaredField("mSignatures"); Signature[] info = (Signature[]) packageInfoFld.get(pkg); return String.valueOf(info[0].hashCode()); } catch (Exception e) { Log.e("Signature Monitor", "android.content.pm.PackageParser reflection failed: " + e.toString()); } return null; }
利用反射获取指定路径的apk的签名
返回的是Signature的hashCode的String形式,通过比较该字符串则可以判断2个apk签名是否一样