2015年10月29日木曜日

Android Studioでモジュール単位のビルドが不安定?

いままでコードを変更するときの影響があまり出ないようにするため、単一プロジェクト、単一モジュールで作成していました。一番の利点はビルドするときに目に見えない影響がほぼないことでしょう。欠点としてはライブラリのようなコードが散在してしまい、管理上はよくありません。
そのため、ほぼ同じコードが存在する複数のプロジェクトを単一プロジェクトでモジュール化してまとめています。

2015年10月28日水曜日

インポート文を自動で設定させる

こんな機能いらない。
ほんと要らない。

そもそもALT+ENTERで追加されるだけで十分じゃないか?

と思うわけですが。

こんな設定。
オフですオフ。

参考
Android Studio最速入門~効率的にコーディングするための使い方

コーディングは効率=ケアレスミスをいかに減らすかです。

2015年10月27日火曜日

ちょw おまwww

Android Studioに呪われ始めました…。

Android Studioのプロジェクト内モジュールのJavaソース

最近Androidよりも開発環境のAndroid Studioに問題が集中しています。

プロジェクト管理を簡単にしようと、とりあえず同様のソースを多重化させてアプリを作っていたのですが、そろそろ一本化させようかとあれやこれや奮闘し行き着いた先がモジュールという管理単位。

2015年10月22日木曜日

どうやってもモジュール分割ができない

Android Studio 1.5 Preview 2のアップデートを済ませ、一つのプロジェクトで複数のモジュールに分けてできれば一つのプロジェクトに複数のアプリをと頑張っています。
途中で色々なエラーに躓きながら、JDKも8をインストールしたり、そのためにリンクできないとか色々な状態に陥りましたが、なんとかapkファイルまでは作られるようにはなりました。

残念なことに並行してNDKの組み込みも行おうとしていて、うまくできないかと試したところやっぱりうまくいかない(笑)

あと一歩というところまでは来ている感じがするものの、うまくコンパイルが通る形にすると、肝心のオブジェクトファイルが無いという…。
com.android.model.libraryの指定しているライブラリ側のbuild.gradle内にandroid.productFlavors {を記述すると途端にライブラリ側のモジュールがどこかに消え去ってしまっているようです。
まぁ無茶なんだなとあきらめるというのがいまのところいいんじゃないかという結論。
 Information:Gradle tasks [clean, :library:generateAllDebugSources, :library:generateAllDebugAndroidTestSources, :library:compileAllDebugSources, :library:compileAllDebugAndroidTestSources, :app:generateDebugSources, :app:generateDebugAndroidTestSources, :app:compileDebugSources, :app:compileDebugAndroidTestSources, :samplelib:generateDebugSources, :samplelib:generateDebugAndroidTestSources, :samplelib:compileDebugSources, :samplelib:compileDebugAndroidTestSources]
:app:clean
:library:clean
:samplelib:clean
:library:preBuild UP-TO-DATE
:library:preAllDebugBuild UP-TO-DATE
:library:checkAllDebugManifest
:library:prepareAllDebugDependencies
:library:compileAllDebugAidl
:library:compileAllDebugRenderscript
:library:generateAllDebugBuildConfig
:library:generateAllDebugAssets UP-TO-DATE
:library:mergeAllDebugAssets
:library:generateAllDebugResValues UP-TO-DATE
:library:generateAllDebugResources
:library:packageAllDebugResources
:library:processAllDebugManifest
:library:processAllDebugResources
:library:generateAllDebugSources
:library:preAllDebugAndroidTestBuild UP-TO-DATE
:library:prepareAllDebugAndroidTestDependencies
:library:compileAllDebugAndroidTestAidl
:library:compileLint
:library:copyAllDebugLint UP-TO-DATE
:library:mergeAllDebugProguardFiles UP-TO-DATE
:library:processAllDebugJavaRes UP-TO-DATE
:library:compileAllDebugJavaWithJavac
:library:packageAllDebugJar
:library:packageAllDebugJniLibs UP-TO-DATE
:library:packageAllDebugLocalJar UP-TO-DATE
:library:packageAllDebugRenderscript UP-TO-DATE
:library:bundleAllDebug
:library:copyArm64-v8aDebugAllRaincharSharedLibraryGdbServer
:library:createArm64-v8aDebugAllRaincharSharedLibraryGdbsetup
:library:compileArm64-v8aDebugAllRaincharSharedLibraryRaincharMainC
:library:linkArm64-v8aDebugAllRaincharSharedLibrary
:library:stripSymbolsArm64-v8aDebugAllRaincharSharedLibrary
:library:arm64-v8aDebugAllRaincharSharedLibrary
:library:copyArmeabi-v7aDebugAllRaincharSharedLibraryGdbServer
:library:createArmeabi-v7aDebugAllRaincharSharedLibraryGdbsetup
:library:compileArmeabi-v7aDebugAllRaincharSharedLibraryRaincharMainC
:library:linkArmeabi-v7aDebugAllRaincharSharedLibrary
:library:stripSymbolsArmeabi-v7aDebugAllRaincharSharedLibrary
:library:armeabi-v7aDebugAllRaincharSharedLibrary
:library:copyArmeabiDebugAllRaincharSharedLibraryGdbServer
:library:createArmeabiDebugAllRaincharSharedLibraryGdbsetup
:library:compileArmeabiDebugAllRaincharSharedLibraryRaincharMainC
:library:linkArmeabiDebugAllRaincharSharedLibrary
:library:stripSymbolsArmeabiDebugAllRaincharSharedLibrary
:library:armeabiDebugAllRaincharSharedLibrary
:library:copyMips64DebugAllRaincharSharedLibraryGdbServer
:library:createMips64DebugAllRaincharSharedLibraryGdbsetup
:library:compileMips64DebugAllRaincharSharedLibraryRaincharMainC
:library:linkMips64DebugAllRaincharSharedLibrary
:library:stripSymbolsMips64DebugAllRaincharSharedLibrary
:library:mips64DebugAllRaincharSharedLibrary
:library:copyMipsDebugAllRaincharSharedLibraryGdbServer
:library:createMipsDebugAllRaincharSharedLibraryGdbsetup
:library:compileMipsDebugAllRaincharSharedLibraryRaincharMainC
:library:linkMipsDebugAllRaincharSharedLibrary
:library:stripSymbolsMipsDebugAllRaincharSharedLibrary
:library:mipsDebugAllRaincharSharedLibrary
:library:copyX86DebugAllRaincharSharedLibraryGdbServer
:library:createX86DebugAllRaincharSharedLibraryGdbsetup
:library:compileX86DebugAllRaincharSharedLibraryRaincharMainC
:library:linkX86DebugAllRaincharSharedLibrary
:library:stripSymbolsX86DebugAllRaincharSharedLibrary
:library:x86DebugAllRaincharSharedLibrary
:library:copyX86_64DebugAllRaincharSharedLibraryGdbServer
:library:createX86_64DebugAllRaincharSharedLibraryGdbsetup
:library:compileX86_64DebugAllRaincharSharedLibraryRaincharMainC
:library:linkX86_64DebugAllRaincharSharedLibrary
:library:stripSymbolsX86_64DebugAllRaincharSharedLibrary
:library:x86_64DebugAllRaincharSharedLibrary
:library:compileAllDebugSources
:library:assembleAllDebug
:library:processAllDebugAndroidTestManifest
:library:compileAllDebugAndroidTestRenderscript
:library:generateAllDebugAndroidTestBuildConfig
:library:generateAllDebugAndroidTestAssets UP-TO-DATE
:library:mergeAllDebugAndroidTestAssets
:library:generateAllDebugAndroidTestResValues UP-TO-DATE
:library:generateAllDebugAndroidTestResources
:library:mergeAllDebugAndroidTestResources
:library:processAllDebugAndroidTestResources
:library:generateAllDebugAndroidTestSources
:library:processAllDebugAndroidTestJavaRes UP-TO-DATE
:library:compileAllDebugAndroidTestJavaWithJavac
:library:compileAllDebugAndroidTestSources
:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
:app:checkDebugManifest
:app:preReleaseBuild UP-TO-DATE
:app:prepareComAndroidSupportSupportV42220Library
:app:prepareComGoogleAndroidGmsPlayServicesAds810Library
:app:prepareComGoogleAndroidGmsPlayServicesAnalytics810Library
:app:prepareComGoogleAndroidGmsPlayServicesAppindexing810Library
:app:prepareComGoogleAndroidGmsPlayServicesBasement810Library
:app:prepareDebugDependencies
:app:compileDebugAidl
:app:compileDebugRenderscript
:app:generateDebugBuildConfig
:app:generateDebugAssets UP-TO-DATE
:app:mergeDebugAssets
:app:generateDebugResValues UP-TO-DATE
:app:generateDebugResources
:app:mergeDebugResources
:app:processDebugManifest
:app:processDebugResources
:app:generateDebugSources
:app:preDebugAndroidTestBuild UP-TO-DATE
:app:prepareDebugAndroidTestDependencies
:app:compileDebugAndroidTestAidl
:app:processDebugAndroidTestManifest
:app:compileDebugAndroidTestRenderscript
:app:generateDebugAndroidTestBuildConfig
:app:generateDebugAndroidTestAssets UP-TO-DATE
:app:mergeDebugAndroidTestAssets
:app:generateDebugAndroidTestResValues UP-TO-DATE
:app:generateDebugAndroidTestResources
:app:mergeDebugAndroidTestResources
:app:processDebugAndroidTestResources
:app:generateDebugAndroidTestSources
:app:processDebugJavaRes UP-TO-DATE
:app:compileDebugJavaWithJavac
C:\AndroidStudioProjects\RainOfCharacter\app\src\main\java\jp\rallwell\siriuth\rainchardream\SirDreamService2.java
Error:(17, 39) エラー: パッケージjp.rallwell.siriuth.raincharlibは存在しません
Error:(33, 24) エラー: シンボルを見つけられません
シンボル:   クラス DreamEffect
場所: クラス SirDreamService2
Error:(38, 22) エラー: シンボルを見つけられません
シンボル:   クラス DreamEffect
場所: クラス SirDreamService2
Error:(174, 26) エラー: シンボルを見つけられません
シンボル:   クラス DreamEffect
場所: クラス RenderingThread
Error:(177, 53) エラー: シンボルを見つけられません
シンボル:   クラス DreamEffect
場所: クラス RenderingThread
C:\AndroidStudioProjects\RainOfCharacter\app\src\main\java\jp\rallwell\siriuth\rainchardream\SirDreamService.java
Error:(24, 39) エラー: パッケージjp.rallwell.siriuth.raincharlibは存在しません
Error:(55, 24) エラー: シンボルを見つけられません
シンボル:   クラス DreamEffect
場所: クラス SirDreamService
Error:(62, 22) エラー: シンボルを見つけられません
シンボル:   クラス DreamEffect
場所: クラス SirDreamService
C:\AndroidStudioProjects\RainOfCharacter\app\src\main\java\jp\rallwell\siriuth\rainchardream\RainCharDreamService.java
Error:(3, 39) エラー: パッケージjp.rallwell.siriuth.raincharlibは存在しません
Error:(4, 39) エラー: パッケージjp.rallwell.siriuth.raincharlibは存在しません
Error:(10, 15) エラー: シンボルを見つけられません
シンボル:   クラス DreamEffect
場所: クラス RainCharDreamService
Error:(11, 21) エラー: シンボルを見つけられません
シンボル:   クラス RainCharBitmapEffect
場所: クラス RainCharDreamService
C:\AndroidStudioProjects\RainOfCharacter\app\src\main\java\jp\rallwell\siriuth\rainchardream\RainCharMDreamService.java
Error:(3, 39) エラー: パッケージjp.rallwell.siriuth.raincharlibは存在しません
Error:(4, 39) エラー: パッケージjp.rallwell.siriuth.raincharlibは存在しません
Error:(11, 12) エラー: シンボルを見つけられません
シンボル:   クラス DreamEffect
場所: クラス RainCharMDreamService
Error:(12, 21) エラー: シンボルを見つけられません
シンボル:   クラス RainCharMEffect
場所: クラス RainCharMDreamService
エラー16個
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
Information:BUILD FAILED
Information:Total time: 44.405 secs
Information:17 errors
Information:0 warnings
Information:See complete output in console

gradleのバージョンやらプラグインなどのしがらみも結構きつく、バージョンを上げようとするとプラグイン側で2.5以外は対応していないとか出てきました。無効化できそうですけど限界です(笑)

そもそも別建ててNDKのオブジェクトを作成すればおそらくそれでいいような気がするし。
まだまだうまく行かない(笑)

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のソースを追っかけるか、サンプルのソースを追っかける必要がある。

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

フルスクリーンのアプリの挙動がおかしい

ダメなシナリオ

1.アプリを起動してフルスクリーンに。
2.ナビゲーションバーを表示させBackさせる。
3.再度アプリを立ち上げると、フルスクリーンになるものの、ナビゲーションバーの表示部分が黒くなってしまう。

画面を回転させるか、キャッシュされているアプリを破棄し、再度アプリを起動させれば復帰する。

 問題ないシナリオ
1.アプリを起動してフルスクリーンに。
2.ホームボタンでホーム画面に戻る。
3.再度アプリを起動するが、アクティビティーが破棄されていなかったため、復帰し無事フルスクリーンのままに。

さらに、ホームボタンではなくアプリ切り替えを行っても問題がなかったことを確認。

予想される問題点

おそらくナビゲーションバーのBackボタンを押したことによりActivityをアプリ側で破棄し、再度起動時に自力で再構築するときにフルスクリーンの対応が不完全ではないかと考えられる。



さて…すぐ対応できるかな…(=_=;

2015年10月11日日曜日

sleep(0)

特定の処理で明らかにsleep(0)を実行するのは解っていたのですが、特に害はないと思ってそのままにしていました。

2015年10月8日木曜日

TextView: テキストが自動的に折り返されないようにする。

TextViewで表示する幅が変わったときや内容が長くなった場合など自動的に折り返されてView自体の縦幅が長くなってしまう。

これを回避する方法は表示する内容を省略させることができます。