Android 如何讀取未安裝的APK 簽名信息

    以前對於APK的簽名信息獲取,是停留在對已安裝的APK進行相關的操做,可是最近因爲工做須要,就整理了一份關於讀取未安裝的APK 簽名信息的資料,下面很少說直接上代碼:android

byte[] signature = getSign(context);
String installPublickey = getPublicKey(signature);//已安裝的應用APK簽名信息獲取
//
apkFile :下載的未安裝APK的安裝包路徑,如:
String apkFile = Environment.getExternalStorageDirectory() + "/download/xxxx.apk";

byte[] unstallSignature = getPackageArchiveInfo(apkFile, PackageManager.GET_ACTIVITIES | PackageManager.GET_SIGNATURES);
String unInstallPublickey
= getPublicKey(unstallSignature );//未安裝的APK包的簽名信息獲取

    以上是代碼調用,用的方法在下面貼出:app

private static byte[] getSign(Context context) {  
        PackageManager pm = context.getPackageManager();  
        List<PackageInfo> apps = pm.getInstalledPackages(PackageManager.GET_SIGNATURES);  
        Iterator<PackageInfo> iter = apps.iterator();  
        while (iter.hasNext()) {  
            PackageInfo info = iter.next();  
            String packageName = info.packageName;  
            //按包名讀取簽名  
            if (packageName.equals("com.XXX.XXX")) { //根據你本身的包名替換
         return info.signatures[0].toByteArray(); } } return null; } @SuppressWarnings({ "unchecked", "rawtypes" }) public static byte[] getPackageArchiveInfo(String apkFile, int flags){ //這個是與顯示有關的, 裏面涉及到一些像素顯示等等, 咱們使用默認的狀況 DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); Object pkgParserPkg = null; Class[] typeArgs = null; Object[] valueArgs = null; try { Class<?> packageParserClass = Class.forName("android.content.pm.PackageParser"); Constructor<?> packageParserConstructor = null; Object packageParser = null; //因爲SDK版本問題,這裏需作適配,來生成不一樣的構造函數 if (Build.VERSION.SDK_INT > 20) { //無參數 constructor packageParserConstructor = packageParserClass.getDeclaredConstructor(); packageParser = packageParserConstructor.newInstance(); packageParserConstructor.setAccessible(true);//容許訪問 typeArgs = new Class[2]; typeArgs[0] = File.class; typeArgs[1] = int.class; Method pkgParser_parsePackageMtd = packageParserClass.getDeclaredMethod("parsePackage", typeArgs); pkgParser_parsePackageMtd.setAccessible(true); valueArgs = new Object[2]; valueArgs[0] = new File(apkFile); valueArgs[1] = PackageManager.GET_SIGNATURES; pkgParserPkg = pkgParser_parsePackageMtd.invoke(packageParser, valueArgs); } else { //低版本有參數 constructor packageParserConstructor = packageParserClass.getDeclaredConstructor(String.class); Object[] fileArgs = { apkFile }; packageParser = packageParserConstructor.newInstance(fileArgs); packageParserConstructor.setAccessible(true);//容許訪問 typeArgs = new Class[4]; typeArgs[0] = File.class; typeArgs[1] = String.class; typeArgs[2] = DisplayMetrics.class; typeArgs[3] = int.class; Method pkgParser_parsePackageMtd = packageParserClass.getDeclaredMethod("parsePackage", typeArgs); pkgParser_parsePackageMtd.setAccessible(true); valueArgs = new Object[4]; valueArgs[0] = new File(apkFile); valueArgs[1] = apkFile; valueArgs[2] = metrics; valueArgs[3] = PackageManager.GET_SIGNATURES; pkgParserPkg = pkgParser_parsePackageMtd.invoke(packageParser, valueArgs); } typeArgs = new Class[2]; typeArgs[0] = pkgParserPkg.getClass(); typeArgs[1] = int.class; Method pkgParser_collectCertificatesMtd = packageParserClass.getDeclaredMethod("collectCertificates", typeArgs); valueArgs = new Object[2]; valueArgs[0] = pkgParserPkg; valueArgs[1] = PackageManager.GET_SIGNATURES; pkgParser_collectCertificatesMtd.invoke(packageParser, valueArgs); // 應用程序信息包, 這個公開的, 不過有些函數變量沒公開 Field packageInfoFld = pkgParserPkg.getClass().getDeclaredField("mSignatures"); Signature[] info = (Signature[]) packageInfoFld.get(pkgParserPkg); return info[0].toByteArray(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return null; } public static String getPublicKey(byte[] signature) { try { CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(signature)); return cert.getPublicKey().toString(); } catch (CertificateException e) { e.printStackTrace(); } return null; }

 乾貨獻給有須要的人,不喜勿噴!函數

相關文章
相關標籤/搜索