获取未安装的APK文件的签名信息,反射实现

	@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签名是否一样

猜你喜欢

转载自assistne.iteye.com/blog/1954309