今開発中のアプリでは、アプリとブラウザを行ったり来たりする機能がありますが、単純に実装したところアプリから対象のWebページをブラウザで開く際に毎回新しいタブで開かれてしまったので、解決法を探ってみました。
ネット上ではChrome限定で行う方法などしか見つかりませんでしたが、もうちょっと汎用的な方法を見つけましたので、こちらに残しておきます。
環境
- Pixel 3a (Android 11)
方法
こんな感じで
fun openBrowser(url: String) {
val intent = Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse(url)
val resolveInfo = context.packageManager.resolveActivity(this, PackageManager.MATCH_DEFAULT_ONLY)
val packageName = resolveInfo?.activityInfo?.packageName ?: PACKAGE_NAME_CHROME
putExtra(Browser.EXTRA_APPLICATION_ID, packageName)
}
context.startActivity(intent)
}
説明
Intentに EXTRA_APPLICATION_ID
でブラウザアプリのアプリケーションIDを指定しない場合、デフォルトアプリに設定されているブラウザが立ち上がりますが、常に新しいタブで開いてしまいます。
そこで、例えばChromeを開く場合は、 EXTRA_APPLICATION_ID
に "com.android.chrome" を指定してやれば、同じページを開いているタブがすでに存在する場合は、Chromeがそのタブを再利用して開いてくれます。すべてのブラウザが同様に動作してくれるかは未確認ですが、少なくともChromeとOperaでは同様にタブを使い回してくれることを確認済みです。
デフォルトに設定されているブラウザアプリのパッケージ名はPackageManagerの resolveActivity
から取得できるので、それを EXTRA_APPLICATION_ID
に指定してやることで、デフォルトのブラウザアプリが開きつつ、同じタブで開いてくれます。
懸念事項としては、 resoleActivity
から取得したパッケージ名と、 EXTRA_APPLICATION_ID
で指定すべきアプリケーションIDが一致しないようなブラウザアプリが存在する場合にうまく動かないということが考えられます。この辺りは色々なブラウザについて調査する必要がありそうです。
補足
デフォルトのブラウザアプリが設定されていない場合は?
Operaをデフォルトに設定した状態でOperaをアンインストールして、デフォルトのブラウザアプリが設定されていない状態にしてパッケージ名が取得できるか確かめてみたところ、 "com.android.chrome" が取得されました。てっきり resolveInfo
がnullで返ってくるものかと思っていましたが、よしなに返してくれるようです。(端末によって変わるかもしれません。)
EXTRA_CREATE_NEW_TAB
について
Androidの Browser
クラスのドキュメントを眺めていると、何かそれっぽい EXTRA_CREATE_NEW_TAB
なるものを見つけました。
public static final String EXTRA_CREATE_NEW_TAB
Boolean extra passed along with an Intent to a browser, specifying that a new tab be created. Overrides EXTRA_APPLICATION_ID; if both are set, a new tab will be used, rather than using the same one.
これにfalseを設定したらいけるんじゃね?と思って EXTRA_APPLICATION_ID
の有無と組み合わせて試してみましたが、特に動作に変わりは見られなかったため、今回は指定していません。