- 投稿日:2019-02-15T11:44:21+09:00
Nexus7(2013)に TWRP で Android 9.0.0(Pie) をインストール後、Open GApps の error70 を回避する方法
原因:インストール作業領域のシステムパーティションが容量フルで空きが無いため(英文詳細)。
対策:初回にパーティションリサイズツール sysrepart_1280_120.zip で変更する。インストールの順番(参考)
adb push sysrepart_1280_120.zip /sdcard/ adb push AospExtended-v6.2-deb-20190208-1518-UNOFFICIAL.zip /sdcard/ adb push open_gapps-arm-9.0-nano-20190209.zip /sdcard/上記作業は、Nexus7(2013年モデル)にAndroid 9.0.0(Pie)をインストールしようのサイトが参考になる。
- 投稿日:2019-02-15T02:00:49+09:00
buildSrcでDependencyをIDE補完で記述する
はじめに
AndroidアプリのDependencyを下記のように記述していないでしょうか?
build.gradle... dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' }このように記述すると、バージョン変更時に一つずつ編集しなければならなかったり、そもそも可読性が低いように感じます。
そこで、buildSrcでこれらを保持する方法が良さそうだったのでメモしておきます。参考:
Kotlin + buildSrc for Better Gradle Dependency Managementやり方
1. buildSrcフォルダを作成
モジュールと同じようにプロジェクトルートに
buildSrc
という名前のフォルダを作成します。
2. build.gradle.ktsを作成
作成した
buildSrc
フォルダにbuild.gradle.kts
という名前のkotlin-scriptファイルを作成します。
この段階ではまだ何も記述しなくていいです。
3. Sync Gradle !
sync gradle
しましょう。buildSrc
内に以下のようなファイルが生成されれば成功です。
4. dslを記述
build.gradle.kts
に以下を記述してsync gradle
しましょう。build.gradle.ktsplugins { `kotlin-dsl` }5. Dependencyを保持するオブジェクトクラスを作成
buildSrc
内にsrc/main/java/Dependencies.ktを作成します。
一旦今のDependencyを全て保持させておきたいので、下記のようにします。Dependencies.ktobject Dependencies { object Version { val kotlin = "1.2.71" val support = "28.0.0" val constraint = "1.1.3" val runner = "1.0.2" val espresso = "3.0.2" } val kotlinLib = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Version.kotlin}" val appCompat = "com.android.support:appcompat-v7:${Version.support}" val constraintLayout = "com.android.support.constraint:constraint-layout:${Version.constraint}" val junit = "junit:junit:4.12" val testRunner = "com.android.support.test:runner:${Version.runner}" val espressoCore = "com.android.support.test.espresso:espresso-core:${Version.espresso}" }6. 実際に使う
これで使えるようになりました! 実際に
build.gradle
に適用しましょう!build.gradle... dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation Dep.kotlinLib implementation Dep.appCompat implementation Dep.constraintLayout testImplementation Dep.junit androidTestImplementation Dep.testRunner androidTestImplementation Dep.espressoCore }以前と比べて何を読み込んでいるか分かりやすくなり、IDE補完が効くので編集もしやすくなったかと思います。
サンプル
今回のプロジェクトをGitHubに上げたので、よければ参考にしてください。
https://github.com/TaigaNatto/BuildSorceSample
- 投稿日:2019-02-15T02:00:49+09:00
【Android】dependenciesをIDE補完で記述する
はじめに
Androidアプリのdependenciesを下記のように記述していないでしょうか?
build.gradle... dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' }このように記述すると、バージョン変更時に一つずつ編集しなければならなかったり、そもそも可読性が低いように感じます。
そこで、buildSrcでこれらを保持する方法が良さそうだったのでメモしておきます。参考:
Kotlin + buildSrc for Better Gradle Dependency Managementやり方
1. buildSrcフォルダを作成
モジュールと同じようにプロジェクトルートに
buildSrc
という名前のフォルダを作成します。
2. build.gradle.ktsを作成
作成した
buildSrc
フォルダにbuild.gradle.kts
という名前のkotlin-scriptファイルを作成します。
この段階ではまだ何も記述しなくていいです。
3. Sync Gradle !
sync gradle
しましょう。buildSrc
内に以下のようなファイルが生成されれば成功です。
4. dslを記述
build.gradle.kts
に以下を記述してsync gradle
しましょう。build.gradle.ktsplugins { `kotlin-dsl` }5. Dependencyを保持するオブジェクトクラスを作成
buildSrc
内にsrc/main/java/Dependencies.ktを作成します。
一旦今のDependencyを全て保持させておきたいので、下記のようにします。Dependencies.ktobject Dependencies { object Version { val kotlin = "1.2.71" val support = "28.0.0" val constraint = "1.1.3" val runner = "1.0.2" val espresso = "3.0.2" } val kotlinLib = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Version.kotlin}" val appCompat = "com.android.support:appcompat-v7:${Version.support}" val constraintLayout = "com.android.support.constraint:constraint-layout:${Version.constraint}" val junit = "junit:junit:4.12" val testRunner = "com.android.support.test:runner:${Version.runner}" val espressoCore = "com.android.support.test.espresso:espresso-core:${Version.espresso}" }6. 実際に使う
これで使えるようになりました! 実際に
build.gradle
に適用しましょう!build.gradle... dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation Dependencies.kotlinLib implementation Dependencies.appCompat implementation Dependencies.constraintLayout testImplementation Dependencies.junit androidTestImplementation Dependencies.testRunner androidTestImplementation Dependencies.espressoCore }以前と比べて何を読み込んでいるか分かりやすくなり、IDE補完が効くので編集もしやすくなったかと思います。
サンプル
今回のプロジェクトをGitHubに上げたので、よければ参考にしてください。
https://github.com/TaigaNatto/BuildSorceSample
- 投稿日:2019-02-15T00:40:54+09:00
Kotlin Coroutineの悪い例と解決策
昨日、Coroutineを理解するために以下の記事を書いた
Kotlin Coroutinesパターン&アンチパターン - Qiita
https://qiita.com/ikemura23/items/fb8caeba4c35fcd85644ただ書いただけではなく、本当にそうなのか実装して確かめてみた。
例外処理をtry/catchに頼らない
エラーが発生する
doWork()
をtry / catchしてもダメclass MainActivity : AppCompatActivity() { private val job = Job() private val scope = CoroutineScope(Dispatchers.Default + job) override fun onResume() { super.onResume() // Throw Exceptionの可能性がある処理 fun doWork(): Deferred<String> = scope.async { throw UnknownError() } scope.launch { try { doWork().await() // ここで落ちる } catch (e: Exception) { Log.d(TAG, "ここに到達しない") } } }結果
実行すると、trt / catchの意味なくエラーでアプリが落ちる
E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1 Process: com.ikemura.android_kotlin_lab, PID: 9287 java.util.concurrent.TimeoutException ...解決策
SupervisorJob
で子のエラーを回避する。class MainActivity : AppCompatActivity() { private val job = SupervisorJob() // <= SupervisorJobに変更 private val scope = CoroutineScope(Dispatchers.Default + job) override fun onResume() { super.onResume() // Throw Exceptionの可能性がある処理 fun doWork(): Deferred<String> = scope.async { throw UnknownError() } scope.launch { try { doWork().await() // ここで落ちる } catch (e: Exception) { Log.d(TAG, "キャッチされる") } } }注意すべきasync
↑で示した解決は、SupervisorJobを使用してCoroutineScopeで非同期を明示的に実行した場合にのみ機能する。
以下の async は
SupervisorJob
を使用してもエラーとなる。private val job = SupervisorJob() private val scope = CoroutineScope(Dispatchers.Default + job) // エラーの可能性がある処理 fun doWork(): Deferred<String> = throw TimeoutException() fun loadData() = scope.launch { try { async { doWork() // ここで落ちる } } catch (e: Exception) { Log.d(TAG, "キャッチされない") } }理由は、async内で別のcoroutineが作成され、その範囲内で起動されるから。(ちょっと曖昧)
解決策
coroutineScopeを使ってasyncをラップする。
// エラーの可能性がある処理 fun doWork(): Deferred<String> = throw TimeoutException() fun loadData() { scope.launch { try { coroutineScope { // 追加 async { doWork() } } Log.d(TAG, "ここは実行されない") } catch (e: Exception) { Log.d(TAG, "キャッチされる") } } }上記コードは分かりにくいので、こう見やすくできる。
// エラーの可能性がある処理 suspend fun doWork(): Deferred<String> = coroutineScope { async { throw TimeoutException() } } fun loadData() { scope.launch { try { doWork() // coroutineScopeとasyncをdoWorkに移動させた Log.d(TAG, "ここは実行されない") } catch (e: Exception) { Log.d(TAG, "キャッチされる") } } }try/catchばかり使わない
SupervisorJobを作り、try/catchでラップしておけば大概のエラーはキャッチできるはず。
だが毎回try/catchを使うのではなく、コルーチンの例外をキャッチしてくれるCoroutineExceptionHandlerが用意されているので、こちらを使う。CoroutineExceptionHandlerを個別に指定する例
// エラーハンドリングを作成 private val exceptionHandler: CoroutineExceptionHandler = CoroutineExceptionHandler { _, throwable -> Log.e(TAG, "例外キャッチ $throwable") // ログ出力のみ } private val job = SupervisorJob() private val scope = CoroutineScope(Dispatchers.Default + job) // エラーの可能性がある処理 fun doWork(): Deferred<String> = throw TimeoutException() fun loadData() { scope.launch(exceptionHandler) { // エラーハンドリングを指定 doWork() } }ログ
E/MainActivity: 例外キャッチ java.util.concurrent.TimeoutExceptiontry/catchがなくなり、スッキリした。
CoroutineExceptionHandlerを共通で使い回す
CoroutineExceptionHandlerを個別に指定するのもいいが、CoroutineScopeに渡せば共通で使い回せる。
private val exceptionHandler: CoroutineExceptionHandler = CoroutineExceptionHandler { _, throwable -> Log.e(TAG, "例外キャッチ $throwable") } private val job = SupervisorJob() private val scope = CoroutineScope(Dispatchers.Default + job + exceptionHandler) // exceptionHandlerを渡す // エラーの可能性がある処理 fun doWork(): Deferred<String> = throw TimeoutException() fun loadData() { scope.launch { // exceptionHandler指定が無くなった doWork() Log.d(TAG, "到達しない") } }普段は共通でしておき、必要な時だけ個別に例外を指定するのがベストだろう。
実装したコード
https://github.com/banbara23/Android-Kotlin-Lab/tree/coroutine-sample
参考リンク
https://proandroiddev.com/kotlin-coroutines-patterns-anti-patterns-f9d12984c68e