概要
作成したAndroidアプリでリンクから外部ブラウザを開くという処理を行う際に、AmazonやXのリンクが開けないという問題があったので、その際に行った対処法です。
問題の原因
外部ブラウザを開けるかどうかという基準だけで判定していたため、AmazonやXのネイティブアプリが同端末でインストールされていた場合にエラーを出すような作りになってしまっていました。
実装
以下のように実装しました。
下記のようにすることで、AmazonやXなどのアプリがインストールされていればそれを開き、インストールされていなければデフォルト設定されているブラウザを開きます。
また基本考えにくいですが、Chromeなどが無効になっていれば有効なブラウザがないとしてエラー処理を行います。
fun Activity.openBrowser(url: String) {
// 有効なリンクかどうか判定
val isValidUrl = Patterns.WEB_URL.matcher(url).matches()
if (!isValidUrl) {
// エラー処理
return
}
val target = Intent(Intent.ACTION_VIEW, url.toUri())
val activities = packageManager.queryIntentActivities(target, PackageManager.MATCH_ALL)
when {
activities.isEmpty() || activities.none { it.activityInfo.enabled } -> {
// 有効なブラウザがない時の処理
}
else -> startActivity(target)
}
}
queryIntentActivities
は、対象を処理できるすべてのアクティビティを返します。ここでは、ネイティブアプリまたはブラウザというところになるでしょうか。
対してresolveActivity
を使う場合は、それを処理する最善のものを判断して返してくれます。
基本的にはどちらでも大丈夫です。
気をつけたいのは、引数にPackageManager.MATCH_ALL
を取っている点です。
PackageManager.MATCH_DEFAULT_ONLY
を使う場面も多いとは思うのですが、こちらは「常にこのアプリで開く」としているものが対象となります。そのため、基本的にresolveActivity
の方と一緒に使われます。
今回の場合にはqueryIntentActivities
と合わせてMATCH_ALL
の方にしておかないとネイティブアプリを認識してくれないのか、上記の「有効なブラウザがない時の処理」に入ってしまいます。
もうちょっと良い実装方法があるかもしれませんが、今回はこちらで表題の問題を解決できました。
以上です。