android:从片段中打开chrome自定义选项卡 [英] android : open chrome custom tab from fragment

查看:222
本文介绍了android:从片段中打开chrome自定义选项卡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Activity MainActivity 。它包含一个 ViewPager ,托管一个片段 FragmentPlaceHolder 。这个片段有一个 RecyclerView



现在,点击一个特定的视图, code> RecyclerView 项目,我想在新的 Activity 中打开一个chrome自定义选项卡。任何人都可以帮我解决这个问题吗?我期待 Chrome自定义标签的逐步实施。



谢谢。


所以,我这样做了:

首先,将下面的依赖项添加到 build.gradle(app)


compile'c​​om.android.support:customtabs :23.1.1'


首先创建一个活动 WebviewActivity



WebViewActivity.java

  public class WebviewActivity extends AppCompatActivity {
public static final String EXTRA_URL =extra.url;

@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview);
String url = getIntent()。getStringExtra(EXTRA_URL);
WebView webView =(WebView)findViewById(R.id.webview);
webView.setWebViewClient(新的WebViewClient());
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
setTitle(url);
getSupportActionBar()。setDisplayHomeAsUpEnabled(true);
webView.loadUrl(url);

$ b @Override
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
//响应动作bar的向上/主页按钮
case android.R.id.home:
finish();
返回true;
}
返回super.onOptionsItemSelected(item);


$ / code>

现在,比如在按钮上点击你想打开chrome自定义选项卡并加载 www.google.com ,因此,请按以下方式操作:

  public void onButtonClick(View view){
CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder()。build();
CustomTabActivityHelper.openCustomTab(
this,// activity
customTabsIntent,
Uri.parse(http://www.google.com),
new WebviewFallback ()
);



$ b

activity_webview.xml p>

 <?xml version =1.0encoding =utf-8?> 
<! - 版权所有2015 Google Inc.保留所有权利。

根据Apache许可证2.0版许可(许可证);
除非符合许可证,否则您不得使用此文件。
您可以在

处获得许可证副本http://www.apache.org/licenses/LICENSE-2.0

除非适用法律要求或以书面形式同意,根据许可证分发的软件
是按原样基础,
分发,没有任何形式的明示或暗示保证或条件。
请参阅许可证以了解许可证下特定语言的管理权限和
限制。
- >
< WebView xmlns:android =http://schemas.android.com/apk/res/android
xmlns:tools =http://schemas.android.com/tools
android:id =@ + id / webview
android:layout_width =match_parent
android:layout_height =match_parent
android:paddingBottom =@ dimen / activity_vertical_margin
android:paddingLeft =@ dimen / activity_horizo​​ntal_margin
android:paddingRight =@ dimen / activity_horizo​​ntal_margin
android:paddingTop =@ dimen / activity_vertical_margin
tools:context = .helpers.WebviewActivity/>

然后,简单地按照以下方式制作类:



CustomTabActivityHelper.java 导入android.app.Activity;

  import android.net.Uri ; 
导入android.os.Bundle;
导入android.support.customtabs.CustomTabsClient;
导入android.support.customtabs.CustomTabsIntent;
导入android.support.customtabs.CustomTabsServiceConnection;
导入android.support.customtabs.CustomTabsSession;

import java.util.List;

/ **
*这是一个帮助程序类,用于管理与自定义选项卡服务的连接。
* /
public class CustomTabActivityHelper实现ServiceConnectionCallback {
private CustomTabsSession mCustomTabsSession;
私人CustomTabsClient mClient;
私人CustomTabsServiceConnection mConnection;
private ConnectionCallback mConnectionCallback;

/ **
*如果可能,在自定义选项卡上打开URL。否则将回退到在WebView上打开它。
*
* @param activity主机活动。
* @param customTabsIntent CustomTabsIntent如果自定义选项卡可用,则使用CustomTabsIntent。
* @param uri uri被打开。
* @param回退CustomTabFallback,如果自定义选项卡不可用,则使用CustomTabFallback。
* /
public static void openCustomTab(Activity activity,
CustomTabsIntent customTabsIntent,
Uri uri,
CustomTabFallback fallback){
String packageName = CustomTabsHelper.getPackageNameToUse (活动);

//如果找不到包名称,则表示没有支持安装
// Chrome自定义选项卡的浏览器。所以,如果(packageName == null){
if(fallback!= null){
fallback.openUri(activity,uri);我们回退到webview
;
}
} else {
customTabsIntent.intent.setPackage(packageName);
customTabsIntent.launchUrl(activity,uri);
}
}

/ **
*从自定义标签服务解除绑定活动。
*
* @param活动连接到服务的活动。
* /
public void unbindCustomTabsService(Activity activity){
if(mConnection == null)return;
activity.unbindService(mConnection);
mClient = null;
mCustomTabsSession = null;
mConnection = null;
}

/ **
*创建或检索正在退出的CustomTabsSession。
*
* @返回一个CustomTabsSession。
* /
public CustomTabsSession getSession(){
if(mClient == null){
mCustomTabsSession = null;
} else if(mCustomTabsSession == null){
mCustomTabsSession = mClient.newSession(null);
}
返回mCustomTabsSession;
}

/ **
*注册一个回拨,在连接或断开自定义标签服务时被调用。
*
* @param connectionCallback
* /
public void setConnectionCallback(ConnectionCallback connectionCallback){
this.mConnectionCallback = connectionCallback;
}

/ **
*将活动绑定到自定义选项卡服务。
*
* @param activity将要绑定到服务的活动。
* /
public void bindCustomTabsService(Activity activity){
if(mClient!= null)return;

String packageName = CustomTabsHelper.getPackageNameToUse(activity);
if(packageName == null)return;

mConnection = new ServiceConnection(this);
CustomTabsClient.bindCustomTabsService(activity,packageName,mConnection);
}

/ **
* @如果调用mayLaunchUrl被接受,则返回true。
* @see {@link CustomTabsSession#mayLaunchUrl(Uri,Bundle,List)}。
* /
public boolean mayLaunchUrl(Uri uri,Bundle extras,List< Bundle> otherLikelyBundles){
if(mClient == null)return false;

CustomTabsSession session = getSession();
if(session == null)return false;

return session.mayLaunchUrl(uri,extras,otherLikelyBundles);
}

@Override
public void onServiceConnected(CustomTabsClient client){
mClient = client;
mClient.warmup(0L);
if(mConnectionCallback!= null)mConnectionCallback.onCustomTabsConnected();
}

@Override
public void onServiceDisconnected(){
mClient = null;
mCustomTabsSession = null;
if(mConnectionCallback!= null)mConnectionCallback.onCustomTabsDisconnected();
}

/ **
*服务连接或断开时的回拨。当服务连接或断开连接时,将这些回调用于
*处理UI更改。
* /
public interface ConnectionCallback {
/ **
*服务连接时调用。
* /
void onCustomTabsConnected();

/ **
*服务断开时调用。
* /
void onCustomTabsDisconnected();
}

/ **
*当自定义选项卡不可用时,用作后备打开Uri。
* /
public interface CustomTabFallback {
/ **
* @param activity要打开Uri的活动。
* @param uri uri由后备打开。
* /
void openUri(活动活动,Uri uri);




$ b

CustomTabsHelper.java import android.content.Context;

  import android.content.Intent; 
导入android.content.IntentFilter;
导入android.content.pm.PackageManager;
导入android.content.pm.ResolveInfo;
导入android.net.Uri;
导入android.text.TextUtils;
导入android.util.Log;

import java.util.ArrayList;
import java.util.List;

/ **
*自定义标签的辅助类。
* /
public class CustomTabsHelper {
private static final String TAG =CustomTabsHelper;
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;
private static final String EXTRA_CUSTOM_TABS_KEEP_ALIVE =
android.support.customtabs.extra.KEEP_ALIVE;
private static final String ACTION_CUSTOM_TABS_CONNECTION =
android.support.customtabs.action.CustomTabsService;

private static String sPackageNameToUse;

private CustomTabsHelper(){}

public static void addKeepAliveExtra(Context context,Intent intent){
Intent keepAliveIntent = new Intent()。setClassName(
context.getPackageName(),KeepAliveService.class.getCanonicalName());
intent.putExtra(EXTRA_CUSTOM_TABS_KEEP_ALIVE,keepAliveIntent);
}

/ **
*浏览所有处理VIEW意图的应用程序并提供热身服务。如果有的话,选择用户选择的
*,否则会尽最大努力返回一个
*的有效包名称。
*
*这是< strong>不是< / strong>线程安全的。
*
* @param context {@link Context}用于访问{@link PackageManager}。
* @return推荐用于连接到自定义选项卡相关组件的包名称。
* /
public static String getPackageNameToUse(Context context){
if(sPackageNameToUse!= null)return sPackageNameToUse;

PackageManager pm = context.getPackageManager();
//获取默认的VIEW意图处理程序。
Intent activityIntent = new Intent(Intent.ACTION_VIEW,Uri.parse(http://www.example.com));
ResolveInfo defaultViewHandlerInfo = pm.resolveActivity(activityIntent,0);
String defaultViewHandlerPackageName = null;
if(defaultViewHandlerInfo!= null){
defaultViewHandlerPackageName = defaultViewHandlerInfo.activityInfo.packageName;
}

//获取所有可以处理VIEW意图的应用程序。
列表< ResolveInfo> resolvedActivityList = pm.queryIntentActivities(activityIntent,0);
列表< String> packagesSupportingCustomTabs = new ArrayList<>();
for(ResolveInfo info:resolvedActivityList){
Intent serviceIntent = new Intent();
serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION);
serviceIntent.setPackage(info.activityInfo.packageName);
if(pm.resolveService(serviceIntent,0)!= null){
packagesSupportingCustomTabs.add(info.activityInfo.packageName);
}
}

//现在,packagesSupportingCustomTabs包含所有可处理VIEW intents
//和服务调用的应用程序。
if(packagesSupportingCustomTabs.isEmpty()){
sPackageNameToUse = null;
} else if(packagesSupportingCustomTabs.size()== 1){
sPackageNameToUse = packagesSupportingCustomTabs.get(0);
} else if(!TextUtils.isEmpty(defaultViewHandlerPackageName)
&&!hasSpecializedHandlerIntents(context,activityIntent)
&&& packagesSupportingCustomTabs.contains(defaultViewHandlerPackageName)){
sPackageNameToUse = defaultViewHandlerPackageName;
} else if(packagesSupportingCustomTabs.contains(STABLE_PACKAGE)){
sPackageNameToUse = STABLE_PACKAGE;
} else if(packagesSupportingCustomTabs.contains(BETA_PACKAGE)){
sPackageNameToUse = BETA_PACKAGE;
} else if(packagesSupportingCustomTabs.contains(DEV_PACKAGE)){
sPackageNameToUse = DEV_PACKAGE;
} else if(packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)){
sPackageNameToUse = LOCAL_PACKAGE;
}
返回sPackageNameToUse;
}

/ **
*用于检查给定意图是否有专门的处理程序。
* @param intent检查的意图。
* @return是否有针对给定意图的专门处理程序。
* /
private static boolean hasSpecializedHandlerIntents(Context context,Intent intent){
try {
PackageManager pm = context.getPackageManager();
列表< ResolveInfo> handlers = pm.queryIntentActivities(
intent,
PackageManager.GET_RESOLVED_FILTER);
if(handlers == null || handlers.size()== 0){
return false;
}
(ResolveInfo resolveInfo:handlers){
IntentFilter filter = resolveInfo.filter;
if(filter == null)continue;
if(filter.countDataAuthorities()== 0 || filter.countDataPaths()== 0)continue;
if(resolveInfo.activityInfo == null)continue;
返回true;

} catch(RuntimeException e){
Log.e(TAG,获取专门处理程序时的运行时异常);
}
返回false;
}

/ **
* @return提供自定义选项卡功能的所有可能的chrome包名称。
* /
public static String [] getPackages(){
return new String [] {,STABLE_PACKAGE,BETA_PACKAGE,DEV_PACKAGE,LOCAL_PACKAGE};
}
}

ServiceConnection.java

  import android.content.ComponentName; 
导入android.support.customtabs.CustomTabsClient;
导入android.support.customtabs.CustomTabsServiceConnection;

import java.lang.ref.WeakReference;
$ b $ **
*实现CustomTabsServiceConnection,避免泄漏
* ServiceConnectionCallback
* /
public class ServiceConnection extends CustomTabsServiceConnection {
//对ServiceConnectionCallback进行弱引用以避免泄漏。
private WeakReference< ServiceConnectionCallback> mConnectionCallback;

public ServiceConnection(ServiceConnectionCallback connectionCallback){
mConnectionCallback = new WeakReference<>(connectionCallback);

$ b @Override
public void onCustomTabsServiceConnected(ComponentName name,CustomTabsClient client){
ServiceConnectionCallback connectionCallback = mConnectionCallback.get();
if(connectionCallback!= null)connectionCallback.onServiceConnected(client);

$ b @Override
public void onServiceDisconnected(ComponentName name){
ServiceConnectionCallback connectionCallback = mConnectionCallback.get();
if(connectionCallback!= null)connectionCallback.onServiceDisconnected();
}
}

ServiceConnectionCallback.java

  import android.support.customtabs.CustomTabsClient; 

/ **
*在自定义标签服务连接和断开连接时回调事件。
* /
public interface ServiceConnectionCallback {
/ **
*服务连接时调用。
* @param客户端a CustomTabsClient
* /
无效的onServiceConnected(CustomTabsClient客户端);

/ **
*服务断开时调用。
* /
void onServiceDisconnected();
}

WebviewFallback.java

  import android.app.Activity; 
导入android.content.Intent;
导入android.net.Uri;
$ b $ / **
*自定义选项卡不可用时打开Web视图的回退
* /
公共类WebviewFallback实现CustomTabActivityHelper.CustomTabFallback {
@Override
public void openUri(Activity activity,Uri uri){
Intent intent = new Intent(activity,WebviewActivity.class);
intent.putExtra(WebviewActivity.EXTRA_URL,uri.toString());
activity.startActivity(intent);
}
}

现在,您应该可以打开Chrome自定义



如果发现任何问题,请告诉我。



谢谢。


I have one Activity MainActivity. It contains a ViewPager hosting a fragment FragmentPlaceHolder. This fragment has a RecyclerView.

Now, on a click of a particular view, say button, inside a RecyclerView item, I want to open a chrome custom tab in new Activity. Can anyone help me with this one ? I am expecting a step wise implemention of Chrome Custom tabs.

Thanks.

解决方案

So, I did it this way:

First of all, add this following dependency in build.gradle(app):

compile 'com.android.support:customtabs:23.1.1'

First create an activity WebviewActivity:

WebViewActivity.java

public class WebviewActivity extends AppCompatActivity {
    public static final String EXTRA_URL = "extra.url";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);
        String url = getIntent().getStringExtra(EXTRA_URL);
        WebView webView = (WebView)findViewById(R.id.webview);
        webView.setWebViewClient(new WebViewClient());
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        setTitle(url);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        webView.loadUrl(url);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            // Respond to the action bar's Up/Home button
            case android.R.id.home:
                finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Now, say on button click you want to open chrome custom tab and load www.google.com, so, do it as below:

public void onButtonClick(View view){
    CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder().build();
    CustomTabActivityHelper.openCustomTab(
        this,// activity
        customTabsIntent,
        Uri.parse("http://www.google.com"), 
        new WebviewFallback()
    );

}

activity_webview.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2015 Google Inc. All Rights Reserved.

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".helpers.WebviewActivity" />

Then, simply craete the classes as below:

CustomTabActivityHelper.javaimport android.app.Activity;

import android.net.Uri;
import android.os.Bundle;
import android.support.customtabs.CustomTabsClient;
import android.support.customtabs.CustomTabsIntent;
import android.support.customtabs.CustomTabsServiceConnection;
import android.support.customtabs.CustomTabsSession;

import java.util.List;

/**
 * This is a helper class to manage the connection to the Custom Tabs Service.
 */
public class CustomTabActivityHelper implements ServiceConnectionCallback {
    private CustomTabsSession mCustomTabsSession;
    private CustomTabsClient mClient;
    private CustomTabsServiceConnection mConnection;
    private ConnectionCallback mConnectionCallback;

    /**
     * Opens the URL on a Custom Tab if possible. Otherwise fallsback to opening it on a WebView.
     *
     * @param activity         The host activity.
     * @param customTabsIntent a CustomTabsIntent to be used if Custom Tabs is available.
     * @param uri              the Uri to be opened.
     * @param fallback         a CustomTabFallback to be used if Custom Tabs is not available.
     */
    public static void openCustomTab(Activity activity,
                                     CustomTabsIntent customTabsIntent,
                                     Uri uri,
                                     CustomTabFallback fallback) {
        String packageName = CustomTabsHelper.getPackageNameToUse(activity);

        //If we cant find a package name, it means theres no browser that supports
        //Chrome Custom Tabs installed. So, we fallback to the webview
        if (packageName == null) {
            if (fallback != null) {
                fallback.openUri(activity, uri);
            }
        } else {
            customTabsIntent.intent.setPackage(packageName);
            customTabsIntent.launchUrl(activity, uri);
        }
    }

    /**
     * Unbinds the Activity from the Custom Tabs Service.
     *
     * @param activity the activity that is connected to the service.
     */
    public void unbindCustomTabsService(Activity activity) {
        if (mConnection == null) return;
        activity.unbindService(mConnection);
        mClient = null;
        mCustomTabsSession = null;
        mConnection = null;
    }

    /**
     * Creates or retrieves an exiting CustomTabsSession.
     *
     * @return a CustomTabsSession.
     */
    public CustomTabsSession getSession() {
        if (mClient == null) {
            mCustomTabsSession = null;
        } else if (mCustomTabsSession == null) {
            mCustomTabsSession = mClient.newSession(null);
        }
        return mCustomTabsSession;
    }

    /**
     * Register a Callback to be called when connected or disconnected from the Custom Tabs Service.
     *
     * @param connectionCallback
     */
    public void setConnectionCallback(ConnectionCallback connectionCallback) {
        this.mConnectionCallback = connectionCallback;
    }

    /**
     * Binds the Activity to the Custom Tabs Service.
     *
     * @param activity the activity to be binded to the service.
     */
    public void bindCustomTabsService(Activity activity) {
        if (mClient != null) return;

        String packageName = CustomTabsHelper.getPackageNameToUse(activity);
        if (packageName == null) return;

        mConnection = new ServiceConnection(this);
        CustomTabsClient.bindCustomTabsService(activity, packageName, mConnection);
    }

    /**
     * @return true if call to mayLaunchUrl was accepted.
     * @see {@link CustomTabsSession#mayLaunchUrl(Uri, Bundle, List)}.
     */
    public boolean mayLaunchUrl(Uri uri, Bundle extras, List<Bundle> otherLikelyBundles) {
        if (mClient == null) return false;

        CustomTabsSession session = getSession();
        if (session == null) return false;

        return session.mayLaunchUrl(uri, extras, otherLikelyBundles);
    }

    @Override
    public void onServiceConnected(CustomTabsClient client) {
        mClient = client;
        mClient.warmup(0L);
        if (mConnectionCallback != null) mConnectionCallback.onCustomTabsConnected();
    }

    @Override
    public void onServiceDisconnected() {
        mClient = null;
        mCustomTabsSession = null;
        if (mConnectionCallback != null) mConnectionCallback.onCustomTabsDisconnected();
    }

    /**
     * A Callback for when the service is connected or disconnected. Use those callbacks to
     * handle UI changes when the service is connected or disconnected.
     */
    public interface ConnectionCallback {
        /**
         * Called when the service is connected.
         */
        void onCustomTabsConnected();

        /**
         * Called when the service is disconnected.
         */
        void onCustomTabsDisconnected();
    }

    /**
     * To be used as a fallback to open the Uri when Custom Tabs is not available.
     */
    public interface CustomTabFallback {
        /**
         * @param activity The Activity that wants to open the Uri.
         * @param uri      The uri to be opened by the fallback.
         */
        void openUri(Activity activity, Uri uri);
    }

}

CustomTabsHelper.javaimport android.content.Context;

import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

/**
 * Helper class for Custom Tabs.
 */
public class CustomTabsHelper {
    private static final String TAG = "CustomTabsHelper";
    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";
    private static final String EXTRA_CUSTOM_TABS_KEEP_ALIVE =
            "android.support.customtabs.extra.KEEP_ALIVE";
    private static final String ACTION_CUSTOM_TABS_CONNECTION =
            "android.support.customtabs.action.CustomTabsService";

    private static String sPackageNameToUse;

    private CustomTabsHelper() {}

    public static void addKeepAliveExtra(Context context, Intent intent) {
        Intent keepAliveIntent = new Intent().setClassName(
                context.getPackageName(), KeepAliveService.class.getCanonicalName());
        intent.putExtra(EXTRA_CUSTOM_TABS_KEEP_ALIVE, keepAliveIntent);
    }

    /**
     * Goes through all apps that handle VIEW intents and have a warmup service. Picks
     * the one chosen by the user if there is one, otherwise makes a best effort to return a
     * valid package name.
     *
     * This is <strong>not</strong> threadsafe.
     *
     * @param context {@link Context} to use for accessing {@link PackageManager}.
     * @return The package name recommended to use for connecting to custom tabs related components.
     */
    public static String getPackageNameToUse(Context context) {
        if (sPackageNameToUse != null) return sPackageNameToUse;

        PackageManager pm = context.getPackageManager();
        // Get default VIEW intent handler.
        Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
        ResolveInfo defaultViewHandlerInfo = pm.resolveActivity(activityIntent, 0);
        String defaultViewHandlerPackageName = null;
        if (defaultViewHandlerInfo != null) {
            defaultViewHandlerPackageName = defaultViewHandlerInfo.activityInfo.packageName;
        }

        // Get all apps that can handle VIEW intents.
        List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(activityIntent, 0);
        List<String> packagesSupportingCustomTabs = new ArrayList<>();
        for (ResolveInfo info : resolvedActivityList) {
            Intent serviceIntent = new Intent();
            serviceIntent.setAction(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()) {
            sPackageNameToUse = null;
        } else if (packagesSupportingCustomTabs.size() == 1) {
            sPackageNameToUse = packagesSupportingCustomTabs.get(0);
        } else if (!TextUtils.isEmpty(defaultViewHandlerPackageName)
                && !hasSpecializedHandlerIntents(context, activityIntent)
                && packagesSupportingCustomTabs.contains(defaultViewHandlerPackageName)) {
            sPackageNameToUse = defaultViewHandlerPackageName;
        } else if (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) {
            sPackageNameToUse = STABLE_PACKAGE;
        } else if (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) {
            sPackageNameToUse = BETA_PACKAGE;
        } else if (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) {
            sPackageNameToUse = DEV_PACKAGE;
        } else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) {
            sPackageNameToUse = LOCAL_PACKAGE;
        }
        return sPackageNameToUse;
    }

    /**
     * Used to check whether there is a specialized handler for a given intent.
     * @param intent The intent to check with.
     * @return Whether there is a specialized handler for the given intent.
     */
    private static boolean hasSpecializedHandlerIntents(Context context, Intent intent) {
        try {
            PackageManager pm = context.getPackageManager();
            List<ResolveInfo> handlers = pm.queryIntentActivities(
                    intent,
                    PackageManager.GET_RESOLVED_FILTER);
            if (handlers == null || handlers.size() == 0) {
                return false;
            }
            for (ResolveInfo resolveInfo : handlers) {
                IntentFilter filter = resolveInfo.filter;
                if (filter == null) continue;
                if (filter.countDataAuthorities() == 0 || filter.countDataPaths() == 0) continue;
                if (resolveInfo.activityInfo == null) continue;
                return true;
            }
        } catch (RuntimeException e) {
            Log.e(TAG, "Runtime exception while getting specialized handlers");
        }
        return false;
    }

    /**
     * @return All possible chrome package names that provide custom tabs feature.
     */
    public static String[] getPackages() {
        return new String[]{"", STABLE_PACKAGE, BETA_PACKAGE, DEV_PACKAGE, LOCAL_PACKAGE};
    }
}

ServiceConnection.java

import android.content.ComponentName;
import android.support.customtabs.CustomTabsClient;
import android.support.customtabs.CustomTabsServiceConnection;

import java.lang.ref.WeakReference;

/**
 * Implementation for the CustomTabsServiceConnection that avoids leaking the
 * ServiceConnectionCallback
 */
public class ServiceConnection extends CustomTabsServiceConnection {
    // A weak reference to the ServiceConnectionCallback to avoid leaking it.
    private WeakReference<ServiceConnectionCallback> mConnectionCallback;

    public ServiceConnection(ServiceConnectionCallback connectionCallback) {
        mConnectionCallback = new WeakReference<>(connectionCallback);
    }

    @Override
    public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
        ServiceConnectionCallback connectionCallback = mConnectionCallback.get();
        if (connectionCallback != null) connectionCallback.onServiceConnected(client);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        ServiceConnectionCallback connectionCallback = mConnectionCallback.get();
        if (connectionCallback != null) connectionCallback.onServiceDisconnected();
    }
}

ServiceConnectionCallback.java

import android.support.customtabs.CustomTabsClient;

/**
 * Callback for events when connecting and disconnecting from Custom Tabs Service.
 */
public interface ServiceConnectionCallback {
    /**
     * Called when the service is connected.
     * @param client a CustomTabsClient
     */
    void onServiceConnected(CustomTabsClient client);

    /**
     * Called when the service is disconnected.
     */
    void onServiceDisconnected();
}

WebviewFallback.java

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;

/**
 * A Fallback that opens a Webview when Custom Tabs is not available
 */
public class WebviewFallback implements CustomTabActivityHelper.CustomTabFallback {
    @Override
    public void openUri(Activity activity, Uri uri) {
        Intent intent = new Intent(activity, WebviewActivity.class);
        intent.putExtra(WebviewActivity.EXTRA_URL, uri.toString());
        activity.startActivity(intent);
    }
}

By now, you should be able to open Chrome custom tab.

If found any issue with this, just let me know.

Thanks.

这篇关于android:从片段中打开chrome自定义选项卡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆