通过前两篇文章学习我们大致了解了,apk 资源的加载 和 XML 标签创建对象的过程,今天就来学习一下 Android app启动后Manifast中的 标签是怎么被识别的,activity / service等四大组件对象的创建 android 8.0。
- Manifast.xml的加载和解析?
- Activity 等四大组件的包装对象的创建?
其实Manifast是在PackageManagerService中被解析的,所以一切的开始就要从PackageManagerService下手,首先我们需要了解PackageManagerService创建。我们知道在系统启动之后会fork systemserver 去创建系统服务包括PackageManagerService。systemServer启动之后会调用 启动引导服务 : startBootstrapServices() 方法
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
创建PackageManagerService对象,所以转到 main方法
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
ServiceManager.addService("package", m);
return m;
}
可以看到在这里 new 一个 PackageManagerService 对象并且把对象传到 ServiceManager 中去保存,共其他类使用。然后就触发了 PackageManagerService 的构造方法,在构造方法中封装了,系统加载 apk 的路径
File dataDir = Environment.getDataDirectory();
mAppInstallDir = new File(dataDir, "app");
mAppLib32InstallDir = new File(dataDir, "app-lib");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
系统启动的时候就会去 搜索 这几个路径下的文件,查找 apk。
// Collect ordinary system packages.
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// Collected privileged system packages.
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirTracedLI(privilegedAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
.............................................
不同路径的apk都会被加载,
private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
// 创建apk的解析器
ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
mParallelPackageParserCallback);
// Submit files for parsing in parallel
int fileCount = 0;
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
// Ignore entries which are not packages
continue;
}
// 把所有 apk 文件传入线程池中,在线程中持行 解析操作
parallelPackageParser.submit(file, parseFlags);
fileCount++;
}
// Process results one by one
for (; fileCount > 0; fileCount--) {
// 阻塞队列等待解析结果
ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
if (throwable == null) {
try {
if (errorCode == PackageManager.INSTALL_SUCCEEDED) {
// 持久化apk信息并且安装apk
scanPackageLI(parseResult.pkg, parseResult.scanFile, parseFlags, scanFlags,
currentTime, null);
}
}
在这里把所有apk 文件都传到线程池中解析,并把解析结果放入阻塞队列中保存,等待被一个一个拿出来到scanPackageLI()去持久化apk信息并且安装apk。
public void submit(File scanFile, int parseFlags) {
mService.submit(() -> {
ParseResult pr = new ParseResult();
try {
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
pp.setCacheDir(mCacheDir);
pp.setCallback(mPackageParserCallback);
pr.scanFile = scanFile;
// 解析 xml tag
pr.pkg = parsePackage(pp, scanFile, parseFlags);
} catch (Throwable e) {
pr.throwable = e;
}
try {
// 把结果 放到阻塞队列中
mQueue.put(pr);
} catch (InterruptedException e) {
}
});
}
这里解析 apk 信息到package中,最终会调到
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
mParseError = PackageManager.INSTALL_SUCCEEDED;
mArchiveSourcePath = apkFile.getAbsolutePath();
final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
Resources res = null;
XmlResourceParser parser = null;
try {
res = new Resources(assets, mMetrics, null);
// 解析 Manifast.xml 文件
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final String[] outError = new String[1];
// 封装 package 包
final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
}
return pkg;
}
最终走到 parseBaseApkCommon () 方法中解析 application / permission 等属性
// 是 当前 application 标签
if (tagName.equals(TAG_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;
// 解析 application 内部的标签,例如 activity等四大组件
if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
return null;
}
在这里解析application 和 其中的 activity 等四大组件。其中在parseBaseApplication()中创建activity对象
String tagName = parser.getName();
if (tagName.equals("activity")) {
// 创建 activity 对象
Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
owner.baseHardwareAccelerated);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.activities.add(a);
} else if (tagName.equals("receiver")) {
} else if (tagName.equals("service")) {
} else if (tagName.equals("provider")) {
在这里我们看到了 activity 对象,这个acitvity不是我们start 的activity,这是个activity info 信息,保存在manifast中获取出来的activity的配置信息。
Activity a = new Activity(cachedArgs.mActivityArgs, new ActivityInfo());
if (outError[0] != null) {
sa.recycle();
return null;
}
本文深入探讨Android应用启动过程,解析Manifast.xml加载与四大组件的创建机制。从PackageManagerService入手,详细介绍系统如何扫描并解析APK文件,以及如何识别与创建Activity、Service等组件。
272





