• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android中如何修改编译的资源ID值(默认值是0x7F...可以随意改成0x02~0x7E)

Android中如何修改编译的资源ID值(默认值是0x7F...可以随意改成0x02~0x7E)

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了Android中如何修改编译的资源ID值(默认值是0x7F...可以随意改成0x02~0x7E)等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android中如何修改编译的资源ID值(默认值是0x7F...可以随意改成0x02~0x7E)


一、技术准备

今天我们来看一下如何修改Android中编译时的资源Id的值,在讲解这内容之前,我们需要先了解一下Android中的资源编译之后的结构和编译过程,这里就不多说了,这篇文章中,介绍了如何解析Android中编译之后的resource.arsc文件,这里就介绍了Android中资源文件编译之后的类型和格式,其实Android中资源编译之后,会产生一个R文件,所有的资源ID都是存储在这个文件中的的,默认我们看到所有的ID都有一个共同的特点,就是他们都是0x7F开头的,其实这个0x7F是包的ID值,我们在在解析resource.arsc文章中提到一点,Android中的id值其实是一个int类型,他的值由三部分组成:PackageId+TypeId+EntryId

PackageId:是包的Id值,Android中如果是第三方应用的话,这个值默认就是0x7F,系统应用的话就是0x01,具体我们可以后面看aapt源码得知,他占用两个字节。

TypeId:是资源的类型Id值,一般Android中有这几个类型:attr,drawable,layout,dimen,string,style等,而且这些类型的值是从1开始逐渐递增的,而且顺序不能改变,attr=0x01,drawable=0x02....他占用两个字节。

EntryId:是在具体的类型下资源实体的id值,从0开始,依次递增,他占用四个字节。

\

 

二、遇到的问题

既然我们了解了Android中的资源Id的结构,下面我们来说说我们遇到的问题:

 

1、在Android项目中偶尔会出现依赖第三方库包,出现资源ID(packageId+typeId+ItemValue)发生冲突的问题(网上有很多解决方案,不一一列举,如public 限定等)。那么对于我们自己提供的库包,如果能指定其包的命令空间(默认是从127=0x7F开始),特别考虑mutiDex的情况,自定义修改package ID显得意义重大。

2、我们在开发Android中插件技术的时候,为了防止插件工程中的资源Id和宿主工程中的资源Id不冲突,也是需要去修改一下插件中编译之后的资源Id值,来减少冲突。

那么上面就是我们遇到的问题,其实我们的解决方案很简单,就是在编译的时候修改资源Id值,给一个限定值。

 

三、解决思路

我们之前讲解了资源Id的组成结构,发现高两个字节是代表PackageId的值,而且第三方app的默认值是0x7F,那么我们能不能修改这个值呢?比如,插件1中的资源Id中的PackageId为0x30,插件2中的资源Id中的PackageId为0x31...这样每个插件的资源就被划分了一定的区域值,同时保证不要和主工程中的0x7F冲突即可,那么这些值就可以从0x02~0x7E了,这个区间值我们都是可以使用的,为什么0x01不能用呢?因为他是系统应用的呀,所以我们就有0x7E-0x02=124个区间,哈哈,听着好兴奋,那么我们是否可以操作了呢?答案是可以的,我们知道Android中编译资源用的是aapt命令,那么我们就可以查看他的源码来看看是否可以。

 

aapt命令是Android中提供的编译apk的一个工具,所以源码可以从 Android源码目录/tools/... 下面查看:

\

这个工具的源码还是不复杂的,没多少文件,当然入口肯定找main啥的关键字了,果然看到一个Main.cpp文件,打开查看,找到入口函数main,这里我们可以看到,他对输入参数做了判断:

\

这里main函数有点长,我们直接看最后的处理函数:

\

这里有一个handleCommand函数,这里就是主要处理命令的功能:

\

这里有好多个函数,但是我们这里需要关注的是doPackage函数,他是打出包的关键,但是这时候我们发现全局搜这个函数,找不到,那么这个函数肯定是被引用的,源码中查找具体函数,

脑补一下:

这里因为是Window系统,不想是Linux系统,可以直接使用find+grep就可以快速的查找到包含指定内容的文件了,但是Windows中提供了可视化的文件搜索,但是他默认在搜索的时候,只是搜索文件名,不搜索包含的内容,所以需要设置一下,可以到文件夹选项中设置:

\

这时候我们可以在tools目录下搜索了:

\

这时候看到了,我们搜到了三个文件,Main.cpp可以不用看了,因为已经看过了,那么就在Command.cpp里面了:

\

这里我们往下面看:

\

这里有一个方法,而且我们看注释,这里就是编译的核心函数:buildResources,我们在全局搜这个函数,没找到,那么我们还是到整个目录下去搜:

\

搜到了,在Resource.cpp中:

\

这里看到,一个packgeType字段,这个就是包类型,这里有三个类型:共享的,系统的,第三方

突然发现这个似乎和PackageId的值有关系,我们接着往下看:

\

在这里,用到了packageType,而且有一个重要的类型ResourceTable,这个就是资源索引表,和ResId有映射关系的数据结构,所以我们查看他的定义:在ResourceTable.cpp中

\

我擦,果然,看到结果了,这里看到了有三个值,0x00,0x01,0x7F。说明我们找到核心的地方了。接着往下看:

\

这里构建了一个Package,这里传入了packageId值的,好了,我们分析源码就到这里了,那么下面我们来看一下源码流程:

首先找到入口类:Main.cpp:main函数,解析参数,然后调用handleCommand函数处理参数对应的逻辑,我们看到了有一个函数doPackage,这里就是处理编译工作的。

然后就搜索到了Command.cpp:在他内部的doPackage函数中进行编译工具的一个函数:buildResources函数,在全局搜索,发现了Resource.cpp:具体查看buildResources函数,发现这里就是处理编译工作,同时在这里我们也看到了核心,构建ResourceTable的逻辑,在ResourceTable.cpp中,也是获取PackageId的地方,到此我们就知道了大体的逻辑,那么知道了逻辑,下面我们就来看看如何修改呢?

其实最好的方法是,能够修改aapt源码,添加一个参数,把我们想要编译的PackageId作为输入值,传进来最好了,其实我们在看源码的时候发现,有一个类型始终传递这,那就是Bundle类型,他是从Main.cpp中的main函数传递到了最后的buildResources函数中,那么我们就可以把这个参数用Bundle进行携带。

 

四、操作实践

既然知道了修改的思路,下面就是来修改源码了:

第一步:修改Main.cpp中的main函数,获取外部传递的PackageId值,然后存入到Bundle中

\

这里我们使用的参数是:-apk-module

第二步:我们只需要在ResourceTable.cpp中的构造方法读取这个值即可

\

到此,我们就修改完了,然后编译,这里编译因为环境不同,所以这里就不列出来如何编译的了,本人使用VC6.0进行编译的,得到了最终的修改之后的appt命令:aapt_win.exe

 

五、工具使用

那么既然上面我们那么辛苦的修改了aapt命令,下面就可以大展生手的修改一下试一试了,用一个简单的demo进行尝试,不过这里还有一个问题,就是这里我们呀用ant脚本来编译apk,因为我们需要修改aapt命令的路径,换成编译之后的aapt_win.exe,关于如何使用Ant脚本编译apk,这里就不做太多的解释了,而且,我就是用这篇文章中的demo做案例的,就是改了一下编译脚本:

修改aapt命令的路径,用我们修改之后的命令

\

在编译生成R文件的时候,添加参数:-apk-module

\

编译resource.arsc也需要修改:

\

这里全部修改成0x78,然后我们跑一个ant脚本:ant release

然后看一下R文件的内容:

\

哈哈哈,这里我们看到修改成功了,不相信的话,我们可以用我们之前写的一个工具:解析Resource.arsc文件的工具类,打印看一下结果(不了解的同学可以查看这篇文章:http://blog.csdn.net/jiangwei09

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

相关文章

  • 2017-05-26Android开发艺术探索学习笔记(三),android艺术探索
  • 2017-05-26开启我的Android之旅-----记录Android环境搭建遇到的问题,-----android
  • 2017-05-26Android中Window添加View的底层原理
  • 2017-05-26android基础部分再学习---再谈Service进程服务通信
  • 2017-05-26谈谈Android中的Divider,AndroidDivider
  • 2017-05-26关于eclipse android 在manifest改app应用包名注意事项,androidmanifest
  • 2017-05-26仿Android印象笔记底部导航栏
  • 2017-05-26Stack Overflow 排错翻译,stackoverflow
  • 2017-05-26Android 连接webservice(利用谷歌提供的jar包),androidwebservice
  • 2017-05-26安卓客户端a标签长按弹框提示解决办法,安卓标签

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • include的用法例子,以及include+merge的用法例子,includemerge
    • Android View体系(五)从源码解析View的事件分发机制
    • Andriod中自定义Dialog样式的Activity点击空白处隐藏软件盘(Dialog不消失),andrioddialog
    • Android实战技巧之五十一:libjpeg与Android
    • cobbler系统使用之二高级篇的补充篇---关于kickstart文件内容的配置说明
    • Android5.0开发范例大全 读书笔记(六),android5.0范例
    • 高仿360手机卫士应用源码,高仿360卫士源码
    • Android开发技巧——大图裁剪
    • Android studio图片ERROR: 9-patch image xx .9.png malformed
    • XAMARIN ANDROID 二维码扫描示例,xamarinandroid

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有