デバッグアプリにパッケージ名のサフィックスを追加するようにGradleを設定したので、使用しているリリースバージョンと1台の電話でデバッグバージョンを使用できます。私はこれを参照していました: http://tools.Android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types
私のbuild.gradleファイルは次のようになります。
...
Android
{
...
buildTypes
{
debug
{
packageNameSuffix ".debug"
versionNameSuffix " debug"
}
}
}
アプリでContentProviderの使用を開始するまで、すべてが正常に機能します。私は得る:
Failure [INSTALL_FAILED_CONFLICTING_PROVIDER]
これは、2つのアプリ(リリースとデバッグ)が同じContentProvider権限を登録しているために発生することを理解しています。
これを解決する可能性があると思います。私が正しく理解していれば、ビルド時に使用するさまざまなファイルを指定できるはずです。それから、異なるリソースファイルに(およびマニフェストから権限を文字列リソースとして設定して)異なる権限を配置し、デバッグビルドに異なるリソースを使用するようにGradleに指示できるはずです。それは可能ですか?はいの場合、それを達成する方法に関するヒントは素晴らしいでしょう!
または、Gradleを使用してマニフェストを直接変更することは可能ですか? 1つのデバイスでContentProviderを使用して同じアプリを実行する方法に関する他のソリューションは、いつでも歓迎します。
既存の答えはどれも私を満足させませんでしたが、Libertyは近かったです。だからこれは私がそれをやっている方法です。まず第一に、私は一緒に仕事をしています:
私の目標は、同じDebug
を使用して、同じデバイスでRelease
バージョンとともにContentProvider
バージョンを実行することです。
アプリのbuild.gradleで、デバッグビルドのサフィックスを設定します。
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
AndroidManifest.xml file set ContentProvider
のAndroid:authorities
プロパティ:
<provider
Android:name="com.example.app.YourProvider"
Android:authorities="${applicationId}.provider"
Android:enabled="true"
Android:exported="false" >
</provider>
codeで、実装の必要な場所で使用できるAUTHORITY
プロパティを設定します。
public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".provider";
ヒント:以前のBuildConfig.PACKAGE_NAME
もう一度、現在のセットアップから始めます。
基本的に、異なるビルド用にいくつかの値をカスタマイズする必要がある場合は、build.gradleファイルからそれを行うことができます。
BuildConfig.Java
クラスからアクセスしますリソースの代替として、個別のbuildTypeまたはフレーバーディレクトリを作成し、それらの中のXMLまたは値をオーバーライドできます。ただし、以下の例では使用しません。
build.gradleファイルに次を追加します。
defaultConfig {
resValue "string", "your_authorities", applicationId + '.provider'
resValue "string", "account_type", "your.syncadapter.type"
buildConfigField "String", "ACCOUNT_TYPE", '"your.syncadapter.type"'
}
buildTypes {
debug {
applicationIdSuffix ".debug"
resValue "string", "your_authorities", defaultConfig.applicationId + '.debug.provider'
resValue "string", "account_type", "your.syncadapter.type.debug"
buildConfigField "String", "ACCOUNT_TYPE", '"your.syncadapter.type.debug"'
}
}
BuildConfig.Java classに結果が表示されます
public static final String ACCOUNT_TYPE = "your.syncadapter.type.debug";
およびbuild/generated/res/generated/debug/values/generated.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Automatically generated file. DO NOT MODIFY -->
<!-- Values from default config. -->
<item name="account_type" type="string">your.syncadapter.type.debug</item>
<item name="authorities" type="string">com.example.app.provider</item>
</resources>
authenticator.xml build.gradleファイルで指定されたリソースを使用します
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:accountType="@string/account_type"
Android:icon="@drawable/ic_launcher"
Android:smallIcon="@drawable/ic_launcher"
Android:label="@string/app_name"
/>
syncadapter.xmlで同じリソースを再度使用し、@ string/authoritiesも
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:contentAuthority="@string/authorities"
Android:accountType="@string/account_type"
Android:userVisible="true"
Android:supportsUploading="false"
Android:allowParallelSyncs="false"
Android:isAlwaysSyncable="true"
/>
Tip: autocompletion(Ctrl + Space)はこれらの生成されたリソースに対して機能しないため、手動で入力する必要があります
新しいAndroidビルドシステムのヒント:ContentProvider機関の名前変更
皆さんは新しいAndroid Gradleベースのビルドシステムについて聞いたことがあると思います。正直に言って、この新しいビルドシステムは、以前のものと比較して大きな前進です。まだ最終版ではありません(この記事の執筆時点では、最新バージョンは0.4.2です)が、ほとんどのプロジェクトで既に安全に使用できます。
プロジェクトの大部分をこの新しいビルドシステムに個人的に切り替えましたが、特定の状況ではサポートが不足しているため、いくつかの問題がありました。その1つは、ContentProvider権限の名前変更のサポートです
新しいAndroidビルドシステムを使用すると、ビルド時にパッケージ名を変更するだけで、さまざまな種類のアプリに対応できます。この改善の主な利点の1つは、アプリの2つの異なるバージョンを同じデバイスに同時にインストールできることです。例えば:
Android {
compileSdkVersion 17
buildToolsVersion "17.0.0"
defaultConfig {
packageName "com.cyrilmottier.Android.app"
versionCode 1
versionName "1"
minSdkVersion 14 // Listen to +Jeff Gilfelt advices :)
targetSdkVersion 17
}
buildTypes {
debug {
packageNameSuffix ".debug"
versionNameSuffix "-debug"
}
}
}
このようなGradle構成を使用すると、2つの異なるAPKを組み立てることができます。
•com.cyrilmottier.Android.app.debugパッケージ名のデバッグAPK•com.cyrilmottier.Android.appパッケージ名のリリースAPK
それに関する唯一の問題は、両方が同じ権限を持つContentProviderを公開している場合、2つのAPKを同時にインストールできないことです。かなり論理的には、現在のビルドタイプに応じて権限を変更する必要がありますが、これはGradleビルドシステムではサポートされていません(まだ?...まもなく修正されると確信しています)。だからここに行く方法です:
まず、プロバイダーAndroidマニフェストContentProvider宣言を適切なビルドタイプに移動する必要があります。それをするために私達は単に持っている:
src/debug/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="com.cyrilmottier.Android.app"
Android:versionCode="1"
Android:versionName="1">
<application>
<provider
Android:name=".provider.Provider1"
Android:authorities="com.cyrilmottier.Android.app.debug.provider"
Android:exported="false" />
</application>
</manifest>
src/release/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="com.cyrilmottier.Android.app"
Android:versionCode="1"
Android:versionName="1">
<application>
<provider
Android:name=".provider.Provider1"
Android:authorities="com.cyrilmottier.Android.app.provider"
Android:exported="false" />
</application>
</manifest>
Src/main /のAndroidManifest.xmlからContentProvider宣言を削除してください。Gradleは、同じ名前で権限が異なるContentProviderをマージする方法を知らないためです。
最後に、コード内の機関にアクセスする必要があります。これは、BuildConfigファイルとbuildConfigメソッドを使用して非常に簡単に実行できます。
Android {
// ...
final PROVIDER_DEBUG = "com.cyrilmottier.Android.app.debug.provider"
final PROVIDER_RELEASE = "com.cyrilmottier.Android.app.provider"
buildTypes {
debug {
// ...
buildConfigField "String", "PROVIDER_AUTHORITY", PROVIDER_DEBUG
}
release {
buildConfigField "String", "PROVIDER_AUTHORITY", PROVIDER_RELEASE
}
}
}
この回避策のおかげで、ProviderContractでBuildConfig.PROVIDER_AUTHORITYを使用して、アプリの2つの異なるバージョンを同時にインストールできます。
Google+独自: https://plus.google.com/u/0/118417777153109946393/posts/EATUmhntaCQ
Cyrilの例は、ビルドタイプが少数しかない場合はうまく機能しますが、多くの異なるAndroidManifest.xmlを維持する必要があるため、ビルドタイプや製品フレーバーが多い場合はすぐに複雑になります。
私たちのプロジェクトは、3つの異なるビルドタイプと合計18のビルドバリアントの6つのフレーバーで構成されているため、代わりにContentProvider機関に「.res-auto」のサポートを追加しました。
/**
* 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)
}
}
サンプルコードはこちらにあります: https://Gist.github.com/cmelchior/6988275
プラグインバージョン0.8.3(実際には0.8.1ですが、正常に機能していませんでした)から、ビルドファイル内でリソースを定義できるため、文字列ファイルや追加のデバッグ/リリースを作成する必要がないため、よりクリーンなソリューションになります。フォルダー。
build.gradle
Android {
buildTypes {
debug{
resValue "string", "authority", "com.yourpackage.debug.provider"
}
release {
resValue "string", "authority", "com.yourpackage.provider"
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="com.yourpackage"
Android:versionCode="1"
Android:versionName="1">
<application>
<provider
Android:name=".provider.Provider1"
Android:authorities="@string/authority"
Android:exported="false" />
</application>
</manifest>
誰かが言及したかどうかはわかりません。実際、Android gradleプラグイン0.10+の後、マニフェストの統合により、この機能の公式サポートが提供されます。 http://tools.Android.com/tech-docs/new-build-system/ user-guide/manifest-merger
AndroidManifest.xmlでは、次のように$ {packageName}を使用できます。
<provider
Android:name=".provider.DatabasesProvider"
Android:authorities="${packageName}.databasesprovider"
Android:exported="true"
Android:multiprocess="true" />
そして、build.gradleには次のものがあります。
productFlavors {
free {
packageName "org.pkg1"
}
pro {
packageName "org.pkg2"
}
}
完全な例をご覧ください: https://code.google.com/p/anymemo/source/browse/AndroidManifest.xml#152
そしてここ: https://code.google.com/p/anymemo/source/browse/build.gradle#41
Xmlで${applicationId}
プレースホルダーを使用し、コードでBuildConfig.APPLICATION_ID
プレースホルダーを使用します。
ビルドスクリプトを拡張して、マニフェスト以外のxmlファイルのプレースホルダーを有効にする必要があります。ビルドバリアントごとにソースディレクトリを使用して、異なるバージョンのxmlファイルを提供できますが、メンテナンスは非常に迅速に面倒になります。
AndroidManifest.xml
マニフェストでそのまま使用できるapplicationIdプレースホルダーを使用できます。プロバイダーを次のように宣言します。
<provider
Android:name=".provider.DatabaseProvider"
Android:authorities="${applicationId}.DatabaseProvider"
Android:exported="false" />
${applicationId}
ビットに注意してください。これは、ビルド時に、ビルドされているビルドバリアントの実際のapplicationIdに置き換えられます。
コード内
ContentProviderは、コードで権限文字列を構築する必要があります。 BuildConfigクラスを使用できます。
public class DatabaseContract {
/** The authority for the database provider */
public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".DatabaseProvider";
// ...
}
BuildConfig.APPLICATION_ID
ビットに注意してください。これは、ビルドされるビルドバリアントの実際のapplicationIdを持つ生成されたクラスです。
res/xml /ファイル、例えばsyncadapter.xml、accountauthenticator.xml
同期アダプタを使用する場合は、res/xml /ディレクトリ内のxmlファイルでContentProviderおよびAccountManagerのメタデータを提供する必要があります。ここではapplicationIdプレースホルダーはサポートされていません。ただし、自分でビルドスクリプトを拡張して、ハッキングすることはできます。
<sync-adapter xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:accountType="${applicationId}"
Android:allowParallelSyncs="false"
Android:contentAuthority="${applicationId}.DatabaseProvider"
Android:isAlwaysSyncable="true"
Android:supportsUploading="true"
Android:userVisible="true" />
<account-authenticator xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:accountType="${applicationId}"
Android:icon="@drawable/ic_launcher"
Android:label="@string/account_authenticator_label"
Android:smallIcon="@drawable/ic_launcher" />
繰り返しますが、${applicationId}
に注意してください。これは、以下のgradleスクリプトをモジュールのルートに追加し、build.gradleから適用する場合にのみ機能します。
build.gradle
モジュールbuild.gradleスクリプトから追加のビルドスクリプトを適用します。適切な場所は、Android gradleプラグインの下です。
apply plugin: 'com.Android.application'
apply from: './build-processApplicationId.gradle'
Android {
compileSdkVersion 21
// etc.
build-processApplicationId.gradle
以下は、res/xml /プレースホルダービルドスクリプトの作業ソースです。より良い文書化されたバージョンは github で利用可能です。改善と拡張は大歓迎です。
def replace(File file, String target, String replacement) {
def result = false;
def reader = new FileReader(file)
def lines = reader.readLines()
reader.close()
def writer = new FileWriter(file)
lines.each { line ->
String replacedLine = line.replace(target, replacement)
writer.write(replacedLine)
writer.write("\n")
result = result || !replacedLine.equals(line)
}
writer.close()
return result
}
def processXmlFile(File file, String applicationId) {
if (replace(file, "\${applicationId}", applicationId)) {
logger.info("Processed \${applicationId} in $file")
}
}
def processXmlDir(File dir, String applicationId) {
dir.list().each { entry ->
File file = new File(dir, entry)
if (file.isFile()) {
processXmlFile(file, applicationId)
}
}
}
Android.applicationVariants.all { variant ->
variant.mergeResources.doLast {
def applicationId = variant.mergedFlavor.applicationId + (variant.buildType.applicationIdSuffix == null ? "" : variant.buildType.applicationIdSuffix)
def path = "${buildDir}/intermediates/res/${variant.dirName}/xml/"
processXmlDir(new File(path), applicationId)
}
}
Strings.xml
私の意見では、リソース文字列のプレースホルダーサポートを追加する必要はありません。上記のユースケースでは、少なくとも必要ありません。ただし、res/xml /ディレクトリ内のプレースホルダーだけでなく、res/values /ディレクトリ内のプレースホルダーも置き換えるようにスクリプトを簡単に変更できます。
私はむしろシリルとrciovatiの混合物を好むでしょう。私はもっと簡単だと思う、あなたは2つの変更しかありません。
build.gradle
は次のようになります。
Android {
...
productFlavors {
production {
packageName "package.name.production"
resValue "string", "authority", "package.name.production.provider"
buildConfigField "String", "AUTHORITY", "package.name.production.provider"
}
testing {
packageName "package.name.debug"
resValue "string", "authority", "package.name.debug.provider"
buildConfigField "String", "AUTHORITY", "package.name.debug.provider"
}
}
...
}
そしてAndroidManifest.xml
:
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="package.name" >
<application
...>
<provider Android:name=".contentprovider.Provider" Android:authorities="@string/authority" />
</application>
</manifest>
gradle.build
Android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.example.awsomeapp"
minSdkVersion 9
targetSdkVersion 23
versionCode 1
versionName "1.0.0"
}
productFlavors
{
prod {
applicationId = "com.example.awsomeapp"
}
demo {
applicationId = "com.example.awsomeapp.demo"
versionName = defaultConfig.versionName + ".DEMO"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
debuggable false
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.txt'
}
debug {
applicationIdSuffix ".debug"
versionNameSuffix = ".DEBUG"
debuggable true
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
// rename the apk
def file = output.outputFile;
def newName;
newName = file.name.replace(".apk", "-" + defaultConfig.versionName + ".apk");
newName = newName.replace(project.name, "awsomeapp");
output.outputFile = new File(file.parent, newName);
}
//Generate values Content Authority and Account Type used in Sync Adapter, Content Provider, Authenticator
def valueAccountType = applicationId + '.account'
def valueContentAuthority = applicationId + '.authority'
//generate fields in Resource string file generated.xml
resValue "string", "content_authority", valueContentAuthority
resValue "string", "account_type", valueAccountType
//generate fields in BuildConfig class
buildConfigField "String", "ACCOUNT_TYPE", '"'+valueAccountType+'"'
buildConfigField "String", "CONTENT_AUTHORITY", '"'+valueContentAuthority+'"'
//replace field ${valueContentAuthority} in AndroidManifest.xml
mergedFlavor.manifestPlaceholders = [ valueContentAuthority: valueContentAuthority ]
}
}
authenticator.xml
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:accountType="@string/account_type"
Android:icon="@drawable/ic_launcher"
Android:label="@string/app_name"
Android:smallIcon="@drawable/ic_launcher" />
sync_adapter.xml
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:contentAuthority="@string/content_authority"
Android:accountType="@string/account_type"
Android:userVisible="true"
Android:allowParallelSyncs="false"
Android:isAlwaysSyncable="true"
Android:supportsUploading="true"/>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:versionCode="1" Android:versionName="1.0.0" package="com.example.awsomeapp">
<uses-permission Android:name="Android.permission.GET_ACCOUNTS"/><!-- SyncAdapter and GCM requires a Google account. -->
<uses-permission Android:name="Android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission Android:name="Android.permission.USE_CREDENTIALS"/>
<!-- GCM Creates a custom permission so only this app can receive its messages. -->
<permission Android:name="${applicationId}.permission.C2D_MESSAGE" Android:protectionLevel="signature"/>
<uses-permission Android:name="${applicationId}.permission.C2D_MESSAGE"/>
<application....
.......
<!-- Stub Authenticator -->
<service
Android:name="com.example.awsomeapp.service.authenticator.CAuthenticatorService"
Android:exported="true">
<intent-filter>
<action Android:name="Android.accounts.AccountAuthenticator"/>
</intent-filter>
<meta-data Android:name="Android.accounts.AccountAuthenticator" Android:resource="@xml/authenticator"/>
</service>
<!-- -->
<!-- Sync Adapter -->
<service
Android:name="com.example.awsomeapp.service.sync.CSyncService"
Android:exported="true"
Android:process=":sync">
<intent-filter>
<action Android:name="Android.content.SyncAdapter"/>
</intent-filter>
<meta-data Android:name="Android.content.SyncAdapter" Android:resource="@xml/sync_adapter" />
</service>
<!-- -->
<!-- Content Provider -->
<provider Android:authorities="${valueContentAuthority}"
Android:exported="false"
Android:name="com.example.awsomeapp.database.contentprovider.CProvider">
</provider>
<!-- -->
</application>
</manifest>
コード:
public static final String CONTENT_AUTHORITY = BuildConfig.CONTENT_AUTHORITY;
public static final String ACCOUNT_TYPE = BuildConfig.ACCOUNT_TYPE;
この問題(および他の同様の問題)に対処するGithubサンプルプロジェクトで、Cyrilとは少し異なる方法でブログ投稿を書いています。
http://brad-Android.blogspot.com/2013/08/Android-gradle-building-unique-build.html
残念ながら、Androidプラグインの現在のバージョン(0.4.1)は、これに対する適切なソリューションを提供していないようです。私はまだこれを試す時間がありませんでしたが、この問題の可能な回避策は、文字列リソース@string/provider_authority
を使用し、それをマニフェストで使用することです:Android:authority="@string/provider_authority"
。その後、権限をオーバーライドする各ビルドタイプのresフォルダーにres/values/provider.xml
があります。この場合、これはsrc/debug/res
になります。
私はその場でxmlファイルを生成することを検討しましたが、再び、プラグインの現在のバージョンにはそれに対する良いフックはないようです。ただし、機能のリクエストを送信することをお勧めします。同じ問題に遭遇する人が増えると想像できます。
この投稿の答えは私のために機能します。
私は3つの異なるフレーバーを使用しているため、kevinrschultzが言ったように、各フレーバーのコンテンツプロバイダーで3つのマニフェストを作成します。
productFlavors {
free {
packageName "your.package.name.free"
}
paid {
packageName "your.package.name.paid"
}
other {
packageName "your.package.name.other"
}
}
メインのマニフェストにはプロバイダーが含まれていません。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android" >
<!-- Permissions -->
<application>
<!-- Nothing about Content Providers at all -->
<!-- Activities -->
...
<!-- Services -->
...
</application>
そして、プロバイダーを含む各フレーバーのマニフェスト。
自由:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android" >
<application>
<!-- Content Providers -->
<provider
Android:name="your.package.name.Provider"
Android:authorities="your.package.name.free"
Android:exported="false" >
</provider>
</application>
</manifest>
有料:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android" >
<application>
<!-- Content Providers -->
<provider
Android:name="your.package.name.Provider"
Android:authorities="your.package.name.paid"
Android:exported="false" >
</provider>
</application>
</manifest>
その他:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android" >
<application>
<!-- Content Providers -->
<provider
Android:name="your.package.name.Provider"
Android:authorities="your.package.name.other"
Android:exported="false" >
</provider>
</application>
</manifest>
私の解決策は、AndroidManifest.xml
でプレースホルダー置換を使用することです。また、packageNameSuffix
属性も処理するため、debug
およびrelease
を、同じデバイス上で他のカスタムビルドと同様に使用できます。
applicationVariants.all { variant ->
def flavor = variant.productFlavors.get(0)
def buildType = variant.buildType
variant.processManifest.doLast {
println '################# Adding Package Names to Manifest #######################'
replaceInManifest(variant,
'PACKAGE_NAME',
[flavor.packageName, buildType.packageNameSuffix].findAll().join()) // ignores null
}
}
def replaceInManifest(variant, fromString, toString) {
def flavor = variant.productFlavors.get(0)
def buildtype = variant.buildType
def manifestFile = "$buildDir/manifests/${flavor.name}/${buildtype.name}/AndroidManifest.xml"
def updatedContent = new File(manifestFile).getText('UTF-8').replaceAll(fromString, toString)
new File(manifestFile).write(updatedContent, 'UTF-8')
}
後で進化するかどうかを確認したい場合は、 Gist
にも記載しています。
複数のリソースとXML解析アプローチよりもエレガントなアプローチであることがわかりました。
なぜこれを追加しないのですか?
type.packageNameSuffix = "。$ type.name"