专栏首页MelonTeam专栏Android资源热修复之修改aapt源码

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 条评论
登录 后参与评论

相关文章

  • 深入理解C++11(一)

    导语 从最初的代号C++0x到最终的名称C++11,C++的第二个真正意义上的标准姗姗来迟。 C++11是一种新语言的开端。虽然设计C++11的目...

    MelonTeam
  • 机器学习入门系列05,classification: probabilistic generative model(分类:概率生成模型)

    引用课程:http://speech.ee.ntu.edu.tw/~tlkagk/courses_ml16.html 先看这里,可能由于你正在查看这个平台行...

    MelonTeam
  • 重磅整理---Android进程保活组件

    导语 Android进程保活的文章很多,但是基本没有一个完整的工程化的东西。所以在这里整理主流的保活方案,将其工程化到github上供大家直接使用。 ...

    MelonTeam
  • aapt获取apk版本等信息

    简介: aapt即Android Asset Packaging Tool,我们可以在SDK的platform-tools目录下找到该工具。aapt可以查看、 ...

    苦咖啡
  • hanlp源码解析之中文分词算法

    词图指的是句子中所有词可能构成的图。如果一个词A的下一个词可能是B的话,那么A和B之间具有一条路径E(A,B)。一个词可能有多个后续,同时也可能有多个前驱,它们...

    用户3492023
  • 利用PySpark 数据预处理(特征化)实战

    之前说要自己维护一个spark deep learning的分支,加快SDL的进度,这次终于提供了一些组件和实践,可以很大简化数据的预处理。

    用户2936994
  • (1)

    试用期工资为5000元,法律有规定,试用期工资是转正后工资的80%。试用期工资是5000元,转正后工资就得6250元

    达达前端
  • python图像处理-gif动图

    本系列课程是针对无基础的,争取用简单明了的语言来讲解,学习前需要具备基本的电脑操作能力,准备一个已安装python环境的电脑。如果觉得好可以分享转发,有问题的地...

    用户7054460
  • 如何使用sublime text 远程开发(附带please adjust the remote_encoding错误解决)

    用Package Control安装插件 按下Ctrl+Shift+P调出命令面板 输入install 调出 Install Package 选项并回车

    梦_之_旅
  • jenkins构建时支持git选择分支

    易兒善

扫码关注云+社区

领取腾讯云代金券