Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to apply Android Resource Thermal repair Technology

2025-04-03 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces the relevant knowledge of "how to apply Android resource thermal repair technology". The editor shows you the operation process through an actual case. The operation method is simple, fast and practical. I hope this article "how to apply Android resource thermal repair technology" can help you solve the problem.

I. the universal way of implementation

At present, many resource hot repair schemes on the market basically refer to the implementation of Instant Run.

In a nutshell, resource hotfix in Instant Run is divided into two steps:

1. Construct a new AssetManager and call addAssetPath through reflection to add the completed new resource bundle to the AssetManager. This results in an AssetManager with all the new resources.

two。 Find all the places that were previously referenced to the original AssetManager and replace the reference with AssetManager through reflection.

An Android process contains only one ResTable, and the member variable mPackageGroups of ResTable is a collection of all parsed resource bundles. Any resource bundle contains resources.arsc, which records the id allocation of all resources and all strings in the resource. This information is stored in binary form. What the underlying AssetManager does is parse the file and store the relevant information in mPackageGroups.

II. Format of resource files

The whole resources.arse file is actually stitched together by ResChunk (hereinafter referred to as chunk). Starting from the header of the file, the header of each chunk is a ResChunk_header structure that indicates the size and data type of the chunk.

Through the type member in the ResChunk_header, you can know what type the chunk is, so you can know how to parse the chunko.

After parsing a chunk, starting from the location of chunk + size, you can get the next chunk starting position, so that you can read the data contents of the entire file in turn.

Generally speaking, a resources.arsc contains several package, but by default, a package typed by the packaging tool aapt has only one package. This package contains all the resource information in the app.

Resource information mainly refers to the name of each resource and its corresponding number. We know that every resource in Android has its unique number. The number is a 32-digit number, which is 0xPPTTEEEE in hexadecimal. PP is package id, TT is type id, and EEEE is entry id.

What do they stand for? How is it recorded in resources.arse?

For package id, each package corresponds to a ResTable_package structure of type RES_TABLE_PACKAG E _ TYPE, and the id member variable of the ResTable_package structure represents its package id.

For type id, each type corresponds to a ResTable_typeSpec structure of type RES_TABLE_TYPE_SPEC_ TYPE. Its id member variable is type id. However, the specific type of the type id needs to be parsed in the Type String Pool in package chunk. For example, there are attr, drawablex mipmap, and layout strings in Type String Pool. It means that the type id of attr type is 1, the type id of drawable type is 2, the type id of mipmap type is 3, and the type id of layout type is 4. Therefore, each type id corresponds to the type specified in the character order in the Type String Pool.

For entry id, each entry represents a resource item, which is automatically numbered in the order in which it is arranged. That is, the entry id of the first resource item that appears by location in a type is 0x0000, the second is 0x0001, and so on. So we can't specify entry id directly, we can only decide according to the arrangement order. The resource items are closely arranged and there are no gaps, but you can specify the resource item as ResTable_type::NO_ENTRY to fill in an empty resource.

For example, let's find a random apk with resources, parse it with aapt, and see that the line is:

$aapt d resources app-debug.apk

.

Spec resource 0x7f040019 com.taobao.patch.demo:layout/activity_main: flags=0x00000000

.

This means that the number of the activity_main.xml resource is 0x7f040019. Its package id is 0x7f, the id of resource type is 0x04, the fourth string in Type String Pool is layout type, and the 0x0019 resource item of 0x04 type is activity_main.

Third, the analysis of runtime resources

Apk, compiled by Android SDK by default, is packaged by aapt, and the package id of its resource bundle is 0x7f.

The resource bundle of the system, namely framework-res.jar, and package id is 0x01.

Before we get to the first line of app code, the system has already helped us construct an AssetManager that has added the installation package resources.

Therefore, this AssetManager already contains the system resource package and the app installation package, which is the resource in the framework-res.jar for 0x01 by package id and the app installation package for 0x7f by package id.

If you continue the complete patch pack of addAssetPath directly on the original AssetManager at this time, because the package id in the patch pack is also 0x7f, the package of the same package id will be loaded twice. What kind of problem will there be?

After Android L, this is no problem, he will silently add the subsequent package to the previous package under the same PackageGroup.

When parsing, the type corresponding to the same type id will be compared with the previous package. If the number of resource items under this type is not the same as that previously added, a warning log will be typed, but it will still be added to the TypeList of this type.

When getting the resources of a Type, it will traverse from the destination to the end, that is, to get the resources in the original installation package first, unless the config of the later resources is more detailed than the previous one. For the same config, the resources in the patch will never take effect. Therefore, in the version above Android L, it is useless to add a patch pack to the original AssetManager, and the resources in the patch cannot take effect.

In Android 4.4 and below, addAssetPath simply adds the path of the patch pack to mAssetPath, while the logic of the resource bundle that is actually parsed is when app first executes AssetManager::getResTable.

GetResTable has been executed countless times by the time the patch code is loaded. This is because even if we haven't done any resource-related operations before, the code in Android framework will be called there many times. So, in the future, even addAssetPath will only be added to mAssetPath, and parsing will not occur. So the resources in the patch pack are completely ineffective!

So, for a solution like Instant Run, you must need a brand new AssetManager, and then add a complete new resource bundle to replace the original AssetManager.

Fourth, find another way to restore resources.

And what is a good resource hot repair scheme?

First of all, the patch package should be small enough, like directly issuing a complete patch package is definitely not good, it takes up a lot of space.

For example, in some scenarios, we first bsdiff, make a difference to the resource package, then send out the difference package, and then synthesize the complete package at run time and then load it. This does reduce the size of the package, but there are more compositing operations at run time, consuming run time and memory. The synthesized package is also a complete package and will still take up disk space.

If you do not adopt a scheme similar to Instant Run, many implementations on the market modify the aapt themselves and renumber the patch pack resources when packaging. This involves modifying the Android SDK toolkit, which is not good for integration and will not be able to upgrade future versions of aapt.

In view of the above problems, a good resource hot repair scheme should not only ensure that the patch package is small enough, do not occupy a lot of resources at run time, but also do not invade the packaging process. We have put forward a plan that has not been realized on the market at present.

To put it simply, we construct a resource bundle whose package id is 0x66, which contains only the changed resource items, and then addAssetPath the package directly in the original AssetManager. And then it's okay. Is it really that simple?

That's right! Since the package id of the patch pack is 0x66, it does not conflict with the currently loaded 0x7f, so it can be directly added to the existing AssetManager and can be used directly. The resources in the patch package only contain the new resources that are not in the original package but those in the new package, and those that have changed the original content.

The change of resources includes increasing and decreasing 'modification'. How do we deal with them respectively?

For new resources, add the patch pack directly, and then reference it directly in the new code. There is nothing to say.

For reducing resources, we just don't need to use it, so we don't have to consider this situation, and it doesn't affect the patch pack.

For modifying resources, such as replacing a picture and so on. We regard it as a new resource, and when we put in a patch, the code will be modified accordingly, that is, we will directly change the place where the old resource id is used into the new id.

To illustrate the patch pack with a picture, it looks like this:

The green line in the figure indicates the new resources. The red line represents the resource whose content has been modified. Black lines represent resources where the content has not changed, but the id has changed. X represents a deleted resource.

4.1. new resources and their causes of id offset

As you can see, compared with the old resource bundle, the new resource bundle has added holo_grey and dropdn_item2 resources, and the new resources have been added to the patch. And assign the resource id at the beginning of 0x66.

The two new resources result in a shift in the resource id that follows them in the type to which they belong. For example, holojight, id changes from 0x7f020002 to 0x7f020003, and abc_dialog from 0x7f030004 to 0x7f030003. The location of the new resource insertion is random, depending on the order in which the xml is parsed each time the aapt is packaged. Resources that are displaced will not be added to patch, but the reference of id will be adjusted in the code of patch.

For example, in the code, this is what we write.

ImageView.setImageResource (R.drawable.holo_light)

This R.drawable.holojight is an int value, and its value is specified by aapt. It is transparent to developers. Even if you click on it, it will jump directly to the corresponding res/drawable/holo_light.jpg and cannot be viewed. However, you can use the decompiler to see that its real value is 0x7f020002. So this line of code is actually equivalent to:

ImageView.setImageResource (0x7f020002)

When a new package is typed out, the content of the holojight image and the usefulness of the code remain the same for developers. But in the new package, the same sentence, due to the id change caused by the insertion of new resources, the reference to R.drawable.holojight has become:

ImageView.setImageResource (0x7f020003)

But in fact, this situation is not a resource change, let alone a code change, so we will correct this line of code in the new package back to the original id before comparing the new and old code.

ImageView.setImageResource (0x7f020002)

Then compare the subsequent code. In this way, a change will not be detected during subsequent code comparisons.

4.2. Resources with changed content

For resources whose content has changed (activity_main of type layout, it may be that we have modified the content of the activity_main.xml file. There are also no of type string (maybe we modified the value of this string), which are all added to the patch and renamed as the new id. And the corresponding code will also change, such as

SetContentView (R.layout.activity_main)

In fact, that is,

SetContentView (0x7f030000)

Before we compare the new and old code, we will change this line of code in the new package into

SetContentView (0x6 6020000)

In this way, when comparing the code, the function in which the line of code is located will be detected to have changed. The corresponding code fixes occur at run time, referencing the correct new content resource.

4.3. Deleted resources

For deleted resources, the patch pack is not affected.

It is understandable that since the resource has been deleted, it means that it will not be used in the new code, and that the resource is left unused, which is tantamount to non-existence.

4.4. impact on type

As you can see, because all the resource items in type0x01 remain unchanged, the entire type0x01 resource is not added to the patch. This also makes the id of the following type move forward one bit. So the string in Type String Pool also needs to be modified so that the type of 0x01 points to drawable instead of the original attr.

So we can see that by simple, it means that it becomes easier to apply patch at run time.

The real complication lies in the construction of patch. We need to unpack the old and new resource bundles, parse the resources.arsc files, compare the old and new ones, and repackage them into new bundles with the new package id. As long as the package id specified in the patch pack is not 0x7f and 0x01, it can be any number below 0x7f. We specify it as 0x66 by default.

To construct such a patch resource package, you need to have a good understanding of the structure of the entire resources.arsc, parse and classify a chunk in binary form, and then reassemble the patch information into a binary chunk. A lot of this work is similar to what aapt does. In fact, when developing packaging tools, you also refer to a lot of aapt and the code that the system loads resources.

Replace AssetManager more elegantly

For later versions of Android L, it is OK to apply patch directly to the original AssetManager. And because the original AssetManager is used, a large number of reflection modification and replacement operations are completely unnecessary, which greatly improves the efficiency of loading patches.

But as mentioned earlier, in Android KK and below, addAssetPath does not load resources, so you have to reconstruct a new AssetManager, add patch, and replace the original one. So don't we have to do a lot of compatible versions and reflection replacements like Instant Run?

We have also found a more elegant way to deal with this situation without having to go to so much trouble.

Obviously, this is a function that destroys AssetManager and releases resources, so let's take a look at what it does.

As you can see, first, it destructs the AssetManager of the native layer, and then sets the reference of the AssetManager of the java layer to the AssetManager of the native layer to null.

The AssetManager destructor of the native layer destructs all its members, which releases previously loaded resources.

Now, the AssetManager of the java layer has become an empty shell. We can call its init method and reinitialize it!

This is also a native method.

In this way, when the init is executed, an AssetManager with no resources added and mResources not initialized is created in the native layer. Then we addAssetPath it, and since mResource has not been initialized, we can normally go to the logic of parsing mResources and load all the resources that add enters at this time!

Because we are directly destructing and refactoring the original AssetManager, all the original references to AssetManager objects remain unchanged, so there is no need to make tedious changes like Instant Run.

By the way, the complete replacement of resources similar to Instant Run can also be replaced in our way in the step of replacing AssetManager, which saves time, effort and worry.

This is the end of the content about "how to apply Android resource hot repair technology". Thank you for your reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report