GoogleChrome / GoogleChrome/android-browser-helper

CustomTabsCallback.onRelationshipValidationResult doesn't get called.

Open
#396 0 comments 2 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
832
Forks
370
Avg merge
1d 3h
Merged PRs (30d)
6

Description

**Description**
We have used TWA to display the web content for one of our use-case. Custom headers are also passed. On most of the devices, after starting the CustomTabsService, the CustomTabsServiceConnection.onCustomTabsServiceConnected gets called with CustomTabsSession.validateRelationship returning true and followed by CustomTabsCallback.onRelationshipValidationResult getting called.

However, on One Plus 6T, OS - Android 10, post starting the service, onCustomTabsServiceConnected gets called, but the onRelationshipValidationResult method never gets called. No logs are returned whatsoever.

Because we are passing custom headers to maintain the user session from native to the web, we are unable to deterministically verify the app-web relation when onRelationshipValidationResult doesn't get called.

**Expected behavior**
Expected behavior should be that the callback methods should be guaranteed to be called all the time. There should be another deterministic way to know if custom headers can be passed.

**Code Snippets**
`class MFTWALauncher(private val activity: FragmentActivity,
private val navigationController: NavController?,
private val url: String,
private val mfFallbackType: String) : DefaultLifecycleObserver {
private val uri: Uri = Uri.parse(url)
private var mSession: CustomTabsSession? = null
private var isTWALaunched = false
private val chromePackageName = "com.android.chrome"

// Set up a callback that launches the intent after session was validated.
private val callback: CustomTabsCallback = object : CustomTabsCallback() {
override fun onRelationshipValidationResult(
relation: Int,
requestedOrigin: Uri,
result: Boolean,
@Nullable extras: Bundle?,) {
openMFTWA()
}
}

// Set up a connection that warms up and validates a session.
private var connection: CustomTabsServiceConnection? = object : CustomTabsServiceConnection() {
override fun onCustomTabsServiceConnected(name: ComponentName, client: CustomTabsClient) {
mSession = client.newSession(callback)
client.warmup(0)
val validateRelationship = mSession?.validateRelationship(CustomTabsService.RELATION_USE_AS_ORIGIN, uri, null)
}
override fun onServiceDisconnected(name: ComponentName?) {
}
}

fun launchMF() {
// Bind the custom tabs service connection.
connection?.let {
try{
val packageName = CustomTabsClient.getPackageName(activity, listOf(chromePackageName), true)
if(packageName != null && packageName.isNotEmpty()) {
CustomTabsClient.bindCustomTabsService(
activity,
packageName,
it
)
return@let
}
} catch (e: Exception){
e.localizedMessage?.let { msg->
Log.d("Exception", msg)
}
}

handleMFFallback()
}
}

private fun openMFTWA() {
mSession?.let {
try {
activity.lifecycle.addObserver(this)
val intentBuilder = TrustedWebActivityIntentBuilder(uri)
val intent = intentBuilder.build(it)
val headers = bundleOf(
ParamConstants.MFHeaders.DEVICE_ID.value to getDeviceID(),
ParamConstants.MFHeaders.AUTH_TOKEN.value to
if(isExistingUser()) SecuredSharedPref.getNonTradeAccessToken() else SecuredSharedPref.getGuestToken(),
ParamConstants.MFHeaders.REFRESH_TOKEN.value to SecuredSharedPref.getNonTradeRefreshToken(),
ParamConstants.MFHeaders.PLATFORM.value to ParamConstants.MFHeaders.SPARK_ANDROID.value,
ParamConstants.MFHeaders.PLATFORM_VERSION.value to (getVersionName() ?: ""),
ParamConstants.MFHeaders.THEME.value to ThemeUtils.getThemeName(activity),
ParamConstants.MFHeaders.CLEVER_TAP_CLIENT_ID.value to getCleverTapId(),
ParamConstants.MFHeaders.GUEST.value to if(isExistingUser()) ParamConstants.MFHeaders.NO.value else
ParamConstants.MFHeaders.YES.value,
)
intent.intent.putExtra(Browser.EXTRA_HEADERS, headers)
TwaLauncher(activity, chromePackageName).launch(intentBuilder, null, null, null)
isTWALaunched = true
} catch (e: Exception) {
clearAndUnbind()
Log.d("Exception", e.localizedMessage)
}
}
}

private fun handleMFFallback() {
when(mfFallbackType) {
ParamConstants.MFFallbackType.INSTALL_CHROME_MESSAGE.value -> {
sendChromeNotInstalledEvent()
if(activity is MainActivity) {
activity.genericSnackBar(activity.resources.getString(R.string.chrome_not_installed))
}
}
ParamConstants.MFFallbackType.ANGEL_BEE.value -> {
navigationController?.let {
it.navigate(R.id.mutualFundFragment)
}
}
ParamConstants.MFFallbackType.WEB_VIEW.value -> {
val intent = Intent(activity, MFWebViewActivity::class.java)
val bundle = Bundle()
bundle.putString(AppConstants.MF_URL, url)
intent.putExtras(bundle)
activity.startActivity(intent)
}
}
}

private fun clearAndUnbind() {
// Unbind from the service if we connected successfully and clear the session.
if (mSession != null) {
connection?.let {
activity.unbindService(it)
connection = null
mSession = null
}
}
isTWALaunched = false
activity.lifecycle.removeObserver(this)
}

override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
if(isTWALaunched) {
clearAndUnbind()
}
}

private fun sendChromeNotInstalledEvent() {
val analyticalData = AnalyticsUtils().getAnalyticsModel(
screen_name = AnalyticsConstant.SCREEN_NAME_HOME_SCREEN,
event_type = AnalyticsConstant.EVENT_TYPE_IMPRESSION,
event_sub_type = AnalyticsConstant.EVENT_SUB_TYPE_TOAST_BOX,
event_name = AnalyticsConstant.EVENT_NAME_TOAST_MESSAGE,
event_id = AnalyticsConstant.EVENT_ID_CHROME_NOT_INSTALLED,
event_property = "",
event_metadata = "{Message : Please install Google Chrome to access this feature}"
)
EventClient.impression(analyticalData)
}
}
`

And this is called as follows
`
val mfLauncher = MFTWALauncher(activity, navigationController,
url, FeatureManagerUtils.getMFFallbackType())
mfLauncher.launchMF()
`

- Device: One Plus 6T
- OS: Android 10
- Browsers Installed: Chrome
- Browser Versions: Latest from the playstore (106.0.5249.126)
- android-browser-helper library version: 2.4.0

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.