Android 如何检查Chrome是否支持Chrome自定义选项卡?

Android 如何检查Chrome是否支持Chrome自定义选项卡?,android,chrome-custom-tabs,Android,Chrome Custom Tabs,我有一个活动可以将外部url加载到我的应用程序内的Web视图中。我想在有Chrome定制标签的时候使用它,但我支持那些可能没有Chrome版本支持它们的设备 如果不支持CustomTabs,我希望使用我的旧代码,但在需要时使用CustomTabsInt.Builder()。旧代码加载活动中包含的WebView中的内容,我仍然可以在其中管理ActionBar 我想写一个helper方法,告诉我它是否受支持,但我不确定如何支持。开发者页面上的信息非常有限: 它表示,如果绑定成功,则可以安全地使用自

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

如果不支持CustomTabs,我希望使用我的旧代码,但在需要时使用CustomTabsInt.Builder()。旧代码加载活动中包含的WebView中的内容,我仍然可以在其中管理ActionBar

我想写一个helper方法,告诉我它是否受支持,但我不确定如何支持。开发者页面上的信息非常有限:

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

我这样假设:

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
}

最后,我在我的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;
    }

您可以使用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());
    }
private static final String SERVICE_ACTION=“android.support.customtabs.ACTION.customtabs服务”;
私有静态最终字符串CHROME\u PACKAGE=“com.android.CHROME”;
私有静态布尔值IsChromeCustomAbsSupported(@NonNull final Context){
意向服务意向=新意向(服务行动);
serviceIntent.setPackage(CHROME_软件包);
List resolveInfos=context.getPackageManager().QueryInputServices(serviceIntent,0);
return!(resolveInfos==null | | resolveInfos.isEmpty());
}

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

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

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;
}

我通过在catch块中处理
ActivityNotFound
异常解决了这个问题

诀窍是检查chrome浏览器活动是否可以启动,如果无法启动或引发异常,只需通过
Intent.ACTION\u 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());
}

我的回答风格可能显得有些自大,但在单击“向下投票”之前,请告诉我您是否遇到了任何意外错误或此方法可能导致的任何其他问题。请给出您的反馈,毕竟我们是一个社区。

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

从Chrome 45开始,Chrome自定义选项卡现在普遍适用于所有用户 Chrome用户,在所有Chrome支持的Android版本上 (从果冻豆开始)

链接:

因此,我按版本检查了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
}

我不知道它的效率有多高,只是想与大家分享。

这会检查其他浏览器是否支持Chrome自定义选项卡吗?奇妙的答案,可以修改为返回一个简单的布尔值,指示存在与Chrome选项卡兼容的浏览器。确实是一个很好的解决方案,但是
getPackageName()
应该在打开url之前调用eveytime。上次获取MPackageNameouse时,如果用户卸载代表浏览器,则该浏览器可能不存在。因此,如果仍然使用last get browser软件包名称,则可能会导致
任何活动都无法处理intent
异常。我已经在没有设置软件包的情况下进行了快速测试,如果您只想检查是否有任何应用程序支持自定义选项卡,它似乎也能正常工作。
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
}