LoginSignup
0
0

More than 1 year has passed since last update.

Partial Custom Tabを使ってブラウザを良い感じに使う

Posted at

みなさん、こんにちは。
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/

では実際にやってみます。

実装

調べてみると、CustomTabIntentsetInitialActivityHeightPxを設定すればいけるらしい。
そこで、適当な箇所の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も楽で良いです。

実装の参考にしたサイト

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0