${applicationId}
xml と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/ ディレクトリのプレースホルダーも置き換えることができます。