ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

Android アプリビルド時に packageNameSuffix を使った時にはまったこと

以前紹介したように、Gradle の Android プラグインを使って Android アプリをビルドする際、packageNameSuffix により、ビルドタイプごとにパッケージ名に接尾辞を付けることができます。 これにより、開発中のパッケージと、正式リリース版のパッケージを同じ端末に同居させることができたりします。

Android Studio 上で開発しているときにこの機能を使った場合に、はまりそうなことがいくつかあるので書いておきます。

Gradle Beyond the Basics

Gradle Beyond the Basics

packageNameSuffix をつける場合は、AndroidManifest.xml 内のパッケージ名は完全修飾名にしなければならない

例えば、activity 要素の android:name 属性 などの Java クラス名がドットで始まる文字列になっている場合、manifest 要素の package 属性 で指定したパッケージ名が省略されているものとみなされます。

Gradle の Android プラグインで packageNameSuffix を指定した場合、manifest 要素の package 属性で指定されたパッケージ名に接尾辞がつくことになるので、AndroidManifest.xml 内に記述されたドットで始まる Java クラス名の完全修飾名が変化してしまうことになります。

基本的にはそれでは困るので、AndroidManifest.xml 内に Java クラス名を記述する場合は、ドットで始まる省略記法を使うのではなく、完全修飾名を使うようにしましょう。

Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED]

ドットで始まるクラス名を残したまま packageNameSuffix を使った場合に、アプリを端末上にインストールして起動しようとすると上のようなエラーが発生することがありました。 原因は調べていません。

build.gradle の変更後は Android Studio の設定を build.gradle に同期させなければならない

これは別に packageNameSuffix を使う場合に限らない話ですが。

android {
    // ...

    buildTypes {
        debug {
            packageNameSuffix ".debug"
        }
    }
}

build.gradle に上記を追記して Android Studio でビルドして端末上で実行しようとすると、次のようなエラーが発生してしまいました。

Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=info.vividcode.android.sample/.MainActivity }
Error type 3
Error: Activity class {info.vividcode.android.sample/info.vividcode.android.sample.MainActivity} does not exist.

packageNameSuffix を付けたのに、付ける前のパッケージ名を使ってアプリを起動しようとして失敗している、という感じのようでした。 この原因は、build.gradle の変更が Android Studio 側に同期されていないためで、メニューの “Tools” の “Android” の “Sync Project with Gradle Files” を実行すると問題を解消できました。

Android Studio の auto-import 機能が有効になっている場合は、手動で同期する必要はないようです。

ContentProvider の authority をビルドタイプごとに変えるのは packageNameSuffix だけでは不十分

ContentProvider の authorities は packageNameSuffix の影響を受けない *1 ので、ビルドタイプごとに別パッケージのアプリとして同じ端末に同居させようとしても、ContentProvider を使っていると衝突してインストールできないという事態が発生します *2

Failure [INSTALL_FAILED_CONFLICTING_PROVIDER]

とりあえずの回避策として、文字列リソースを使ってビルドタイプごとに異なる authority を指定するなど、何かしらの対策をする必要があります。 (ここにあげたページが参考になります。)

*1:Gradle の Android プラグイン 0.5.0 現在のところ

*2:とはいえ別名だとデバッグ用のパッケージが通常用途で使用されないので、それが困る場合には困ると思うのですが、まあその場合は通常のアプリのパッケージを上書きするしかない気がしますね。