AndroidのmanifestPlaceholdersの使いどころ

📅 2015/05/22

Android

build.gradleのbuildTypesとproductFlavors内でmanifestPlaceholdersと変数展開について軽くまとめてみる。 今のところ使った場面は以下の4つです。

  • GCMのPermission
  • GCMのIntentFilter
  • AndroidManifestでSearchRecentSuggestionsProviderの定義
  • android:schemeのホスト名

build.gradleを以下のように設定している場合についてそれぞれ説明します。

build.gradle

android {
...
  buildTypes {
    release {
      manifestPlaceholders = [hostName: "epy0n0ff.com"]
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    develop {
      debuggable true
      signingConfig signingConfigs.debug
      manifestPlaceholders = [hostName: "dev.epy0n0ff.com"]
      applicationIdSuffix '.develop'
    }
    local {
      debuggable true
      signingConfig signingConfigs.debug
      manifestPlaceholders = [hostName: "local.epy0n0ff.com"]
      applicationIdSuffix '.local'
    }
    debug {
      debuggable true
      signingConfig signingConfigs.debug
      manifestPlaceholders = [hostName: "dev.epy0n0ff.com"]
      applicationIdSuffix '.debug'
    }
  }
...
}

GCMのPermission

GCMのPermission要素にはapplicationIdを含みます。 buildTypes毎にAndroidManiefst.xmlを用意してもいいのですが、事故を減らすために main/AndroidManifest.xmlを以下の用に変更します。

AndroidManifest.xml(適用前)

<permission android:name="com.epy0n0ff.develop.permission.C2D_MESSAGE"
      android:protectionLevel="signature"/>
  <uses-permission android:name="com.epy0n0ff.develop.permission.C2D_MESSAGE"/>
</code></pre>
AndroidManifest.xml(適用後)
<pre><code>
<permission android:name="${applicationId}.permission.C2D_MESSAGE"
      android:protectionLevel="signature"/>
  <uses-permission android:name="com.epy0n0ff.develop.permission.C2D_MESSAGE"/>

GCMのIntentFilter

GCMの設定には前項以外にもIntentFilterにapplicationIdが使用されています。 ここもapplicationIdの変数を使うように変更します。 AndroidManifest.xml(適用前)

    <receiver
        android:name="com.epy0n0ff.GCMReceiver"
        android:permission="com.google.android.c2dm.permission.SEND"
        >
      <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
        <action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
        <category android:name="com.epy0n0ff.develop"/>
      </intent-filter>
    </receiver>

AndroidManifest.xml(適用後)

    <receiver
        android:name="com.epy0n0ff.GCMReceiver"
        android:permission="com.google.android.c2dm.permission.SEND"
        >
      <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
        <action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
        <category android:name="${applicationId}"/>
      </intent-filter>
    </receiver>

AndroidManifestでSearchRecentSuggestionsProviderの定義

見落としがちというか気づきにくいのがSearchRecentSuggestionsProviderの定義です。 Logcatで見ていると以下のようなエラーが出るので修正します。 /com.epy0n0ff.develop E/ActivityThread﹕ Failed to find provider info for com.epy0n0ff.content.provider.search

AndroidManifest.xml(適用前)

<provider
        android:name=".content.provider.RecentSearchSuggestionProvider"
        android:authorities="com.epy0n0ff.content.provider.search"
        android:exported="false"
        />

AndroidManifest.xml(適用後)

<provider
        android:name=".content.provider.RecentSearchSuggestionProvider"
        android:authorities="${applicationId}.content.provider.search"
        android:exported="false"
        />

android:schemeのホスト名

ここでやっとmanifestPlaceholdersの登場です。 manifestPlaceholdersはkey-valueのmapなので${key}と書くとそこにvalueが展開されます。

AndroidManifest.xml(適用前)

   <activity
        android:name=".view.activity.UrlInterpreterActivity"
        android:launchMode="singleTask"
        android:noHistory="true">
      <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data
            android:host="develop.epy0n0ff.com"
            android:pathPattern="/sp/.*"
            android:scheme="http"/>
    </activity>

AndroidManifest.xml(適用後)

    <activity
        android:name=".view.activity.UrlInterpreterActivity"
        android:launchMode="singleTask"
        android:noHistory="true">
      <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data
            android:host="${hostName}"
            android:pathPattern="/sp/.*"
            android:scheme="http"/>
    </activity>

参考