TadaoYamaokaの開発日記

個人開発しているスマホアプリや将棋AIの開発ネタを中心に書いていきます。

Androidアプリの広告版と有料版を一つのプロジェクトにする(補足)

前回の日記で書いたProduct Flavorsを使って、広告版と有料版を一つのプロジェクトにするには、広告ありのlayoutと広告なしのlayoutを用意する必要がある。

layout定義

com.google.android.gms.ads.AdViewをlayoutの一部に使用していて、それ以外は共通の場合は、共通の部分をmainのFlavorに定義して、広告分をそれぞれのFlavorに定義したい。
そのような場合、広告部分だけ別のlayoutファイルにして、ルートノードをmergeタグにして、mainのlayoutからimportするとよい。

共通部分のlayoutファイルのファイル名をactivity_main.xml、広告部分のlayoutファイルのファイル名をadview.xmlとすると以下のように定義する。

adview.xml(広告ありのFlavor)
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <com.google.android.gms.ads.AdView xmlns:ads="http://schemas.android.com/apk/res-auto"
        android:id="@+id/adView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        ads:adSize="BANNER"
        ads:adUnitId="xxxxxxxxxxxxxxxx" />
</merge>
adview.xml(広告なしのFlavor)
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
</merge>
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ... >
    ...
    <include layout="@layout/adview" />
</LinearLayout>

Javaコード

コードの広告を表示する部分で、layoutで定義したadViewのidを参照すると、広告なしのFlavorではidが見つからずエラーとなる。
それを回避するために、広告表示部分を同じクラス名でそれぞれのFlavorのディレクトリに作成する。
広告なし版の方はメソッドを空で実装する。

MyAdView.java(広告ありのFlavor)
import android.app.Activity;

import com.google.android.gms.ads.AdRequest;

public class MyAdView {
    static public void show(Activity activity) {
        com.google.android.gms.ads.AdView adView = (com.google.android.gms.ads.AdView) activity.findViewById(R.id.adView);
        AdRequest adRequest = new AdRequest.Builder().build();
        adView.loadAd(adRequest);
    }
}
MyAdView.java(広告なしのFlavor)
import android.app.Activity;

public class MyAdView {
    static public void show(Activity activity) {
    }
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
    protected void onCreate(Bundle savedInstanceState) {
        ...
        if (BuildConfig.AD) {
            MyAdView.show(this);
        }
    }
}

AndroidManifest.xmlの設定

広告を表示するには、AndroidManifest.xmlパーミッションの設定が必要になる。
AndroidManifest.xmlは、mainに定義したデフォルトの定義と各Flavorの定義がマージされるため、広告版のFlavorにのみ追加のパーミッションを定義すればよい。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
    ...
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

build.gradleの設定

広告を表示するには、build.gradleのdependenciesにcom.google.android.gms:play-services-adsライブラリの設定が必要になる。
広告なし版にも定義してしまうと、自動的にインターネットアクセスのパーミッションが追加されてしまう。

それを回避するため、dependenciesに特定のFlavorのみ使用されるように設定する。

build.gradle例
android {
    ...
    productFlavors {
        ad {
            applicationId "com.xxx.yyy"
            buildConfigField "boolean", "AD", "true"
        }
        noad {
            applicationId "com.xxx.yyynoad"
            buildConfigField "boolean", "AD", "false"
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:24.2.0'
    adCompile 'com.google.android.gms:play-services-ads:8.4.0'
}

adCompileの部分で、Flavorがadの時のみライブラリが使用されるように設定している。
なお、Flavorの名前がすべて小文字でないとエラーとなった。