/*
* Copyright (c) 2016 Ha Duy Trung
*
* 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.
*/
package io.github.hidroh.materialistic;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.customtabs.CustomTabsClient;
import android.support.customtabs.CustomTabsServiceConnection;
import android.support.customtabs.CustomTabsSession;
import android.text.TextUtils;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import io.github.hidroh.materialistic.annotation.Synthetic;
public class CustomTabsDelegate {
private static final String STABLE_PACKAGE = "com.android.chrome";
private static final String BETA_PACKAGE = "com.chrome.beta";
private static final String DEV_PACKAGE = "com.chrome.dev";
private static final String LOCAL_PACKAGE = "com.google.android.apps.chrome";
private static final String ACTION_CUSTOM_TABS_CONNECTION =
"android.support.customtabs.action.CustomTabsService";
private static String sPackageNameToUse;
private CustomTabsSession mCustomTabsSession;
private CustomTabsClient mClient;
private CustomTabsServiceConnection mConnection;
/**
* Binds the Activity to the Custom Tabs Service.
* @param activity the activity to be binded to the service.
*/
void bindCustomTabsService(Activity activity) {
if (mClient != null) {
return;
}
if (TextUtils.isEmpty(getPackageNameToUse(activity))) {
return;
}
mConnection = new ServiceConnection(this);
CustomTabsClient.bindCustomTabsService(activity, sPackageNameToUse, mConnection);
}
/**
* Unbinds the Activity from the Custom Tabs Service.
* @param activity the activity that is connected to the service.
*/
void unbindCustomTabsService(Activity activity) {
if (mConnection == null) {
return;
}
activity.unbindService(mConnection);
mClient = null;
mCustomTabsSession = null;
mConnection = null;
}
/**
* @see {@link CustomTabsSession#mayLaunchUrl(Uri, Bundle, List)}.
* @return true if call to mayLaunchUrl was accepted.
*/
public boolean mayLaunchUrl(Uri uri, Bundle extras, List<Bundle> otherLikelyBundles) {
if (mClient == null) {
return false;
}
CustomTabsSession session = getSession();
return session != null && session.mayLaunchUrl(uri, extras, otherLikelyBundles);
}
/**
* Creates or retrieves an exiting CustomTabsSession.
*
* @return a CustomTabsSession.
*/
CustomTabsSession getSession() {
if (mClient == null) {
mCustomTabsSession = null;
} else if (mCustomTabsSession == null) {
mCustomTabsSession = mClient.newSession(null);
}
return mCustomTabsSession;
}
@Synthetic
void onServiceConnected(CustomTabsClient client) {
mClient = client;
mClient.warmup(0L);
}
@Synthetic
void onServiceDisconnected() {
mClient = null;
mCustomTabsSession = null;
}
private static String getPackageNameToUse(Context context) {
if (sPackageNameToUse != null) {
return sPackageNameToUse;
}
// packagesSupportingCustomTabs contains all apps that can handle both VIEW intents
// and service calls.
List<String> packagesSupportingCustomTabs = new ArrayList<>();
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(
new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com")), 0);
//noinspection Convert2streamapi
for (ResolveInfo info : resolvedActivityList) {
if (pm.resolveService(new Intent()
.setAction(ACTION_CUSTOM_TABS_CONNECTION)
.setPackage(info.activityInfo.packageName), 0) != null) {
packagesSupportingCustomTabs.add(info.activityInfo.packageName);
}
}
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;
}
@Synthetic
static class ServiceConnection extends CustomTabsServiceConnection {
private WeakReference<CustomTabsDelegate> mDelegate;
@Synthetic
ServiceConnection(CustomTabsDelegate delegate) {
mDelegate = new WeakReference<>(delegate);
}
@Override
public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
CustomTabsDelegate delegate = mDelegate.get();
if (delegate != null) {
delegate.onServiceConnected(client);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
CustomTabsDelegate delegate = mDelegate.get();
if (delegate != null) {
delegate.onServiceDisconnected();
}
}
}
}