获取apk签名信息(已经安装和未安装的)

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.List;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.os.Build;
import android.util.DisplayMetrics;

/**
 * apk  签名工具类
 */
public class SignUtils {

    /**
     * 获取未安装Apk的签名
     *
     * @param apkPath
     * @return
     */
    public static String getApkSignature(String apkPath) {
        String PATH_PackageParser = "android.content.pm.PackageParser";
        try {
            // apk包的文件路径
            // 这是一个Package 解释器, 是隐藏的
            // 构造函数的参数只有一个, apk文件的路径
            Class<?> pkgParserCls = Class.forName(PATH_PackageParser);
            Class<?>[] typeArgs = new Class[1];
            typeArgs[0] = String.class;
            Object[] valueArgs = new Object[1];
            valueArgs[0] = apkPath;
            Object pkgParser;
            if (Build.VERSION.SDK_INT > 19) {
                pkgParser = pkgParserCls.newInstance();
            } else {
                Constructor constructor = pkgParserCls.getConstructor(typeArgs);
                pkgParser = constructor.newInstance(valueArgs);
            }

            // 这个是与显示有关的, 里面涉及到一些像素显示等等, 我们使用默认的情况
            DisplayMetrics metrics = new DisplayMetrics();
            metrics.setToDefaults();
            // PackageParser.Package mPkgInfo = packageParser.parsePackage(new
            // File(apkPath), apkPath,
            // metrics, 0);
            Object pkgParserPkg = null;
            if (Build.VERSION.SDK_INT > 19) {
                valueArgs = new Object[2];
                valueArgs[0] = new File(apkPath);
                valueArgs[1] = PackageManager.GET_SIGNATURES;
                Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod(
                        "parsePackage", typeArgs);
                pkgParser_parsePackageMtd.setAccessible(true);

                typeArgs = new Class[2];
                typeArgs[0] = File.class;
                typeArgs[1] = int.class;
                pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser,
                        valueArgs);
            } else {
                typeArgs = new Class[4];
                typeArgs[0] = File.class;
                typeArgs[1] = String.class;
                typeArgs[2] = DisplayMetrics.class;
                typeArgs[3] = int.class;

                Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod(
                        "parsePackage", typeArgs);
                pkgParser_parsePackageMtd.setAccessible(true);

                valueArgs = new Object[4];
                valueArgs[0] = new File(apkPath);
                valueArgs[1] = apkPath;
                valueArgs[2] = metrics;
                valueArgs[3] = PackageManager.GET_SIGNATURES;
                pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser,
                        valueArgs);
            }


            typeArgs = new Class[2];
            typeArgs[0] = pkgParserPkg.getClass();
            typeArgs[1] = int.class;
            Method pkgParser_collectCertificatesMtd = pkgParserCls.getDeclaredMethod("collectCertificates", typeArgs);
            valueArgs = new Object[2];
            valueArgs[0] = pkgParserPkg;
            valueArgs[1] = PackageManager.GET_SIGNATURES;
            pkgParser_collectCertificatesMtd.invoke(pkgParser, valueArgs);
            // 应用程序信息包, 这个公开的, 不过有些函数, 变量没公开
            Field packageInfoFld = pkgParserPkg.getClass().getDeclaredField(
                    "mSignatures");
            Signature[] info = (Signature[]) packageInfoFld.get(pkgParserPkg);
            return info[0].toCharsString();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 获取已安装apk签名
     *
     * @param context
     * @param packageName
     * @return
     */
    public static String getInstallPackageSignature(Context context,
                                                    String packageName) {
        PackageManager pm = context.getPackageManager();
        List<PackageInfo> apps = pm
                .getInstalledPackages(PackageManager.GET_SIGNATURES);

        Iterator<PackageInfo> iter = apps.iterator();
        while (iter.hasNext()) {
            PackageInfo packageinfo = iter.next();
            String thisName = packageinfo.packageName;
            if (thisName.equals(packageName)) {
                return packageinfo.signatures[0].toCharsString();
            }
        }

        return null;
    }


    public static String md5(String string) {
        byte[] hash;
        try {
            hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Huh, MD5 should be supported?", e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("Huh, UTF-8 should be supported?", e);
        }

        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10) hex.append("0");
            hex.append(Integer.toHexString(b & 0xFF));
        }
        return hex.toString();
    }
}

  附上PackageParser的源码:

public Package parsePackage(File packageFile, int flags) throws PackageParserException {
    if (packageFile.isDirectory()) {
        return parseClusterPackage(packageFile, flags);
    } else {
        return parseMonolithicPackage(packageFile, flags);
    }
}

public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
    if (mOnlyCoreApps) {
        final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
        if (!lite.coreApp) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                    "Not a coreApp: " + apkFile);
        }
    }

    final AssetManager assets = new AssetManager();
    try {
        final Package pkg = parseBaseApk(apkFile, assets, flags);
        pkg.codePath = apkFile.getAbsolutePath();
        return pkg;
    } finally {
        IoUtils.closeQuietly(assets);
    }
}
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
        throws PackageParserException {
    final String apkPath = apkFile.getAbsolutePath();

    mParseError = PackageManager.INSTALL_SUCCEEDED;
    mArchiveSourcePath = apkFile.getAbsolutePath();

    if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);

    final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);

    Resources res = null;
    XmlResourceParser parser = null;
    try {
        res = new Resources(assets, mMetrics, null);
        assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                Build.VERSION.RESOURCES_SDK_INT);
        parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);

        final String[] outError = new String[1];
        final Package pkg = parseBaseApk(res, parser, flags, outError);
        if (pkg == null) {
            throw new PackageParserException(mParseError,
                    apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
        }

        pkg.baseCodePath = apkPath;
        pkg.mSignatures = null;

        return pkg;

    } catch (PackageParserException e) {
        throw e;
    } catch (Exception e) {
        throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                "Failed to read manifest from " + apkPath, e);
    } finally {
        IoUtils.closeQuietly(parser);
    }
}

private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
        String[] outError) throws XmlPullParserException, IOException {
    final boolean trustedOverlay = (flags & PARSE_TRUSTED_OVERLAY) != 0;

    AttributeSet attrs = parser;

    mParseInstrumentationArgs = null;
    mParseActivityArgs = null;
    mParseServiceArgs = null;
    mParseProviderArgs = null;

    final String pkgName;
    final String splitName;
    try {
        Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs, flags);
        pkgName = packageSplit.first;
        splitName = packageSplit.second;
    } catch (PackageParserException e) {
        mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
        return null;
    }

    int type;

    if (!TextUtils.isEmpty(splitName)) {
        outError[0] = "Expected base APK, but found split " + splitName;
        mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
        return null;
    }

    final Package pkg = new Package(pkgName);
    boolean foundApp = false;

    TypedArray sa = res.obtainAttributes(attrs,
            com.android.internal.R.styleable.AndroidManifest);
    pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
            com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
    pkg.baseRevisionCode = sa.getInteger(
            com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
    pkg.mVersionName = sa.getNonConfigurationString(
            com.android.internal.R.styleable.AndroidManifest_versionName, 0);
    if (pkg.mVersionName != null) {
        pkg.mVersionName = pkg.mVersionName.intern();
    }
    String str = sa.getNonConfigurationString(
            com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
    if (str != null && str.length() > 0) {
        String nameError = validateName(str, true);
        if (nameError != null && !"android".equals(pkgName)) {
            outError[0] = "<manifest> specifies bad sharedUserId name \""
                + str + "\": " + nameError;
            mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
            return null;
        }
        pkg.mSharedUserId = str.intern();
        pkg.mSharedUserLabel = sa.getResourceId(
                com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
    }

    pkg.installLocation = sa.getInteger(
            com.android.internal.R.styleable.AndroidManifest_installLocation,
            PARSE_DEFAULT_INSTALL_LOCATION);
    pkg.applicationInfo.installLocation = pkg.installLocation;

    pkg.coreApp = attrs.getAttributeBooleanValue(null, "coreApp", false);

    sa.recycle();

    /* Set the global "forward lock" flag */
    if ((flags & PARSE_FORWARD_LOCK) != 0) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
    }

    /* Set the global "on SD card" flag */
    if ((flags & PARSE_ON_SDCARD) != 0) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
    }

    // Resource boolean are -1, so 1 means we don't know the value.
    int supportsSmallScreens = 1;
    int supportsNormalScreens = 1;
    int supportsLargeScreens = 1;
    int supportsXLargeScreens = 1;
    int resizeable = 1;
    int anyDensity = 1;
    
    int outerDepth = parser.getDepth();
    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
            continue;
        }

        String tagName = parser.getName();
        if (tagName.equals("application")) {
            if (foundApp) {
                if (RIGID_PARSER) {
                    outError[0] = "<manifest> has more than one <application>";
                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                    return null;
                } else {
                    Slog.w(TAG, "<manifest> has more than one <application>");
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }
            }

            foundApp = true;
            if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) {
                return null;
            }
        } else if (tagName.equals("overlay")) {
            pkg.mTrustedOverlay = trustedOverlay;

            sa = res.obtainAttributes(attrs,
                    com.android.internal.R.styleable.AndroidManifestResourceOverlay);
            pkg.mOverlayTarget = sa.getString(
                    com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
            pkg.mOverlayPriority = sa.getInt(
                    com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
                    -1);
            sa.recycle();

            if (pkg.mOverlayTarget == null) {
                outError[0] = "<overlay> does not specify a target package";
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return null;
            }
            if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
                outError[0] = "<overlay> priority must be between 0 and 9999";
                mParseError =
                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return null;
            }
            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("key-sets")) {
            if (!parseKeySets(pkg, res, parser, attrs, outError)) {
                return null;
            }
        } else if (tagName.equals("permission-group")) {
            if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) {
                return null;
            }
        } else if (tagName.equals("permission")) {
            if (parsePermission(pkg, res, parser, attrs, outError) == null) {
                return null;
            }
        } else if (tagName.equals("permission-tree")) {
            if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
                return null;
            }
        } else if (tagName.equals("uses-permission")) {
            if (!parseUsesPermission(pkg, res, parser, attrs, outError)) {
                return null;
            }
        } else if (tagName.equals("uses-configuration")) {
            ConfigurationInfo cPref = new ConfigurationInfo();
            sa = res.obtainAttributes(attrs,
                    com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
            cPref.reqTouchScreen = sa.getInt(
                    com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
                    Configuration.TOUCHSCREEN_UNDEFINED);
            cPref.reqKeyboardType = sa.getInt(
                    com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
                    Configuration.KEYBOARD_UNDEFINED);
            if (sa.getBoolean(
                    com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
                    false)) {
                cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
            }
            cPref.reqNavigation = sa.getInt(
                    com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
                    Configuration.NAVIGATION_UNDEFINED);
            if (sa.getBoolean(
                    com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
                    false)) {
                cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
            }
            sa.recycle();
            pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("uses-feature")) {
            FeatureInfo fi = parseUsesFeature(res, attrs);
            pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);

            if (fi.name == null) {
                ConfigurationInfo cPref = new ConfigurationInfo();
                cPref.reqGlEsVersion = fi.reqGlEsVersion;
                pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
            }

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("feature-group")) {
            FeatureGroupInfo group = new FeatureGroupInfo();
            ArrayList<FeatureInfo> features = null;
            final int innerDepth = parser.getDepth();
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                    continue;
                }

                final String innerTagName = parser.getName();
                if (innerTagName.equals("uses-feature")) {
                    FeatureInfo featureInfo = parseUsesFeature(res, attrs);
                    // FeatureGroups are stricter and mandate that
                    // any <uses-feature> declared are mandatory.
                    featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
                    features = ArrayUtils.add(features, featureInfo);
                } else {
                    Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName +
                            " at " + mArchiveSourcePath + " " +
                            parser.getPositionDescription());
                }
                XmlUtils.skipCurrentTag(parser);
            }

            if (features != null) {
                group.features = new FeatureInfo[features.size()];
                group.features = features.toArray(group.features);
            }
            pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);

        } else if (tagName.equals("uses-sdk")) {
            if (SDK_VERSION > 0) {
                sa = res.obtainAttributes(attrs,
                        com.android.internal.R.styleable.AndroidManifestUsesSdk);

                int minVers = 0;
                String minCode = null;
                int targetVers = 0;
                String targetCode = null;
                
                TypedValue val = sa.peekValue(
                        com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
                if (val != null) {
                    if (val.type == TypedValue.TYPE_STRING && val.string != null) {
                        targetCode = minCode = val.string.toString();
                    } else {
                        // If it's not a string, it's an integer.
                        targetVers = minVers = val.data;
                    }
                }
                
                val = sa.peekValue(
                        com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
                if (val != null) {
                    if (val.type == TypedValue.TYPE_STRING && val.string != null) {
                        targetCode = minCode = val.string.toString();
                    } else {
                        // If it's not a string, it's an integer.
                        targetVers = val.data;
                    }
                }
                
                sa.recycle();

                if (minCode != null) {
                    boolean allowedCodename = false;
                    for (String codename : SDK_CODENAMES) {
                        if (minCode.equals(codename)) {
                            allowedCodename = true;
                            break;
                        }
                    }
                    if (!allowedCodename) {
                        if (SDK_CODENAMES.length > 0) {
                            outError[0] = "Requires development platform " + minCode
                                    + " (current platform is any of "
                                    + Arrays.toString(SDK_CODENAMES) + ")";
                        } else {
                            outError[0] = "Requires development platform " + minCode
                                    + " but this is a release platform.";
                        }
                        mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                        return null;
                    }
                } else if (minVers > SDK_VERSION) {
                    outError[0] = "Requires newer sdk version #" + minVers
                            + " (current version is #" + SDK_VERSION + ")";
                    mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                    return null;
                }
                
                if (targetCode != null) {
                    boolean allowedCodename = false;
                    for (String codename : SDK_CODENAMES) {
                        if (targetCode.equals(codename)) {
                            allowedCodename = true;
                            break;
                        }
                    }
                    if (!allowedCodename) {
                        if (SDK_CODENAMES.length > 0) {
                            outError[0] = "Requires development platform " + targetCode
                                    + " (current platform is any of "
                                    + Arrays.toString(SDK_CODENAMES) + ")";
                        } else {
                            outError[0] = "Requires development platform " + targetCode
                                    + " but this is a release platform.";
                        }
                        mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                        return null;
                    }
                    // If the code matches, it definitely targets this SDK.
                    pkg.applicationInfo.targetSdkVersion
                            = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
                } else {
                    pkg.applicationInfo.targetSdkVersion = targetVers;
                }
            }

            XmlUtils.skipCurrentTag(parser);

        } else if (tagName.equals("supports-screens")) {
            sa = res.obtainAttributes(attrs,
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens);

            pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
                    0);
            pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
                    0);
            pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
                    0);

            // This is a trick to get a boolean and still able to detect
            // if a value was actually set.
            supportsSmallScreens = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
                    supportsSmallScreens);
            supportsNormalScreens = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
                    supportsNormalScreens);
            supportsLargeScreens = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
                    supportsLargeScreens);
            supportsXLargeScreens = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
                    supportsXLargeScreens);
            resizeable = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
                    resizeable);
            anyDensity = sa.getInteger(
                    com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
                    anyDensity);

            sa.recycle();
            
            XmlUtils.skipCurrentTag(parser);
            
        } else if (tagName.equals("protected-broadcast")) {
            sa = res.obtainAttributes(attrs,
                    com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);

            // Note: don't allow this value to be a reference to a resource
            // that may change.
            String name = sa.getNonResourceString(
                    com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);

            sa.recycle();

            if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
                if (pkg.protectedBroadcasts == null) {
                    pkg.protectedBroadcasts = new ArrayList<String>();
                }
                if (!pkg.protectedBroadcasts.contains(name)) {
                    pkg.protectedBroadcasts.add(name.intern());
                }
            }

            XmlUtils.skipCurrentTag(parser);
            
        } else if (tagName.equals("instrumentation")) {
            if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
                return null;
            }
            
        } else if (tagName.equals("original-package")) {
            sa = res.obtainAttributes(attrs,
                    com.android.internal.R.styleable.AndroidManifestOriginalPackage);

            String orig =sa.getNonConfigurationString(
                    com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
            if (!pkg.packageName.equals(orig)) {
                if (pkg.mOriginalPackages == null) {
                    pkg.mOriginalPackages = new ArrayList<String>();
                    pkg.mRealPackage = pkg.packageName;
                }
                pkg.mOriginalPackages.add(orig);
            }

            sa.recycle();

            XmlUtils.skipCurrentTag(parser);
            
        } else if (tagName.equals("adopt-permissions")) {
            sa = res.obtainAttributes(attrs,
                    com.android.internal.R.styleable.AndroidManifestOriginalPackage);

            String name = sa.getNonConfigurationString(
                    com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);

            sa.recycle();

            if (name != null) {
                if (pkg.mAdoptPermissions == null) {
                    pkg.mAdoptPermissions = new ArrayList<String>();
                }
                pkg.mAdoptPermissions.add(name);
            }

            XmlUtils.skipCurrentTag(parser);
            
        } else if (tagName.equals("uses-gl-texture")) {
            // Just skip this tag
            XmlUtils.skipCurrentTag(parser);
            continue;
            
        } else if (tagName.equals("compatible-screens")) {
            // Just skip this tag
            XmlUtils.skipCurrentTag(parser);
            continue;
        } else if (tagName.equals("supports-input")) {
            XmlUtils.skipCurrentTag(parser);
            continue;
            
        } else if (tagName.equals("eat-comment")) {
            // Just skip this tag
            XmlUtils.skipCurrentTag(parser);
            continue;
            
        } else if (RIGID_PARSER) {
            outError[0] = "Bad element under <manifest>: "
                + parser.getName();
            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
            return null;

        } else {
            Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
                    + " at " + mArchiveSourcePath + " "
                    + parser.getPositionDescription());
            XmlUtils.skipCurrentTag(parser);
            continue;
        }
    }

    if (!foundApp && pkg.instrumentation.size() == 0) {
        outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
    }

    final int NP = PackageParser.NEW_PERMISSIONS.length;
    StringBuilder implicitPerms = null;
    for (int ip=0; ip<NP; ip++) {
        final PackageParser.NewPermissionInfo npi
                = PackageParser.NEW_PERMISSIONS[ip];
        if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
            break;
        }
        if (!pkg.requestedPermissions.contains(npi.name)) {
            if (implicitPerms == null) {
                implicitPerms = new StringBuilder(128);
                implicitPerms.append(pkg.packageName);
                implicitPerms.append(": compat added ");
            } else {
                implicitPerms.append(' ');
            }
            implicitPerms.append(npi.name);
            pkg.requestedPermissions.add(npi.name);
            pkg.requestedPermissionsRequired.add(Boolean.TRUE);
        }
    }
    if (implicitPerms != null) {
        Slog.i(TAG, implicitPerms.toString());
    }

    final int NS = PackageParser.SPLIT_PERMISSIONS.length;
    for (int is=0; is<NS; is++) {
        final PackageParser.SplitPermissionInfo spi
                = PackageParser.SPLIT_PERMISSIONS[is];
        if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
                || !pkg.requestedPermissions.contains(spi.rootPerm)) {
            continue;
        }
        for (int in=0; in<spi.newPerms.length; in++) {
            final String perm = spi.newPerms[in];
            if (!pkg.requestedPermissions.contains(perm)) {
                pkg.requestedPermissions.add(perm);
                pkg.requestedPermissionsRequired.add(Boolean.TRUE);
            }
        }
    }

    if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
            && pkg.applicationInfo.targetSdkVersion
                    >= android.os.Build.VERSION_CODES.DONUT)) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
    }
    if (supportsNormalScreens != 0) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
    }
    if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
            && pkg.applicationInfo.targetSdkVersion
                    >= android.os.Build.VERSION_CODES.DONUT)) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
    }
    if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
            && pkg.applicationInfo.targetSdkVersion
                    >= android.os.Build.VERSION_CODES.GINGERBREAD)) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
    }
    if (resizeable < 0 || (resizeable > 0
            && pkg.applicationInfo.targetSdkVersion
                    >= android.os.Build.VERSION_CODES.DONUT)) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
    }
    if (anyDensity < 0 || (anyDensity > 0
            && pkg.applicationInfo.targetSdkVersion
                    >= android.os.Build.VERSION_CODES.DONUT)) {
        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
    }

    /*
     * b/8528162: Ignore the <uses-permission android:required> attribute if
     * targetSdkVersion < JELLY_BEAN_MR2. There are lots of apps in the wild
     * which are improperly using this attribute, even though it never worked.
     */
    if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) {
        for (int i = 0; i < pkg.requestedPermissionsRequired.size(); i++) {
            pkg.requestedPermissionsRequired.set(i, Boolean.TRUE);
        }
    }

    return pkg;
}


转载于:https://my.oschina.net/fengcunhan/blog/484932

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值