Android 1.6 PackageParser.java 源码分析
文件目录:
android-1.6_r2\frameworks\base\core\java\android\content\pm\PackageParser.java
# PackageParser.java
1. 解析 APK 包名
public static String parsePackageName(String packageFilePath, int flags) {
XmlResourceParser parser = null;
AssetManager assmgr = null;
try {
assmgr = new AssetManager(); // 创建 AssetManager 对象
int cookie = assmgr.addAssetPath(packageFilePath); // 插入 安装包文件 路径
parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml"); // 解析 Androidmanifest.xml 文件
} catch (Exception e) {
if (assmgr != null) assmgr.close();
Log.w(TAG, "Unable to read AndroidManifest.xml of "
+ packageFilePath, e);
return null;
}
AttributeSet attrs = parser;
String errors[] = new String[1];
String packageName = null;
try {
packageName = parsePackageName(parser, attrs, flags, errors);
} catch (IOException e) {
Log.w(TAG, packageFilePath, e);
} catch (XmlPullParserException e) {
Log.w(TAG, packageFilePath, e);
} finally {
if (parser != null) parser.close();
if (assmgr != null) assmgr.close();
}
if (packageName == null) {
Log.e(TAG, "parsePackageName error: " + errors[0]);
return null;
}
return packageName;
}
private static String parsePackageName(XmlPullParser parser,
AttributeSet attrs, int flags, String[] outError)
throws IOException, XmlPullParserException { int type;
while ((type=parser.next()) != parser.START_TAG
&& type != parser.END_DOCUMENT) {
;
} if (type != parser.START_TAG) {
outError[0] = "No start tag found";
return null;
}
if ((flags&PARSE_CHATTY) != 0 && Config.LOGV) Log.v(
TAG, "Root element name: '" + parser.getName() + "'");
if (!parser.getName().equals("manifest")) {
outError[0] = "No <manifest> tag";
return null;
}
String pkgName = attrs.getAttributeValue(null, "package"); // 解析 package tag
if (pkgName == null || pkgName.length() == 0) {
outError[0] = "<manifest> does not specify package";
return null;
}
String nameError = validateName(pkgName, true); // 校验包名
if (nameError != null && !"android".equals(pkgName)) { // 过滤 "android" 包名
outError[0] = "<manifest> specifies bad package name \""
+ pkgName + "\": " + nameError;
return null;
} return pkgName.intern();
}
private static String validateName(String name, boolean requiresSeparator) {
final int N = name.length();
boolean hasSep = false;
boolean front = true;
for (int i=0; i<N; i++) {
final char c = name.charAt(i);
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
front = false;
continue;
}
if (!front) {
if ((c >= '0' && c <= '9') || c == '_') {
continue;
}
}
if (c == '.') {
hasSep = true;
front = true;
continue;
}
return "bad character '" + c + "'";
}
return hasSep || !requiresSeparator
? null : "must have at least one '.' separator";
}
Android 1.6 PackageParser.java 源码分析的更多相关文章
- Android Small插件化框架源码分析
Android Small插件化框架源码分析 目录 概述 Small如何使用 插件加载流程 待改进的地方 一.概述 Small是一个写得非常简洁的插件化框架,工程源码位置:https://github ...
- Java源码分析 | CharSequence
本文基于 OracleJDK 11, HotSpot 虚拟机. CharSequence 定义 CharSequence 是 java.lang 包下的一个接口,是 char 值的可读序列, 即其本身 ...
- Android服务之PackageManagerService启动源码分析
了解了Android系统的启动过程的读者应该知道,Android的所有Java服务都是通过SystemServer进程启动的,并且驻留在SystemServer进程中.SystemServer进程在启 ...
- Java源码分析:关于 HashMap 1.8 的重大更新(转载)
http://blog.csdn.net/carson_ho/article/details/79373134 前言 HashMap 在 Java 和 Android 开发中非常常见 而HashMap ...
- Android线程间异步通信机制源码分析
本文首先从整体架构分析了Android整个线程间消息传递机制,然后从源码角度介绍了各个组件的作用和完成的任务.文中并未对基础概念进行介绍,关于threadLacal和垃圾回收等等机制请自行研究. 基础 ...
- 【Android】Handler、Looper源码分析
一.前言 源码分析使用的版本是 4.4.2_r1. Handler和Looper的入门知识以及讲解可以参考我的另外一篇博客:Android Handler机制 简单而言:Handler和Looper是 ...
- Android View事件分发-从源码分析
View事件分发-从源码分析 学习自 <Android开发艺术探索> https://blog.csdn.net/qian520ao/article/details/78555397?lo ...
- Android JobService的使用及源码分析
Google在Android 5.0中引入JobScheduler来执行一些需要满足特定条件但不紧急的后台任务,APP利用JobScheduler来执行这些特殊的后台任务时来减少电量的消耗.本文首先介 ...
- JAVA源码分析-HashMap源码分析(二)
本文继续分析HashMap的源码.本文的重点是resize()方法和HashMap中其他的一些方法,希望各位提出宝贵的意见. 话不多说,咱们上源码. final Node<K,V>[] r ...
随机推荐
- cocos2d - Changing the image of a CCSprite
CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:@"new_image_name"]; [spri ...
- js pjax 和window.history.pushState,replaceState
原文:http://blog.linjunhalida.com/blog/pjax/ github:https://github.com/defunkt/jquery-pjax 什么是pjax? 现在 ...
- 利用neon技术对矩阵旋转进行加速(2)
上次介绍的是顺时针旋转90度,最近用到了180度和270度,在这里记录一下. 1.利用neon技术将矩阵顺时针旋转180度: 顺时针旋转180度比顺时针旋转90度容易很多,如下图 A1 A2 A3 A ...
- [AngularJS]ng-repeat指令要点
ng-repeat指令要点 1,基本格式,这里不作过多说明,需要的话查看文档 <div ng-repeat="item in someCollection [| someFilter: ...
- redis的有序集合ZSET(stored set)
相关命令 1.ZADD ZADD key-name score member [score member……] 将带有给定分值的成员添加到有序集合里 2.ZREM ZREM key-name mem ...
- 教你下载BarTender 2016
BarTender是全球领先标签.条形码.RFID和证卡设计打印软件,功能强大,操作简单,具有很强的灵活性.目前,BarTender软件已更新至最新版BarTender 2016.BarTender ...
- Python打包-Pyinstaller
我们知道,Python很优雅,很值得学习.但是Python是解释性语言,代码需要有Python解释器才能执行,相比较我们平时直接运行exe等可执行文件多了一步的麻烦. 于是,希望能将Python程序打 ...
- symfony window下的安装 安装时候出现的问题以及解决方案
1. cmd进入DOS , cd 到 php.exe 的目录下 2. php -r "readfile('http://symfony.com/installer');&q ...
- 更改mysql的加密方式和密码策略
-- 修改密码为用不过期 mysql> ALTER USER 'root'@'%' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER; Query O ...
- [原]NGUI之按钮置灰
传统按钮置灰,需要使用另外一张纹理. 本例通过修改shader和NGUI sprite的r值实现按钮置灰.优势:节省纹理,操作简单 将NGUI Unlit/Transparent Colored片段部 ...