Instant-appを試してみた

Instant-Appを試してみた。FlexibleTimerというアプリを作って、Instant-Appに対応させてみたのである。

https://play.google.com/store/apps/details?id=jp.gcreate.product.flexibletimer

Instant-Appというのは、アプリをインストールすることなく使えるようにする仕組みで、今回作ったアプリはhttps://app.gcreate.jp/flexibletimer/にアクセスすれば試すことができる。(Androidからアクセスすれば実行できるはず)

Instant-Appを実行できる環境

今のところAndroid6.0以上の端末であれば動くらしい。

Android6.0(API23)以上の端末であれば、おそらく設定 > Googleの中にInstant Appsという項目があると思う。それを有効にすればInstant-Appが実行できる。将来的にはAPI21以上もサポートされるらしいが、今は23以上が要件。

1つ注意点があって、Instant-Appはどうもどれか1つのアカウントでしか有効にできないみたい。私は2つのアカウントを1つの端末で使っていて、片方のアカウントでInstant-Appを有効にすると、もう片方は無効になってしまう。

このことで何を注意しなければならないかというと、Chromeにログインしているアカウントと、Instant-Appを有効にするアカウントは揃えておけということである。揃えていないとChromeからInstant-Appを提供しているURLにアクセスしても、Instant-Appが実行されないからである。揃えていなくても、例えばSlackで共有されたURLを開けばInstant-Appが実行されるし、Google Playからサイトに移動しても起動するので、Instant-App自体が使えないわけではない。

用意したURL(これはアプリを作成する際にAndroidManifest.xmlに定義する)にアクセスすれば、Instant-App用のAPKをGoogle Playからロードしてきて、インストールすることなくアプリが実行される。

URLは実際にアクセス可能でなければならない。つまり、Webサイトを所有していない場合には使えないということになる。所有していない場合はFirebase Hostingを利用してねというQAがある。(Stackoverflow

Instant-Appへの対応の仕方

今のところAndroid Studio3.0を使わなければInstant-App対応は不可能である。理由としては、3.0でなければInstant-Appを作成するために使うcom.android.featureプラグインが認識できないからだ。

まだ3.0は正式バージョンではないので、急いで対応しないとならないというものではないと思う。

既存のアプリをInstant-Appへ対応させるのは、そんなに難しい手順が必要なわけではない。たぶん、3.0でビルドできなくなったとか、gradleプラグインが対応してなくて動かないとか、そういった種類のトラブルに対応するほうがはるかに大変なだけだと思う。

細かいやり方はドキュメントを見てもらえばそんなに難しくはないと思う。

ちなみにcodelabで既存のアプリをInstant-App対応させる方法が一通り学べる。

はまったポイント

foreground serviceが動かない

Instant-AppではLong-running background serviceはサポートされていないが、foreground serviceは使うことができる。ことになっているが、現時点ではまだ対応されていないらしい。

Stackoverflow

Architecture Componentが動かない

私の場合LiveDataを使おうとしていたのだが、Instant-Appでは使えなかった。エラーは起きないが、LiveDataの変更が受け取れなかった。

https://issuetracker.google.com/issues/38493434

Read full post gblog_arrow_right

Firebase Crashを使ってみた

Firebase Crash Reportingを使ってみた。今まではCrashlyticsを使っていたのだが、最近はFirebaseをアプリに組み込むことが多いので、クラッシュレポートもFirebaseでやってみようかなというのがことの始まり。

導入手順的に考えると、Firebase Crash Reportingはとても簡単。Firebaseを使うプロジェクトであれば、dependenciesに'com.google.firebase:firebase-crash:<VERSION>'を追加するだけで終わり。これだけでアプリがクラッシュしたら勝手にレポートをあげてくれる。

Firebaseを使う設定に関しても、Android Studioに組み込まれているFirebaseのツール(?)を使えばいとも簡単に使えるようになるので、導入の敷居はCrashlyticsに比べるととても楽である。

一方で、Crashlyticsと比較すると面倒くさいポイントもいくつかあって、単純に乗り換えればいいやという話でもなさそうなのが悩ましい。

mapping.txtのアップロード

ProGuardをかける場合に難読化されたスタックトレースを解読するため、mapping.txtのアップロードが必要になる。Crashlyticsの場合、設定が必要だが自動的にアップロードを行ってくれる。

一方でFirebase Crash Reportingは自分でFirebase Consoleにアップロードしなければならない。gradleタスクでアップロードするための方法が用意されてはいるが、Crashlyticsと比較すると「自動アップロード」とはいえない。初期導入が簡単な反面、ProGuardのmapping.txtをアップロードする設定を行う手間がある。

https://firebase.google.com/docs/crash/android

  1. ルートのbuild.gradleのclasspassに`'com.google.firebase:firebase-plugins:1.0.5'`を追加
  2. app/build.gradleに`apply plugin: 'com.google.firebase.firebase-crash'`を追加
  3. Firebase Consoleからプロジェクトの設定→サービスアカウント→クラッシュレポートから、新しい秘密鍵の生成を行いダウンロードする(jsonファイル)
  4. ダウンロードしたファイルへのパスを`FirebaseServiceAccountFilePath`というプロパティに記述する1
  5. `./gradlew :app:firebaseUploadReleaseProguardMapping`を実行してアップロード(buildVariantなどによってタスク名は変わる)
`firebaseUploadXXX`というタスクを実行しないといけないので、そのままだと確実に忘れそう。`assembleRelease`を実行したらこのタスクも実行するように指定できたらなぁと思ったのだけど、やり方がわからなかった。

そして依存させるなら、assembleReleaseよりもapkをGoogle Playにアップロードするタスク(自動化しているなら)に依存させるのが良さそうではある。

debugビルドでアップロードしてほしくない問題

Firebase Crashは特に何もしなくとも、アプリがクラッシュすればスタックトレースをアップロードしてくれる。カスタムApplicationクラスに初期化処理を書いて・・・なんてことすら必要ない。ContentProviderの初期化の仕組みを使ってライブラリ側で勝手に初期化しているとかなんとか見た気がする。ある意味便利ではあるが、一方で不便なところもある。それは、クラッシュレポートを送信させない手段が存在していないところである(たぶんない)。

CrashlyticsはカスタムApplicationで初期化をする必要があり、ここで例えばデバッグビルド中は送信しないようにしたり設定できる。Firebase Crashにはそういうのはないっぽい。そもそも自分で初期化しないし、送信を停止するようなメソッドも見当たらない。

これはFirebase CrashをreleaseCompileで組み込めば一応回避は可能である。

一方で、プライバシーポリシーの問題というか、ユーザの許可を得ずにクラッシュ情報を収集してよいのかという問題があると思う。このあたりの法的問題に、他の開発者さんはどう対処しているのか私は知らないが、個人を特定する情報は含まれていないとしても、例えばユーザにクラッシュレポートを送信しないような選択肢を提供したいときに、Firebase Crashではそれができないということになる。クラッシュレポートについてオプトアウトできるようにしてあるアプリがあるのかと言われるとよくわからないけれども。まあもし対処する必要が出てきたとしたら、きっとしれっと無効にできるようにアップデートされるのかもしれない。

logとreport

Firebase Crashは基本的には組み込めばそれで終わりな感じで、後は任意のタイミングでFirebaseCrash.log()とかFirebaseCrash.report()などを使ってクラッシュ時の情報を付け加えるくらいしかやることはない。

log()はクラッシュレポートにイベントとして情報を追加することができるものである。

report()は例えばtry~catchでcatchした例外のスタックトレースを送信するのに使う。

私はどちらもうまいこと使いこなせる自信がない。今までもクラッシュレポート見ても、一体どういう状況で発生しているのかよく分からなくて対応ができなかったことがよくある。log()を使えば原因を特定するのに有効な情報を付け足せるのだろうが、どういう情報を付け足せば原因把握に役立つのかはいまいち分からない。


  1. gradle.propertiesなどで指定すれば良い。プロジェクトルートに秘密鍵のファイルを配置したのであれば、`FirebaseServiceAccountFilePath=../<秘密鍵のファイル名>`という感じ。