Android APK应用安装原理(1)-解析AndroidManifest原理-PackageParser.parserPackage

转载来源http://blog.csdn.net/zhbinary/article/details/7353739

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类来进行封装:













[java]  view plain  copy
  1. public Package parsePackage(File sourceFile, String destCodePath,  
  2.             DisplayMetrics metrics, int flags) {  
  3.         //最后要跑出的解析错误信息  
  4.         mParseError = PackageManager.INSTALL_SUCCEEDED;  
  5.   
  6.         //获得要解析的文件的路径  
  7.         mArchiveSourcePath = sourceFile.getPath();  
  8.           
  9.         //如果要解析的不是文件类型就跳过并且返回该方法  
  10.         if (!sourceFile.isFile()) {  
  11.             Log.w(TAG, "Skipping dir: " + mArchiveSourcePath);  
  12.             //更新错误信息  
  13.             mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;  
  14.             return null;  
  15.         }  
  16.           
  17.         //如果文件不是以.apk结尾并且flag没有确定一定是APK,那么也返回  
  18.         if (!isPackageFilename(sourceFile.getName())  
  19.                 && (flags&PARSE_MUST_BE_APK) != 0) {  
  20.             if ((flags&PARSE_IS_SYSTEM) == 0) {  
  21.                 // We expect to have non-.apk files in the system dir,  
  22.                 // so don't warn about them.  
  23.                 Log.w(TAG, "Skipping non-package file: " + mArchiveSourcePath);  
  24.             }  
  25.             //更新错误信息  
  26.             mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;  
  27.             return null;  
  28.         }  
  29.   
  30.         if ((flags&PARSE_CHATTY) != 0 && Config.LOGD) Log.d(  
  31.             TAG, "Scanning package: " + mArchiveSourcePath);  
  32.   
  33.         XmlResourceParser parser = null;  
  34.         AssetManager assmgr = null;  
  35.         boolean assetError = true;  
  36.         try {  
  37.             assmgr = new AssetManager();  
  38.               
  39.             //将一个文件添加到AssetManager中并返回一个唯一标识  
  40.             int cookie = assmgr.addAssetPath(mArchiveSourcePath);  
  41.             if(cookie != 0) {  
  42.                 //通过标识去AssetManager中找到标识对应资源中的Manifest清单文件,并返回一个XML的解析器  
  43.                 parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");  
  44.                 //走到这里证明一切顺利  
  45.                 assetError = false;  
  46.             } else {  
  47.                 Log.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);  
  48.             }  
  49.         } catch (Exception e) {  
  50.             Log.w(TAG, "Unable to read AndroidManifest.xml of "  
  51.                     + mArchiveSourcePath, e);  
  52.         }  
  53.         if(assetError) {  
  54.             if (assmgr != null) assmgr.close();  
  55.             mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;  
  56.             return null;  
  57.         }  
  58.         String[] errorText = new String[1];  
  59.         Package pkg = null;  
  60.         Exception errorException = null;  
  61.         try {  
  62.             // XXXX todo: need to figure out correct configuration.  
  63.             Resources res = new Resources(assmgr, metrics, null);  
  64.             //这个是真正在解析的package的方法,是private method  
  65.             pkg = parsePackage(res, parser, flags, errorText);  
  66.         } catch (Exception e) {  
  67.             errorException = e;  
  68.             mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;  
  69.         }  
  70.   
  71.   
  72.         if (pkg == null) {  
  73.             if (errorException != null) {  
  74.                 Log.w(TAG, mArchiveSourcePath, errorException);  
  75.             } else {  
  76.                 Log.w(TAG, mArchiveSourcePath + " (at "  
  77.                         + parser.getPositionDescription()  
  78.                         + "): " + errorText[0]);  
  79.             }  
  80.             parser.close();  
  81.             assmgr.close();  
  82.             if (mParseError == PackageManager.INSTALL_SUCCEEDED) {  
  83.                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;  
  84.             }  
  85.             return null;  
  86.         }  

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

[java]  view plain  copy
  1. private Package parsePackage(  
  2.         Resources res, XmlResourceParser parser, int flags, String[] outError)  
  3.         throws XmlPullParserException, IOException {  
  4.         AttributeSet attrs = parser;  
  5.   
  6.         //每次调用这个方法时候清空这些变量  
  7.         mParseInstrumentationArgs = null;  
  8.         mParseActivityArgs = null;  
  9.         mParseServiceArgs = null;  
  10.         mParseProviderArgs = null;  
  11.           
  12.         //这里调用这个方法获得包名  
  13.         String pkgName = parsePackageName(parser, attrs, flags, outError);  
  14.         if (pkgName == null) {  
  15.             mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;  
  16.             return null;  
  17.         }  
  18.         int type;  
  19.   
  20.         final Package pkg = new Package(pkgName);  
  21.         boolean foundApp = false;  
  22.           
  23.         //从资源里获得AndroidManifest的数组  
  24.         TypedArray sa = res.obtainAttributes(attrs,  
  25.                 com.android.internal.R.styleable.AndroidManifest);  
  26.           
  27.         //继续挖掘出版本号  
  28.         pkg.mVersionCode = sa.getInteger(  
  29.                 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);  
  30.           
  31.         //获取版本名  
  32.         pkg.mVersionName = sa.getNonConfigurationString(  
  33.                 com.android.internal.R.styleable.AndroidManifest_versionName, 0);  
  34.         if (pkg.mVersionName != null) {  
  35.             pkg.mVersionName = pkg.mVersionName.intern();  
  36.         }  
  37.           
  38.         //获得sharedUserId  
  39.         String str = sa.getNonConfigurationString(  
  40.                 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);  
  41.         if (str != null && str.length() > 0) {  
  42.             //验证包名是否符合规则  
  43.             String nameError = validateName(str, true);  
  44.             if (nameError != null && !"android".equals(pkgName)) {  
  45.                 outError[0] = "<manifest> specifies bad sharedUserId name \""  
  46.                     + str + "\": " + nameError;  
  47.                 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;  
  48.                 return null;  
  49.             }  
  50.             pkg.mSharedUserId = str.intern();  
  51.             pkg.mSharedUserLabel = sa.getResourceId(  
  52.                     com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);  
  53.         }  
  54.         sa.recycle();  
  55.   
  56.         //安装的位置  
  57.         pkg.installLocation = sa.getInteger(  
  58.                 com.android.internal.R.styleable.AndroidManifest_installLocation,  
  59.                 PARSE_DEFAULT_INSTALL_LOCATION);  
  60.   
  61.         // Resource boolean are -1, so 1 means we don't know the value.  
  62.         int supportsSmallScreens = 1;  
  63.         int supportsNormalScreens = 1;  
  64.         int supportsLargeScreens = 1;  
  65.         int resizeable = 1;  
  66.         int anyDensity = 1;  
  67.           
  68.         int outerDepth = parser.getDepth();  
  69.           
  70.         //关键时刻到了,真正的开始解析了  
  71.         while ((type=parser.next()) != parser.END_DOCUMENT  
  72.                && (type != parser.END_TAG || parser.getDepth() > outerDepth)) {  
  73.             if (type == parser.END_TAG || type == parser.TEXT) {  
  74.                 continue;  
  75.             }  
  76.   
  77.             String tagName = parser.getName();  
  78.             if (tagName.equals("application")) {  
  79.                 if (foundApp) {  
  80.                     if (RIGID_PARSER) {  
  81.                         outError[0] = "<manifest> has more than one <application>";  
  82.                         mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;  
  83.                         return null;  
  84.                     } else {  
  85.                         Log.w(TAG, "<manifest> has more than one <application>");  
  86.                         XmlUtils.skipCurrentTag(parser);  
  87.                         continue;  
  88.                     }  
  89.                 }  
  90.   
  91.                 foundApp = true;  
  92.                 if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {  
  93.                     return null;  
  94.                 }  
  95.             } else if (tagName.equals("permission-group")) {  
  96.                 if (parsePermissionGroup(pkg, res, parser, attrs, outError) == null) {  
  97.                     return null;  
  98.                 }  
  99.             } else if (tagName.equals("permission")) {  
  100.                 if (parsePermission(pkg, res, parser, attrs, outError) == null) {  
  101.                     return null;  
  102.                 }  
  103.             } else if (tagName.equals("permission-tree")) {  
  104.                 if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {  
  105.                     return null;  
  106.                 }  
  107.             } else if (tagName.equals("uses-permission")) {  
  108.                 sa = res.obtainAttributes(attrs,  
  109.                         com.android.internal.R.styleable.AndroidManifestUsesPermission);  
  110.   
  111.                 // Note: don't allow this value to be a reference to a resource  
  112.                 // that may change.  
  113.                 String name = sa.getNonResourceString(  
  114.                         com.android.internal.R.styleable.AndroidManifestUsesPermission_name);  
  115.   
  116.                 sa.recycle();  
  117.   
  118.               ...................................................  
  119.               ...................................................  
  120.               ...................................................篇幅有限  




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






这些小方法里其实还是有很多小技巧的,有兴趣的话可以细细品位

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值