はじめに
Xamarinは、C#でアプリ作りたい人は良いかもしれません。
特にXamarin.Formsを使い、Androidアプリでローカル通知も考えている人向きの記事になります。
BroadcastReceiver
Xamarin.Formsは、DependencyService.Get
経由でOSネイティブの処理をDI的に呼び出すことができます。
Androidネイティブ処理と同様にプログラミングするとローカル通知などでネイティブ処理と同様に処理できるのですが、ここでは詳しいことは省略します。
[BroadcastReceiver(DirectBootAware = true)]
public class AlarmReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
などとするとブロードキャストを受け取れます。
OSネイティブからXamarin.Formsの処理も呼び出せる
さてここで、依存プロジェクトを設定するとOSネイティブから Xamarin.Forms
側に書いた処理も呼び出せます。
ログや次の通知などの処理も共通処理として呼び出すことができます。
アプリがメモリ上から消えていた場合の罠
大抵は
OSネイティブ -> Xamarin.Forms
側の処理を呼び出しても問題ないのですが、
長時間アプリが使われてない場合やタスクキルされた場合、
アプリがメモリ上から消えていた場合、DependencyService.Get
で例外が発生する可能性があります。
You MUST call Xamarin.Forms.Init(); prior to using it
DependencyService.Get
は Xamarin.Forms
の初期化が必要だったのです。
タスクキルされるとその初期化の状態も失います。
しかもバックグラウンドなのでアプリが落ちたという表示もありません。
OnReceive
から global::Xamarin.Forms.Forms.Init(this, bundle);
を呼び出せばよいが初期化に時間がかかってバックグラウンドでの制限時間オーバーのため打ち切られてしまう可能性もある。
つまりできることは、
OSネイティブ -> Xamarin.Forms
で呼び出す処理すべてから DependencyService.Get
を取り除かないといけないことになります。
しかも一旦書いてしまったものから取り除くのは大変で、ライブラリの中で書かれていたりすると大変です..
もう投げ出したくなります。
ローカル通知のテスト
OnReceive
で次の通知を設定しようとしているなら、テストがさらに大変です。
直近のローカル通知はおそらく何も問題がないのですが、そのOnReceive
を受け取った段階ではXamarin.Forms
が生きてない可能性があるため、
直近のローカル通知を受け取る前にタスクキルや端末再起動などを行って、メモリ上から消えている状態にして
logcatとにらめっこすることや、adbコマンドなどで通知の存在を確認することになります。
adb shell dumpsys alarm
このコマンドの存在を知らなかったらだいぶきつい。
これをちゃんと確認しないと、「テスト段階では通知来たので大丈夫と思ったのに、本番だと通知が来ない。」
という羽目になります。
まとめ
DependencyService.Get
くらいXamarin.Forms
の初期化なしで使わせてほしい。
そもそもXamarinを