Skip to content

Instantly share code, notes, and snippets.

@chibatching
Created May 12, 2016 00:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chibatching/2e29f2fa80e576c6169675501514c3c7 to your computer and use it in GitHub Desktop.
Save chibatching/2e29f2fa80e576c6169675501514c3c7 to your computer and use it in GitHub Desktop.
import android.app.Activity
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.net.Uri
import android.support.customtabs.CustomTabsClient
import android.support.customtabs.CustomTabsIntent
import android.support.customtabs.CustomTabsServiceConnection
import android.support.customtabs.CustomTabsSession
import android.text.TextUtils
import java.util.*
class CustomTabsHelper(
val activity: Activity,
val showTitle: Boolean,
val toolbarColorInt: Int? = null,
val secondaryToolbarColor: Int? = null,
val closeButtonIcon: Bitmap? = null,
val startAnimation: Pair<Int, Int>? = null,
val exitAnimation: Pair<Int, Int>? = null,
val urlBarHiding: Boolean = false
) {
private var mayLaunchUrl: String? = null
private var customTabsConnection: CustomTabsServiceConnection? = null
private var customTabsClient: CustomTabsClient? = null
var customTabsSession: CustomTabsSession? = null
fun bindCustomTabs(url: String? = null) {
mayLaunchUrl = url
customTabsConnection?.let { return }
customTabsConnection = BargainCustomTabConnection()
CustomTabsClient.bindCustomTabsService(activity, getPackageNameToUse(activity), customTabsConnection)
}
fun unbindCustomTabs() {
customTabsConnection?.let {
activity.unbindService(it)
customTabsClient = null
customTabsSession = null
customTabsConnection = null
}
}
fun launchUrl(url: String? = mayLaunchUrl) {
url?.let {
CustomTabsIntent.Builder(customTabsSession).apply {
setShowTitle(showTitle)
toolbarColorInt?.let { setToolbarColor(it) }
secondaryToolbarColor?.let { setSecondaryToolbarColor(it) }
closeButtonIcon?.let { setCloseButtonIcon(it) }
startAnimation?.let { setStartAnimations(activity, it.first, it.second) }
exitAnimation?.let { setExitAnimations(activity, it.first, it.second) }
if (urlBarHiding) {
enableUrlBarHiding()
}
}.build()
.launchUrl(activity, Uri.parse(it))
}
}
inner class BargainCustomTabConnection : CustomTabsServiceConnection() {
override fun onCustomTabsServiceConnected(componentName: ComponentName, customTabsClient: CustomTabsClient) {
this@CustomTabsHelper.customTabsClient = customTabsClient.apply { warmup(0) }
this@CustomTabsHelper.customTabsSession = this@CustomTabsHelper.customTabsClient?.newSession(null)
this@CustomTabsHelper.customTabsSession?.mayLaunchUrl(Uri.parse(mayLaunchUrl), null, null)
}
override fun onServiceDisconnected(name: ComponentName?) {
this@CustomTabsHelper.customTabsClient = null
}
}
// Below code from custom-tabs-client sample
// https://github.com/GoogleChrome/custom-tabs-client/blob/addb26ad8fce8cdcb640217f4c9da75dd19763cc/shared/src/main/java/org/chromium/customtabsclient/shared/CustomTabsHelper.java
companion object {
private val STABLE_PACKAGE = "com.android.chrome"
private val BETA_PACKAGE = "com.chrome.beta"
private val DEV_PACKAGE = "com.chrome.dev"
private val LOCAL_PACKAGE = "com.google.android.apps.chrome"
private val ACTION_CUSTOM_TABS_CONNECTION = "android.support.customtabs.action.CustomTabsService"
private var packageNameToUse: String? = null
}
fun getPackageNameToUse(context: Context): String? {
packageNameToUse?.let { return it }
val pm = context.packageManager
// Get default VIEW intent handler.
val activityIntent = Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"))
val defaultViewHandlerInfo = pm.resolveActivity(activityIntent, 0)
var defaultViewHandlerPackageName: String? = null
if (defaultViewHandlerInfo != null) {
defaultViewHandlerPackageName = defaultViewHandlerInfo.activityInfo.packageName
}
// Get all apps that can handle VIEW intents.
val resolvedActivityList = pm.queryIntentActivities(activityIntent, 0)
val packagesSupportingCustomTabs = ArrayList<String>()
for (info in resolvedActivityList) {
val serviceIntent = Intent()
serviceIntent.action = ACTION_CUSTOM_TABS_CONNECTION
serviceIntent.`package` = 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()) {
packageNameToUse = null
} else if (packagesSupportingCustomTabs.size == 1) {
packageNameToUse = packagesSupportingCustomTabs[0]
} else if (!TextUtils.isEmpty(defaultViewHandlerPackageName)
&& !hasSpecializedHandlerIntents(activityIntent)
&& packagesSupportingCustomTabs.contains(defaultViewHandlerPackageName)) {
packageNameToUse = defaultViewHandlerPackageName
} else if (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) {
packageNameToUse = STABLE_PACKAGE
} else if (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) {
packageNameToUse = BETA_PACKAGE
} else if (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) {
packageNameToUse = DEV_PACKAGE
} else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) {
packageNameToUse = LOCAL_PACKAGE
}
return packageNameToUse
}
private fun hasSpecializedHandlerIntents(intent: Intent): Boolean {
try {
val pm = activity.packageManager
val handlers = pm.queryIntentActivities(
intent,
PackageManager.GET_RESOLVED_FILTER)
if (handlers == null || handlers.size == 0) {
return false
}
for (resolveInfo in handlers) {
val filter = resolveInfo.filter ?: continue
if (filter.countDataAuthorities() == 0 || filter.countDataPaths() == 0) continue
if (resolveInfo.activityInfo == null) continue
return true
}
} catch (e: RuntimeException) {
}
return false
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment