13

我有一个将外部 url 加载到我的应用程序中的 web 视图中的活动。我想在 Chrome 自定义标签可用时使用它,但我支持的设备可能没有支持它们的 Chrome 版本。

在不支持 CustomTabs 的情况下,我想使用我的旧代码,但在支持时使用 CustomTabsIntent.Builder()。旧代码将内容加载到 Activity 中包含的 WebView 中,我仍然可以在其中管理 ActionBar。

我想写一个帮助方法,它会告诉我它是否受支持,但我不确定如何。开发者页面上的信息非常少: https ://developer.chrome.com/multidevice/android/customtabs

它说如果您绑定成功,则可以安全地使用自定义选项卡。有没有一种简单的方法来绑定来测试这个?

像这样我假设:

Intent serviceIntent = new Intent("android.support.customtabs.action.CustomTabsService");
serviceIntent.setPackage("com.android.chrome");
boolean customTabsSupported = bindService(serviceIntent, new CustomTabsServiceConnection() {
            @Override
            public void onCustomTabsServiceConnected(final ComponentName componentName, final CustomTabsClient customTabsClient) {}

            @Override
            public void onServiceDisconnected(final ComponentName name) {}
        },
        Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY);

if (customTabsSupported) {
    // is supported
}
4

6 回答 6

14

您可以使用 PackageManager 来检查是否支持自定义选项卡,而不是绑定和取消绑定服务。

  private static final String SERVICE_ACTION = "android.support.customtabs.action.CustomTabsService";
    private static final String CHROME_PACKAGE = "com.android.chrome";

    private static boolean isChromeCustomTabsSupported(@NonNull final Context context) {
        Intent serviceIntent = new Intent(SERVICE_ACTION);
        serviceIntent.setPackage(CHROME_PACKAGE);
        List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentServices(serviceIntent, 0);
        return !(resolveInfos == null || resolveInfos.isEmpty());
    }

请注意,其他浏览器将来可能会支持自定义选项卡,因此您可能需要对其进行修改以支持这种情况。

于 2015-10-09T15:17:37.957 回答
7

您可以尝试以下代码来确定您是否有支持自定义选项卡的浏览器:

private static final String TAG = "CustomTabLauncher";
static final String STABLE_PACKAGE = "com.android.chrome";
static final String BETA_PACKAGE = "com.chrome.beta";
static final String DEV_PACKAGE = "com.chrome.dev";
static final String LOCAL_PACKAGE = "com.google.android.apps.chrome";
String mPackageNameToUse;

private String getPackageName(Context context) {
    if (mPackageNameToUse != null) {
        return mPackageNameToUse;
    }

    // Get default VIEW intent handler that can view a web url.
    Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.test-url.com"));

    // Get all apps that can handle VIEW intents.
    PackageManager pm = context.getPackageManager();
    List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(activityIntent, 0);
    List<String> packagesSupportingCustomTabs = new ArrayList<>();
    for (ResolveInfo info : resolvedActivityList) {
        Intent serviceIntent = new Intent();
        serviceIntent.setAction(CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION);
        serviceIntent.setPackage(info.activityInfo.packageName);
        if (pm.resolveService(serviceIntent, 0) != null) {
            packagesSupportingCustomTabs.add(info.activityInfo.packageName);
        }
    }

    // Now packagesSupportingCustomTabs contains all apps that can handle both VIEW intents
    // and service calls.
    if (packagesSupportingCustomTabs.isEmpty()) {
        mPackageNameToUse = null;
    } else if (packagesSupportingCustomTabs.size() == 1) {
        mPackageNameToUse = packagesSupportingCustomTabs.get(0);
    } else if (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) {
        mPackageNameToUse = STABLE_PACKAGE;
    } else if (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) {
        mPackageNameToUse = BETA_PACKAGE;
    } else if (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) {
        mPackageNameToUse = DEV_PACKAGE;
    } else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) {
        mPackageNameToUse = LOCAL_PACKAGE;
    }
    return mPackageNameToUse;
}

调用时,您可以执行以下操作:

public void openCustomTab(Uri uri, Activity activity) {
    //If we cant find a package name, it means there's no browser that supports
    //Chrome Custom Tabs installed. So, we fallback to the default browser
    if (getPackageName(activity) == null) {
        activity.startActivity(new Intent(Intent.ACTION_VIEW, uri));
    } else {
        CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder();
        intentBuilder.enableUrlBarHiding();
        intentBuilder.setToolbarColor(activity.getResources().getColor(R.color.purple_a_01));

        CustomTabsIntent customTabsIntent = intentBuilder.build();
        customTabsIntent.intent.setPackage(mPackageNameToUse);

        customTabsIntent.launchUrl(activity, uri);
    }
}
于 2015-10-22T12:30:04.337 回答
6

我最终在我的 Utils 类中编写了一个静态方法,这样我就可以检查和处理不支持它的情况:

/**
     * Check if Chrome CustomTabs are supported. 
     * Some devices don't have Chrome or it may not be
     * updated to a version where custom tabs is supported.
     *
     * @param context the context
     * @return whether custom tabs are supported
     */
    public static boolean isChromeCustomTabsSupported(@NonNull final Context context) {
        Intent serviceIntent = new Intent("android.support.customtabs.action.CustomTabsService");
        serviceIntent.setPackage("com.android.chrome");

        CustomTabsServiceConnection serviceConnection = new CustomTabsServiceConnection() {
            @Override
            public void onCustomTabsServiceConnected(final ComponentName componentName, final CustomTabsClient customTabsClient) { }

            @Override
            public void onServiceDisconnected(final ComponentName name) { }
        };

        boolean customTabsSupported =
                context.bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY);
        context.unbindService(serviceConnection);

        return customTabsSupported;
    }
于 2015-10-06T20:29:31.677 回答
3

我通过处理ActivityNotFoundcatch 块中的异常解决了这个问题。

诀窍是检查chrome的浏览器活动是否可以启动,如果无法启动或抛出异常,则只需通过Intent.ACTION_VIEW.

这是所有相关代码....

private void onBtnLinkClicked(View v, int pos) {
    try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            openCustomTab(url);
        } else {
            openBrowserActivity(url);
        }
    } catch (Exception e) {
        e.printStackTrace();
        openBrowserActivity(url);
    }
}

private void openBrowserActivity(String url) {
    Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
    context.startActivity(browserIntent);
}

openCustomTab(url)在说什么:这是它的相关代码。

private void openCustomTab(String url) {
    CustomTabsIntent.Builder intentBuilder = new CustomTabsIntent.Builder();

    int color = context.getResources().getColor(R.color.colorPrimary);
    intentBuilder.setToolbarColor(color);
    intentBuilder.setShowTitle(true);

    String menuItemTitle = context.getString(R.string.menu_title_share);
    PendingIntent menuItemPendingIntent = createPendingShareIntent();
    intentBuilder.addMenuItem(menuItemTitle, menuItemPendingIntent);     

    intentBuilder.setStartAnimations(context,
            R.anim.slide_in_right, R.anim.slide_out_left);
    intentBuilder.setExitAnimations(context,
            android.R.anim.slide_in_left, android.R.anim.slide_out_right);

    CustomTabActivityHelper.openCustomTab(
            activity, intentBuilder.build(), Uri.parse(url), new WebviewFallback());
}

我的回答风格可能看起来很自大,但在点击否决之前让我知道您是否遇到了任何意外错误或这种方法可能导致的任何其他问题。请给出您的反馈,毕竟我们是一个社区。

于 2016-04-01T14:20:21.207 回答
2

如果您的目标是 API 级别 30 并在 Android 11 设备上运行,则可能会出现新问题。

您需要在清单中添加一个部分,例如:

<queries>
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="https" />
    </intent>
</queries>

或者

<queries>
    <intent>
        <action android:name="android.support.customtabs.action.CustomTabsService" />
    </intent>
</queries>

如果没有这个,上面帖子中提到的对 PackageManager 的一些调用将无法按您预期的那样工作。

https://developer.android.com/training/package-visibility/use-cases

于 2021-09-01T16:38:01.247 回答
1

Chrome的开发者网站,我发现以下内容 -

从 Chrome 45 开始,Chrome 自定义选项卡现在对所有 Chrome 用户普遍可用,适用于所有 Chrome 支持的 Android 版本(从 Jellybean 开始)。

链接:https ://developer.chrome.com/multidevice/android/customtabs#whencaniuseit

因此,我按版本检查了Chrome是否支持Chrome 自定义选项卡

检查我的代码:

String chromePackageName = "com.android.chrome";
int chromeTargetVersion  = 45;

boolean isSupportCustomTab = false;
try {
    String chromeVersion = getApplicationContext().getPackageManager().getPackageInfo(chromePackageName, 0).versionName;
    if(chromeVersion.contains(".")) {
        chromeVersion = chromeVersion.substring(0, chromeVersion.indexOf('.'));
    }
    isSupportCustomTab = (Integer.valueOf(chromeVersion) >= chromeTargetVersion);
} catch (PackageManager.NameNotFoundException ex) {
} catch (Exception ex) { }

if (isSupportCustomTab) {
    //Use Chrome Custom Tab
} else {
    //Use WebView or other Browser
}

不知道效率如何,只是想分享一下。

于 2017-01-09T19:37:00.943 回答