AdMobからのオススメ

     Google AdMobから「Firebaseと3三将棋アプリをリンクすればユーザー分析に役立ちますよ」的なメールをもらったので導入してみました。でもFirebaseを導入するとAdMob広告が表示されなくなりました(何故かテスト広告だけは表示される)。以前も「あなたのサイトが検索されていますよ」というメールを貰ったので、Google Adsenseに申し込むと審査に落とされたことがあります1。Googleはいつもツンデレです、振り回されないようにしたいものです。
     でも今回はなんとかFirebaseを導入して尚且つAdMob広告も出すことが出来たのでその手順を紹介しようと思います。ついでに以前から気になっていたPush通知も実装してみました。

    AdMobとリンク

    • AdMobのサイトからアプリを選択して「Firebaseにリンク」を選んでFirebaseとリンク(「新しいFirebaseプロジェクトを作成する」を選ぶ)
    • Firebaseのサイトから新しく作成したプロジェクトを選んで歯車アイコンから「プロジェクトの設定」メニューを選んでgoogle-services.jsonをダウンロードしておく

    Firebaseプラグイン

     cordova-plugin-firebaseを普通にインストールするとビルドで苦労すると思います。
     先にダウンロード済みのgoogle-services.jsonをCordovaプロジェクト直下にコピーしておいて、cordova plugin add cordova-plugin-firebaseではなくcordova plugin add https://github.com/dpa99c/cordova-plugin-firebase#GH-1057-April-05-android-build-issueで修正済みのプラグインをインストールすれば、Firebaseの構成ファイル(google-services.json)を読み込んでAndroidManifest.xmlやproject.propertiesに必要なものを追記してくれます。アプリがPush通知を受信する際に必要な設定もAndroidManifest.xmlに書き込まれていました。Firebaseに関してネットで検索するとbuild.gradleを書き換える例が多いと思いますが、Cordovaの場合はproject.propertiesの内容で上書きされるので、project.propertiesファイルを書き換える必要があります。google-services.jsonの情報を元に自動でFirebase用のgradleファイルも生成してくれるようです。以下が自分の場合のproject.propertiesファイルの内容です。

    Firebaseプラグイン導入前 project.properties

    target=android-26
    android.library.reference.1=CordovaLib
    android.library.reference.2=app
    cordova.system.library.1=com.google.android.gms:play-services-ads:11.0.4
    cordova.system.library.2=com.android.support:support-v4:25.+
    

    Firebaseプラグイン導入後 project.properties

    target=android-26
    android.library.reference.1=CordovaLib
    android.library.reference.2=app
    cordova.system.library.1=com.google.android.gms:play-services-ads:+
    cordova.system.library.2=com.android.support:support-v4:25.+
    cordova.gradle.include.1=cordova-plugin-firebase/happyclam-build.gradle
    cordova.system.library.3=com.google.android.gms:play-services-tagmanager:+
    cordova.system.library.4=com.google.firebase:firebase-core:+
    cordova.system.library.5=com.google.firebase:firebase-messaging:+
    cordova.system.library.6=com.google.firebase:firebase-config:+
    cordova.system.library.7=com.google.firebase:firebase-perf:+
    

     この段階でcordova build androidでビルドするとcom.google.android.gms:play-services-basementとバージョンが合っていないとかいうメッセージが出てエラーになったので、com.google.android.gms:play-services-adsのバージョン指定を手動で+に書き換えたら成功しました。-> com.google.android.gms:play-services-ads:+

    Firebase対応AdMobプラグイン

     Firebaseを使う前はAdMob広告表示のためにcordova-plugin-admobプラグインを使っていました。Firebase導入後もそのままでテスト広告は表示されるのですが、実機では表示されないという状態になったので、以下のようにFirebase用のAdMobプラグイン(cordova-plugin-admob-free)に置き換えます。

    • cordova plugin remove cordova-plugin-admob
    • cordova plugin add cordova-plugin-admob-free –save –variable ADMOB_APP_ID=”ca-app-pub-xxxxxxxxxxxxxxxx~xxxxxxxxxx”

     ca-app-pub-xxxxの部分はアプリ毎のAdMobのアプリケーションIDです。->参考記事

    AdMobプラグイン導入後 project.properties

    target=android-26
    android.library.reference.1=CordovaLib
    android.library.reference.2=app
    cordova.system.library.1=com.google.android.gms:play-services-ads:+
    cordova.system.library.2=com.android.support:support-v4:25.+
    cordova.gradle.include.1=cordova-plugin-firebase/happyclam-build.gradle
    cordova.system.library.3=com.google.android.gms:play-services-tagmanager:+
    cordova.system.library.4=com.google.firebase:firebase-core:+
    cordova.system.library.5=com.google.firebase:firebase-messaging:+
    cordova.system.library.6=com.google.firebase:firebase-config:+
    cordova.system.library.7=com.google.firebase:firebase-perf:+
    cordova.system.library.8=com.google.android.gms:play-services-base:11.0.4
    cordova.system.library.9=com.google.android.gms:play-services-ads:11.0.4
    

     下二行が追加されたものです。play-services-adsが重複しています。これでビルドは通ったのですが、最終的には重複行を削除して以下のようにしました。

    最終的に使用している project.properties

    target=android-26
    android.library.reference.1=CordovaLib
    android.library.reference.2=app
    cordova.system.library.1=com.android.support:support-v4:25.+
    cordova.gradle.include.1=cordova-plugin-firebase/happyclam-build.gradle
    cordova.system.library.2=com.google.android.gms:play-services-tagmanager:+
    cordova.system.library.3=com.google.firebase:firebase-core:+
    cordova.system.library.4=com.google.firebase:firebase-messaging:+
    cordova.system.library.5=com.google.firebase:firebase-config:+
    cordova.system.library.6=com.google.firebase:firebase-perf:+
    cordova.system.library.7=com.google.android.gms:play-services-base:+
    cordova.system.library.8=com.google.android.gms:play-services-ads:+
    

     本当はこのリンク先を見てバージョンを指定する方がいいのかもしれませんが、自分が確認した限りでは+の時よりWarningの種類が増えたので結局全部+に揃えました。

    AdMob表示スクリプト

     自分の場合、凝った使い方はしていないので、cordova-plugin-admobプラグインを使った場合とほとんどコードは同じです。->参考

        document.addEventListener('admob.interstitial.events.LOAD', this.onAdLoaded, false);
        document.addEventListener('admob.interstitial.events.LOAD_FAIL', this.onAdFailed, false);
        document.addEventListener('admob.interstitial.events.CLOSE', this.onAdClosed, false);
    
        onAdLoaded: function() {
            console.log("=== onAdLoaded ============================")
            admob.interstitial.show();
        },
        onAdFailed: function() {
            console.log("=== onAdFailed ============================")
        },
        onAdClosed: function() {
            console.log("=== onAdClosed ============================")
        },
        onDeviceReady: function() {
            admob.banner.config({
                id: admobid.banner,
                isTesting: false,
                autoShow: true,
            });
            admob.banner.prepare();
            admob.interstitial.config({
                id: admobid.interstitial,
                isTesting: false,
                autoShow: true,
            });
            admob.interstitial.prepare();
        }
    

    Push通知

     cordova-plugin-firebaseプラグインだけあれば、受信が可能です。Firebaseサイトの「Cloud Messaging」メニューから「通知の作成」も出来ます。

    受信部:

        onDeviceReady: function() {
            window.FirebasePlugin.hasPermission(function(data){
                console.log('hasPermission: ' + data.isEnabled);
            });
            window.FirebasePlugin.getToken(function(token) {
                localStorage.setItem("FCMtoken", token);
            }, function(error) {
                console.log('token: ' + error);
            });
            window.FirebasePlugin.onTokenRefresh(function(token) {
                localStorage.setItem("FCMtoken", token);
            }, function(error) {
                console.log('tokenRefresh: ' + error);
            });
            window.FirebasePlugin.onNotificationOpen(function(data) {
                if (data.wasTapped) {
                    localStorage.setItem("serverMessage",JSON.stringify(data));
                } else {
                    localStorage.setItem("serverMessage",JSON.stringify(data));
                    window.plugins.toast.showWithOptions({
                        message: data[lng.slice(0,2)],
                        duration: '15000',
                        position: 'center',
                        styling: {
                            opacity: 0.75,
                            backgroundColor: '#E6E6E6',
                            textColor: '#000000',
                            textSize: 40,
                            cornerRadius: 16
                        }
                    });
                }
            }, function(msg) {
                console.log(msg);
            }, function(err) {
                console.log(err);
            });
        }
    

    Firebase通知作成画面:

    Push通知作成画面

    アプリでの通知受信時:

    Push通知サンプル

     アプリを立ち上げている人に通知内容をtoast表示しているだけです。アプリを立ち上げていない場合はスマホの通知欄にメッセージが届きます。いろいろ使い道はありそうですが、何をするにも運用コストがかかるので難しいところです。

    プライバシーポリシー

     Firebaseをアプリに導入するとポリシー違反でアプリが削除されるケースがあると聞いたので、一応プライバシーポリシーにFirebase利用している旨を明記しました。自分のアプリの場合全てのアプリのAndroidManifest.xmlに<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />の一行を入れてる2ので問題ないと思っています。

    追記:実施環境

     上記手順は以下の環境で実施しました。

    $cordova -v
    8.1.2 (cordova-lib@8.1.1)
    
    $cordova platform ls
    Installed platforms:
      android 7.1.0
    Available platforms: 
      browser ~5.0.1
      ios ~4.5.4
      osx ~4.0.1
      windows ~6.0.0
    
    

     android@7.1.0の環境だと3つのプロジェクトですんなりFirebase導入出来ましたが、android@7.1.4の別プロジェクトでやってみるとFirebaseライブラリのバージョンによるConflictが発生して上記のようにすんなりとは出来ませんでした。
     うまくビルド出来ても、Firebase導入後ダッシュボードを眺めていると、以下のようにステータスが調査が必要となって「クラッシュに遭遇していないユーザー数」が100%になりません。問題のない他のアプリのステータスは成功と出力され、「クラッシュに遭遇していないユーザー数」が100%になります。

    リリース直後のステータス

     やはり環境によっては苦労が伴いそうです。

    追記:AndroidXに移行

     android@7.1.4だとバージョンに違いによるConflictが起きたと書きましたが、cordovaのandroid環境を8.0.0にバージョンアップした後、以下の手順でandroidxライブラリに移行することで簡単にビルド出来ました。

    1. Android Studioを使ってCordovaプロジェクトをAndroidXに移行([Refactor] -> [Migrate to AndroidX…] -> [Do Refactor]) → 不要?
    2. Cordova環境でビルド後、既に紹介済みの手順でcordova-plugin-firebase 2.0.5を導入。
    3. ビルドエラーが出る状態でも構わずcordova-plugin-androidxプラグインとcordova-plugin-androidx-adapterプラグインをインストール
    $cordova -v
    8.1.2 (cordova-lib@8.1.1)
    
    $cordova platform ls
    Installed platforms:
      android 8.0.0
    Available platforms: 
      browser ~5.0.1
      ios ~4.5.4
      osx ~4.0.1
      windows ~6.0.0
    
    $cordova plugin list
    cordova-admob-sdk 0.24.1 "AdMob SDK"
    cordova-plugin-admob-free 0.27.0 "Cordova AdMob Plugin"
    cordova-plugin-androidx 1.0.2 "cordova-plugin-androidx"
    cordova-plugin-androidx-adapter 1.1.0 "cordova-plugin-androidx-adapter"
    cordova-plugin-console 1.1.0 "Console"
    cordova-plugin-crypt-file 1.3.3 "CordovaCrypt"
    cordova-plugin-device 1.1.7 "Device"
    cordova-plugin-dialogs 1.3.4 "Notification"
    cordova-plugin-firebase 2.0.5 "Google Firebase Plugin"
    cordova-plugin-globalization 1.11.0 "Globalization"
    cordova-plugin-splashscreen 4.1.0 "Splashscreen"
    cordova-plugin-whitelist 1.3.3 "Whitelist"
    cordova-plugin-x-socialsharing 5.2.1 "SocialSharing"
    cordova-plugin-x-toast 2.7.2 "Toast"
    cordova-promise-polyfill 0.0.2 "cordova-promise-polyfill"
    es6-promise-plugin 4.1.0 "Promise"
    
    

    Cordova android@8.0.0環境で最終的に使用している project.properties

    target=android-28
    android.library.reference.1=CordovaLib
    android.library.reference.2=app
    cordova.system.library.1=androidx.legacy:legacy-support-v4:1.0.0
    cordova.system.library.2=com.google.android.gms:play-services-base:+
    cordova.system.library.3=com.google.android.gms:play-services-ads:+
    cordova.gradle.include.1=cordova-plugin-firebase/happyclam-build.gradle
    cordova.system.library.4=com.google.android.gms:play-services-tagmanager:+
    cordova.system.library.5=com.google.firebase:firebase-core:+
    cordova.system.library.6=com.google.firebase:firebase-messaging:+
    cordova.system.library.7=com.google.firebase:firebase-config:+
    cordova.system.library.8=com.google.firebase:firebase-perf:+
    

     cordova-plugin-androidx-adapterをインストールしたことで、androidサポートライブラリの部分がcom.android.support:support-v4:25.+からandroidx.legacy:legacy-support-v4:1.0.0に書き換わっているところがミソです。

    追記:Cordova9.0にすれば簡単?

     上で紹介した修正済みのfirebase用プラグイン(https://github.com/dpa99c/cordova-plugin-firebase#GH-1057-April-05-android-build-issue)は現在は公開されていないようです(参照)。なので既存のプロジェクトなら上記方法で問題ありませんが、今から新規プロジェクトでFirebaseを使うなら、Cordovaを9.0にバージョンアップしてプラグインもそれに対応したものを使用するのが一番簡単なようです。Cordova 9.0でcordova-plugin-firebasex末尾にxがついていることに注意)をインストールすれば、すでに説明したcordova-plugin-androidxcordova-plugin-androidx-adapterが自動でインストールされて簡単にFirebase導入が完了しました。Android Studioを使った作業も不要でした。
     但し、使用しているプラグインによってはCordova 9.0に対応していないものもあるようなので注意が必要です。私の場合cordova-plugin-crypt-fileを使用していたのですが、これが対応していなくて対応済みのcordova-plugin-crypto-filecryptではなくcrypto)に差し替えて一応ビルド出来ました。このプラグインも少し問題があったのですが3、実行時エラーが発生する場合は、まずプラグインを疑うのが余計な時間を取られないと思います。

    $ cordova -v
    9.0.0 (cordova-lib@9.0.1)
    $ cordova platform ls
    Installed platforms:
      android 8.1.0
    Available platforms: 
      browser ^6.0.0
      electron ^1.0.0
      ios ^5.0.0
      osx ^5.0.0
      windows ^7.0.0
    
    $cordova plugin list
    cordova-admob-sdk 0.24.1 "AdMob SDK"
    cordova-plugin-admob-free 0.27.0 "Cordova AdMob Plugin"
    cordova-plugin-androidx 1.0.2 "cordova-plugin-androidx"
    cordova-plugin-androidx-adapter 1.1.0 "cordova-plugin-androidx-adapter"
    cordova-plugin-crypto-file 1.2.1 "Crypt File"
    cordova-plugin-device 2.0.3 "Device"
    cordova-plugin-dialogs 2.0.2 "Notification"
    cordova-plugin-firebasex 6.1.0 "Google Firebase Plugin"
    cordova-plugin-globalization 1.11.0 "Globalization"
    cordova-plugin-splashscreen 5.0.3 "Splashscreen"
    cordova-plugin-whitelist 1.3.4 "Whitelist"
    cordova-plugin-x-socialsharing 5.6.0 "SocialSharing"
    cordova-plugin-x-toast 2.7.2 "Toast"
    cordova-promise-polyfill 0.0.2 "cordova-promise-polyfill"
    es6-promise-plugin 4.2.2 "Promise"
    

    重要:上記「Push通知」のコード例のFirebasePlugin.onNotificationOpenイベントはcordova-plugin-firebasexFirebasePlugin.onMessageReceivedに変わったようです。

    追記 2019-09-25

     上記環境でビルドが出来てとりあえずgoogle playにリリース(Tic-tac-toe Evo)したのですが、googleからリジェクト食らいました。このアプリで新しい環境を試す意味もあったのですが、やはりまだ急いで最新環境にしないほうがいいかもしれません。google からのメールには「ポリシー違反がある」としか書かれていないのでリジェクトの理由はいつものようにはっきりしないのですが、cordova-plugin-crypto-fileに原因があるのではと疑っています。Cordovaのバージョンを下げて以下の環境でビルドしたらすぐに承認されました。

    $ cordova -v
    8.1.2 (cordova-lib@8.1.1)
    $ cordova platform ls
    Installed platforms:
      android 8.0.0
    Available platforms: 
      browser ~5.0.1
      ios ~4.5.4
      osx ~4.0.1
      windows ~6.0.0
    $ cordova plugin list
    cordova-admob-sdk 0.24.1 "AdMob SDK"
    cordova-plugin-admob-free 0.27.0 "Cordova AdMob Plugin"
    cordova-plugin-androidx 1.0.2 "cordova-plugin-androidx"
    cordova-plugin-androidx-adapter 1.1.0 "cordova-plugin-androidx-adapter"
    cordova-plugin-crypt-file 1.3.3 "CordovaCrypt"
    cordova-plugin-device 2.0.3 "Device"
    cordova-plugin-dialogs 2.0.2 "Notification"
    cordova-plugin-globalization 1.11.0 "Globalization"
    cordova-plugin-splashscreen 4.0.3 "Splashscreen"
    cordova-plugin-whitelist 1.3.4 "Whitelist"
    cordova-plugin-x-socialsharing 5.4.7 "SocialSharing"
    cordova-plugin-x-toast 2.7.2 "Toast"
    cordova-promise-polyfill 0.0.2 "cordova-promise-polyfill"
    es6-promise-plugin 4.2.2 "Promise"
    
    

     リジェクトされた内容と違うのは主にCordovaのバージョンとcordova-plugin-crypto-fileを使わなくしたことです。Cordova 9.0に問題があるとは思えないので、cordova-plugin-crypto-fileプラグインに問題があったのだと思います。AdMob関連のプラグインでも裏で怪しい動きをするものがあるようですし、サードパーティ製のプラグインを使うときは今回のように様子見ながらのほうが良さそうです。

    → 追加記事「Cordova 9 移行で少しハマった」参照


    1. 有料のgoogle広告のお誘いだったようです。 

    2. 元々個人情報にはアクセスしていないのですが、それを明示するために以前GDPR問題の際に追記したと思います。 

    3. cordova-plugin-crypto-fileは元のcordova-plugin-crypt-fileと全く同じものでは無いようで、plugin.xmlを編集して独自の使い方をしていると原因不明のアプリ起動時のエラーに悩まされました。