惠州学院网站建设,建网站要定制还是第三方系统,网站建设研究课题,网站的题目原文 http://blog.votzone.com/2018/05/12/apk-merge.html 之前接手过一个sdk的开发工作#xff0c;在开发过程中有一个很重要的点就是尽量使用代码来创建控件#xff0c;资源文件最好放到assets目录下#xff0c;如果必须使用res资源#xff0c;需要通过 getResources().g…  原文 http://blog.votzone.com/2018/05/12/apk-merge.html 之前接手过一个sdk的开发工作在开发过程中有一个很重要的点就是尽量使用代码来创建控件资源文件最好放到assets目录下如果必须使用res资源需要通过 getResources().getIdentifier(activity_splash,layout, getPackageName()) 这种方式来获取资源id而不能直接通过R文件获取。 今天就来研究一下这个问题。 一、lib项目中r文件中资源唯一标志为static变量 一般的app项目中自动生成的R文件为常量而在library项目中为变量。根据Android官方文档在android 14 之后添加的这一特性之前编译后的lib项目中是常量之后的为static 变量。 目的是为了在资源冲突时能够修改资源唯一值。 如图在library项目中自动生成的R文件如下  有一个需要关注的点是R文件是java 代码在build时会生成.class文件并添加到dex中。 因为R文件中的常量值仅仅受编译器控制在lib发布之后添加到jar包中的.class并不会受到当前编译器的影响。而通常lib发布之后要给第三方使用。 看一下反编译后的apk  反编译后查看mylib 下对应的R文件smali代码可见其值又被设置为final常量了。 因此我们可以知道编译器在生成apk时虽然没有lib的java代码可以重置和修改但是在将jar转化为dex时可以转换为常量。 转化为常量后并不影响其使用 如图在lib中使用layout资源的反编译代码  我们可以看出使用静态常量可以在生成apk时动态修改其指定的值。 如果是常量编译后v0的值将直接使用常量值这样修改R.class文件中的值将没有意义。例如在app中反编译后代码如下  二、从反编译后代结构中查看资源对应问题 可以看到反编译后的代码与我们写的java代码基本是一一对应的那么问题来了Android是怎么通过一个id值来找到需要的资源呢通过分析Android源码我们当然可以找出过程但是分析apk反编译后的结构可以给我们更直接的思路。  在res/values/文件夹下有个public.xml文件其中每行有三对值分别为type、name、id 通过分析我们可以直接得出结论 public.xml中的对应关系直接关系到哪个id找那个资源。 三、添加资源 Unity3d和cocos2d引擎有自己一套方式来添加资源id假如我们自己搞一个游戏又想为其添加一些java代码和资源该怎么操作 根据之前的分析我们可以设计如下测试方案 假定我们要添加代码的apk为targetapp我们编写一个叫mergelib的apk然后将mergelib中资源和代码添加到targetapp中。在编写mergelib时使用 getResources().getIdentifier(activity_splash,layout, getPackageName()) 的方式获取资源id通过apktool反编译代码将资源文件复制到要加入的目标apk中将mergelib的public.xml文件中需要的资源项添加到targetapp中编译并签名测试。根据如上实验我们可以确定这样的操作是可行的。测试流程如下 需要的资源 targetapp- 目标app, 在这里代表游戏mergelib- 要将其中包含资源的代码合并进去mergelib 中对资源通过getIdentifier()的方式使用: 例如设置启动页Activity中的ContentView的设置  int id  getResources().getIdentifier(activity_splash,layout, getPackageName());    setContentView(id);我们的目标为targetapp添加一个启动页启动页代码在mergelib中编写。 执行流程  修改targetapp中AndroidManifest.xml文件 1) 将SplashActivity 的声明添加进去 2) 修改启动Activity  复制需要的代码进入targetapp: 复制mergelib中SplashActivity的代码并修改启动MainActivity的启动代码 如图   复制资源1) 将res/anim 下alpha.xml复制到target2) 将res/layout 下 spalsh.xml复制到target 下  修改ids 将 res/values/ids.xml 中多出来的行复制到 对应ids.xml文件中 如图, 本例中仅有一个id 即ImageView的id, 因此将该行复制到targetapp 中对应的ids.xml文件中即可 位置不重要  修改public.xml文件 mergelib Splash中用到了 anim, layout, id, 并且间接用到了 mipmap,因此这些对应的值都需要添加到targetapp。观察public.xml的文件结构,可以发现如下特点: 1) 所有同类型(type相同)的id连续 2) 同类型的id 前4字节相同, 如下图 anim 的前四字节0x7f01 与 attr 不同  3) 所有id唯一 根据以上三个特点,我们将多出来的id添加到target为了保证唯一且方便修改,我们做了如下替换(右侧为target)  一切就绪,编译并安装 四、工具化处理public.xml的替换过程 上述手动测试仅仅只有一个资源id的情况假如我们加入了一个support包或者其他一些包含资源的包那么资源数量将会增加到几百个这样的话手动添加肯定是不行的我们需要一个脚本工具来实现。 脚本接收两个public.xml格式的文本并输出一个合并版本。 其中targetapp中的id值是不可变得在遇到id冲突时我们改变mergelib的public.xml。 1) 复制mergelib的public文件为mergeid.xml  2) 复制target app 的public 并命名为oriid.xml 3) 将mergeid.xml 和oriid.xml 放到RIDreset.py同目录下, 运行py脚本   4) 出现 oriid.xml_ 文件, 即生成的合并文件 案例及脚本 https://github.com/votzone/DroidCode/tree/master/VotAndroid/Mergeapp    转载于:https://www.cnblogs.com/fog2012/p/apk_merge.html