温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Android APK中AndroidManifest使用PackageParser.parserPackage的示例分析

发布时间:2021-08-09 11:37:23 来源:亿速云 阅读:247 作者:小新 栏目:移动开发

这篇文章将为大家详细讲解有关Android APK中AndroidManifest使用PackageParser.parserPackage的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

Android 安装一个APK的时候首先会解析APK,这里要做很多事情,其中一个事情就是解析Manifest.xml文件,并将所有APK的Manifest封装到各种对象中并保存在内存当中

解析Manifest的类是非常重要的,该类就是frameworks\base\core\java\android\content\pm\PackageParser

PackageManagerService会调用PackageParser.parserPackage方法来解析APK清单,下面开始分析PackageParser的实现:

PackageParser是使用的XMLPullParser工具来对XML进行解析的,然后分别通过android.content.pm下各种xxxInfo类来进行封装:

Android APK中AndroidManifest使用PackageParser.parserPackage的示例分析

public Package parsePackage(File sourceFile, String destCodePath,   DisplayMetrics metrics, int flags) { //最后要跑出的解析错误信息 mParseError = PackageManager.INSTALL_SUCCEEDED; //获得要解析的文件的路径 mArchiveSourcePath = sourceFile.getPath(); //如果要解析的不是文件类型就跳过并且返回该方法 if (!sourceFile.isFile()) {   Log.w(TAG, "Skipping dir: " + mArchiveSourcePath);   //更新错误信息   mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;   return null; } //如果文件不是以.apk结尾并且flag没有确定一定是APK,那么也返回 if (!isPackageFilename(sourceFile.getName())     && (flags&PARSE_MUST_BE_APK) != 0) {   if ((flags&PARSE_IS_SYSTEM) == 0) {     // We expect to have non-.apk files in the system dir,     // so don't warn about them.     Log.w(TAG, "Skipping non-package file: " + mArchiveSourcePath);   }   //更新错误信息   mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;   return null; } if ((flags&PARSE_CHATTY) != 0 && Config.LOGD) Log.d(   TAG, "Scanning package: " + mArchiveSourcePath); XmlResourceParser parser = null; AssetManager assmgr = null; boolean assetError = true; try {   assmgr = new AssetManager();   //将一个文件添加到AssetManager中并返回一个唯一标识   int cookie = assmgr.addAssetPath(mArchiveSourcePath);   if(cookie != 0) {     //通过标识去AssetManager中找到标识对应资源中的Manifest清单文件,并返回一个XML的解析器     parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");     //走到这里证明一切顺利     assetError = false;   } else {     Log.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);   } } catch (Exception e) {   Log.w(TAG, "Unable to read AndroidManifest.xml of "       + mArchiveSourcePath, e); } if(assetError) {   if (assmgr != null) assmgr.close();   mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;   return null; } String[] errorText = new String[1]; Package pkg = null; Exception errorException = null; try {   // XXXX todo: need to figure out correct configuration.   Resources res = new Resources(assmgr, metrics, null);   //这个是真正在解析的package的方法,是private method   pkg = parsePackage(res, parser, flags, errorText); } catch (Exception e) {   errorException = e;   mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; } if (pkg == null) {   if (errorException != null) {     Log.w(TAG, mArchiveSourcePath, errorException);   } else {     Log.w(TAG, mArchiveSourcePath + " (at "         + parser.getPositionDescription()         + "): " + errorText[0]);   }   parser.close();   assmgr.close();   if (mParseError == PackageManager.INSTALL_SUCCEEDED) {     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;   }   return null; }

parserPackage调用了重载的另外一个parserPackage

private Package parsePackage(     Resources res, XmlResourceParser parser, int flags, String[] outError)     throws XmlPullParserException, IOException {     AttributeSet attrs = parser;     //每次调用这个方法时候清空这些变量     mParseInstrumentationArgs = null;     mParseActivityArgs = null;     mParseServiceArgs = null;     mParseProviderArgs = null;     //这里调用这个方法获得包名     String pkgName = parsePackageName(parser, attrs, flags, outError);     if (pkgName == null) {       mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;       return null;     }     int type;     final Package pkg = new Package(pkgName);     boolean foundApp = false;     //从资源里获得AndroidManifest的数组     TypedArray sa = res.obtainAttributes(attrs,         com.android.internal.R.styleable.AndroidManifest);     //继续挖掘出版本号     pkg.mVersionCode = sa.getInteger(         com.android.internal.R.styleable.AndroidManifest_versionCode, 0);     //获取版本名     pkg.mVersionName = sa.getNonConfigurationString(         com.android.internal.R.styleable.AndroidManifest_versionName, 0);     if (pkg.mVersionName != null) {       pkg.mVersionName = pkg.mVersionName.intern();     }     //获得sharedUserId     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);     }     sa.recycle();     //安装的位置     pkg.installLocation = sa.getInteger(         com.android.internal.R.styleable.AndroidManifest_installLocation,         PARSE_DEFAULT_INSTALL_LOCATION);     // Resource boolean are -1, so 1 means we don't know the value.     int supportsSmallScreens = 1;     int supportsNormalScreens = 1;     int supportsLargeScreens = 1;     int resizeable = 1;     int anyDensity = 1;     int outerDepth = parser.getDepth();     //关键时刻到了,真正的开始解析了     while ((type=parser.next()) != parser.END_DOCUMENT         && (type != parser.END_TAG || parser.getDepth() > outerDepth)) {       if (type == parser.END_TAG || type == parser.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 {             Log.w(TAG, "<manifest> has more than one <application>");             XmlUtils.skipCurrentTag(parser);             continue;           }         }         foundApp = true;         if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {           return null;         }       } else if (tagName.equals("permission-group")) {         if (parsePermissionGroup(pkg, 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")) {         sa = res.obtainAttributes(attrs,             com.android.internal.R.styleable.AndroidManifestUsesPermission);         // 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.AndroidManifestUsesPermission_name);         sa.recycle();        ...................................................        ...................................................        ...................................................篇幅有限

这里分别把每种不同的element用不同的小方法去解析,他们的调用顺序是:

Android APK中AndroidManifest使用PackageParser.parserPackage的示例分析

关于“Android APK中AndroidManifest使用PackageParser.parserPackage的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI