美文网首页
完美解决安卓9.0获取软件签名失败

完美解决安卓9.0获取软件签名失败

作者: 毛毛虫撤回一条消息 | 来源:发表于2019-06-19 17:46 被阅读0次

今天突然 有人反馈签名校验失败了,后来查看发现是安卓9的系统改了方法了,调用签名校验的方法时抛出了异常
java.lang.NoSuchMethodException: collectCertificates [class android.content.pm.PackageParser$Package, int]

查看源码发现
android-28的 PackageParser

public static void collectCertificates(Package pkg, boolean skipVerify)
        throws PackageParserException {
    collectCertificatesInternal(pkg, skipVerify);
    final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
    for (int i = 0; i < childCount; i++) {
        Package childPkg = pkg.childPackages.get(i);
        childPkg.mSigningDetails = pkg.mSigningDetails; // 不同点
    }
}

android-28以下的 PackageParser

public static void collectCertificates(Package pkg, int parseFlags)
        throws PackageParserException {
    collectCertificatesInternal(pkg, parseFlags);
    final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
    for (int i = 0; i < childCount; i++) {
        Package childPkg = pkg.childPackages.get(i);
        childPkg.mCertificates = pkg.mCertificates; // 不同点
        childPkg.mSignatures = pkg.mSignatures;    // 不同点
        childPkg.mSigningKeys = pkg.mSigningKeys; // 不同点
    }
}

所以针对安卓9 修改了 签名校验方法如下:

    public static String  getPackageArchiveInfo(String apkPath) {
        String PATH_PackageParser = "android.content.pm.PackageParser";
        try {
            // apk包的文件路径
            // 这是一个Package 解释器, 是隐藏的
            // 构造函数的参数只有一个, apk文件的路径
            // PackageParser packageParser = new PackageParser(apkPath);
            Class pkgParserCls = Class.forName(PATH_PackageParser);
            Class[] typeArgs = new Class[1];
            typeArgs[0] = String.class;
            // 这个是与显示有关的, 里面涉及到一些像素显示等等, 我们使用默认的情况
            DisplayMetrics metrics = new DisplayMetrics();
            metrics.setToDefaults();
            Constructor pkgParserCt = null;
            Object pkgParser = null;
            if(Build.VERSION.SDK_INT>20){
                pkgParserCt = pkgParserCls.getConstructor();
                pkgParser = pkgParserCt.newInstance();
                Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod("parsePackage", File.class, int.class);
                Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, new File(apkPath), PackageManager.GET_SIGNATURES);
           if(Build.VERSION.SDK_INT>=28){
                    Method pkgParser_collectCertificatesMtd = pkgParserCls.getDeclaredMethod("collectCertificates", pkgParserPkg.getClass(), Boolean.TYPE);
                    pkgParser_collectCertificatesMtd.invoke(pkgParser, pkgParserPkg, Build.VERSION.SDK_INT>28);
                    Method pkgParser_collect  = pkgParserCls.getDeclaredMethod("collectCertificates", pkgParserPkg.getClass(), Boolean.TYPE);
                   pkgParser_collect.invoke(pkgParser, pkgParserPkg, false);
                    Field mSigningDetailsField = pkgParserPkg.getClass().getDeclaredField("mSigningDetails"); // SigningDetails
                    mSigningDetailsField.setAccessible(true);
                    Object mSigningDetails =  mSigningDetailsField.get(pkgParserPkg);
                    Field infoField = mSigningDetails.getClass().getDeclaredField("signatures");
                    infoField.setAccessible(true);
                    Signature[] info = (Signature[]) infoField.get(mSigningDetails);
                    return info[0].toCharsString();

                }else{
                    Method pkgParser_collectCertificatesMtd = pkgParserCls.getDeclaredMethod("collectCertificates", pkgParserPkg.getClass(), Integer.TYPE);
                    pkgParser_collectCertificatesMtd.invoke(pkgParser, pkgParserPkg, PackageManager.GET_SIGNATURES);

                    Field packageInfoFld = pkgParserPkg.getClass().getDeclaredField("mSignatures");
                    Signature[] info = (Signature[]) packageInfoFld.get(pkgParserPkg);
                    return info[0].toCharsString();
                }


            }else {
                pkgParserCt = pkgParserCls.getConstructor(typeArgs);
                pkgParser = pkgParserCt.newInstance(apkPath);
                Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod("parsePackage", File.class, String.class,DisplayMetrics.class,Integer.TYPE);
                Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, new File(apkPath), apkPath,metrics,PackageManager.GET_SIGNATURES);
                Method pkgParser_collectCertificatesMtd = pkgParserCls.getDeclaredMethod("collectCertificates", pkgParserPkg.getClass(),Integer.TYPE);
                pkgParser_collectCertificatesMtd.invoke(pkgParser, pkgParserPkg,PackageManager.GET_SIGNATURES);
                // 应用程序信息包, 这个公开的, 不过有些函数, 变量没公开
                Field packageInfoFld = pkgParserPkg.getClass().getDeclaredField("mSignatures");
                Signature[] info = (Signature[]) packageInfoFld.get(pkgParserPkg);
                return info[0].toCharsString();
            }
        } catch (Exception e) {
            LogUtil.e("getAPKSignatures",e.getMessage());
            e.printStackTrace();
        }
        return null;


    }

//调用

 String unstallSignature = getPackageArchiveInfo("xxx/xxxx.apk"); 

相关文章

网友评论

      本文标题:完美解决安卓9.0获取软件签名失败

      本文链接:https://www.haomeiwen.com/subject/ebtlqctx.html