首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > 移动开发 >

获取已装配或未安装的apk签名

2012-11-14 
获取已安装或未安装的apk签名某些时候需要获取已安装的apk或者是未安装的apk的签名信息,以下代码片段将会

获取已安装或未安装的apk签名

某些时候需要获取已安装的apk或者是未安装的apk的签名信息,以下代码片段将会很有用。

1.通过app的packageName获取已安装的apk的签名信息

?

public Signature getPackageSignature(Context context, String packageName){PackageManager pm = context.getPackageManager();List<PackageInfo> apps = pm.getInstalledPackages(PackageManager.GET_SIGNATURES);Iterator<PackageInfo> it = apps.iterator();while(it.hasNext()){PackageInfo info = it.next();if(info.packageName.equals(packageName)){return info.signatures[0];}}return null;}

?

2.根据文件路径获取未安装的apk的签名信息

由于android平台本身的一个小bug,使用PackageManager方式获取未安装的apk文件的签名会稍微费事一点。

(android平台的这个小bug有些狗血,是因为PackageManager的的getPackageArchiveInfo中少了如下代码的原因导致)

缺少的代码:

?

if ((flags & GET_SIGNATURES) != 0)            packageParser.collectCertificates(pkg, 0);

问题的详细信息可以查看以下链接:

https://code.google.com/p/android/issues/detail?id=9151#c8

https://android-review.googlesource.com/#/c/18769/1/core/java/android/content/pm/PackageManager.java

?

这样一来,获取apk文件的签名方式将会变得稍微啰嗦一点

(1)首先自定义一个getPackageArchiveInfo函数,如下:

@SuppressWarnings("unchecked")public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags){        // Workaround for https://code.google.com/p/android/issues/detail?id=9151#c8        try{            Class packageParserClass = Class.forName(                    "android.content.pm.PackageParser");            Class[] innerClasses = packageParserClass.getDeclaredClasses();            Class packageParserPackageClass = null;            for (Class innerClass : innerClasses){                if (0 == innerClass.getName().compareTo("android.content.pm.PackageParser$Package")){                    packageParserPackageClass = innerClass;                    break;                }            }            Constructor packageParserConstructor = packageParserClass.getConstructor(                    String.class);            Method parsePackageMethod = packageParserClass.getDeclaredMethod(                    "parsePackage", File.class, String.class, DisplayMetrics.class, int.class);            Method collectCertificatesMethod = packageParserClass.getDeclaredMethod(                    "collectCertificates", packageParserPackageClass, int.class);            Method generatePackageInfoMethod = packageParserClass.getDeclaredMethod(                    "generatePackageInfo", packageParserPackageClass, int[].class, int.class, long.class, long.class);            packageParserConstructor.setAccessible(true);            parsePackageMethod.setAccessible(true);            collectCertificatesMethod.setAccessible(true);            generatePackageInfoMethod.setAccessible(true);                        Object packageParser = packageParserConstructor.newInstance(archiveFilePath);                DisplayMetrics metrics = new DisplayMetrics();            metrics.setToDefaults();                        final File sourceFile = new File(archiveFilePath);            Object pkg = parsePackageMethod.invoke(                    packageParser,                    sourceFile,                    archiveFilePath,                    metrics,                    0);            if (pkg == null){                return null;            }                if ((flags & android.content.pm.PackageManager.GET_SIGNATURES) != 0){                collectCertificatesMethod.invoke(packageParser, pkg, 0);            }                return (PackageInfo)generatePackageInfoMethod.invoke(null, pkg, null, flags, 0, 0);        }        catch (Exception e)        {            Log.e("Signature Monitor",                "android.content.pm.PackageParser reflection failed: " + e.toString());        }        return null;    }

?(2)使用自定义的getPackageArchiveInfo函数获取PackageInfo,从而获取签名信息,如下:

/** *  * @param context * @param apkFile 文件的全路径信息(包括apk文件的名称),如果是无效的apk文件,返回值为null * @return */public Signature getApkSignatureByFilePath(Context context, String apkFile){PackageInfo newInfo = getPackageArchiveInfo(apkFile, PackageManager.GET_ACTIVITIES | PackageManager.GET_SIGNATURES);if(newInfo != null){if(newInfo.signatures != null && newInfo.signatures.length >0){return newInfo.signatures[0];}}return null;}
?

?

热点排行