Android二次打包之重新生成R文件

安卓经常需要打多个渠道包,当二次打包时,资源ID会重新生成。如果代码中有第三方SDK通过直接引用R文件的方式来获取资源ID,就会出现资源ID不匹配的问题。
本文主要介绍解决此类问题的三种方法。

一 背景

为什么要二次打包

大家都知道,国内安卓渠道众多,游戏想要上架渠道就要接入他们的sdk。这对于游戏开发商(CP)来说是一个不小的工作量。

通过接入我们的聚合SDK,CP只需要提供一个母包,然后使用我们的打包工具就可以打出几十个渠道包,非常的高效。

二次打包的基本原理

打包工具的基本原理就是通过反编译,把SDK的代码和资源文件打入到游戏母包,然后重新打包签名,生成对应的渠道包。

当然这其中会涉及到许多细节方面的东西,不是本文重点,就不展开了。

二次打包之资源文件ID

打包时,会生成两个文件。

一个是resources.arsc.里面包含了所有资源文件的索引ID

示例:

<?xml version="1.0" encoding="utf-8"?> 另外一个是R文件,里面提供了代码中引用的name和resources.arsc中对应的ID

示例:

public final class R {
public static final class drawable {
public static final int btn_login = 2130837507;
}
public static final class layout {
public static final int paydialog = 2130903049;
}
}
这样我们通过引用R文件就可以找到对应的资源。

但是,正如前面所说,resources.arsc和R.java是打包的时候才会生成。因此,二次打包会重新生成资源ID,如果我们通过直接引用R文件的方式来寻找资源,就会出现问题。

二 解决方法

  1. 常规操作:动态获取资源ID
    这是最简单最通用的解决方法。

比如说我们可以通过如下方式获取一个布局文件的ID:

public static int getLayoutId(Context context,String paramString) {
mContext = context;
return getResourceId(“layout”, paramString);
}

protected static int getResourceId(String paramString1, String paramString2) {
return mContext.getResources().getIdentifier(paramString2, paramString1,
mContext.getPackageName());
}

  1. 奇技淫巧:替换掉第三方SDK中R文件的引用
    可是,如果第三方SDK就是通过R文件直接引用资源ID怎么办?

比如说,他们引用了com.corpA.sdk.R,重新打包之后,会在我们的包名(com.corpB.demo)文件夹下生成新的R文件。因此,我们可以让SDK直接引用我们包名文件夹下的R文件。

具体咋做呢?

2.1 SDK代码反编译为smali文件
使用apktool将第三方SDK的所有java代码反编译为smali文件。

2.2 查找替换所有R文件的引用
将smali文件中所有com/corpA/sdk/R替换为com/corp/demo/R。这样,重新打包后,第三方SDK在运行时会去我们包名下最新的R文件中寻找资源ID

这种方法简单粗暴,不需要手动生成R文件,也不需要更改SDK中原来的R文件,直接通过打包脚本在反编译阶段改掉第三方SDK的代码。

  1. 曲线救国:直接修改第三方SDK中引用的R文件
    凡是总有例外,不是所有的SDK都能反编译的。比如有些SDK会将Java代码打成一个加密的Dex文件,放到asset文件夹下面。这种加密的Dex文件我们是无法反编译的,所以上面的方法2就行不通了。

由于无法反编译,这个Dex里面的内容对于我们就是一个黑盒,我们无法知道它里面是否有直接引用R文件的情况,以及引用了哪里的R文件。

这个其实没有很好地办法,只能先按照方法2来处理掉可以反编译的Java代码,然后打出一个包来进行测试。如果加密Dex中有直接引用到R文件,那么就会出现崩溃,从日志中我们就可以找到引用R文件的位置。然后我们就可以修改指定位置的R文件啦。

过程有些繁琐,下面详细说明:

3.1 找到引用R文件的位置
通过崩溃日志,我们可以找到Dex文件中所引用的R文件的位置,假设该R文件的路径是com.corpA.sdk.R

3.2 使用aapt手动生成R文件
aapt(Android Asset Packaging Tool)是安卓sdk中负责将资源文件和代码进行打包的工具。基本上所有的打包工具都是在aapt的基础上进行封装和修改的,打包的过程比较繁琐,总结下来大概有如下几个步骤:

通过aapt工具,生成R.java和.arsc文件
通过aidl工具,把aidl文件打包成java文件
通过javac工具,将Java文件编译成.class文件
通过dx工具,把class文件和第三方jar打包成dex文件
通过apkbuilder工具,把dex和资源文件打包成apk文件
通过JarSinger工具,对apk进行签名
通过zipAlign工具,对apk做对齐处理
我们要改的就是第一步:aapt生成R文件!步骤如下

反编译游戏母包和接入渠道SDK的插件包,将代码和资源文件合并

修改AndroidManifest.xml中的包名为最终渠道包的包名

使用Android sdk的aapt工具手动生成R文件

前提是需要首先安装Andorid sdk相应的工具,并配置好环境变量。aapt指令比较复杂,核心就是下面这个:

os.getenv(‘ANDROID_BUILD_TOOL’) + "/aapt package -f -m -J " + temp_path + " -S " + res_path + " -I " + os.getenv(‘ANDROID_PLATFORM’) + "/android.jar -M " + manifest_path
其中temp_path是生成的R文件输出路径;res_path是res文件夹的路径;manifest_path是manifest的路径

3.3 将R文件转换为Smali文件
这个过程大概4个步骤: java --> class --> jar --> dex --> smali

示例:

# 1. build_r_class
r_java_path = temp_path + os.sep + package_name.replace('.', os.sep) + os.sep + "R.java"
cmd_build_r_class = "javac -source 1.6 -target 1.6 " + r_java_path
execCmd(cmd_build_r_class)
file_util.deleteFile(r_java_path)

# 2. generate jar
os.chdir("/data/soft/jenkins/workspace/Packaging_Tools-All" + os.sep + temp_path)
cmd_generate_r_jar = "jar cvf " + "r.jar " + "com"
execCmd(cmd_generate_r_jar)

# 3. generate dex
cmd_generate_dex = os.getenv('ANDROID_BUILD_TOOL') + "/dx --dex --output=" + "r.dex " +         "r.jar"
execCmd(cmd_generate_dex)

# 4. generate smali
cmd_generate_smali = "java -jar " + "/data/soft/jenkins/workspace/Packaging_Tools-All" +         os.sep + "baksmali-2.0.jar " + "r.dex"
execCmd(cmd_generate_smali)

3.4 拷贝smali文件到对应位置
我们要拷贝一份smali文件到包名下对应目录。

然后同样拷贝到3.1步骤中R文件的路径(com.corpA.sdk.R)。同时,我们需要修改smali中R文件的引用为com.corpA.sdk.R。这样才能保持更Asset下面的Dex文件中的引用一致。

至此,关于R文件的处理已经完成,然后重新打包就可以啦~

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
1、集成了大部分app开发的必要组件, 2、修复了一些第三方组件的bug,并进行了扩展。3、现成的工具类,提示窗口工具类,主界面、登陆、注册界面和交互流程… 开发工具在软件开发生命周期中扮演着至关重要的角色,它们旨在简化和加速从概念设计到产品部署的各个环节。以下是开发工具的主要作用: 代码编写与编辑: 提供集成开发环境(IDE),如Visual Studio、Eclipse、Android Studio和Sublime Text等,这些工具集成了文本编辑器,支持语法高亮、自动补全、代码片段管理和版本控制等功能,有助于开发者高效编写和维护代码。 项目管理: 支持项目创建、组织、构建自动化以及依赖管理,确保不同模块和组件之间的协调一致。 编译与构建: 包括编译器、构建工具(如Make、Gradle、Maven)等,用于将源代码转换为可执行文件或库,并进行打包、优化等处理。 调试与测试: 集成调试器允许开发者逐行执行代码,设置断点、查看变量值、跟踪调用堆栈等,帮助定位并修复代码中的错误。 测试框架和工具则协助开发者编写和运行单元测试、集成测试及性能测试,确保软件质量。 版本控制与协作: 通过集成Git、SVN等版本控制系统,支持团队成员间的代码共享、分支管理、合并请求和冲突解决。 可视化设计与原型制作: 对于UI/UX设计,有界面设计工具,如Sketch、Adobe XD,可以帮助设计师快速构建应用程序界面模型,并生成规范的设计稿供开发人员参考实现。 跨平台支持: 跨平台开发工具如Xamarin、React Native和Flutter,让开发者使用一种语言或框架编写可以在多个操作系统上运行的应用程序。 文档编写与API管理: 文档生成工具可以自动生成代码注释文档,便于团队内外理解和使用项目代码。 API管理工具则方便开发者创建、测试、发布和维护API接口。 持续集成与持续部署(CI/CD): Jenkins、Travis CI、GitHub Actions等工具负责自动化构建、测试和部署流程,提高交付效率和可靠性。 数据库管理与ORM工具: 数据库客户端工具用于连接、查询、更新数据库,ORM(对象关系映射)工具简化了数据操作和持久化层的开发工作。 总之,开发工具极大地提升了软件工程师的工作效率,保证了开发过程中的准确性与一致性,同时也促进了团队合作,使得软件开发更系统化、规范化和工业化。
Android Killer是一个工具,它可以帮助开发者修改Android的源代码并进行二次打包。 首先,为了使用Android Killer,我们需要下载并安装它。安装完成后,可以在命令行中输入“androidkiller”来启动它。 接下来,我们需要准备Android源码。Android源码可以从Google官方网站上下载。下载完成后,我们需要将源码解压缩到一个指定的目录中。 在Android Killer中,我们需要指定源码所在的路径。我们可以在命令行中输入“androidkiller --path [源码路径]”来设置源码路径。 完成以上准备工作后,我们可以开始修改源码。通过修改源码,我们可以添加新功能、修改现有功能或者删除功能。要修改源码,我们需要具备Java编程的基础知识和Android开发的经验。 在完成源码修改后,我们可以使用Android Killer进行二次打包二次打包的过程包括编译源码、生成APK文件和签名APK文件。 通过Android Killer,我们可以执行以下命令来进行二次打包: 1. 编译源码:输入“androidkiller --build”来编译源码。编译过程可能需要一些时间,具体视源码大小和电脑性能而定。 2. 生成APK文件:编译完成后,我们可以在输出目录中找到生成的APK文件。APK文件二次打包后的最终产物。 3. 签名APK文件:为了能够在Android设备上安装和运行APK文件,我们需要对APK文件进行签名。我们可以使用以下命令来签名APK文件:“androidkiller --sign [APK文件路径] [签名文件路径]”。 以上就是使用Android Killer修改源码并进行二次打包的基本流程。通过修改源码,我们可以定制化我们的Android系统和应用,以满足自己的需求。使用Android Killer,我们可以更加灵活地进行二次开发和定制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浅墨cgz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值