投稿

2月, 2020の投稿を表示しています

Application と ViewModel の使い分けはどうすればいいのか?

Activity か Fragment を基点として「ある程度安定して動けばいいや」的スタイルで Android プログラミングを続けてきたので、Application はたまに使用例に従って採用していただけで、主体的に判断して使用したことはない。それで最近、ボンヤリと、Android プログラミングに関する情報を調べていたら、Activity のライフサイクルに巻き込まれない、モデル(ビジネスロジック)的なデータは Application で扱う(格納する)べしみたいな話があって、ちょっと気になっていた。その辺りは特に他のアイデアがなく、自分は Activity や Fragment でそのままデータを持たせていたので、onSaveInstanceState / onRestoreInstanceState で Bundle を使って退避してライフサイクルの輪廻転生をくぐり抜けられるようにしたり、SharedPreferences を使って逐次 Persistent なデータとして退避するなどして、力技で対抗していた。Application を使えば、もうちょっと楽にできたのかなと思って気にしていたところ、ViewModel なんてものも存在することを(今さら)知り、Application と ViewModel の使い分けでどうなんだろう? と思った。もちろん、継承関係からしてそもそも存在意義が全然違うんだろうけど、「Activity のライフサイクルの輪廻転生をくぐり抜けて過去・現在・未来の三世を通じた一貫した記憶を保つ」という意味で、Application を使うか ViewModel を使うかといことに、どういう違いがあるのだろうかといことだ。まあそもそも、Application の方は、ライフサイクルというよりは、スコープ的なグローバル性やシングルトン性の方がテーマとなるのだろうし、ViewModel の方はライフサイクルまで Activity に巻き添えを食らわないというだけで、あくまでも Activity / Fragment に従属したローカルなインスタンスなんだろうけど。書いているうちに、全然違うよね〜、誰も疑問に思わないよね〜、という気持ちになってきた……。Model とは言っても、ViewModel で扱うデータなんて、所詮 UI 用のもの…

HTML ドキュメントのオフライン化

HTML ドキュメントをアプリ内の asset(場所は app/src/main/assets/ )として APK に内包して WebView で表示するサンプル。画像や CSS、HTML 同士の相対リンクも機能する。バックキーでリンクを戻れるようにもしている。MainActivity import android.app.Activity; import android.os.Bundle; import android.view.KeyEvent; import android.webkit.WebView; import android.webkit.WebViewClient; public class MainActivity extends Activity { WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = findViewById(R.id.webView); webView.setWebViewClient(new WebViewClient()); webView.loadUrl("file:///android_asset/index.html"); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) { webView.goBack(); return true; } return super.onKeyDown(keyCode, event); } } layout/activity_…

Firebase Crashlytics

Firebase 推しの Google に従って Firebase Crash Reporting を導入したと思ったら、少し経ったら Google 都合で Crashlytics に変更を余儀なくされることになった。Crash Reporting に比べて、結構、設定が複雑で、適当に一つ目に導入したアプリのプロジェクトを見て二つ目にも導入しようとしたら、意外と抜けていたので、公式の説明を一つ一つ確認してやるのが無難だと思った。Google の日本語のチームが糞なのか、単に日本語のサイトが糞なのかどちらかわからないが、Crashlytics の公式のページが Android を選択しても iOS の説明しか表示せず、内容以前にサイトの表示機能自体がバグバグだし、そういう問題がない場合でも Developers サイトの日本語版の情報は内容的にも大体が、古くて腐敗した有害ですらある情報だったりもするのであくまでも英語の公式ページを参照すべし。また上記の通りに設定しても、依然として LogCat に Crashlytics 絡みの謎のエラーログが出ていたので、StackOverFlow で調べたところ、Firebase のコンソールでアプリの署名の SHA-1/SHA-256 のハッシュ値を登録しておいてその設定 JSON ファイルを使う必要があるとのこと。鳴り物入りで Crashlytics へ変更された割には、まだ全然洗練されてないような気がするのだが……。(この件も、英語版ではちゃんと修正されていた。日本語版情報が腐っているだけの話のようだ)リンク集firebase 全般1: Web コンソールでプロジェクトを作成し(場合によっては App nickname と Debug signing certificate SHA-1 を登録し)、google-services.json をダウンロードして、モジュールのルートに置く; 2: プロジェクトレベルの Gradle とモジュールレベルの Gradle に一定の設定を追加する; 3: モジュールレベルの Gradle に必要な implementation 設定を追加する。firebase-analyticsモジュールレベル Gradle のimplementation 設定firebase-ads1: モジュー…

ANDROID_ID の Android 8.0 における仕様変更

ANDROID_ID が Android 8.0(Oreo: API-26)において仕様変更されたようだ。このため、従来のように ANDROID_ID がデバイス固有の ID と思って扱っていると、意図しない結果につながる。Android IDIn O, Android ID (Settings.Secure.ANDROID_ID or SSAID) has a different value for each app and each user on the device. Developers requiring a device-scoped identifier, should instead use a resettable identifier, such as Advertising ID, giving users more control. Advertising ID also provides a user-facing setting to limit ad tracking.Additionally in Android O:The ANDROID_ID value won't change on package uninstall/reinstall, as long as the package name and signing key are the same. Apps can rely on this value to maintain state across reinstalls.If an app was installed on a device running an earlier version of Android, the Android ID remains the same when the device is updated to Android O, unless the app is uninstalled and reinstalled.The Android ID value only changes if the device is factory reset or if the signing key rotates between uninstall and reinstall eve…