preface

In the introduction of resource compilation process in Android Reverse Analysis (2) Packaging and Installation of APK, THE author mentioned the concept of overlay. A friend who was impressed by the article every day asked me what overlay was. The author thought about it. Indeed, many students do not know this concept very well. They searched the introduction on the Internet and hardly saw any explanation of this concept, only Lao Luo’s blog mentioned it

– mOverlay: overlapping packages of resources being compiled. What is the concept of overlapping packages? Suppose we are compiling package-1, we can set another package-2 to tell AAPT that if package-2 defines the same resources as package-1, Replace the resources defined in package-1 with those defined in package-2. With this Overlay mechanism, we can customize resources without losing generality.

So how do we use overlapping packages? Where can it be used and what convenience can it bring?

The test source for this article has been uploaded: ResourceOverlayDemo.

aapt overlay

Aapt = aapt = aapt = aapt = aapt

Usage: aapt l[ist] [-v] [-a] file.{zip,jar,apk} List contents of Zip-compatible archive. aapt d[ump] [--values] [--include-meta-data] WHAT file.{apk} [asset [asset ...]] ... aapt p[ackage] [-d][-f][-m][-u][-v][-x][-z][-M AndroidManifest.xml] \ ... [--utf16] [--auto-add-overlay] \ ... [-S resource-sources [-S resource-sources ...]] \ [-F apk-file] [-J R-file-dir] \ ... Package the android resources. It will read assets and resources that are supplied with the -M -A -S or raw-files-dir arguments. The -J -P -F and -R options control which files are output. ... Modifiers: ... Android. jar -i add an existing package to base include set android.jar -i add an existing package to base include set Overlay can be specified with -s  -S directory in which to find resources. Multiple directories will be scanned and the first match found (left to right)  will take precedence. ... Auto-add-overlay Automatically add resources that are only in overlays....Copy the code

For example

aapt package \
-M AndroidManifest.xml \
-m -J gen \
-S src/com/example/res \
-S src/com/example/ui/res
Copy the code

SRC /com/example/res/UI /res/SRC /com/example/ UI /res/SRC /com/example/ UI /res/SRC /com/example/ UI /res For example, if both values/string.xml folders have a description of the same string ID, the former string will be used in the end.

And then let’s see what auto-add-overlay does,

If SRC /com/example/ UI /res defines the resource string a, but SRC /com/example/res does not have the string, then we will get an error because the base package does not have that resource. So you need to add –auto-add-overlay, and it automatically adds all the new resources.

So overlay is basically what it is.

Gradle practice

aaptOptions

Google’s official documentation says as much as it doesn’t. Create a new Testapp project using the template of AS. Create two res folders and place two strings. XML files in each folder.

├ ─ ─ res │ ├ ─ ─ drawable │ ├ ─ ─ layout │ │ ├ ─ ─ activity_main. XML │ │ └ ─ ─ content_main. XML │ ├ ─ ─ menu │ │ └ ─ ─ menu_main. The XML │ ├ ─ ─ mipmap - xxxhdpi │ │ └ ─ ─ ic_launcher. PNG │ └ ─ ─ values │ ├ ─ ─ colors. The XML │ ├ ─ ─ dimens. XML │ ├ ─ ─ strings. The XML │ └ ─ ─ Styles. XML ├ ─ ─ res2 │ └ ─ ─ values │ └ ─ ─ strings. The XML └ ─ ─ res3 └ ─ ─ values └ ─ ─ strings. The XMLCopy the code

Res2 and res3 define a string hehe with values hehe res2 and hehe res3, respectively.

The content_main.xml TextView uses hehe (the original Hello World). Of course, there is an error in as because res2 and RES3 are not marked as resource folders.

In build.gradle of module:

android { ... aaptOptions { additionalParameters '-S', '/Users/yifan/dev/github/Testapp/app/src/main/res3', '-S', '/Users/yifan/dev/github/Testapp/app/src/main/res2', '--auto-add-overlay' noCompress 'foo', 'bar' ignoreAssetsPattern '! .svn:! .git:! .ds_store:! *.scc:.*:_*:! CVS:! thumbs.db:! picasa.ini:! * ~ '}... }Copy the code

Then we try to compile:

All input files are considered out-of-date for incremental task ':app:processDebugResources'. Starting process 'command '/ Users/yifan/dev/SDK/adt - bundle - MAC - SDK/build - the tools / 23.0.2 aapt' '. The Working directory: /Users/yifan/dev/github/Testapp/app Command: /Users/yifan/dev/ SDK /adt-bundle-mac-sdk/build-tools/23.0.2/aapt package -f --no-crunch -i /Users/yifan/dev/sdk/adt-bundle-mac-sdk/platforms/android-23/android.jar -M /Users/yifan/dev/github/Testapp/app/build/intermediates/manifests/full/debug/AndroidManifest.xml -S /Users/yifan/dev/github/Testapp/app/build/intermediates/res/merged/debug -A /Users/yifan/dev/github/Testapp/app/build/intermediates/assets/debug -m -J /Users/yifan/dev/github/Testapp/app/build/generated/source/r/debug -F /Users/yifan/dev/github/Testapp/app/build/intermediates/res/resources-debug.ap_ --debug-mode --custom-package cn.zhaiyifan.testapp -0 apk -S /Users/yifan/dev/github/Testapp/app/src/main/res2 --output-text-symbols /Users/yifan/dev/github/Testapp/app/build/intermediates/symbols/debug Successfully started process 'command '/ Users/yifan/dev/SDK/adt - bundle - MAC - SDK/build - the tools / 23.0.2 aapt' ' /Users/yifan/dev/github/Testapp/app/build/intermediates/res/merged/debug/values-af/values-af.xml:3 : AAPT: Resource at abc_action_bar_home_description appears in overlay but not in the base package; use to add. ... . All kinds of similar error reports /usr/local/google/buildbot/src/googleplex-android/mnc-supportlib-release/frameworks/support/v7/appcompat/res/color/switc h_thumb_material_light.xml:19 : AAPT: No resource found that matches the given name (at 'color' with value '@color/switch_thumb_normal_material_light'). App: processDebugResources FAILED: app: processDebugResources (Thread [main, 5, the main]) completed. Took 10.493 secs.Copy the code

Seeing this, I guess I know what the problem is… Add –auto-add-overlay to additionalParameters and run successfully.

In the center of the screen, hehe res3 is displayed, and after swapping the -s order, it becomes Hehe res2, in accordance with the first matching principle we discussed in section 1.

Not only string, anim, layout, and so on can be dynamically specified using overlapping packages.

Resources combined

It has to do with AAPT overlay, but with slightly different scenarios.

Google dedicated a page to this in the Android Tools Project Site: Resource Merging.

In past compilation systems, resource merging was done by passing aAPT a list of resource folders that served as overlapping packages, plus — auto-add-overlay to ensure that new resources in the overlapping packages were automatically added (the default behavior only overrides existing resources).

One of the goals of the basic Gradle compilation system is to provide greater flexibility, while another frequently asked feature is the ability to have multiple resource folders. Aapt can’t handle this, so the new build system introduces a new merge mechanism that goes beyond AAPT, generating a separate, merged resource folder and making it available to AAPT. This merge mechanism has the advantage of increments, both because of Gradle’s input/output change detection and because of the way it is implemented (you can remerge using only a single change file).

The combined resources come from three sources:

  1. Main resources, associated with main sourceSet, are mostly located in SRC /main/res
  2. Variant overlap package, from Build Type and Flavor(S).
  3. Library projects rely on providing resources through their AAR bundles.

priority

The priority is: BuildType -> Flavor -> main -> Dependencies.

This means that if a resource exists in both Build Type and main, the resource in Build Type will be used.

Note that the merged scope, the same resource (type, name) but different identifier, is treated separately.

If SRC /main/res has:

  • res/layout/foo.xml
  • Res /layout-land/foo. XML while SRC /debug/res has:
  • res/layout/foo.xml

The merged resource folder will contain the default foo. XML from SRC /debug/res, but the landscape version will be SRC /main/res.

PS: Android resources have 19 dimensions. See Table 2 of Grouping Resource Types. The 19 dimensions uniquely specify one Resource (qualifier). There were 18 dimensions mentioned in luo’s resource introduction blog, now it is 19 because of the Round Screen dimension, which describes Android Wear, added to API 23.

Process multiple resource folders

Each sourceSet can define multiple resource folders, for example:

android.sourceSets {
   main.res.srcDirs = ['src/main/res', 'src/main/res2']
}
Copy the code

In this case, both resource folders have the same priority, that is, if a resource is declared in both folders, the merge will report an error.

The priority order that Library depends on

Depending on the dependencies passed, the actual set of Library items is treated by the project as a graph rather than a tiled list, and then the merge mechanism only processes a flat priority list.

If we consider the dependency of the following example: items -> A, B (meaning A has higher priority than B) A -> C, D B -> C then the final priority list is A, D, B, C, while ensuring that A and B can override C.

A small test

Let’s go ahead and do a little test based on the project that we set up earlier. Add the res2 folder to sourceSet and finally build. Gradle’s Android domain looks like this:

Android {compileSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig {applicationId "cn.zhaiyifan.testApp" MinSdkVersion 14 targetSdkVersion 23 versionCode 1 versionName "1.0"} buildTypes {release {minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } aaptOptions { additionalParameters '-S', '/Users/yifan/dev/github/Testapp/app/src/main/res3', '-S', '/Users/yifan/dev/github/Testapp/app/src/main/res2', '--auto-add-overlay' noCompress 'foo', 'bar' ignoreAssetsPattern '! .svn:! .git:! .ds_store:! *.scc:.*:_*:! CVS:! thumbs.db:! picasa.ini:! *~' } android.sourceSets { main.res.srcDirs = ['src/main/res', 'src/main/res2'] } }Copy the code

After the operation found interface shows hehe res2, in line with expectations, because res2 have merged and res, so first find the build/intermediates/res/merged under the/debug string, use res3.

Usage scenarios

Different buildTypes, packages under channels, using different resources, doing some customization without breaking into the logic of the code itself. Resource consolidation helps group resources, such as by business.

conclusion

We learned about Android AAPT Overlay mechanism and resource consolidation under Gradle, and wrote and ran a demo to verify the results of resource application.

reference

  • Android.googlesource.com/platform/fr…
  • Blog.csdn.net/luoshengyan…
  • Tools.android.com/tech-docs/n…