-
-
Save cmelchior/6988275 to your computer and use it in GitHub Desktop.
<?xml version="1.0" encoding="utf-8"?> | |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
package="com.trifork.example" | |
android:installLocation="auto" | |
android:versionName="@string/client_info" > | |
<!-- ... --> | |
<application | |
android:hardwareAccelerated="true" | |
android:icon="@drawable/icon" | |
android:label="@string/app_name" | |
android:theme="@style/Theme.Standard" > | |
<!-- ... --> | |
<provider | |
android:name="path.to.provider.ProviderImpl" | |
android:authorities=".res-auto.path.to.provider.ProviderImpl" | |
android:exported="false" > | |
</provider> | |
<provider | |
android:name="path.to.provider.ProviderImpl" | |
android:authorities="@string/provider_auth" | |
android:exported="false" > | |
</provider> | |
</application> | |
</manifest> |
buildscript { | |
repositories { | |
mavenCentral() | |
} | |
dependencies { | |
classpath 'com.android.tools.build:gradle:0.6.+' | |
} | |
} | |
apply plugin: 'android' | |
apply from: './build_extras.gradle' | |
repositories { | |
mavenCentral() | |
} | |
android { | |
compileSdkVersion 18 | |
buildToolsVersion "18.0.1" | |
defaultConfig { | |
minSdkVersion 10 | |
targetSdkVersion 18 | |
} | |
} | |
dependencies { | |
} |
/** | |
* Version 1.1. | |
* | |
* Add support for installing multiple variants of the same app which have a | |
* content provider. Do this by overriding occurrences of ".res-auto" in | |
* android:authorities with the current package name (which should be unique) | |
* | |
* V1.0 : Initial version | |
* V1.1 : Support for ".res-auto" in strings added, | |
* eg. use "<string name="auth">.res-auto.path.to.provider</string>" | |
* | |
*/ | |
def overrideProviderAuthority(buildVariant) { | |
def flavor = buildVariant.productFlavors.get(0).name | |
def buildType = buildVariant.buildType.name | |
def pathToManifest = "${buildDir}/manifests/${flavor}/${buildType}/AndroidManifest.xml" | |
def ns = new groovy.xml.Namespace("http://schemas.android.com/apk/res/android", "android") | |
def xml = new XmlParser().parse(pathToManifest) | |
def variantPackageName = xml.@package | |
// Update all content providers | |
xml.application.provider.each { provider -> | |
def newAuthorities = provider.attribute(ns.authorities).replaceAll('.res-auto', variantPackageName) | |
provider.attributes().put(ns.authorities, newAuthorities) | |
} | |
// Save modified AndroidManifest back into build dir | |
saveXML(pathToManifest, xml) | |
// Also make sure that all strings with ".res-auto" are expanded automagically | |
def pathToValues = "${buildDir}/res/all/${flavor}/${buildType}/values/values.xml" | |
xml = new XmlParser().parse(pathToValues) | |
xml.findAll{it.name() == 'string'}.each{item -> | |
if (!item.value().isEmpty() && item.value()[0].startsWith(".res-auto")) { | |
item.value()[0] = item.value()[0].replace(".res-auto", variantPackageName) | |
} | |
} | |
saveXML(pathToValues, xml) | |
} | |
def saveXML(pathToFile, xml) { | |
def writer = new FileWriter(pathToFile) | |
def printer = new XmlNodePrinter(new PrintWriter(writer)) | |
printer.preserveWhitespace = true | |
printer.print(xml) | |
} | |
// Post processing of AndroidManifest.xml for supporting provider authorities | |
// across build variants. | |
android.applicationVariants.all { variant -> | |
variant.processManifest.doLast { | |
overrideProviderAuthority(variant) | |
} | |
} |
The problem I have with this is it works during a rebuild, but if I attempt to deploy via the RUN button in the Android Studio GUI the strings in the values.xml file appear to get re-replaced with the original values (the manifest file is still correctly processed).
I'm executing this script during variant.processResources.doLast as well as processManifest, and I added some logging so I can tell it's still getting executed - but the strings will not have replaced ".res-auto" once it's deployed (If I examine values.xml after a Build->Rebuild Project, it's correct, but if I examine it after I hit Run it has the wrong string values - however, I can see that the script is running in the processResources phase in the gradle console.)
EDIT: this is with Gradle 1.9
This works very well for the AndroidManifest provider authorities substitution. However for each of my three providers classes I declare unique authorities.
private static final String IDENTITY_AUTHORITY = "com.company.android.identityprovider";
private static final String CUSTOMER_AUTHORITY = "com.company.android.customerprovider";
private static final String BLABLA_AUTHORITY = "com.company.android.blablaprovider";
I found out the hard way that these must be named the same as the ones in the AndroidManifest.xml for it to work.
Any ideas on how to best substitute these too?
I tried using BuildConfigLine but failed miserably :)
OK, I still haven't got the modified value.xml to make it into a deployed build with the latest Android Studio plugin/Gradle, but I have got the process working other than that.
The alternative I'm using is simply to define something like:
public final static String AUTHORITY = BuildConfig.PACKAGE_NAME + ".MyProviderName";
in my provider class, and using the direct form of .res-auto in the manifest:
<provider android:name=".MyProviderName" android:authorities=".res-auto.MyProviderName" />
which works fine. Since the provider I'm specifically using is a SearchSuggestionProvider, I also tried adding a new section to overrideProviderAuthority that processes searchable configuration xml files, but this suffers from the same issue as values.xml - the modified version is getting replaced with the original prior to deployment.
I do not, as yet, have a workaround for that...
@influenced, in searchable.xml
you can use something like
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/search_hint"
android:searchSuggestAuthority="@string/search_provider"
android:searchSuggestSelection=" ?"
>
</searchable>
and add to your strings.xml
<string name="search_provider">.res-auto.util.LocationSuggestionProvider</string>
But I do have the same issue with the values being overwritten when I use IntelliJ.
That's what I'd like to do - and what I originally did - but by the time it gets onto the device, it'll have been reset to .res-auto again, so the OS won't be able to find that provider.
I spent way too much time on this, but I finally have a version that works. Please check out https://gist.github.com/paour/9189462
@influenced: do you manage to get .res-auto replaced when you hit run/debug?
Please see my fork for a small fix.
Prevent exceptions for cases like
<string name="with_markup"><b>Warning</b>This will crash the build</string>