package moe.feng.bilinyan.util; import android.annotation.TargetApi; import 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.os.Build; import android.os.Bundle; import android.os.IBinder; import android.text.TextUtils; import java.util.ArrayList; import java.util.List; /** * * 这个方法似乎只能在 Chrome 45 上实现,目前 Stable 还在 43 * */ public class ChromeTabCompat { private String url; private Intent intent; private Bundle extra; 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 String mPackageNameToUse; public static final String EXTRA_TITLE_VISIBILITY_STATE = "android.support.customtabs.extra.TITLE_VISIBILITY"; private static final int NO_TITLE = 0; private static final int SHOW_PAGE_TITLE = 1; public static final String EXTRA_CLOSE_BUTTON_STYLE = "android.support.customtabs.extra.CLOSE_BUTTON_STYLE"; public static final int CLOSE_BUTTON_CROSS = 0; public static final int CLOSE_BUTTON_ARROW = 1; private static final String EXTRA_CUSTOM_TABS_SESSION = "android.support.customtabs.extra.SESSION"; private static final String EXTRA_CUSTOM_TABS_TOOLBAR_COLOR = "android.support.customtabs.extra.TOOLBAR_COLOR"; private static final String KEY_CUSTOM_TABS_ICON = "android.support.customtabs.customaction.ICON"; public static final String KEY_CUSTOM_TABS_PENDING_INTENT = "android.support.customtabs.customaction.PENDING_INTENT"; public static final String EXTRA_CUSTOM_TABS_ACTION_BUTTON_BUNDLE = "android.support.customtabs.extra.ACTION_BUNDLE_BUTTON"; public static final String KEY_CUSTOM_TABS_MENU_TITLE = "android.support.customtabs.customaction.MENU_ITEM_TITLE"; public static final String EXTRA_CUSTOM_TABS_MENU_ITEMS = "android.support.customtabs.extra.MENU_ITEMS"; public static final String EXTRA_CUSTOM_TABS_EXIT_ANIMATION_BUNDLE = "android.support.customtabs.extra.EXIT_ANIMATION_BUNDLE"; public static final String ACTION_CUSTOM_TABS_CONNECTION = "android.support.customtabs.action.CustomTabsService"; private ChromeTabCompat(String url) { this.url = url; intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); extra = new Bundle(); } public void start(Context context) { context.startActivity(intent); } public static boolean isAvailable(Context context) { return getPackageNameToUse(context) != null; } public static String getPackageNameToUse(Context context) { if (mPackageNameToUse != null) return mPackageNameToUse; 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()) { mPackageNameToUse = null; } else if (packagesSupportingCustomTabs.size() == 1) { mPackageNameToUse = packagesSupportingCustomTabs.get(0); } else if (!TextUtils.isEmpty(defaultViewHandlerPackageName) && !hasSpecializedHandlerIntents(context, activityIntent) && packagesSupportingCustomTabs.contains(defaultViewHandlerPackageName)) { mPackageNameToUse = defaultViewHandlerPackageName; } 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; } 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) { } return false; } public static class Builder { private ChromeTabCompat tab; public Builder(String url) { this.tab = new ChromeTabCompat(url); if (Build.VERSION.SDK_INT >= 18) { this.tab.extra.putBinder(EXTRA_CUSTOM_TABS_SESSION, null); } } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) public Builder sessionBinder(IBinder binder) { this.tab.extra.putBinder(EXTRA_CUSTOM_TABS_SESSION, binder); return this; } public Builder toolbarColor(int color) { this.tab.extra.putInt(EXTRA_CUSTOM_TABS_TOOLBAR_COLOR, color); return this; } public Builder setShowTitle(boolean showTitle) { int titleVisibilityState = showTitle ? SHOW_PAGE_TITLE : NO_TITLE; this.tab.extra.putInt(EXTRA_TITLE_VISIBILITY_STATE, titleVisibilityState); return this; } public Builder setCloseButtonStyle(int style) { if (style == CLOSE_BUTTON_CROSS || style == CLOSE_BUTTON_ARROW) { this.tab.extra.putInt(EXTRA_CLOSE_BUTTON_STYLE, style); } return this; } public ChromeTabCompat build() { this.tab.intent.putExtras(this.tab.extra); return this.tab; } } }