为什么 CustomTabsClient.bindCustomTabsService 不起作用?

Joe*_*ler 5 android kotlin android-studio chrome-custom-tabs

我最近一直致力于向我的 Android 应用程序添加一些Chrome 自定义选项卡,但由于某种原因,我无法绑定到 CustomTabsService。

  • 我有 Chrome 的更新版本
  • Android Gradle 插件版本 4.0.0
  • 摇篮版本 6.1.1

我添加了日志调用来查看连接是否成功,但从未成功。我尝试使用 CustomTabsCallback 根据用户在 CustomTabs 中的导航采取操作,但我需要先连接到该服务。任何帮助表示赞赏!

依赖关系

// Custom Tabs
    implementation 'androidx.browser:browser:1.3.0-alpha01'
    implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
Run Code Online (Sandbox Code Playgroud)

我也尝试过这个(当前版本在这里):

implementation 'androidx.browser:browser:1.2.0'
Run Code Online (Sandbox Code Playgroud)

自定义选项卡片段

package com.mullr.rabbithole.ui.dig

import android.app.Service
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.content.res.AppCompatResources
import androidx.browser.customtabs.*
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.graphics.drawable.toBitmap
import com.mullr.rabbithole.R
import com.mullr.rabbithole.main.MainActivity
import kotlinx.android.synthetic.main.dig_fragment.*

private lateinit var main: MainActivity

class DigTabs : Fragment() {

    // Custom Tabs
    lateinit var client: CustomTabsClient
    lateinit var session: CustomTabsSession
    lateinit var serviceConnection: CustomTabsServiceConnection
    var builder = CustomTabsIntent.Builder()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        main = requireActivity() as MainActivity

       serviceConnection = object : CustomTabsServiceConnection() {
            override fun onCustomTabsServiceConnected(name: ComponentName, mClient: CustomTabsClient) {
                Log.d("Service", "Connected")
                client = mClient
                client.warmup(0L)
                val callback = RabbitCallback()
                session = mClient.newSession(callback)!!
                builder = CustomTabsIntent.Builder(session);
            }

            override fun onServiceDisconnected(name: ComponentName?) {

            }
        }

        Log.d("start", "attempt")
        // Connect to service
        var ok =  CustomTabsClient.bindCustomTabsService(main, main.packageName, serviceConnection)
        if (ok) {
            Log.d("start", "connected")
        } else {
            Log.d("start", ok.toString())
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_dig_tabs, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        wiki_button.setOnClickListener {
            var url = "https://www.wikipedia.org/"
            loadCustomTab(url)
        }

        google_button.setOnClickListener {
            var url = "https://www.google.com"
            loadCustomTab(url)
        }
    }

    fun loadCustomTab(url: String) {
        builder.setSecondaryToolbarColor(ContextCompat.getColor(main, R.color.colorAccent))
        builder.setToolbarColor(
            ContextCompat.getColor(
                main,
                R.color.black
            )
        ) // Change tab toolbar color
        builder.setShowTitle(true)
        builder.addDefaultShareMenuItem()
        builder.enableUrlBarHiding()
        AppCompatResources.getDrawable(main, R.drawable.close_icon)?.let {
            DrawableCompat.setTint(it, Color.WHITE)
            builder.setCloseButtonIcon(it.toBitmap())
        }
        val customTabsIntent: CustomTabsIntent = builder.build()
        customTabsIntent.launchUrl(main, Uri.parse(url))
    }

    override fun onDestroy() {
        super.onDestroy()
        main.unbindService(serviceConnection)
    }

    class RabbitCallback : CustomTabsCallback() {
        override fun onNavigationEvent(navigationEvent: Int, extras: Bundle?) {
            super.onNavigationEvent(navigationEvent, extras)
            Log.d("Nav", "test")
            when (navigationEvent) {
                1 -> Log.d("Navigation", "Start")
                NAVIGATION_FINISHED -> Log.d("Navigation", "Finished")
                NAVIGATION_FAILED -> Log.d("Navigation", "Failed")
                NAVIGATION_ABORTED -> Log.d("Navigation", "Aborted")
                TAB_SHOWN -> Log.d("Navigation", "Tab Shown")
                TAB_HIDDEN -> Log.d("Navigation", "Tab Hidden")
                else -> Log.d("Navigation", "Else")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 10

Android 11 引入了包可见性更改。如果您的 Android 应用程序的目标 API 级别为 30 或更高级别,则需要向 AndroidManifest.xml 添加查询部分,否则上面的代码片段将不会返回结果:

<queries>
    <intent>
        <action android:name=
            "android.support.customtabs.action.CustomTabsService" />
    </intent>
</queries>
Run Code Online (Sandbox Code Playgroud)


Joe*_*ler 8

事实证明这是一个愚蠢的错误。CustomTabsClient.bindCustomTabsService 方法需要自定义选项卡服务的包名称,而不是调用活动的包。所以这...

var ok =  CustomTabsClient.bindCustomTabsService(main, main.packageName, serviceConnection)
Run Code Online (Sandbox Code Playgroud)

应该...

var ok =  CustomTabsClient.bindCustomTabsService(main, "com.android.chrome", serviceConnection)
Run Code Online (Sandbox Code Playgroud)

可以在此处找到可能的包名称。他们包括:

  • com.android.chrome
  • com.chrome.beta
  • com.chrome.dev