zoukankan      html  css  js  c++  java
  • 解决 安卓9 签名校验报错

    最近有客户反馈签名校验失败了,后来查看发现是安卓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 getAPKSignatures(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_collectCertificatesMtd = pkgParserCls.getDeclaredMethod("collectCertificates", pkgParserPkg.getClass(), Boolean.TYPE);
    pkgParser_collectCertificatesMtd.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;
    }
  • 相关阅读:
    怎么能让json_decode解析带斜杠的字符串
    **PHP转义Json里的特殊字符的函数
    sql中exists,not exists的用法
    **mysql数据库中实现内连接、左连接、右连接
    **PHP foreach 如何判断为数组最后一个最高效?
    mysql sql语句中用括号处理or和and的运算顺序
    iOS图片缓存
    linux regulator之浅见【转】
    Linux中THIS_MODULE宏定义详解
    likely()与unlikely()
  • 原文地址:https://www.cnblogs.com/lucktian/p/10221266.html
Copyright © 2011-2022 走看看