読者です 読者をやめる 読者になる 読者になる

build.gradleでapplicationIdSuffix を使う上での注意点メモ

はじめに

のお話なのですが、

  • app/build.gradle
    buildTypes {
        debug {
            debuggable true
            applicationIdSuffix ".debug"
            versionNameSuffix "-DEBUG"
        }
    }

このまま適応してしまうと、実行時にクラッシュエラーになる場合があるので、

どこを修正しないと駄目なのか辺りをちょっと整理してみました。*1

書き換えると、違うパッケージになるので楽だぜー な話しか見ないんですよね・・(汗

動作環境

  • macOS Sierra
  • 16G
  • HDDタイプのiMac
  • AS 2.3.1

applicationIdSuffix を適応したときはどういう状態なのか?

  • AndroidManifest.xml のみ書き換わる
  • class.jar 等はそのまま

書き換えられる箇所(ベース)

  • 変更前
<manifest 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="hoge.fuga.maiu"> <!--★-->
  • 変更後
<manifest 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="hoge.fuga.maiu.debug"> <!--★★-->

★ => ★★

物理package名 が補われるもの

android:name の場所は基本置き換えてくれるみたい

  • 変更前
<activity
    android:name=".activity.MainActivity"
    android:screenOrientation = "portrait">
</activity>


<service
     android:name=".service.MainService"
     android:exported="false">
</service>
  • 変更後
<activity
    android:name="hoge.fuga.maiu.activity.MainActivity"
    android:screenOrientation = "portrait">
</activity>


<service
     android:name="hoge.fuga.maiu.service.MainService"
     android:exported="false">
</service>

物理package名 が補われないもの

  • meta-data
<-- meta-dataはフルパスにしておかないと駄目 (class.jarは変更されないため) -->
    <meta-data
        android:name="hoge.fuga.maiu.application.LimitCacheSizeGlideModule"
        android:value="GlideModule" />

 桜さんのブログの記載箇所

GCMの箇所

ただGCMは現在新規登録できないので、古いアプリメンテ用の記載になるかも

  • app/AndroidManifest.xml
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
    android:name="${applicationId}.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />

<receiver
    android:name="com.google.android.gms.gcm.GcmReceiver"
    android:exported="true"
    android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <category android:name="${applicationId}" />
    </intent-filter>
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="${applicationId}" />
    </intent-filter>
</receiver>

FCMだと

上記あたりの記載は一切いらなくなる。移行は下記のページ参照

自動生成系

下記は、ManifestMarger時にマージされて付与される

<receiver android:exported="true" 
    android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" 
    android:permission="com.google.android.c2dm.permission.SEND">
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
        <category android:name="${applicationId}"/>
    </intent-filter>
</receiver>

<provider 
    android:authorities="${applicationId}.firebaseinitprovider" 
    android:exported="false" 
    android:initOrder="100" 
    android:name="com.google.firebase.provider.FirebaseInitProvider"/>

packageごとに、独自登録が必要なもの

google-play-service.json

MainP -- src/main
      -- google-services.json          hoge.fuga.maiu 用
       |        
       -- src/debug
              |        
              -- google-services.json  hoge.fuga.maiu.debug 用

登録時のFinglerPrint

keytool -exportcert -list -v -alias androiddebugkey -keystore ./app/irof_history_debug.keystore

な感じで算出

facebook provider

MainP -- src/main/res
      -- config.xml          hoge.fuga.maiu 用 [FacebookアプリID]
       |        
       -- src/debug/res
              |        
              -- config.xml  hoge.fuga.maiu.debug 用 [FacebookアプリID]
  • app/AndroidManifest.xml
<provider android:authorities="com.facebook.app.FacebookContentProvider[FacebookアプリID]"
          android:name="com.facebook.FacebookContentProvider"
          android:exported="true" /> 

登録時のキーハッシュ

keytool -exportcert -alias androiddebugkey -keystore ./app/irof_history_debug.keystore | openssl sha1 -binary | openssl base64

な感じで作成

自動生成系

下記は、ManifestMarger時にマージされて付与される

<provider 
    android:authorities="${applicationId}.FacebookInitProvider" 
    android:exported="false" 
    android:name="com.facebook.internal.FacebookInitProvider"/>

TwitterKit(febric)

これは AndroidManifest.xmlべた書きしか駄目*2

  • app/src/main/AndroidManifest.xml
<meta-data
            android:name="io.fabric.ApiKey"
            android:value="YOUR_API_KEY" />
  • app/src/debug/AndroidManifest.xml
<meta-data
            tools:reprace="android:value"
            android:name="io.fabric.ApiKey"
            android:value="YOUR_DEBUG_API_KEY" />

独自ContentProvider の話

  • app/AndroidManifest.xml
<provider
    android:name=".provider.DatabaseProvider"
    android:authorities="${applicationId}.DatabaseProvider" <!--◎-->
    android:exported="false" />

◎が端末ユニークである必要があるため、別々にしないと駄目

  • libraryProject側に記載しても、MainP側で
    • ManifestMargerで全 AndroidManifest.xmlがマージ
    • ${applicationId}を置き換え
    • placeHolderが適応

の流れなので、library-projectのパッケージが違う場合は期待通り動かない

  • app/DatabaseContract.java
public class DatabaseContract {
    /** The authority for the database provider */
    public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".DatabaseProvider";
    // ...
}

かプログラムで動的に取るか・・・*3

類似の話

<sync-adapter 
    android:accountType="${applicationId}"
    android:allowParallelSyncs="false"
    android:contentAuthority="${applicationId}.DatabaseProvider"
    android:isAlwaysSyncable="true"
    android:supportsUploading="true"
    android:userVisible="true" />

<account-authenticator 
    android:accountType="${applicationId}"
    android:icon="@drawable/ic_launcher"
    android:label="@string/account_authenticator_label"
    android:smallIcon="@drawable/ic_launcher" />

で問題となることは・・・

正にこの現象。

  • debugSuffix とかつけたり
  • productFlavorつくったり

すると Rの生成がたまにおかしくなって Fragmentのレイアウト参照箇所のソースとかが定期的に真っ赤になる

cleanすれば治るんだけど、ビルドが不安定orz

だた、

とかあると、debugサフィックス を除去して、上記のファイルを除くとか正直面倒くさい><


併用すると便利なライブラリ

gradle-android-ribbonizer-plugin

debug=true

のbuildTypeのアイコンに、buildType名でリボンを付けてくれるgradle plugin*4

Android-Iconics

  • 基本、素材作成は
    • iOS作成=>android流用 が多いので
    • iOSが未着手の場合、素材がない

場合にココらへんのものを使うと便利。

のテクニックを使って画像化して利用する。

勿論残念ながらレイアウトプレビューでは見れないので、tools:txt でイメージ代替する

ただ、Activityに一々かくと面倒なので、下記の記載のほうが楽かも

protected void attachBaseContext(Context base) { 
       if(base instanceof Activity){ 
            super.attachBaseContext(IconicsContextWrapper.wrap(base)); 
       } else { 
            super.attachBaseContext(base); } 
       } 
}

*1:なんか検索すると sakura_bird1 さんと stackoverFlowぐらいしか情報が無いでござる!

*2:meta-data のため・・

*3:でも個体値でfinal宣言しているのが多いんですよね・・。直上のjavaソースと同じく

*4:ただカスタムは難しいんだよな><