您的位置:首页 > 移动开发 > Android开发

源码分析之应用加载过程解析AndroidManifest

2017-11-23 15:46 716 查看
一.SystemServer的main方法

/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}


二.SystemServer 的startBootstrapServices()方法::

SystemServer中run()方法会初始化一系列的服务,PackageManagerService就是其中之一run()方法回调用

startBootstrapServices()


这个时候就会调用以下方法,来初始化PackageManagerService.

PackageManagerService.main()


三.PackageManagerService的初始化:(针对用户应用展开分析,系统应用和用户应用目录结构不同)

mian()方法被调用后会new出PackageManagerService 在其中可以发现以下目录

File dataDir = Environment.getDataDirectory();
mAppInstallDir = new File(dataDir, "app");
mAppLib32InstallDir = new File(dataDir, "app-lib");
mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
4000

mDrmAppPrivateInstallDir = new File(dataDir, "app-private");

这几个目录就是对应apk的目录,android会扫描这几个目录,如果存在apk会解析应用.
四.解析apk:

1.解析文件:

调用private void scanDirLI(File dir, final int parseFlags, int scanFlags, long currentTime) {}

scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);

scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
| PackageParser.PARSE_FORWARD_LOCK,
scanFlags | SCAN_REQUIRE_KNOWN, 0);

scanDirLI(mEphemeralInstallDir, mDefParseFlags
| PackageParser.PARSE_IS_EPHEMERAL,
scanFlags | SCAN_REQUIRE_KNOWN, 0);

这个方法比较简单就是对apk文件进行校验,校验成功后会调用以下方法

private PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
try {
return scanPackageLI(scanFile, parseFlags, scanFlags, currentTime, user);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}


解析出  PackageParser.Package

2.解析 AndroidManifest.xml:

此时比较重要的另外一个类就可以介绍了PackageParser,前面调用了scanPackageLI

private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
....
PackageParser pp = new PackageParser();
.... pkg = pp.parsePackage(scanFile, parseFlags); ..... return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);}

而这个方法又调用了 public Package parsePackage(File packageFile, int flags)之后又一连串的调用最后调用到

private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
....

Resources res = null;
XmlResourceParser parser = null;
....
res = new Resources(assets, mMetrics, null);
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);

final String[] outError = new String[1];
final Package pkg = parseBaseApk(res, parser, flags, outError);
....
return pkg;
.......

}

在这个方法中我们就发现了我们即熟悉而又陌生的老朋友

/** File name in an APK for the Android manifest. */
private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";

继续往下看我们就会发现更多老朋友

private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
IOException {
......

while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}

if (tagName.equals(TAG_APPLICATION)) {
.....
} else if (tagName.equals(TAG_OVERLAY)) {

.....

return pkg;
}

private static final String TAG_APPLICATION = "application";
private static final String TAG_USES_PERMISSION = "uses-permission";


等等不断的出现,解析整个apk后的信息存到了

/**
* Holds information about dynamic settings.
*/
final class Settings {

这个类中
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐