Search code examples
androidandroid-libraryr.java-fileaaptaar

How does the build system get google_play_services_version from the .aar?


Can anyone help me understand how the resource merging works when using the google-play-services.aar?

An AndroidManifest.xml that implements google play services might have something like below:

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

If using google-play-services_lib, the google_play_services_version integer is found in res/values/version.xml and that manifest requirement is satisfied by passing the google-play-services/res folder to the aapt tool with the -S flag.

But when unzipping the google-play-services.aar I do not see that xml file and simply passing the unzipped .aar's res folder to aapt brings up the related complaint about No resource found.

How does the application that depends on the .aar get the google_play_services_version integer into its R.java?


Solution

  • After poking at this, I have found an answer that is close enough for my purposes.

    Since Play Services 6.5 you can now selectively add certain Google Play Services modules instead of the monolithic library it used to be. The google_play_services_version resource is defined in the play-service submodules.

    When you add a dependency to a gradle build, it could look like this:

    dependencies {
        compile 'com.google.android.gms:play-services:+'
    }
    

    Using this, gradle pulls in the .aar for all the gms modules from the m2 repo installed in the SDK.

    I couldn't find the version number in the base play-services package when I unpacked it by hand which is what prompted this question. But then I saw that the play-services dependency was actually pulling in several other play-services modules.

    This is made explicit by the .pom in the SDK m2 repo. The pom at ./extras/google/m2repository/com/google/android/gms/play-services/7.0.0/play-services-7.0.0.pom shows the other plays-services modules as deps:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.google.android.gms</groupId>
      <artifactId>play-services</artifactId>
      <version>7.0.0</version>
      <packaging>aar</packaging>
      <dependencies>
        <dependency>
          <groupId>com.google.android.gms</groupId>
          <artifactId>play-services-ads</artifactId>
          <version>7.0.0</version>
          <scope>compile</scope>
          <type>aar</type>
        </dependency>
    ...
        <dependency>
          <groupId>com.google.android.gms</groupId>
          <artifactId>play-services-wearable</artifactId>
          <version>7.0.0</version>
          <scope>compile</scope>
          <type>aar</type>
        </dependency>
      </dependencies>
    </project>
    

    The various sub-modules have the google_play_services_version in their R.txt files.

    int integer google_play_services_version 0x7f050000
    

    This is used as a classpath resource and makes its way into the various R.java files for each gms module. It is then added to the final AndroidManifest.xml for the entire package during the manifestMerging step.