Merge branch 'chrome-custom-tabs' of https://github.com/sturmen/Tusky into sturmen-chrome-custom-tabs
commit
e557d0c002
@ -0,0 +1,60 @@ |
|||||||
|
package com.keylesspalace.tusky; |
||||||
|
|
||||||
|
import android.content.ActivityNotFoundException; |
||||||
|
import android.content.Context; |
||||||
|
import android.net.Uri; |
||||||
|
import android.os.Parcel; |
||||||
|
import android.os.Parcelable; |
||||||
|
import android.preference.PreferenceManager; |
||||||
|
import android.support.customtabs.CustomTabsIntent; |
||||||
|
import android.support.v4.content.ContextCompat; |
||||||
|
import android.text.style.URLSpan; |
||||||
|
import android.view.View; |
||||||
|
|
||||||
|
class CustomTabURLSpan extends URLSpan { |
||||||
|
CustomTabURLSpan(String url) { |
||||||
|
super(url); |
||||||
|
} |
||||||
|
|
||||||
|
private CustomTabURLSpan(Parcel src) { |
||||||
|
super(src); |
||||||
|
} |
||||||
|
|
||||||
|
public static final Parcelable.Creator<CustomTabURLSpan> CREATOR = new Parcelable.Creator<CustomTabURLSpan>() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public CustomTabURLSpan createFromParcel(Parcel source) { |
||||||
|
return new CustomTabURLSpan(source); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public CustomTabURLSpan[] newArray(int size) { |
||||||
|
return new CustomTabURLSpan[size]; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onClick(View widget) { |
||||||
|
Uri uri = Uri.parse(getURL()); |
||||||
|
Context context = widget.getContext(); |
||||||
|
boolean lightTheme = PreferenceManager.getDefaultSharedPreferences(context).getBoolean("lightTheme", false); |
||||||
|
int toolbarColor = ContextCompat.getColor(context, lightTheme ? R.color.custom_tab_toolbar_light : R.color.custom_tab_toolbar_dark); |
||||||
|
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); |
||||||
|
builder.setToolbarColor(toolbarColor); |
||||||
|
CustomTabsIntent customTabsIntent = builder.build(); |
||||||
|
try { |
||||||
|
String packageName = CustomTabsHelper.getPackageNameToUse(context); |
||||||
|
|
||||||
|
//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) { |
||||||
|
super.onClick(widget); |
||||||
|
} else { |
||||||
|
customTabsIntent.intent.setPackage(packageName); |
||||||
|
customTabsIntent.launchUrl(context, uri); |
||||||
|
} |
||||||
|
} catch (ActivityNotFoundException e) { |
||||||
|
android.util.Log.w("URLSpan", "Activity was not found for intent, " + customTabsIntent.toString()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,122 @@ |
|||||||
|
package com.keylesspalace.tusky; |
||||||
|
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.text.TextUtils; |
||||||
|
import android.util.Log; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* stolen from https://github.com/GoogleChrome/custom-tabs-client/blob/master/shared/src/main/java/org/chromium/customtabsclient/shared/CustomTabsHelper.java
|
||||||
|
*/ |
||||||
|
|
||||||
|
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() {} |
||||||
|
|
||||||
|
/** |
||||||
|
* 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}; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue