Android资源热修复之修改aapt源码

导语 : 在Windows下定制自己的aapt!

一、环境配置

1.1 软件和源码

Codeblocks下载地址:< mingw64下载地址:<https://jaist.dl.sourceforge.net/project/tdm-gcc/TDM- GCC%20Installer/> aapt源码地址(为了避免麻烦,特地弄好了aaptCodeblocks项目,直接从我的githubclone下来就能在Codeblocks中用):https://github.com/ClaymanTwinkle/aapt

1.2 软件配置

软件安装好了就要先配置下

1.2.1Codeblocks配置Compiler

步骤一: 选择进入工具栏 Settings » Compiler,如下图所示;

步骤二: (1)选择Global compiler settings; (2)在Selected compiler中选择GNU GCC Compiler,然后下方点击Copy按钮,就会出现Copy of GNU GCC Compiler; (3)在下方Toolchain executables配置mingw64,相关配置如下图所示; (4)最后选择OK即可;

配置好编译环境后,就可以打开项目了;进入aapt/aapt-v24中打开aapt-v24.workspace

工程目录结构如下图所示;

1.2.2 为每个工程配置Compiler

步骤一:右键一个工程,在右键菜单中选择Build Options

步骤二:第一次配置的时候,会出现一个弹窗,如下图;选择刚刚自己创建的Copy of GNU GCC Compiler,点击确定;

步骤三:注意,如果此时,出现以下对话框,请选择

对每个工程重复以上步骤;

二、改aapt源码

没错,如果上面的步骤都弄成功了,现在就可以改aapt源码了,是的,在Windows上改aapt源码,想想就激动! 普及一下一个小知识,在R.Java中可以看到系统资源的id都是以0x01开头的,而自己的资源id都是以0x7f开头的;这也就是说0x010x7f之间的的值我们都可以拿来用。 废话不多说,赶紧动手!

2.1 试改0x7f0x66

(1)在CodeBlocks中打开aapt-v24,找到我们要找的入口类main.cpp;同时也找到了入口方法main

(2)找到这个main.cpp有什么用,怎么修改0x7f呢?

我们可以这样,按快捷键Ctrl+F(真的很好用!),在aapt-v24中搜索0x7f,如下图所示;

搜索结果如下,这样我们就找到赋值0x7f的地方了;

ResourceTable.cpp这个类中;

(3)既然找到了位置,那赶紧改下这个值试试(直接改硬编码不太优雅,后面介绍一种优雅的方式),修改结果如下图所示;

接着,打包出自己的aapt吧!

(4)右键aapt-v24,在右键菜单中选择build或者rebuild,编译成功,打包出aapt.exe

aapt\aapt-v24\bin\Debug目录下可以看到打包好的aapt-24.exe

(5)打包好了,是骡子是马牵出来溜溜吧。

随便找个Android工程,然后在cmd中敲出类似这样一段命令行生成R.java

aapt-v24.exe p -f -m -I C:\Android\sdk\platforms\android-25\android.jar -J C:\Users\andyqtchen\Desktop\plurals -M C:\Android\workspace\AndroidQQ_Lite_proj/QQLite//AndroidManifest.xml -S C:\Android\workspace\AndroidQQ_Lite_proj/QQLite/res

结果……出乎意料啊,居然错了,是啊,哪有那么容易,想得美;但是,这些log好像是aapt自己内部打印出来吧?让我们看看这些log是从哪里打印出来的!

(6)神一样的快捷键Ctrl+F,搜~,结果如下图所示;

原来是在androidfw工程下的ResourceTypes.cpp搞的鬼! 先看看ResourceTypes.cpp耍的是什么把戏!

原来是这么回事,aapt除了会在aapt-v24中赋值,在androidfw中后面还会做一个判断拦截;

那么我在这里再加一个或者packageId==0x66就ok了(又一不文明操作,请勿模仿)! 改完重新rebuild androidfw,然后rebuild aapt-24打包出aapt.exe; 重新生成一次R.java,接下来就是见证奇迹的时刻!

2.2 定制化aapt

好了,上面的2.1只是小打小闹的一个实验而已,接下来要定制下随意修改资源ID前缀(packageId)的aapt

步骤一、定义一个单例

我在androidfw中定义一个单例,用来记录0x7f(默认值)或者其他自定义packageId的值;

// BlinkPackageId.h文件
#ifndef __BlinkPackageId_h
#define __BlinkPackageId_h

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

class BlinkPackageId
{
        ssize_t mPackageId;
public:
        static BlinkPackageId* getInstance()
        {
                static BlinkPackageId instance;
                return &instance;
        }
        ssize_t getPackageId();
        void setPackageId(ssize_t packageId);
        void setPackageId(const char* packageId);
protected:
        struct Object_Creator
        {
                Object_Creator()
                {
                        BlinkPackageId::getInstance();
                }
        };
        static Object_Creator _object_creator;
        BlinkPackageId() {
                mPackageId=0x7f;
        }
        ~BlinkPackageId() {
        }
};
#endif



// BlinkPackageId.cpp文件
#include 

#include 
#include 
#include 
using namespace std;

// char2int
static uint32_t apkgetHex(char c, bool* outError){
    if (c >= '0' && c <= '9') {
        return c - '0';
    } else if (c >= 'a' && c <= 'f') {
        return c - 'a' + 0xa;
    } else if (c >= 'A' && c <= 'F') {
        return c - 'A' + 0xa;
    }
    *outError = true;
    return 0;
}

// string2int
static ssize_t apkStringToInt(const android::String8& s){
    size_t i = 0;
    ssize_t val = 0;
    size_t len=s.length();
    if (s[i] < '0' || s[i] > '9') {
        return -1;
    }
    // Decimal or hex?
    if (s[i] == '0' && s[i+1] == 'x') {
        i += 2;
        bool error = false;
        while (i < len && !error) {
            val = (val*16) + apkgetHex(s[i], &error);
            i++;
        }
        if (error) {
            return -1;
        }
    } else {
        while (i < len) {
            if (s[i] < '0' || s[i] > '9') {
                return false;
            }
            val = (val*10) + s[i]-'0';
            i++;
        }
    }
    if (i == len) {
        return val;
    }
    return -1;
}

BlinkPackageId::Object_Creator BlinkPackageId::_object_creator;

ssize_t BlinkPackageId::getPackageId(){
        return mPackageId;
}
void BlinkPackageId::setPackageId(ssize_t  packageId){
        mPackageId=packageId;
}
void BlinkPackageId::setPackageId(const char* packageId){
        android::String8 str = android::String8(packageId);
        mPackageId=apkStringToInt(str);
}

步骤二、改造aapt命令行

定个需求,要加个--blink-package-id命令参数,后面带packageId;

锁定到aapt-v24工程下main.cpp源代码:

ResourceTable.cpp,将0x7f改成BlinkPackageId::getInstance()->getPackageId()

然后到androidfw工程下,把BlinkPackageId::getInstance()->getPackageId()放到if中:

ok!大功告成!

看看效果!!!

aapt-v24.exe p -f -m -I C:\Android\sdk\platforms\android-25\android.jar -J C:\Users\andyqtchen\Desktop\plurals -M C:\Android\workspace\AndroidQQ_Lite_proj/QQLite//AndroidManifest.xml -S C:\Android\workspace\AndroidQQ_Lite_proj/QQLite/res --blink-package-id 0x55

参考文章

如何实现携程动态加载插件中对aapt的改造 Android中如何修改编译的资源ID值(默认值是0x7F…可以随意改成0x02~0x7E)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏哲学驱动设计

数据层扩展包EFCachingProvider 总结

    前不久学习了《EFCachingProvider》,该扩展包不但可以用于EntityFramework的扩展,所有与数据库连接相关的应用程序都可以使用类...

1717
来自专栏坚毅的PHP

hbase问题总结

 1 java.io.IOException: java.io.IOException: java.lang.IllegalArgumentException:...

4246
来自专栏岑玉海

Hadoop源码系列(一)FairScheduler申请和分配container的过程

1、如何申请资源 1.1 如何启动AM并申请资源 1.1.1 如何启动AM val yarnClient = YarnClient.createYarnClie...

3903
来自专栏跟着阿笨一起玩NET

Remoting配置文件的用法

本文转载:http://www.cnblogs.com/rickie/archive/2004/10/10/50392.html

702
来自专栏Janti

基础巩固——长连接 、短连接、心跳机制与断线重连

本文将从长连接和短连接的概念切入,再到长连接与短连接的区别,以及应用场景,引出心跳机制和断线重连,给出代码实现。

1051
来自专栏Albert陈凯

Hadoop数据分析平台实战——250JSSDK数据收集引擎编写离线数据分析平台实战——250JSSDK数据收集引擎编写

离线数据分析平台实战——250JSSDK数据收集引擎编写 JsSDK设计规则 在js sdk中我们需要收集launch、pageview、chargeReque...

3348
来自专栏安富莱嵌入式技术分享

【RL-TCPnet网络教程】第14章 RL-TCPnet之TCP客户端

本章节为大家讲解RL-TCPnet的TCP客户端实现,学习本章节前,务必要优先学习第12章TCP传输控制协议基础知识。有了这些基础知识之后,再搞本章节会有事半功...

781
来自专栏向治洪

React Native开发之调试

在做React Native开发时,少不了的需要对React Native程序进行调试。调试程序是每一位开发者的基本功,高效的调试不仅能提高开发效率,也能降低B...

2608
来自专栏圣杰的专栏

ABP入门系列(13)——Redis缓存用起来

源码路径:Github-LearningMpaAbp 1. 引言 创建任务时我们需要指定分配给谁,Demo中我们使用一个下拉列表用来显示当前系统的所有用户,以...

2479
来自专栏24K纯开源

Ubuntu13.04配置:Vim+Syntastic+Vundle+YouCompleteMe

序言     使用Ubuntu和vim已经有一段时间了,对于Vim下的插件应用,我总是抱着一股狂热的态度。这次,又在网上闲逛着,发现了一个个人博客提到了Vim代...

24110

扫码关注云+社区