AndroidでSHARP SDK AddOnとAdMobを共存する方法

かなりはまったのでメモ。

Android SDK r16時点での情報です。

前提として、SHARP製Android携帯固有の機能を使うには、SHARPが公開しているSDKを使う必要がある。

これはいわゆるAddOnの形で提供されてるので、固有APIを使うアプリは、Build TargetをSHARPのAddOnに設定する必要がある。platform x.xx等を選んではいけない。

普通のアプリならこれで問題無いのだが、AdMobを使おうとすると事情は変わってくる。

SHARPで現在公開されているAddOnは、ベースのAndroidが2.3.3のもの。

よって、使えるAPIやManifestファイルに記述できるオプションなども、2.3.3までの物のみになる。

ところが、AdMobの最新バージョンは、

http://code.google.com/intl/ja/mobile/ads/docs/android/fundamentals.html

で指示されているように、Manifestファイル中に

<activity android:name="com.google.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>

という記述をしなくてはならない。

このandroid:configChangesの内容が問題で、smallestScreenSizeなどは2.3.3の段階ではサポートされていないので、当然ビルドエラーになってしまう。

ここでさっそくぐぐってみたわけだが、SHARPの公式フォーラムで次のようなやりとりを発見した。

https://sh-dev.sharp.co.jp/android/modules/d3forum/index.php?topic_id=121

この人の場合は、Build TargetをGoogle APIsにしたままSHARP固有のAPIを使えないか、というものだが、私の問題と本質は同じである。

私の場合は、Build Targetをplatform 4.xxにして、なおかつSHARP固有のAPIを使いたいわけだ。

SHARPの公式回答として、ビルドパスにAddOn内の*.jarをユーザーライブラリの形で指定しろ、という解決策が提示されており、質問者もそれで解決したとある。

さて、実際に上記の方法を試してみると、あっさりと期待は裏切られる。

class resolved by unexpected dexというワーニングを吐いた後、class ref in pre-verified class resolved to unexpected implementationなるエラーでアプリが強制終了してしまう。

結論から言えば、apkファイルの中に既にSHARP提供のhardware.jarが存在するのに、実機のシステム内にもhardware.jarの中身に相当するものが存在するので、実行時にどちらで定義されてるクラスを呼び出せば良いか判別できずにエラーになっていると思われる。

じゃあManifestファイルでuses-libraryしなけりゃいいんじゃねって思って、<uses-library android:name=”jp.co.sharp.android.hardware” />を削ってみた。

結果、エラーは出なくなったが、まあ当然というか、実際には固有の機能が動作しない。

詳しく言えば、フラッシュライトをONに設定しても、全く光らない。

公開されてるhardware.jarの中身は恐らく定義だけなのだろう。

ここでさらにネットの海へダイブしてみると、次のようなやりとりを発見した。

http://www.mailinglistarchive.com/html/android-group-japan@googlegroups.com/2011-10/msg00427.html

質問者は、私と全く同じケースで困っており、どうもAndroid SDK r14あたりから発生しだした現象らしい。

それに対するアドバイスが「対処方法は僕のTwitterのどこかにあるよ!」とかいうかなりフリーダムなものなのだが、がんばって回答者のTLを見まくったところ、「SDKをr12にダウングレードしてね!」というものだった。

しかし、そこに提示されたリンクは既に死亡しており、そもそもr12に戻せたとしてもAndroid 4.xxに対応しなくなるので、本末転倒である。

仕方ないので、特定のライブラリをapkにパッケージングしないような方法は無いかと色々検索してみたのだが、結局それっぽいものは見つからず。

結局、まる1日費やして出した対処方法は以下の通り。

/add-ons内にあるSHARPのAddOnフォルダを別名でコピーする。仮にmy_addonという名前とする。

/add-ons/my_addon/manifest.iniというのがあるので、これを編集する。

api=から始まる行があるので、その行をapi=15にする。15は現時点での最新のAPIレベルになる。

判別しやすいように、name=から始まる行も、適当にname=my_addonなどとすれば良いと思う。

後は、この自作のAddOnをBuild Targetに指定すれば目的達成である。

Google APIsも使いたい場合は、上で指定したAPIレベルのGoogle APIs AddOn内のlibsフォルダ内にある*.jarファイルを自作AddOn内のlibsフォルダ内に全てコピーして、manifest.ini内のlibraries=から始まる行と、その下のほうにある、パッケージ名=jarファイル名の羅列を適切に記述すれば良い。

最終的に私が編集したmanifest.iniは以下のようになった。

# SDK Add-on Manifest
# File encoding is UTF-8
name=my_addon
vendor=S.T.
description=My AddOn
# version of the Android platform on which this add-on is built.
api=15
# default skin
skin=QHD960x540
# revision of the add-on
revision=1
# list of libraries, separated by a semi-colon.
# libraries=com.example.android.platform_library
libraries=jp.co.sharp.android.hardware;jp.co.sharp.android.io.obex;jp.co.sharp.android.io.irrc;jp.co.sharp.android.stereo3dlcd;com.google.android.maps;com.android.future.usb.accessory;com.google.android.media.effects
# details for each library
# com.example.android.platform_library=platform_library.jar;Sample optional plaform library
jp.co.sharp.android.hardware=hardware.jar;
jp.co.sharp.android.io.obex=obex.jar;
jp.co.sharp.android.io.irrc=irrc.jar;
jp.co.sharp.android.stereo3dlcd=stereo3dlcd.jar;
com.google.android.maps=maps.jar;API for Google Maps
com.android.future.usb.accessory=usb.jar;API for USB Accessories
com.google.android.media.effects=effects.jar;Collection of video effects
# USB Vendor ID
# This 16-bit integer allows adb to detect new devices, by extending the list
# of USB Vendor IDs it knows. After installing an add-on the command
# 'android update' adb' must be run to update a file that adb reads during
# start-up.
#usb-vendor=0x0000
usb-vendor=0x0000

以上だが、これはあくまでAPIを使いたいというだけの目的なので、このAddOnで作成したエミュレータ内でMap系のAPI等を使うと、恐らくエラーになると思われる。

他に良い方法をご存じの方がおられたら、ぜひご一報下さい。

こちらの記事もどうぞ