2016年5月23日月曜日

Google Play Services (Rev.30)でUnityにAdMob表示しようとしてハマる(実はまだ半分ハマっている)

UnityからAndroid用のビルドができるように環境を整えていたが、予想外にAdMob広告の実装でハマってしまった。
自分はAndroidに関しては知識がほとんどないので、ネットの情報が頼りだったのだが、出回っている情報が微妙に古かったりすると応用を効かせて解決することが難しく途方に暮れることが多い。

cocos2d-xでAndroid用に「ごはんよそって2」(iOS版はこちら)を作った時は、AdMob実装にそんなに手間取らなかったのだが、最新のGoogle Play Servicesでは状況が違った。
そもそもはAPKの肥大化を避けるために、Google Play Servicesのすべてをプロジェクトにインポートする方式をやめて、必要なサービスだけをインポートするようになったらしい。

Java SE 1.7、Android SDK、Android Studio、Google Play Services、Unity Plugin for the Google Mobile Ads SDKなどのセットアップをすませ、いざAndroid用にプロジェクトをBuild&Runするとエラーで止まってしまう。コンソールには以下のエラーが表示されている。途方に暮れる瞬間である。
CommandInvokationFailure: Failed to re-package resources. See the Console for details.
/Users/kenichi/Library/Android/sdk/build-tools/23.0.3/aapt package --auto-add-overlay -v -f -m -J gen -M AndroidManifest.xml -S "res" -I "/Users/kenichi/Library/Android/sdk/platforms/android-23/android.jar" -F bin/resources.ap_ --extra-packages com.hamken100per.android.helloandroid:android.support.v7.appcompat:com.google.firebase:com.google.android.gms.ads.impl:com.google.android.gms.ads:com.google.android.gms.base:com.google.android.gms:com.google.android.gms.tasks:android.support.v4 -S "/Users/kenichi/Documents/Programs/Unity/AndroidTest/Temp/StagingArea/android-libraries/appcompat-v7-23.1.1/res" -S "/Users/kenichi/Documents/Programs/Unity/AndroidTest/Temp/StagingArea/android-libraries/firebase-common-9.0.0/res" -S "/Users/kenichi/Documents/Programs/Unity/AndroidTest/Temp/StagingArea/android-libraries/play-services-ads-9.0.0/res" -S "/Users/kenichi/Documents/Programs/Unity/AndroidTest/Temp/StagingArea/android-libraries/play-services-ads-lite-9.0.0/res" -S "/Users/kenichi/Documents/Programs/Unity/AndroidTest/Temp/StagingArea/android-libraries/play-services-base-9.0.0/res" -S "/Users/kenichi/Documents/Programs/Unity/AndroidTest/Temp/StagingArea/android-libraries/play-services-basement-9.0.0/res" -S "/Users/kenichi/Documents/Programs/Unity/AndroidTest/Temp/StagingArea/android-libraries/play-services-tasks-9.0.0/res" -S "/Users/kenichi/Documents/Programs/Unity/AndroidTest/Temp/StagingArea/android-libraries/support-v4-23.1.1/res"

stderr[
/Users/kenichi/Documents/Programs/Unity/AndroidTest/Temp/StagingArea/android-libraries/appcompat-v7-23.1.1/res/layout/abc_screen_toolbar.xml:27: note: removing attribute http://schemas.android.com/apk/res/android:touchscreenBlocksFocus from <android.support.v7.widget.ActionBarContainer>
/Users/kenichi/Documents/Programs/Unity/AndroidTest/Temp/StagingArea/android-libraries/appcompat-v7-23.1.1/res/layout/abc_screen_toolbar.xml: note: using v21 attributes; synthesizing resource com.hamken100per.android.helloandroid:layout/abc_screen_toolbar for configuration v21.
AndroidManifest.xml:19: Tag <provider> attribute authorities has invalid character '$'.
]


古いレビジョンのGoogle Play Servicesを使ってUnityでAdMob実装する記事はいくつか見つかったのだが、最新版の情報が見つからなかった。公式マニュアルを読んでも、肝心なところが書いてなかったりして解決策は分からなかった。

しかし、最初、何だか分からなかったエラーログも、整理してみると
AndroidManifest.xml:19: Tag <provider> attribute authorities has invalid character '$'.
の部分が一番怪しいことに気がついた。

AndroidManifest.xmlの19行目は
<provider android:authorities="${applicationId}.firebaseinitprovider" android:exported="false" android:initOrder="100" android:name="com.google.firebase.provider.FirebaseInitProvider" />
となっており、先のエラーログと合わせると、${applicationId}の変換が行われていない事が推測できた。
この辺りを調べてみると、build.gradleファイルにapplicationIdとアプリのBundle Identifierを紐付ける設定をすれば良いらしいのだが、UnityからBuild&Runする時に、その設定が使用できるのか分からない。Unityから一旦Androidプロジェクトを生成して Android Studioでビルドすれば良さそうなのだが、それは面倒だと思い、別の解決策を模索する。

AndroidManifest.xmlの19行目のFirebaseという名前から、<Unityプロジェクト>Assets/Plugins/Android/の中に展開されている firebase-common-9.0.0.aar ファイルが怪しいと推測する。aarファイルの本性はzipファイルで、それぞれのaarファイルには専用のAndroidManifest.xmlが格納されているということが分かった。

早速、展開してAndroidManifest.xmlを見ると、問題の箇所があった。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.google.firebase">
    <uses-sdk android:minSdkVersion="9" />
    <application>

        <provider
            android:authorities="${applicationId}.firebaseinitprovider" <--- ここ
            android:name=".provider.FirebaseInitProvider"
            android:exported="false"
            android:initOrder="100" />
    </application>
</manifest>

この${applicationId}を自分のアプリのBundle Identifierに無理やり書き換え、展開された全てのファイルをzip圧縮して、zipファイル名を firebase-common-9.0.0.aar に書き換える。その後、この出来上がったファイルを<Unityプロジェクト>Assets/Plugins/Android/ に戻してやる。
かくして、Build&Runをすると、今度は問題なく実行することができた。

とても残念な解決方法だが、何もないよりはマシではある。どなたか詳しい方が、スマートな解決策を記事にしてくれる事を期待するばかりである。

この解決策は、以下のフォーラムを参考にさせて頂いた。

関連記事

3 件のコメント:

  1. 自分も似たようなとこでハマったので情報助かりました。

    さらに調べてみたんですが、どうやらPlayServiceResolverの
    1.1で修正が入ったっぽいですね。
    https://github.com/googlesamples/unity-jar-resolver/blob/master/plugin/Assets/PlayServicesResolver/Editor/ResolverVer1_1.cs

    Unityで設定したBundleIDでapplicationIdを置き換えてくれるっぽいです。

    普通にココのパッケージで更新したら直りましたよー
    https://github.com/googlesamples/unity-jar-resolver

    返信削除
    返信
    1. コメントありがとうございます。
      修正入りましたね。
      情報ありがとうございます。
      私の方もその後、正常にビルドできるようになりました。

      削除
  2. if only use admob https://github.com/unity-plugins/Firebase-Admob-Unity is a good choose

    返信削除

Related Posts Plugin for WordPress, Blogger...