みなさん、こんにちは。
AndroidでもiPhoneのように良い感じでブラウザが開けるようになったようです。
公式の記事は以下になります。
https://android-developers.googleblog.com/2023/02/bringing-best-of-chrome-to-android-developers-and-users.html
どのようなものかと言うと、今までもCustomTab自体はありアプリ内で別ページで開きながら、Chromeとしての機能を使えるようになっていました。
アプリでのWebViewだと使えなかったりするパスワードマネージャ等も良い感じに使えてとても便利でした。
しかし、これだと画面が別で開いてしまうため、元のアプリと同時に使うことができませんでした。
しかし、それができるようになった!!と言うことで実際に少し試してみました。
これらの機能はandroidx.browser:browser:1.5.0
以上で提供されています。
また、ChromeのVersionが45以上でないといけないらしいです。
実装に必要なものに関しては、以下の公式サイトに書いてあります。
https://developer.chrome.com/docs/android/custom-tabs/
では実際にやってみます。
実装
調べてみると、CustomTabIntent
でsetInitialActivityHeightPx
を設定すればいけるらしい。
そこで、適当な箇所のsetOnClickListnerで以下で実装してみたが、動かない!!
いや、CustomTab自体は開くが、PartialCustomTabになっていない。
動かない理由は正直よくわかってないです。
詳しい方教えてください。
val customTabsIntent = CustomTabsIntent.Builder()
.setInitialActivityHeightPx(600)
.build()
customTabsIntent.launchUrl(this, Uri.parse("https://developer.android.com/"))
公式を見ると、二種類の実装を推奨しているらしい。
customTabsSession
を用いた実装、もしくはstartActivityForResult
を使った実装があるらしい。
とりあえず両方実装してみました。
CustomTabsSessionを用いた実装
CustomTab周りを扱うためのクラスを作成
class CustomTabActivityHelper (private val context: Context) {
private var customTabsClient: CustomTabsClient? = null
private var customTabsSession: CustomTabsSession? = null
fun openCustomTabWithSession(url: String) {
val customTabsIntent = CustomTabsIntent.Builder(customTabsSession)
.setInitialActivityHeightPx(2000)
.build()
val packageName = CustomTabsClient.getPackageName(context, null)
packageName?.let {
customTabsIntent.intent.setPackage(packageName)
customTabsIntent.launchUrl(context, Uri.parse(url))
} ?: run {
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
}
}
fun bindCustomTabsService() {
val packageName = CustomTabsClient.getPackageName(context, null) ?: return
val connection = object : CustomTabsServiceConnection() {
override fun onCustomTabsServiceConnected(name: ComponentName, client: CustomTabsClient) {
customTabsClient = client
// Warm up the browser process
client.warmup(0L)
// Create a new session
createNewSession()
}
override fun onServiceDisconnected(name: ComponentName) {
customTabsClient = null
}
}
CustomTabsClient.bindCustomTabsService(context, packageName, connection)
}
private fun createNewSession() {
customTabsClient?.let { client ->
val callback = object : CustomTabsCallback() {
// 終了時に呼び出されるコールバック
// 必要であれば、実装してください。
}
customTabsSession = client.newSession(callback)
}
}
fun unbindCustomTabsService() {
customTabsClient = null
}
}
そして、ActivityのOnCreateで以下を実行
var customTabActivityHelper = CustomTabActivityHelper(this)
// Custom Tabs サービスへのバインドを開始
customTabActivityHelper.bindCustomTabsService()
あとは適当な箇所でcustomTabActivityHelper.openCustomTabWithSession("https://google.com")
を実行すれば、動きました。
ちょっと面倒ですが、良い感じに取り回せるので良さそうです。
StartActivityForResultを使った実装
こちらはActivityのOnCreate
内でActivityResultLauncherを用いて実装します。
val activityResultLauncher: ActivityResultLauncher<String> =
registerForActivityResult(object: ActivityResultContract<String, Int>() {
override fun createIntent(
context: Context,
url: String
): Intent {
val builder = CustomTabsIntent.Builder()
.setInitialActivityHeightPx(500)
val customTabsIntent = builder.build().intent
customTabsIntent.data = Uri.parse(url)
return customTabsIntent
}
override fun parseResult(
resultCode: Int,
intent: Intent?
): Int {
return resultCode
}
}) { resultCode ->
// 終了時に呼び出されるコールバック
// 必要であれば実装してください。
}
あとは適当な場所で activityResultLauncher.launch("https://google.com")
を実行すれば動きます。
まとめ
とても便利で、なんで今までなかったんだ!!と言いたくなる機能でした。
実装として使い勝手が良さそうなのは、CustomTabsSessionを用いた実装かなと感じました。
ただ、ちょっと複雑になるので、特に実装を複雑にしないのであれば、ActivityForResultも楽で良いです。
実装の参考にしたサイト