In Android, how to modify the compiled resource ID value (the default value is 0x7F... can be changed to 0x02 ~ 0x7E)
I. Technical preparation
Today, let's take a look at how to modify the value of the resource Id during Android compilation. Before explaining this, we need to first understand the structure and compilation process of the resources in Android after compilation, this article describes how to parse the compiled resource in Android. arsc file, which describes the types and formats of Android Chinese source files after compilation. In fact, after Android resources are compiled, an R file is generated, all resource IDs are stored in this file. By default, we can see that all IDs share a common feature that they all start with 0x7F, in fact, 0x7F is the package ID value. We are parsing the resource. as mentioned in arsc, the id value in Android is actually an int type. Its value consists of three parts: PackageId + TypeId + EntryId
PackageId: indicates the package Id value. for Android, if it is a third-party application, the default value is 0x7F. For system applications, the value is 0x01. For details, refer to the aapt source code, it occupies two bytes.
TypeId: indicates the type Id value of a resource. Generally, Android has the following types: attr, drawable, layout, dimen, string, style, etc, these types of values gradually increase from 1, and the order cannot be changed. attr = 0x01, drawable = 0x02 .... it occupies two bytes.
EntryId: indicates the id value of the resource entity under a specific type. It starts from 0 and increments sequentially. It occupies four bytes.
Ii. Problems Encountered
Now that we understand the structure of the resource Id in Android, let's talk about the problem we encountered:
1. Occasionally, third-party library packages are dependent on Android projects, and resource IDS (packageId + typeId + ItemValue) conflict with each other (there are many solutions on the Internet, which are not listed one by one, such as public limitation ). For our own library package, if you can specify the Command Space of the package (the default value is from 127 = 0x7F), especially in the case of mutiDex, it is significant to modify the package ID.
2. When developing the plug-in technology in Android, to prevent the resource Id in the plug-in project from conflict with the resource Id in the host project, you also need to modify the compiled resource Id value in the plug-in to reduce conflicts.
The above is the problem we encountered. In fact, our solution is very simple, that is, to modify the resource Id value during compilation and give a limit value.
Iii. Solution
We have explained the composition structure of the resource Id and found that the two high bytes represent the value of PackageId, and the default value of the third-party app is 0x7F. Can we modify this value? For example, PackageId in resource Id in Plug-in 1 is 0x30, and PackageId in resource Id in Plug-in 2 is 0x31... in this way, the resources of each plug-in are divided into certain region values, and ensure that they do not conflict with 0x7F in the main project. Then these values can be changed from 0x02 ~ 0x7E. We can use this range value. Why is 0x01 unavailable? Because he is a system application, we have 0x7E-0x02 = 124 intervals. Haha, I'm so excited. Can we operate it? The answer is yes. We know that the aapt command is used for compiling resources in Android, so we can check its source code to see if it is okay.
The aapt command is a tool for compiling apk provided by Android, so the source code can beAndroid source code directory/tools /...View the following information:
The source code of this tool is still not complex. There are not many files. Of course, the entry must find the keyword of main.Main. cppFile, open and view, find the main entry function, here we can see that he made a judgment on the input parameters:
Here the main function is a little long. Let's look at the final processing function:
Here isHandleCommandFunction, which is mainly used to process commands:
There are many functions, but here we need to pay attention to the doPackage function, which is the key to playing the package, but at this time we find that the function is not found globally, then this function must be referenced. Find the specific function in the source code,
Make up your mind:
Because it is a Windows system and does not want to be a Linux system, you can use find + grep to quickly find the files containing the specified content. However, Windows provides visual file search, however, by default, when searching, he only searches for the file name and does not search for contained content. Therefore, you need to set it in the folder options:
At this time, we can search in the tools directory:
At this time, we found three files,Main. cppYou don't need to read it. Because you have already read it, you canCommand. cppInside:
Here we will look at the following:
Here is a method, and let's look at the annotations. Here is the core function of Compilation:BuildResourcesWe searched for this function globally and did not find it. Then we searched the entire directory:
Found, inResource. cppMedium:
Here we can see a packgeType field, which is the package type. There are three types: shared, system, and third-party.
Suddenly, this seems to have something to do with the value of PackageId. Let's look at it:
Here, packageType is used and there is an important type.ResourceTableThis is the data structure mapped to the resource index table and ResId, so we can view its definition:ResourceTable. cppMedium
I wiped it, and I saw the result. Here I saw three values,0x00,0x01, 0x7F. This shows that we have found the core. Next, let's look:
A Package is built here, And the packageId value is passed in here. Well, we can analyze the source code here, so let's take a look at it.Source code process:
First, find the entry class: Main. cpp: main function, parse the parameter, and then call the handleCommand function to process the logic corresponding to the parameter. We can see that there is a function doPackage, which is used to process compilation.
Then the Command is searched. cpp: A function used to compile the tool in its internal doPackage function: buildResources function. In the global search, the Resource is found. cpp: Check the buildResources function and find that this is the process of compilation. At the same time, we also see the core, building the ResourceTable logic, in ResourceTable. in cpp, it is also the place where PackageId is obtained. Now we know the general logic, so we know the logic. Let's take a look at how to modify it?
In fact, the best way is to modify the aapt source code, add a parameter, and pass the PackageId we want to compile as the input value. In fact, it is best to see the source code, there is a type always passed this, that is, the Bundle type, which is from Main. the main function in cpp is passed to the final buildResources function, so we can use Bundle to carry this parameter.
Iv. operation practices
Now that you know how to modify the source code, the following is how to modify the source code:
Step 1: Modify the Main function in main. cpp, obtain the PackageId value passed externally, and store it in the Bundle.
Here we use the following parameters:-Apk-module
Step 2: You only need to read this value from the constructor in ResourceTable. cpp.
At this point, we have finished the modification and then compiled it. The compiling environment is different here, so we will not list how to compile it here. I used VC6.0 for compilation, the modified appt command is obtained:Aapt_win.exe
V. Use of tools
Finally, I will not explain much about how to use the Ant script to compile the apk. Besides, I just used the demo in this article to compile the script:
Modify the path of the aapt command and use the modified command.
When compiling the R file, add the following parameters:-Apk-module
To compile resource. arsc, you also need to modify it:
Change all0x78Then we run an ant script:Ant release
Then let's take a look at the content of the R file:
Hahaha, here we can see that the modification is successful. If you don't believe it, we can use a tool we wrote earlier: parse the tool class of the Resource. arsc file and print the result (Do not understand the students can view this article: http://blog.csdn.net/jiangwei0910410003/article/details/50628894):
The printed result is also normal. Well, let's take a look at it. We use dynamic loading to load this apk (The specific code is not pasted here,First, we can view the log information. We use reflection in the code to obtain the id value of the app_name field in the plug-in apk.
The id displayed in the log is 0x78050000, And the displayed value is correct. In this way, the ResId range of the plug-in distinguishes 0x7F from the host project, there will be no resource conflict issues. Let's take a look at the running results:
Now, we have finished the contents of this chapter.
Source code and tools after aapt modification: http://download.csdn.net/detail/jiangwei0910410003/9454867
6. Technical Points learned
1. I learned how to find the source code in Windows.
2. Learned The overall aapt compilation process.
3. Learned to modify the compiled resource id value
7. Solved problems
By modifying the aapt source code, we can customize the resId value after compilation at will to solve the resource id value conflicts we encounter when referencing third-party packages or projects and developing plug-ins, so remember that we can modify the compiled resource ID value in Android.
VIII. Summary
After finishing this article, I feel that there are still a lot of GAINS. At least we know that the compiled resource ID in Android can be customized. Although some students may not be able to use this function now, but I believe that sooner or later you will certainly use it, so you just need to remember to have this technical solution.