以前KudanARライブラリを使用したKudanARアプリをリリースしました。
Xamarin.FormsでKudan ARを試してみる
そのアプリのテスト環境として使用していたAndroid8.0では発生しなかったが、Android9.0だと発生するエラーがありました。
少し調査したので軽くまとめたいと思います。
先に結論
Contextの実体にはApplication Context
、Activity Context
があります。
実体を把握した上で使用しよう。
現象
まずは、下記が確認できたエラーメッセージの内容です。
Android.Util.AndroidRuntimeException: 'Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?'
どうやら下記のStartActivity
実行時にエラーが発生していることがわかりました。
// Androidバージョンによってはエラーが発生する書き方
var context = Android.App.Application.Context;
using (var intent = new Android.Content.Intent(context, typeof(MarkerARActivity)))
{
context.StartActivity(intent);
}
原因
Contextと一言に言っても、実体が異なる場合があることを把握しないまま使用したことが原因です。
なぜアプリリリース前に気づけなかった?
KudanARライブラリを使用すると、エミュレータで動作確認ができなくなる仕様があります。
また、私が持っている一番新しいAndroidバージョンは8.0です。
よって、他のAndroidバージョンでの挙動を確認できなかったため、リリース後に気づいた次第です。
言い訳終了。
エラー対処方法
Xamarinのテンプレートソリューションから、空のActivityを呼び出すだけのアプリを作成し、動作を確認しました。
対処方法にはいくつかあるようです。
-
context = Android.App.Application.Context;
を使う場合- Contextの実体は
Application
- Intentにフラグを追加して対応
intent.SetFlags(ActivityFlags.NewTask);
- Contextの実体は
-
context = (Context)Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity;
を使う場合- Contextの実体は
Activity
- NuGetから
Plugin.CurrentActivity
をインストールする必要あり - Intentへのフラグ追加は必要なし
- Contextの実体は
-
context = MainActivity.Context;
を使う場合- Contextの実体は
Activity
-
public static Context Context { get; private set; }
のような適当な静的プロパティをMainActivityに用意する必要あり(OnCreateでthisの代入を行っておく) - Intentへのフラグ追加は必要なし
- Contextの実体は
下記の記事が参考になりました。
Androidの勉強:Contextについて
最終的な実装
フラグ設定処理を追加して行数を増やすのは避けたかったので、対処方法の2番目に挙げた方法で実装しました。
// 正常に動作する書き方
var context = (Context)Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity;
using (var intent = new Android.Content.Intent(context, typeof(MarkerARActivity)))
{
context.StartActivity(intent);
}
まとめ
Contextの実体にはApplication Context
、Activity Context
があるので、実体を把握した上で使用しよう。
Contextの取得には、Plugin.CurrentActivity
を使用するのが安定。