Macbook Pro(15-inch, 2016)のキーボードが2回押されるので修理に出した
これです。
実は買ってから結構序盤の段階でbが2回押されたり1回も押されなかったりする問題が起きてました。上のプログラムが発表されてからいつか修理に出したいなーと思いつつも1週間くらいPCないのはなーと思いとどまってました。このゴールデンウィークで1週間海外旅行に行くことになったのでその間に出すことにしました。
流れ
まずバックアップを取ります。Apple Storeでバックアップ取ったか聞かれます。結局データは消えずに戻ってきました。
バックアップを取ったらApple Storeに行きます(ちゃんと調べてないけどWebから直接修理に出せる気もする)。職場が近いので表参道店に行きました。平日11:30から昼休みを取って行ったんですが、12:40からしか空いてないと言われました。平日でも混んでいる・・・。1時間後にもう1度行きました。
まず症状を伝えたところキーボード内部の掃除をしてくれました。この段階でbが1回も押されない現象は直りました。ただ2回押される問題は直らなかったので結局修理に出すことに。キーボード下の基盤を全交換なので本来ならば88000円のようでしたが上記プログラムがあるので無料でした。
配送と店舗受け取りか選べます。私は店舗受け取りにしました。
4/24に修理に出したのですが4/26にはもう受取可能のメールが来ました。これだったら旅行とかなくても出せばよかった・・・。むしろ到着が早すぎて5/3受け取り以降は要連絡(日程調整が要る?)となってしまったので帰国後すぐ受け取らなければならなかったです。
あとは受け取って終わりです。受け渡しのときにMacbook Proだけ渡されたので何か袋とか大きいバッグを持っていったほうがよいです。
終わりに
2~3日で修理が終わって受け取れるのでいつ出してもよかったなと思いました。キーボードが直っただけでなくディスプレイなども綺麗にしてくれたのでありがたかったです。
Ultimate Hacking Keyboardを買いました
会社ではErgoDoxを使っていますが、リモートワークするときに毎回持って帰るのがめんどくさいなーと思って会社の自作キーボードチャンネルを見ていたところ良さげな分離キーボードだったので買ってみました。去年の11/3に注文して3/21にようやく到着した。
かっちょいい。
箱を開けるとこんな感じ
パームレストも買いました。
値段
計40533円($324.93+2380円)
- キーボード本体: $240
- パームレスト: $55
- 送料: $29.93
- 関税: 2380円
組み立て
半田とかのスキルはないのでキーボードが完成済みなのは助かります。↓に従って組み立てます。
3種類組み立て方があって、今回はTentingを選択。
まずパームレストをつけます。パームレストにネジが入っています。
左右2箇所ずつネジ止めします。
足をつけます。上下に3個ずつのネジをつけます。
足をはめます。
完成。
キーマップ
繋いでみると現在のキーマップが表示されます。MacのQWERTYなのでFn+4で切り替える。
Keymap Name | Keymap Abbreviation | Keymap Switch Shortcut |
---|---|---|
QWERTY for PC | QWR | Fn + 1 |
Dvorak for PC | DVO | Fn + 2 |
Colemak for PC | COL | Fn + 3 |
QWERTY for Mac | QWM | Fn + 4 |
Dvorak for Mac | DVM | Fn + 5 |
Colemak for Mac | COM | Fn + 6 |
Mouseキー
Macの左Ctrlの位置にMouseキーがあります。これでマウスを操作したりクリックしたり画面をスクロールしたりできる模様。
Modキー
矢印キーを打つときはModキーを押しながらjkliで打つ。他にもDeleteキーやHomeキーもModキーを押しながらで打てるようになる。
Agentがあってこれでキーをいじれるようです。 github.com
終わりに
まだまだ操作に慣れないですが、慣れると使いやすそうです。ErgoDoxほど自由ではないかなと思ってましたが以外にカスタマイズできそう。キーボード自体の品質も良くて満足です。ただ来るまで半年近くかかったので今から買う人はそのくらいかかること前提で注文したほうがいいと思います。
追記(2019/3/23)
公式アカウントからリプライが来ました。どうやら4月中旬からは改善されて1週間以内に発送できるようになるようです。
Thank you very much for sharing! The wait time will be much less in the future. It'll take less than a week for us to ship new orders starting from about the middle of April.
— Ult. Hack. Keyboard (@UltHackKeyboard) March 22, 2019
Android Gradle plugin 3.2.0からjacocoでJavaファイルのカバレッジが取れない問題の修正
通常はKotlinだけで書くと思うので関係ないです。Java -> Kotlin移行中のプロジェクトだと起きる。
↓以前の記事
原因
Product Falvorを free
としたとき、Javaのクラスファイルの出力先がAndroid Gradle plugin 3.2.0で ${buildDir}/intermediates/classes/free/debug/
から ${buildDir}/intermediates/javac/freeDebug/compileFreeDebugJavaWithJavac/classes/
に変わった。
修正
あとGradleのアップデートでパスの指定がdeprecatedになったのでそれも修正
task jacocoTestReport(type: JacocoReport, dependsOn: ['testFreeDebugUnitTest']) { group = "Reporting" description = "Generate Jacoco coverage reports after running tests." reports { xml.enabled true html.enabled true csv.enabled false xml.destination new File("${buildDir}/reports/jacoco/jacocoTestReport.xml") html.destination new File("${buildDir}/reports/jacoco/html") classDirectories.setFrom( files( fileTree( dir: "${buildDir}/intermediates/javac/freeDebug/compileFreeDebugJavaWithJavac/classes/", exclude: coverageExcludeFiles ) + fileTree( dir: "$buildDir/tmp/kotlin-classes/freeDebug", excludes: coverageExcludeFiles ) ) ) } sourceDirectories.setFrom(files(coverageSourceDirs)) executionData.setFrom(new File("${buildDir}/jacoco/testFreeDebugUnitTest.exec")) doLast { println "jacoco xml report has been generated to file://${buildDir}/reports/jacoco/jacocoTestReport.xml" println "jacoco html report has been generated to file://${reports.html.destination}/index.html" } }
?attr/selectableItemBackgroundは何色か
答え:
アプリ・Activityに適用しているテーマ、起動するAndroid OS VersionとcompileSdkVersionとサポートライブラリのバージョンによる。
Theme.AppCompat.Light
を使っていてAndroid 5.0以上でcompileSdkVersion 28でAndroidXなら #21000000
以下解説
?attrとは何か
?attrは適用しているテーマに定義されている値を参照する。なのでアプリに適用しているテーマを確認すればよい。
テーマを辿る
例えばAndroidXで Theme.AppCompat.Light
を使っているとする。
AndroidXのres/values を見ると values-v16~v28まである。それぞれの theme_base.xml
を見て階層構造を確認してみると以下の図のようになる(もはやAndroid 4系を見る必要はないのでここではv21以上を対象とする)。
では実際にどの selectableItemBackground
が使われるかを見る。
selectableItemBackground
は android:Theme.Material.Light.NoActionBar
以外には宣言されていないので android:Theme.Material.Light.NoActionBar
の selectableItemBackground
が使われることになる。
これはアプリのAndroid SDK、つまり compileSdkVersion
で指定しているSDKにあるスタイルが使われる。
ここからはAndroid Studio上でコードを確認できる。
マテリアルデザイン系のテーマは themes_material.xml
に定義されている。
Theme.Material.Light.NoActionBar
には selectableItemBackground
がないのでその一つ前の Theme.Material.Light
を見る。
<style name="Theme.Material.Light" parent="Theme.Light"> ... <item name="selectableItemBackground">@drawable/item_background_material</item>
ようやく宣言が見つかった。
item_background_material.xml
を見てみる。
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?attr/colorControlHighlight"> <item android:id="@id/mask"> <color android:color="@color/white" /> </item> </ripple>
?attrなのでもう一度上のテーマ階層を順に見ていくが colorControlHighlight
は宣言されていないので Theme.Material.Light
に戻る。
<style name="Theme.Material.Light" parent="Theme.Light”> ... <item name="colorControlHighlight">@color/ripple_material_light</item>
Android SDK内の ripple_material_light.xml
を見る。
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:alpha="@dimen/highlight_alpha_material_light" android:color="@color/foreground_material_light" /> </selector>
色は foreground_material_light
であることがわかった。更に辿っていく。
colors_material_xml
<color name="foreground_material_light">@color/black</color>
colors.xml
<color name="black">#ff000000</color>
ついに到達。 #ff000000
である。
同様にアルファも見ると0.12であることがわかった。
<item name="highlight_alpha_material_light" format="float" type="dimen">0.12</item>
アルファを16進数にに置き換えると21。つまり #21000000
となる。
おわりに
全部は確認していないが、Android 5.0以上であればどのcompileSdkVersionでどのサポートライブラリのバージョンでもそうそうこの色は変わらないのではないかと思う。必要であればそれぞれの環境の値をこの記事と同じ方法で辿っていけば実際の値が確認できる。
Droidkaigi 2019に参加しました
2019/2/7~2/8に行われたDroidkaigi 2019に参加してきました。
弁当おいしかった。
バリスタさんは長蛇の列でした。おいしかった。
今年はコントリビュートしました🎉(左上)
パーティーはめっちゃ人がいました...
以下参加したセッションのメモです。
1日目
マルチモジュールなプロジェクトでテストはどう変わる?
- Mutation testing
- 変更検知してテストが通ってしまったら変更点に関するテストがないと判断されて失敗する
- 抜けているテストがわかる
- PIT pitest.org
- マルチモジュール化したとき、どの組み合わせまでテストを書くか?を要検討
マルチモジュールプロジェクトでのDagger2を用いたDependency Injection
- Dagger-AndroidのモチベーションとしてはApplicationがinjectできることを知っているのが良くないよね
- FragmentInjectが上書きされるので考える必要がある
LiveData と Coroutines で実装する DDD の戦術的設計
- IDをStringにしない(理由は2017?で発表済み)
- Stringで比べたときに他のIDだとしてもマッチングしてしまう
- 文字列のテキスト表現をどこに置くか?
- 誰の関心事か?
- 日付・時間がモデルの関心事で共通ならモデル
- UIごとに変わるならUIの関心事
- 誰の関心事か?
- Repository
- オブジェクトがメモリ上にあるかのように振る舞う
- nullableにするのではなく共通項目をsealed classで定義
- Lunch, PartyをTimelineItemとしたが、そのようなユビキタス言語はないので悩ましいところ。ドメインエキスパートとすり合わせる
- suspend は非同期を表明するものとも言える
Master of Android Theme
- どんなattributeがあるかはAndroid Studioの補完→GitHubでコード見る
- どう共通化するかでstyle(部分的)かtheme(アプリ全体)か選ぶ
The good and bad of modern app architecture
- BDDでテストかけるようにしてもメンバーの母国語が英語じゃないから逆にわかりづらくなる
- きれいな設計にしても新人がなぜこんなにコードを書かなければならないのかとなり教育も大変
- リリースが迫ってくるとワークアラウンド的に規約から外れたコードが入ってメンテナンスが大変になる
- 層を分けて担当する
Redux for Android
- ReduxはFlux実装の一部
- Reduxは状態管理のため
2日目
中規模以上のアプリ開発におけるCIレシピとリリースフロー戦略
- BitriseだとGUIで組めて属人化しにくくできる
- tagトリガーでGoogle Playアップロード
- 規模の大きいときのfeatureのブランチ名をきめておいてCIを設定
- Bitriseでは_をつけることで単体では実行できないユーティリティフローとして定義できる
- Google Play Developer APIで段階公開を自動化できる
- Crashlytics APIでは統計データを取れないので連携はしんどい
Guide to app architectureを踏まえた既存アプリの設計改良
- 人的リソースや設計の将来性も考慮する
- イベントはSingleLiveEventで、状態はDatabindigで行う
Deep dive into MotionLayout
- スワイプやクリックに応じてViewを動かしたり色を変えたりできる
- CycleEditorでGUIで設定できる
- KeyTriggerでどこまでスクロールしたかでモーションを指定できる
- alpha4でRecyclerViewとの組み合わせが入る。SharedElementTransitionみたいなことがMotionLayoutでできる。
Android Studio設定見直してみませんか?
- File Colorでバリアントでビルドされるところが色付けされるの助かる
- Layout EditorでXMLが左に来るのありがたい...
Lifecycle, LiveData, ViewModels - The inner wiring
- Android PからonSavedInstanceState()がコールされるタイミングがonStop()の後になった
- FragmentとFragmentのViewのライフサイクルは異なる
Androidにおけるパフォーマンスチューニング実践
- ライフサイクルを考慮していつ破棄するのかを意識する
- レンダリングはハード(HWA)とソフトで2種類ある
- ソフトは全描画
- ハードはdirty(必要な分)のみ
- トラバーサルで描画するのでコストが高い
- 開発者オプションを有効
- 赤はoverdrawが4回以上走っているので要改善
- 階層を減らす。inflateの第二引数をtrue。ConstraintLayoutを使う
- Protocol bufferでサイズを減らす
- WebPでサイズ圧縮
Navigation Architecture Component によるアプリ内遷移の管理
- Deeplink時でもバックスタックを自動形成してくれる
- SafeArgで引数を渡した遷移のためのメソッドが自動生成される
build.gradle.ktsに移行しよう
- Kotlin移行で補完が効くようになる。エラーが表示されるようになる
- 一部分だけでも移行できる
- エラー修正の最終手段はgroovyとして別ファイルで読み込む
おわりに
今年はマルチモジュール関連の話が多かった印象でした。Droidkaigiに参加しているようなエンジニアでもまだまだ導入できてないところが多そうなのでまだ安心・・・という訳じゃないですが、積極的にマルチモジュール化していきたいと感じました。アーキテクチャ系の話もいくつか聞きましたが、MVVMからFluxにしたみたいな話もあったのでFluxの何がいいか調べ始めないとだめだなと。その上でMVP/MVVM/Flux/その他でどのアーキテクチャがアプリに適しているかを検討したい。
MotlonLayoutやNavigationは導入したら面白そうだなという雰囲気を感じれたので導入機会を探っていきたいところ。AACは入っているの当たり前でしょ感があったのでMVPだったらどう入れるか?MVVMにしてViewModel入れるか?等考えたほうがいいなと思いました。
2日間お疲れ様でした。
Gradle plugin 3.3へのアップデート
先日Android Studio 3.3と共にGradle plugin 3.3.0がきたのでアップデートしてみた。
Crashlyticsを使っているとWarning
WARNING: API 'variant.getExternalNativeBuildTasks()' is obsolete and has been replaced with 'variant.getExternalNativeBuildProviders()'. It will be removed at the end of 2019. For more information, see https://d.android.com/r/tools/task-configuration-avoidance. To determine what is calling variant.getExternalNativeBuildTasks(), use -Pandroid.debug.obsoleteApi=true on the command line to display a stack trace. Affected Modules: app
android.debug.obsoleteApi=true
をgradle.propertiesに追加するとstacktraceが見れる
WARNING: API 'variant.getExternalNativeBuildTasks()' is obsolete and has been replaced with 'variant.getExternalNativeBuildProviders()'. It will be removed at the end of 2019. For more information, see https://d.android.com/r/tools/task-configuration-avoidance. REASON: It is currently called from the following trace: java.lang.Thread.getStackTrace(Thread.java:1556) com.android.build.gradle.internal.errors.DeprecationReporterImpl.reportDeprecatedApi(DeprecationReporterImpl.kt:79) com.android.build.gradle.internal.api.BaseVariantImpl.getExternalNativeBuildTasks(BaseVariantImpl.java:487) com.android.build.gradle.internal.api.ApplicationVariantImpl_Decorated.getExternalNativeBuildTasks(null:-1) sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:498) org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:98) groovy.lang.MetaBeanProperty.getProperty(MetaBeanProperty.java:59) org.gradle.internal.metaobject.BeanDynamicObject$MetaClassAdapter.getProperty(BeanDynamicObject.java:228) org.gradle.internal.metaobject.BeanDynamicObject.tryGetProperty(BeanDynamicObject.java:171) org.gradle.internal.metaobject.CompositeDynamicObject.tryGetProperty(CompositeDynamicObject.java:55) org.gradle.internal.metaobject.AbstractDynamicObject.getProperty(AbstractDynamicObject.java:59) com.android.build.gradle.internal.api.ApplicationVariantImpl_Decorated.getProperty(null:-1) org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:49) org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:299) com.crashlytics.tools.gradle.ProjectVariantState.resolveDebugNativeLibsPath(ProjectVariantState.groovy:130) sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:498) org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:98) groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:352) groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:68) org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:177) com.crashlytics.tools.gradle.ProjectVariantState$_deriveFrom_closure1.doCall(ProjectVariantState.groovy:55) sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:498) org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:98) groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:264) groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) groovy.lang.Closure.call(Closure.java:418) groovy.lang.Closure.call(Closure.java:434) org.codehaus.groovy.runtime.DefaultGroovyMethods.with(DefaultGroovyMethods.java:327) org.codehaus.groovy.runtime.dgm$758.invoke(null:-1) org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoMetaMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:251) org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:71) org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:128) com.crashlytics.tools.gradle.ProjectVariantState.deriveFrom(ProjectVariantState.groovy:43) com.crashlytics.tools.gradle.ProjectVariantState$deriveFrom.call(null:-1) com.crashlytics.tools.gradle.CrashlyticsPlugin.createTaskBuilder(CrashlyticsPlugin.groovy:271) com.crashlytics.tools.gradle.CrashlyticsPlugin.this$2$createTaskBuilder(CrashlyticsPlugin.groovy:-1) sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:498) org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:210) org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:59) com.crashlytics.tools.gradle.CrashlyticsPlugin.addPluginTasks(CrashlyticsPlugin.groovy:245) com.crashlytics.tools.gradle.CrashlyticsPlugin.this$2$addPluginTasks(CrashlyticsPlugin.groovy:-1) sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-2) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:498) org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:98) groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) org.gradle.internal.metaobject.BeanDynamicObject$MetaClassAdapter.invokeMethod(BeanDynamicObject.java:479) org.gradle.internal.metaobject.BeanDynamicObject.tryInvokeMethod(BeanDynamicObject.java:191) org.gradle.internal.metaobject.ConfigureDelegate.invokeMethod(ConfigureDelegate.java:78) org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeOnDelegationObjects(ClosureMetaClass.java:398) org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:338) groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:68) org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:185) com.crashlytics.tools.gradle.CrashlyticsPlugin$_addPluginTasksToApplicationVariantsIn_closure2.doCall(CrashlyticsPlugin.groovy:92) sun.reflect.GeneratedMethodAccessor2168.invoke(null:-1) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:498) org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:98) groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:264) groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) groovy.lang.Closure.call(Closure.java:418) groovy.lang.Closure.call(Closure.java:434) org.gradle.api.internal.ClosureBackedAction.execute(ClosureBackedAction.java:71) org.gradle.util.ConfigureUtil.configureTarget(ConfigureUtil.java:155) org.gradle.util.ConfigureUtil.configure(ConfigureUtil.java:106) org.gradle.util.ConfigureUtil$WrappedConfigureAction.execute(ConfigureUtil.java:167) org.gradle.internal.ImmutableActionSet$SetWithFewActions.execute(ImmutableActionSet.java:285) org.gradle.api.internal.DefaultDomainObjectCollection.doAdd(DefaultDomainObjectCollection.java:244) org.gradle.api.internal.DefaultDomainObjectCollection.add(DefaultDomainObjectCollection.java:233) com.android.build.gradle.AppExtension.addVariant(AppExtension.java:87) com.android.build.gradle.internal.ApiObjectFactory.create(ApiObjectFactory.java:134) com.android.build.gradle.BasePlugin.createAndroidTasks(BasePlugin.java:777) com.android.builder.profile.ThreadRecorder.record(ThreadRecorder.java:81) com.android.build.gradle.BasePlugin.lambda$createTasks$4(BasePlugin.java:651) com.android.build.gradle.internal.crash.CrashReporting$afterEvaluate$1.execute(crash_reporting.kt:37) com.android.build.gradle.internal.crash.CrashReporting$afterEvaluate$1.execute(crash_reporting.kt:-1) org.gradle.configuration.internal.DefaultListenerBuildOperationDecorator$BuildOperationEmittingAction$1$1.run(DefaultListenerBuildOperationDecorator.java:155) org.gradle.configuration.internal.DefaultUserCodeApplicationContext.reapply(DefaultUserCodeApplicationContext.java:58) org.gradle.configuration.internal.DefaultListenerBuildOperationDecorator$BuildOperationEmittingAction$1.run(DefaultListenerBuildOperationDecorator.java:152) org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300) org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292) org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174) org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) org.gradle.configuration.internal.DefaultListenerBuildOperationDecorator$BuildOperationEmittingAction.execute(DefaultListenerBuildOperationDecorator.java:149) org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:91) org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:80) org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:42) org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:230) org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:149) org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:58) org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:324) org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:234) org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:140) org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:37) org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) com.sun.proxy.$Proxy27.afterEvaluate(null:-1) org.gradle.configuration.project.LifecycleProjectEvaluator$NotifyAfterEvaluate$1.execute(LifecycleProjectEvaluator.java:187) org.gradle.configuration.project.LifecycleProjectEvaluator$NotifyAfterEvaluate$1.execute(LifecycleProjectEvaluator.java:184) org.gradle.api.internal.project.DefaultProject.stepEvaluationListener(DefaultProject.java:1418) org.gradle.configuration.project.LifecycleProjectEvaluator$NotifyAfterEvaluate.run(LifecycleProjectEvaluator.java:193) org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300) org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292) org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174) org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31) org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.run(LifecycleProjectEvaluator.java:110) org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300) org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292) org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174) org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31) org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:68) org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:687) org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:140) org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:35) org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:62) org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:41) org.gradle.initialization.DefaultGradleLauncher$ConfigureBuild.run(DefaultGradleLauncher.java:274) org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300) org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292) org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174) org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31) org.gradle.initialization.DefaultGradleLauncher.configureBuild(DefaultGradleLauncher.java:182) org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:141) org.gradle.initialization.DefaultGradleLauncher.getConfiguredBuild(DefaultGradleLauncher.java:119) org.gradle.internal.invocation.GradleBuildController$2.call(GradleBuildController.java:86) org.gradle.internal.invocation.GradleBuildController$2.call(GradleBuildController.java:83) org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:154) org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:38) org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:96) org.gradle.internal.invocation.GradleBuildController.configure(GradleBuildController.java:83) org.gradle.tooling.internal.provider.runner.ClientProvidedBuildActionRunner.run(ClientProvidedBuildActionRunner.java:70) org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35) org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35) org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32) org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.run(RunAsBuildOperationBuildActionRunner.java:50) org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300) org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292) org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174) org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31) org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:45) org.gradle.tooling.internal.provider.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:51) org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:47) org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:44) org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:79) org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:44) org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:30) org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:39) org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:25) org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:80) org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:53) org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:62) org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:34) org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:36) org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:25) org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43) org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29) org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:59) org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:31) org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:59) org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:44) org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:46) org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:30) org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:67) org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36) org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122) org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37) org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122) org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26) org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122) org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34) org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122) org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74) org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72) org.gradle.util.Swapper.swap(Swapper.java:38) org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72) org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122) org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55) org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122) org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:62) org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36) org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122) org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:81) org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36) org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:122) org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50) org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:295) org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) java.lang.Thread.run(Thread.java:745) WARNING: Debugging obsolete API calls can take time during configuration. It's recommended to not keep it on at all times. Affected Modules: app
どうやらCrashlyticsを使うときに必要な apply plugin: ‘io.fabric'
が原因の模様。Warningだし、その内直るだろうということで許容する。
起動直後にクラッシュ
java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process com.hoge. Make sure to call FirebaseApp.initializeApp(Context) first. at com.google.firebase.FirebaseApp.getInstance(com.google.firebase:firebase-common@@16.0.2:240) at com.google.firebase.iid.FirebaseInstanceId.getInstance(Unknown Source:1)
classpath 'com.google.gms:google-services:4.2.0’
にアップデートすることで解決
Gradle 5.1.1にアップデート
Gradle 5.1からAndroid Studio 3.3でも使えるようになったのでアップデートする。
If you are using Gradle for Android, you need to move to version 3.3 or higher of both the Android Gradle Plugin and Android Studio.
※Gradle 5.0まではAndroid Studio 3.4以上だった
If you are using Gradle for Android, you need to move to version 3.4 or higher of both the Android Gradle Plugin and Android Studio.
どうやらGradle 5.1だとバグがあるようなのでGradle 5.1.1を使うように注意。
./gradlew wrapper
でjarも更新。
CIで./gradlew dependenciesがエラー
./gradlew dependencies
は足りないSDKをインストールするという認識だったがいつからか dependencies - Displays all dependencies declared in root project 'SampleProject'
となっていた。そもそもGradle plugin 2.2.0からは自動で足りないSDKをダウンロードしてくれるのでやる必要がなさそう...
注意として、Gradle plugin 3.3からはNDKも自動ダウンロードの範囲に入ったので古いNDKを使っている場合は先にダウンロードしておかないと最新版が入ってしまう。
Error: This view is not constrained horizontally: at runtime it will jump to the left unless you add a horizontal constraint [MissingConstraints]
lintでContraintLayoutの横の制約がきちんと設定されていないとエラーになるようになったので設定する
個人アプリのAndroidX対応時のメモ
Support Libraryに依存した3rd party libraryが入っていないせいかあっさり終わった。
移行前の環境
- Android Studio 3.2.1
- compileSdkVersion 28
- targetSdkVersion 28
- Support Library 28.0.0
Refactor -> Migrate to AndroidX
ほぼこれで終わる。ただこれだけではビルドが通らないので修正する。
コンパイルエラーの修正
Non-Nullが返ってきたり型指定が必須になるので直す。
override fun onAttachFragment(fragment: Fragment?)
->override fun onAttachFragment(fragment: Fragment)
override fun onAttach(context: Context?)
->override fun onAttach(context: Context)
progressDialog.show(activity?.supportFragmentManager, null)
->
activity?.supportFragmentManager?.let {
progressDialog.show(it, null)
}
findPreference()
->findPreference<Preference>()
リファクタリング
ツールの不具合かimportしているのにクラスを直指定しているところがあったので修正
- RecylcerView周りの
androidx.recyclerview.widget
を消す androidx.fragment.app.Fragment
->Fragment
androidx.swiperefreshlayout.widget.SwipeRefreshLayout
->SwipeRefreshLayout
クラッシュ修正
ビルドが通るようになったが実行時クラッシュがあった。
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sample/com.sample.HogeActivity}: android.view.InflateException: Binary XML file line #23: Binary XML file line #23: Error inflating class com.google.android.material.textfield.TextInputLayout Caused by: java.lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.MaterialComponents (or a descendant).
どうやら新しい TextInputLayout
はマテリアルのテーマが必要なようなので、アプリのテーマを Theme.MaterialComponent
にするかTextInputLayoutにstyle="@style/Widget.MaterialComponents.FloatingActionButton”
を適用する。
FloatingActionButtonの色が変わる問題の修正
どうやらデフォルトの背景色がcolorAccentからcolorSecondaryに変わり、アイコンの色(tint)がcolorOnSecondaryに変わった模様。必要であれば色を指定する。
- 旧 https://developer.android.com/reference/com/google/android/material/floatingactionbutton/FloatingActionButton
- 新 https://material.io/develop/android/components/floating-action-button/
おわりに
以外とあっさり終わった。Support Libraryに依存しているライブラリが入っているとその対応を待ったり、下手したらライブラリの置き換えも考慮しなければいけないと思う。あとMigrate to AndroidXするとalphaだろうが最新のバージョンを指定してくるので会社のプロダクトではバージョンを下げたほうが良さそう。