-
Notifications
You must be signed in to change notification settings - Fork 51
/
CustomTabsHelper.java
153 lines (139 loc) · 6.48 KB
/
CustomTabsHelper.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
* Copyright (c) 2015 Zhang Hai <Dreaming.in.Code.ZH@Gmail.com>
* All Rights Reserved.
*/
package org.chromium.customtabsclient;
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.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
// 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.
/**
* 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;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
resolvedActivityList = pm.queryIntentActivities(activityIntent, PackageManager.MATCH_ALL);
} else {
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};
}
}