LicenseChecker.javaでエラー
APK拡張ファイルなどで使用する「play_licensing_library」で以下のようなエラーが発生した。
java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.android.vending.licensing.ILicensingService } ...
Android5.0で「com.android.vending」関連へのbindServiceの仕様が変わったらしく、「LicenseChecker.java」の149行目あたりの以下の個所を
boolean bindResult = mContext .bindService( new Intent( new String( Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U="))), this, // ServiceConnection. Context.BIND_AUTO_CREATE);
以下の用に書き換えたところ解決した。(setPackageが増えている)
boolean bindResult = mContext .bindService( new Intent( new String( Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U="))) .setPackage("com.android.vending"), this, // ServiceConnection. Context.BIND_AUTO_CREATE);
参考サイト:http://stackoverflow.com/questions/28305125/android-app-crashes-on-lollipop
APK拡張ファイルのダウンロード失敗
APK拡張ファイルのダウンロードに失敗した。
(エラーメッセージ:Download failed because the resources could not be found)
原因を完全には特定できなかったが、以下のあたりを試したところ動くようになった。
1.アルファ版(ベータ版)としてAPKを公開し、Google Playからダウンロード
ドラフト版ではダウンロードできない。
またadbでインストールするのではなく、Google Playからダウンロードする必要がある。
(adbでインストールしても動いたときもあったが、正確な仕様は不明)
2.proguardの設定
progurad-project.txtに以下を追記した。
-keepclassmembers public class com.google.android.vending.expansion.downloader.impl.DownloadsDB$* { public static final java.lang.String[][] SCHEMA; public static final java.lang.String TABLE_NAME; }
3.SALT値の変更
DownloaderServiceのgetSALTで返すSALT値を変えてみた。
これが原因だったのかは不明だが、とりあえず変えてみれば良さそう。
参考サイト:http://www.scriptscoop.com/t/93ac0fd00beb/expansion-file-android-download-failed-because-the-resources-could-not.html
4.待つ
しばらく時間をおくと動くようになる
参考サイト:http://stackoverflow.com/questions/23866536/expansion-file-error-download-failed-because-the-resources-could-not-be-found
補足
com.google.android.vending.expansion.downloaderの「Constants.java」の以下の値を書きかえることで、詳細なログが出力されるようになる。
/** Enable verbose logging */ public static final boolean LOGV = false; /** Enable super-verbose logging */ private static final boolean LOCAL_LOGVV = false;
両方trueにすると、ログだけで処理の流れがだいたいわかるようになる。
最終パッケージではfalseに戻した方が良さそう。
アプリ内課金のbindServiceで失敗
一部端末でアプリ内課金処理のためのbindServiceで以下のようなエラーが発生した。
java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.android.vending.licensing.ILicensingService } ...
前述の「LicenseChecker.javaでエラー」と同じく、Android5.0で「com.android.vending」関連へのbindServiceの仕様が変わったことが原因のよう。
以下のようになっている個所に、
Intent aIntentService = new Intent("com.android.vending.billing.InAppBillingService.BIND");
以下のように追記したところ解決した。
Intent aIntentService = new Intent("com.android.vending.billing.InAppBillingService.BIND"); aIntentService.setPackage("com.android.vending");
横向き固定時にスリープから復帰すると落ちる
android:screenOrientation=”landscape”
のアクティビティで、実行中にスリープしたとき、復帰させてアプリに戻ろうとするとエラーで落ちた。
スリープ時に縦向きに戻るのが原因のようで、
android:configChanges=”keyboardHidden|orientation|screenSize”
を指定して、回転時にアクティビティの再生成が行われないようにしたところ解決した。
onCreate内でstartActivity
onCreate内でstartActivityを呼び出すと挙動がおかしくなった。
仕様上呼び出してはいけないようなので、Handler経由で呼び出したところ解決した。
参考サイト:http://d.hatena.ne.jp/esmasui/20130528/1369762487
一部端末でテクスチャなしのポリゴン描画がおかしくなる
一部の端末でテクスチャを使用しないポリゴン描画の色がおかしくなった。
glBindTexture(GL_TEXTURE_2D, 0);
このようにしてポリゴン描画前に明示的にテクスチャをOFFにすることで解決した。
ただシェーダではテクスチャフェッチを行ってないので、なぜこれが影響したのかは謎。
一部端末でシェーダの構造体メンバのmat4に値を設定できない
以下のようにシェーダでuniformを宣言したとき
struct SStruct { mat4 matrix; }; uniform SStruct sUniform;
一部端末でだけこのmatrixに値が設定できなかった。
構造体ではなく単体のmat4だと動作する。
vec4[4]なら大丈夫なのでそちらを使用した。
struct SStruct { vec4 matrix[4]; };
参考サイト:http://stackoverflow.com/questions/14598168/opengl-es-2-0-glsl-mat4-in-uniform-struct-doesnt-work
glBindFramebufferで画面のフレームバッファに戻す
以下のように0を指定すれば良い。
glBindFramebuffer(GL_FRAMEBUFFER, 0);
iostreamをincludeするとハング
Android NDKを使用したC++コードでiostreamをinlcudeしたところ、一部端末でハングした。
Application.mkに以下を追記して、LLVMのSTLを使用するようにしたところ解決した。
APP_STL := c++_static
参考サイト:https://code.google.com/p/android/issues/detail?id=43819
NDKのビルドが重い
そのままだとNDKのビルドがとても遅かったので分散ビルドを設定。
プロジェクトプロパティ>C++ ビルド
のビルドコマンドを
ndk-build -j6
のようにするとで分散ビルドされて早くなった。(この場合6ソースが並列にコンパイルされる)
さらにプリコンパイルヘッダを使用。
Android.mkに以下のようにプリコンパイル用のヘッダファイル名を指定するだけ。
PCH_FILE := stdafx.h
NDKのプリコンパイルヘッダ使用時に強制終了
NDKでプリコンパイル済みヘッダファイルのサイズが大きくなると(100MBちょい)ビルド時に強制終了する。
直接的な対処は出来なかったので、includeする量を調整した。
(コンパイラをclangに変更しても解決したが、そもそものコンパイル時間がclangの方が遅いようだったので断念)
NDKのデバッグ
NDKコードのデバッグ(ブレークポイント等)のためにコンパイルオプションを変更。
プロジェクトプロパティ>C++ ビルド
のビルドコマンドを
ndk-build NDK_DEBUG=1
のように変更。
また構成を「Debug」と「Release」に分けて、デバッグ用と非デバッグ用を簡単に切り替えられるようにした。
なおNDK_DEBUG=1を指定しないと自動的に「NDEBUG」が定義される。
(NDK_DEBUG=1を指定すると「NDEBUG」は定義されない)
「_DEBUG」や「DEBUG」はどちらにしろ定義されないので、必要なら自分で定義する。
NDKでブレークポイントが効かないことがある
NDKでブレークポイントが無視されることがあった。
どうやら起動直後数秒はブレークポイントが効かないらしい。
そこでデバッグ時にはアクティビティのonCreateに以下を追加。
try { Thread.sleep(5000); } catch (InterruptedException iException) { }
JNIEnvを取得する
JNIEnvはネイティブ関数の引数として渡されてくるが、これを保持したり引数として渡すのが難しいことがある。
以下のようにすることで、任意の個所からJNIEnvが取得できる。
static JavaVM* sJavaVM; JNIEnv* GetJNIEnv() { JNIEnv* aEnv; sJavaVM->GetEnv((void**)&aEnv, JNI_VERSION_1_6); return aEnv; } extern "C" { jint JNI_OnLoad(JavaVM* iJavaVM, void* iReserved) { sJavaVM = iJavaVM; return JNI_VERSION_1_6; } }
JNI_OnLoadはJNI初期化時に自動的に呼ばれる。
GetJNIEnv()を呼び出せば、JNIEnvが取得できる。
ただしpthreadなどc++で作成したスレッドからではそのままでは使用できない。
以下のような関数を用意する。
void AttachCurrentThread() { JNIEnv* aEnv; sJavaVM->AttachCurrentThread(&aEnv, nullptr); } void DetachCurrentThread() { sJavaVM->DetachCurrentThread(); }
スレッド開始直後にAttachCurrentThread()を呼び出すことで、そのスレッドがJavaに関連付けられ、GetJNIEnv()関数でJNIEnvが取得できるようになる。
スレッド終了直前にはDetachCurrentThread()を呼び出して関連付けを解除する必要がある。