| Interface | Description |
|---|---|
| IdProvider |
Provides IDs for resource assignment.
|
| Class | Description |
|---|---|
| ResourceDirectoryParser |
Parser that scans a resource directory for all resources and builds a
SymbolTable. |
| ResourceExtraXmlParser |
A parser used for finding all inline declaration of android resources in XML files.
|
| ResourceValuesXmlParser |
Parser that can load a
SymbolTable from a resource XML file. |
| RGeneration |
Utility class to generate
R.java files. |
| SymbolIo |
Reads and writes symbol tables to files.
|
| Enum | Description |
|---|---|
| SymbolJavaType |
| Exception | Description |
|---|---|
| ResourceDirectoryParseException |
Exception thrown when failed to parse a resource directory.
|
| ResourceValuesXmlParseException |
Exception thrown when failed to parse the resource values XML.
|
Symbols package contains classes used for parsing and processing android resources
and generating the R.java files.
The Symbol class is used to represent a single android
resource by a resource type, a name, a java type and a value. A set of Symbols with unique
type/name pairs can be represented by a SymbolTable.
Various parsers in this package were introduced to enable resource parsing without the use of AAPT for libraries. They provide means to scan through the resource directory, parse XML files in search for declared resources and find non-XML files, such as drawables.
The parsers' flow is as follows:
Library resources are passed to a ResourceDirectoryParser. There the parser goes through each of
the directories and takes different paths depending on the directories' names and their files'
types:
values directory (directory name starts with a "values" prefix and
is followed by optional qualifiers, like "-v21" or "-w820dp"), all files inside are XML
files with declared values inside of them (for example values/strings.xml). Parse
each file with a ResourceValuesXmlParser.
drawable-v21/a.png we would create a new Symbol with name "a" and type "drawable".
layout/activity_main.xml could contain an inline declaration of an
id such as {code android:id="@+id/activity_main"}. From such a line a new Symbol
should be created with a name "activity_main" and type "id". Such inline
declarations are identified by the "@+" prefix and follow a "@+type/name" pattern. This is
done by calling the parse method in ResourceExtraXmlParser
The ResourceDirectoryParser collects all Symbols from aforementioned cases and collects them in a SymbolTable which is later used
to create the R.txt and R.java files for the library as well as R.java files for all the
libraries it depends on.
It is worth mentioning that with this new flow, the new pipeline needs to also create minify
rules in the aapt_rules.txt file since we are not calling AAPT anymore. It is done by
parsing the library's android manifest, creating keep rules and writing the file in method SymbolUtils.generateMinifyKeepRules(com.android.ide.common.xml.ManifestData, java.io.File).
Naming conventions:
values directories are allowed to
contain lower- and upper-case letters, numbers and the underscore character. Dots and
colons are allowed to accommodate AAPT's old behaviour, but are deprecated and the support
for them might end in the near future.
"a.png"), the usage of two dots is only allowed for 9-patch image extension (for
example "a.9.png"). It is also worth noting that some resources can be declared
with a prefix like aapt: or android:. Following aapt's original behaviour,
we strip the type names from those prefixes. This behaviour is deprecated and might be the
support for it might end in the near future.
Example:
Assume in the resources directory we have the following sub-directories and files:
+---.drawable | +---.a.png +---.layout | +---.activity_main.xml +---.values | +---.colors.xml
Contents of activity_main,xml include a FloatingActionButton:
(...)
(...)
And colors.xml contains:
#3F51B5 #303F9F #FF4081
Then the parsers would create a following SymbolTable:
| Java type | Resource type | Resource name | ID |
|---|---|---|---|
| int | drawable | a | 1 |
| int | layout | activity_main | 2 |
| int | id | fab | 3 |
| int | color | colorPrimary | 4 |
| int | color | colorPrimaryDark | 5 |
| int | color | colorAccent | 6 |
See ResourceValuesXmlParserTest and ResourceDirectoryParserTest for more
examples of the parsers' behaviour.
Historically, processing resources using AAPT was a one-step process: the android gradle plugin merged the values files, handled overlays and placed all merged files into an intermediate directory, which was later passed to AAPT 'package' command.
Now, AAPT2 is used by default. Instead of one call to 'package', a two-step process is used: first during merging the resources are compiled by AAPT2 using the 'compile' command (this is where PNG crunching and pseudo-localization take place) and then all compiled resources are passed to AAPT2 for the 'link' command to create the AP_ file (APK file with the manifest and the resources only). R.txt and R.java files are generated at this point.
In oder to generate R.java earlier in the build process (and, in turn, to faster start java compilation tasks) the concept of partial R files was introduced. The idea is to generate a partial R.txt file for each resource during compilation and then merge them to generate the R.txt and R.java files before we reach the linking stage.
There will be two ways of generating the partial R.txt files:
The line format of the partial R.txt files will be: <access qualifier> <java type>
<symbol type> <resource name>.
For example: default int[] styleable MyStyleable.
Access qualifiers can be one of: default, public, private.
For more information about java types and symbol types look at ResourceValuesXmlParser.
Resources defined with the public keyword will have the access qualifier public in the partial R.txt, resources defined using java-symbol will have the private access qualifier, and all other resources will have the default qualifier.
If a string is declared in values/strings.xml as <string name="s1">v1</string>
then the partial R.txt will contain default int string s1. If the same string is also
marked as public in the values/public.xml as: <public type="string" name="foo"
id="0x7f000001"/> then the partial R.txt for that file will contain: public int string
foo. If both are in the same file, then the partial R.txt will contain public int string
foo as the resource will be already marked as public.
The resource IDs will be skipped as this is only for compilation, proper IDs will be generated at linking phase.
More information about resource visibility can be found in the javadoc for ResourceVisibility.
After the partial R files generation phase, we should have a set of partial R files for each source-set.
The merging strategies will depend on the type of the original resource:
default and private (or public) then it should be de-duplicated and only exist as private (or public).
To make all of these cases work, the algorithm is as follows:
Symbol).
default and the other one is private (or public), keep the non-default one.
public and the other private, abort with error. A resource
cannot be both private and public.
public resources from the table to generate the public.txt file, private resources for the private.txt and all of the resources
regardless of the access modifier to generate the R.txt.