2015年10月21日水曜日

Error:Unable to load class 'org.gradle.nativeplatform.internal.DefaultBuildType_Decorated'.

よくわからない状態になったらこんなエラーメッセージが表示されるようになってビルドも何も通らなくなってしまった。

Error:Unable to load class 'org.gradle.nativeplatform.internal.DefaultBuildType_Decorated'. Possible causes for this unexpected error include:
  • You are using JDK version 'java version "1.7.0_79"'. Some versions of JDK 1.7 (e.g. 1.7.0_10) may cause class loading errors in Gradle. Please update to a newer version (e.g. 1.7.0_67). Open JDK Settings
  • Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.) Re-download dependencies and sync project (requires network)
  • The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem. Stop Gradle build processes (requires restart)
  • Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project.
In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.

挙句の果てにJDK 8u60もインストールして 1.8にバージョンアップさせたりしてもやはりだめ(笑)

結局検索してみると、いつものスタックオーバーフローが引っかかり
Android Studio: Gradle Build fails with error: Unable to load class 'com.android.build.gradle.ndk.NdkPlugin' にて
Vinod Khosla「Try cleaning your project and re-build.」
とのこと。プロジェクトのクリーンとリビルドを試しなさい。ってことでエラーがまともに出るようになりました。
以前おかしな挙動が収まらなかったときは、プロジェクト内の自動生成物をほとんど削除すればまともになったのですが、正当法はこちらなんでしょうね。

2015年10月19日月曜日

五里霧中な開発環境

いったい何が問題なのかと言えばGoogle playのライセンスチェックがorg.apache.httpに依存している状態なのにもかかわらず、SDK 23からorg.apache.httpがライブラリから外されるという状態になりました。

ネイティブ クラッシュ(/system/lib64/libskia.so)

一通りダウンロード数の多いアプリの変更が済み一夜明けてみると、DeveloperConsoleにバグレポートのカウントが上がってました。

2015年10月16日金曜日

TextureViewしかないのかな?

問題が発覚してからほぼ丸一日SampleのソースコードとSDKのソースコードをにらめっこしていた。
色々と確定した要素が一晩経ってから判明したことは、どうも描画が行われなくなるタイミングががロック画面が生成されたタイミングで表示されなくなるということが確定要素として分かった。

Android 5.xまではロック画面の生成タイミングが若干不安定だったのか、Daydreamの時にだけすこし挙動が異なっていたのかはわからないが、Android 6.0 からはロックまでのタイミングと、スリープまでのタイミングの扱いが今までと変わっているということのようだ。(まだ混乱してる感じが強く日本語になってない(笑))

ちょっと言い方を変えると、Daydreamの表示されている意味合いが変わったのかともとれる。5.xまではDaydreamの表示が行われ、スリープのタイミングまでなにも行動は起こされなかったか、またはロック画面の生成が不安定だったのかもしれない。

Daydreamを動作直後に話を限定するともう少し具体的になる。

6.0ではDaydreamの表示が行われたタイミングでロック画面とスリープ画面のカウントダウンが始まり、ロック画面までの時間が来た時点でロック画面が生成され、表示上のWindowレイヤーが変更されている。
ただし、この状態で画面スリープまでの時間が経過していなければまだ表示は行われている。
逆に先に画面スリープの時間がロック時間よりも短くても画面は表示されたままとなる。

その後、画面スリープまでの時間が経過してもDaydreamの表示は行われたままとなる。
インタラクティブモードではないDaydreamの場合は、この状態で画面タッチなどを行いDaydreamが終了するとロック画面の時間が経過していなくてもスリープまでの時間が経過していればロック画面が表示される。

おそらく仕様としてその辺が整理されたのかもしれない。
挙動も納得の行く動作結果になっていると感じます。

さて、ここまで行くまでにソースを色々と確認していました。

標準のDaydreamとして時計がありますが、時計の実装方法はとてもシンプルに行われていて、Daydream独自のコードはほとんどありません。
実際の処理の中身はカスタムビューとして定義されています。とくにSurfaceViewが使われているわけでもなく、一般的なView要素として表示が行われているため、Android的にはものすごくスマートな実装方法になっています。

またもう一つのColorsは、SurfaceViewに近いおそらくGLSurfaceViewで実装され、描画もほとんどView側で処理され最終的にはOpenGLに表示は委ねられている形になっています。

どちらも個人的に一般的だと思っていたSurfaceViewでの実装ではなく、なんというかマニアックな実装方法だと感じています。

ここでソースコードを忘れて結果だけとらえれば「SurfaceViewがダメなんじゃね?」的な発想になりますが、この時点ではまだSurfaceViewを悪く考えることができませんでした(笑)
結果、シンプルなDaydreamのソースを作り、そのあとlayoutファイルでTextViewとSurfaceViewの要素のものを画面に表示させていろいろと試したところ、TextViewの内容はいつでもどのタイミングでもしっかりと表示され、同時に表示されているSurfaceViewはロック画面が生成されていると思われるタイミングで描画しなくなっているという結果が確定しました。

ではSurfaceViewがダメならいったいどうすれば良いのだろうと言う事に本題が(ようやく)移行します。もうこの時点でほぼ丸一日、どんだけどんくさいんだよ…。

さて、選択肢は色々ありますね? あるのかな?
アプリをできるだけ手軽に修正したいというのが前提になります。
OpenGL化するには色々と面倒なことになりそうです。
ほかは??
と、いろいろ見ていましたが前から気になっていたSurfaceViewの下のTextureViewというものが使えるのかな?という期待で検索してみました。
結果としてはほぼ代用できそうです。

そのままの状態でCanvasが扱えるのが一番の利点でしょうか。
実際にSurfaceViewのものを強引にTextureViewに置き換えて実行してみます。

ちゃんとまともに動作するのがようやく確認できました。

例外処理の発生タイミングがわからないのと、API14以降というハードルが残っていますが、API14以降というのはそもそもDaydreamがAndroid 4.2(Jelly Bean MR1)の17なので問題はありません。古いバージョンに対応しているのはちょっと対応に悩みそうです。

daydreamで表示されなくなるという現象

Android 6.0で自前のdaydreamを動かしたところで表示がされなくなってしまうという現象に悩み始めて6時間ほど。

とてもシンプルな形のソースも拾ってきて実行したところ同様の結果になった。

ログを見てみると

10-15 23:06:04.876 1832-1832/? D/PhoneStatusBar: disable: < expand ICONS* alerts SYSTEM_INFO* back home recent clock search quick_settings >
10-15 23:06:05.000 1832-1832/? D/PhoneStatusBar: disable: < expand ICONS alerts SYSTEM_INFO back HOME* RECENT* clock SEARCH* quick_settings >
10-15 23:06:05.020 1832-1832/? D/PhoneStatusBar: disable: < expand ICONS alerts SYSTEM_INFO back home* RECENT clock SEARCH quick_settings >
10-15 23:06:05.022 1832-1832/? D/PhoneStatusBar: disable: < expand icons* alerts system_info* back home RECENT clock SEARCH quick_settings >

と言ったログが出る瞬間に消えていることから、PhoneStatusBarの挙動が変わったということなのだろうか?

そもそもPhoneStatusBarって?みたいな初心者なわけですが、AndroidではJBから大幅にWindowのレイヤー階層が変わったとかなんとか。Windowのレイヤーって話はちょこちょこ見ているものの正直直接どうのこうのできそうにないのでスルーしていた部分です。

似たような現象が発生したことがあるのはフルスクリーンにしたときに一定のタイミングで表示が消えてしまうという現象。
今まではロック画面が構築されたタイミングで落ちている感じだったので悩んでいた時もあったけど、まぁそういう仕様なのだとあきらめていました。

が、今回は何をどうやっても消えてしまうような感じになっています。

フルスクリーンのアプリではステータスバーの表示が絡んでいそうなので、もしかすると同じくPhoneStatusBarが関係している気もしないでもないわけで…

ドキュメントやSDKのソースを見ていてもこれと言ったヒントがまったく見えてこない。

さて…愚痴もこの辺でもう少し調べてみよう。

2015年10月15日木曜日

ようやくSDK23へ

今までどう足掻いてもダメだったSDK23でのコンパイル。
proguardを使わなければコンパイルは出来てはいたのですが、今まで使えなかったものを使わないというのはなんとも。

エラーメッセージを頼りにいろいろやっていたのですが結局どこかでつまずいてしまうという。
そして摩訶不思議なビルドを繰り返すとまた再度エラーになるとか、ファイル同期の罠にはまりつつ結局導き出した打開策は「SDK22で時期が来るまで待つ」という結論でしたが、マッシュルームが今朝NEXUS9に落ちてきて、手持ちのアプリの不具合もちょこちょこ見つかったので、ビルドを見直すかと…

proguard-rules.proのファイルの設定をいじって結局どこが原因か判断点かなかったのですが、結果を知った今だとなんとなくproguardのログを見ればわかったのかな?って思います。

私の場合は結局のところproguard-rules.proに

-keep class com.google.android.gms.** { *; }
-dontwarn com.google.android.gms.**

と追加してあげれば大丈夫だったという結論です。
そもそもgoogleさんのライブラリを使うためにいろいろと揺れている感じの設定事項のお話があるようですが、現状のSDK23ベースのproguardでは自前でルールを設定しなさい。という感じなのかな?

不要かもしれないけど追加したルールは

-keep class org.apache.http.** { *; }
-dontwarn org.apache.http.**

-keep class android.net.http.** { *; }
-dontwarn android.net.http.**

-keep class android.support.v7.** { *; }
-keep class android.support.v4.** { *; }

-keep class com.google.android.gms.** { *; }
-dontwarn com.google.android.gms.**

となっています。使ってないサポートライブラリもあったりしますが、経験上エラーで見たことのあるライブラリのapacheやnetも含めています。

とりあえず一つの問題が解決した(笑)

参考
http://stackoverflow.com/questions/31643339/errorexecution-failed-for-task-apppackagerelease-unable-to-compute-hash
answered Oct 8 at 17:26 のgoRGonさんに感謝!

スクリーンセイバーの挙動がおかしい

どうもスクリーンセイバーの挙動がおかしくなってしまった。

表示はされるが、15~30秒程度で画面が消失してしまう。

2つのパターン(handlerで動かしているものと、自前のスレッドで動かしているもの)で同様の現象が発生している。

原因がおそらく不完全な実装になっているということなのだろう。

対応策としてSDK22でコンパイルされているのでこれをSDK23に変更してコンパイルしてみること。
あとは…SDKのソースを追っかけるか、サンプルのソースを追っかける必要がある。

さて…これも早急に対応したい。