/**
* Parse the package at the given location. Automatically detects if the
* package is a monolithic style (single APK file) or cluster style
* (directory of APKs).在指定位置解析包,自动检测包是单片样式(单个APK)还是群集样式(APK的目录)。
* <p>
* This performs sanity checking on cluster style packages, such as
* requiring identical package name and version codes, a single base APK,
* and unique split names.这将对群集样式包执行完整性检查,例如要求相同的包名,版本号,单个基本APK,唯一的拆分名称。
* <p>
* Note that this <em>does not</em> perform signature verification; that
* must be done separately in {@link #collectCertificates(Package, int)}.
*不会执行签名认证,必须在collectCertificates方法中单独完成。
* 如果useCaches为true,则包解析器可能会从具有相同packageFile相同flags
* 的先前解析结果中返回缓存数据。
* Note that this method does not check whether {@code packageFile}
* has changed since the last parse, it's up to callers to do so.
*
* @see #parsePackageLite(File, int)
*/
public Package parsePackage(File packageFile, int flags, boolean useCaches)
throws PackageParserException {
Package parsed = useCaches ? getCachedResult(packageFile, flags) : null;//是否返回缓存中的对象
if (parsed != null) {
return parsed;
}
long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
if (packageFile.isDirectory()) {
parsed = parseClusterPackage(packageFile, flags);//1.群集样式
} else {
parsed = parseMonolithicPackage(packageFile, flags);//2.单片样式
}
long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
cacheResult(packageFile, flags, parsed);//3.cacheResult
......
return parsed;
}
一、先看单片样式parseMonolithicPackage()方法。
/**
* Parse the given APK file, treating it as as a single monolithic package.
* <p>
* Note that this <em>does not</em> perform signature verification; that
* must be done separately in {@link #collectCertificates(Package, int)}.
*
* @deprecated external callers should move to
* {@link #parsePackage(File, int)}. Eventually this method will
* be marked private.
*/
@Deprecated
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
final AssetManager assets = newConfiguredAssetManager();//构建AssetManager对象
final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);//1.解析后获得PackageLite对象
if (mOnlyCoreApps) {
if (!lite.coreApp) {
......
}
}
try {
final Package pkg = parseBaseApk(apkFile, assets, flags);//2.解析base APK,返回Package对象
pkg.setCodePath(apkFile.getAbsolutePath());
pkg.setUse32bitAbi(lite.use32bitAbi);
return pkg;
} finally {
IoUtils.closeQuietly(assets);
}
}
(一)parseMonolithicPackageLite()解析APK信息,并返回一个PackageLite对象
private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
throws PackageParserException {
......
final ApkLite baseApk = parseApkLite(packageFile, flags);//1. parseApkLite解析APK
final String packagePath = packageFile.getAbsolutePath();
......
return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);//2.创建PackageLite,表示轻量级解析单个包的详细信息
}
parseApkLite()方法解析APK文件,只是解析一下AndroidManifest.xml中的信息,用ApkLite来表示解析出的关于apk的轻量级信息对象。最后将获得的ApkLite对象和packagePath对象最为参数,创建PackageLite对象并返回。
parseApkLite()
/**
* Utility method that retrieves lightweight details about a single APK
* file, including package name, split name, and install location.
* 检索单个APK文件的轻量级详细信息,包括包名,拆分名,安装位置。
* @param apkFile path to a single APK
* @param flags optional parse flags, such as
* {@link #PARSE_COLLECT_CERTIFICATES}
*/
public static ApkLite parseApkLite(File apkFile, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
AssetManager assets = null;
XmlResourceParser parser = null;
try {
assets = newConfiguredAssetManager();//构建AssetManager对象
int cookie = assets.addAssetPath(apkPath);//设置assetPath
if (cookie == 0) {
......
}
final DisplayMetrics metrics = new DisplayMetrics();//创建DisplayMetrics对象
metrics.setToDefaults();
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);//获取XmlResourceParser对象
final Signature[] signatures;
final Certificate[][] certificates;
if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
// TODO: factor signature related items out of Package object
final Package tempPkg = new Package((String) null);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
try {
collectCertificates(tempPkg, apkFile, flags);//收集证书,获取应用的签名信息
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
signatures = tempPkg.mSignatures;
certificates = tempPkg.mCertificates;
} else {
signatures = null;
certificates = null;
}
final AttributeSet attrs = parser;
return parseApkLite(apkPath, parser, attrs, signatures, certificates);//调用parseApkLite继续解析
} catch (XmlPullParserException | IOException | RuntimeException e) {
......
} finally {
IoUtils.closeQuietly(parser);
IoUtils.closeQuietly(assets);
}
}
private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
Signature[] signatures, Certificate[][] certificates)
throws IOException, XmlPullParserException, PackageParserException {
final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);//解析AndroidManifest中的包名和拆分报名
int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
int versionCode = 0;
int revisionCode = 0;
boolean coreApp = false;
boolean debuggable = false;
boolean multiArch = false;
boolean use32bitAbi = false;
boolean extractNativeLibs = true;
boolean isolatedSplits = false;
boolean isFeatureSplit = false;
String configForSplit = null;
String usesSplitName = null;
for (int i = 0; i < attrs.getAttributeCount(); i++) {//从AndroidManifest中解析下面的属性
final String attr = attrs.getAttributeName(i);
if (attr.equals("installLocation")) {
installLocation = attrs.getAttributeIntValue(i,
PARSE_DEFAULT_INSTALL_LOCATION);
} else if (attr.equals("versionCode")) {
versionCode = attrs.getAttributeIntValue(i, 0);
} else if (attr.equals("revisionCode")) {
revisionCode = attrs.getAttributeIntValue(i, 0);
} else if (attr.equals("coreApp")) {
coreApp = attrs.getAttributeBooleanValue(i, false);
} else if (attr.equals("isolatedSplits")) {
isolatedSplits = attrs.getAttributeBooleanValue(i, false);
} else if (attr.equals("configForSplit")) {
configForSplit = attrs.getAttributeValue(i);
} else if (attr.equals("isFeatureSplit")) {
isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
}
}
// Only search the tree when the tag is directly below <manifest>
int type;
final int searchDepth = parser.getDepth() + 1;
final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
if (parser.getDepth() != searchDepth) {
continue;
}
if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {//“package-verifier”
final VerifierInfo verifier = parseVerifier(attrs);
if (verifier != null) {
verifiers.add(verifier);
}
} else if (TAG_APPLICATION.equals(parser.getName())) {//解析“application”标签
for (int i = 0; i < attrs.getAttributeCount(); ++i) {
final String attr = attrs.getAttributeName(i);
if ("debuggable".equals(attr)) {
debuggable = attrs.getAttributeBooleanValue(i, false);
}
if ("multiArch".equals(attr)) {
multiArch = attrs.getAttributeBooleanValue(i, false);
}
if ("use32bitAbi".equals(attr)) {
use32bitAbi = attrs.getAttributeBooleanValue(i, false);
}
if ("extractNativeLibs".equals(attr)) {
extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
}
}
} else if (TAG_USES_SPLIT.equals(parser.getName())) {//uses-split
if (usesSplitName != null) {
Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
continue;
}
usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, "name");
if (usesSplitName == null) {
......
}
}
}
return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
configForSplit, usesSplitName, versionCode, revisionCode, installLocation,
verifiers, signatures, certificates, coreApp, debuggable, multiArch, use32bitAbi,
extractNativeLibs, isolatedSplits);//根据解析的参数,创建一个ApkLite(对APK的轻量级解析)对象
}
private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
AttributeSet attrs) throws IOException, XmlPullParserException,
PackageParserException {//该方法主要就是解析AndroidManifest.xml中的包名和拆分包名
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
}
......
final String packageName = attrs.getAttributeValue(null, "package");//解析出包名
if (!"android".equals(packageName)) {//非系统应用
final String error = validateName(packageName, true, true);//判断包名是否有效
if (error != null) {
......
}
}
String splitName = attrs.getAttributeValue(null, "split");//拆分APK
if (splitName != null) {
if (splitName.length() == 0) {
splitName = null;
} else {
final String error = validateName(splitName, false, false);//判断