Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,54 +62,22 @@ class OSIABCustomTabsSessionHelper: OSIABCustomTabsSessionHelperInterface {
flowHelper: OSIABFlowHelperInterface,
) : CustomTabsCallback() {

private var isCustomTabsActivityOnTop = false
private var pendingTabHiddenEvent = false

init {
var browserEventsJob: Job? = null

browserEventsJob = flowHelper.listenToEvents(browserId, lifecycleScope) { event ->
if(event is OSIABEvents.OSIABCustomTabsEvent) {
when (event.action) {
OSIABCustomTabsControllerActivity.EVENT_CUSTOM_TABS_RESUMED -> {
isCustomTabsActivityOnTop = true
if (pendingTabHiddenEvent) {
pendingTabHiddenEvent = false
lifecycleScope.launch {
OSIABEvents.postEvent(OSIABEvents.BrowserFinished(browserId))
}
}
}
OSIABCustomTabsControllerActivity.EVENT_CUSTOM_TABS_PAUSED -> {
isCustomTabsActivityOnTop = false
pendingTabHiddenEvent = false
}
OSIABCustomTabsControllerActivity.EVENT_CUSTOM_TABS_DESTROYED -> {
browserEventsJob?.cancel()
}
}
if (event is OSIABEvents.OSIABCustomTabsEvent
&& event.action == OSIABCustomTabsControllerActivity.EVENT_CUSTOM_TABS_DESTROYED) {
browserEventsJob?.cancel()
}
}
}

override fun onNavigationEvent(navigationEvent: Int, extras: Bundle?) {
super.onNavigationEvent(navigationEvent, extras)
val browserEvent = when (navigationEvent) {
NAVIGATION_FINISHED -> OSIABEvents.BrowserPageLoaded(browserId)
TAB_HIDDEN -> {
if(isCustomTabsActivityOnTop) {
OSIABEvents.BrowserFinished(browserId)
}
else {
// App not open but custom tabs is hidden (home button, recent apps, etc.)
pendingTabHiddenEvent = true
return
}
if (navigationEvent == NAVIGATION_FINISHED) {
lifecycleScope.launch {
OSIABEvents.postEvent(OSIABEvents.BrowserPageLoaded(browserId))
}
else -> return
}
lifecycleScope.launch {
OSIABEvents.postEvent(browserEvent)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,28 @@ class OSIABCustomTabsRouterAdapter(
var closeEventJob: Job? = null

closeEventJob = flowHelper.listenToEvents(browserId, lifecycleScope) { event ->
if(event is OSIABEvents.OSIABCustomTabsEvent) {
when(event.action) {
OSIABCustomTabsControllerActivity.EVENT_CUSTOM_TABS_READY -> {
completionHandler(false)
}
OSIABCustomTabsControllerActivity.EVENT_CUSTOM_TABS_DESTROYED -> {
completionHandler(true)
}
else -> {
return@listenToEvents
}
}
if(event is OSIABEvents.OSIABCustomTabsEvent
&& event.action == OSIABCustomTabsControllerActivity.EVENT_CUSTOM_TABS_DESTROYED) {
completionHandler(true)
closeEventJob?.cancel()
}
}

startCustomTabsControllerActivity(true)
startCustomTabsControllerActivity(doClose = true)
}

private fun resolveStartAnimationRes(animation: OSIABAnimation): Pair<Int, Int> = when (animation) {
OSIABAnimation.FADE_IN -> android.R.anim.fade_in to android.R.anim.fade_out
OSIABAnimation.FADE_OUT -> android.R.anim.fade_out to android.R.anim.fade_in
OSIABAnimation.SLIDE_IN_LEFT -> android.R.anim.slide_in_left to android.R.anim.slide_out_right
OSIABAnimation.SLIDE_OUT_RIGHT -> android.R.anim.slide_out_right to android.R.anim.slide_in_left
}

private fun resolveExitAnimationRes(animation: OSIABAnimation): Pair<Int, Int> = when (animation) {
OSIABAnimation.FADE_IN -> android.R.anim.fade_out to android.R.anim.fade_in
OSIABAnimation.FADE_OUT -> android.R.anim.fade_in to android.R.anim.fade_out
OSIABAnimation.SLIDE_IN_LEFT -> android.R.anim.slide_out_right to android.R.anim.slide_in_left
OSIABAnimation.SLIDE_OUT_RIGHT -> android.R.anim.slide_in_left to android.R.anim.slide_out_right
}

private fun buildCustomTabsIntent(customTabsSession: CustomTabsSession?): CustomTabsIntent {
Expand All @@ -76,57 +81,11 @@ class OSIABCustomTabsRouterAdapter(
builder.setShowTitle(options.showTitle)
builder.setUrlBarHidingEnabled(options.hideToolbarOnScroll)

when (options.startAnimation) {
OSIABAnimation.FADE_IN -> builder.setStartAnimations(
context,
android.R.anim.fade_in,
android.R.anim.fade_out
)

OSIABAnimation.FADE_OUT -> builder.setStartAnimations(
context,
android.R.anim.fade_out,
android.R.anim.fade_in
)

OSIABAnimation.SLIDE_IN_LEFT -> builder.setStartAnimations(
context,
android.R.anim.slide_in_left,
android.R.anim.slide_out_right
)

OSIABAnimation.SLIDE_OUT_RIGHT -> builder.setStartAnimations(
context,
android.R.anim.slide_out_right,
android.R.anim.slide_in_left
)
}

when (options.exitAnimation) {
OSIABAnimation.FADE_IN -> builder.setExitAnimations(
context,
android.R.anim.fade_out,
android.R.anim.fade_in
)

OSIABAnimation.FADE_OUT -> builder.setExitAnimations(
context,
android.R.anim.fade_in,
android.R.anim.fade_out
)
val (startEnter, startExit) = resolveStartAnimationRes(options.startAnimation)
builder.setStartAnimations(context, startEnter, startExit)

OSIABAnimation.SLIDE_IN_LEFT -> builder.setExitAnimations(
context,
android.R.anim.slide_out_right,
android.R.anim.slide_in_left
)

OSIABAnimation.SLIDE_OUT_RIGHT -> builder.setExitAnimations(
context,
android.R.anim.slide_in_left,
android.R.anim.slide_out_right
)
}
val (exitEnter, exitExit) = resolveExitAnimationRes(options.exitAnimation)
builder.setExitAnimations(context, exitEnter, exitExit)

if (options.viewStyle == OSIABViewStyle.BOTTOM_SHEET) {
options.bottomSheetOptions?.let { bottomSheetOptions ->
Expand Down Expand Up @@ -161,9 +120,7 @@ class OSIABCustomTabsRouterAdapter(
completionHandler(false)
return@generateNewCustomTabsSession
}

openCustomTabsIntent(it, uri, completionHandler)
startCustomTabsControllerActivity()
}
)
} catch (e: Exception) {
Expand All @@ -174,21 +131,13 @@ class OSIABCustomTabsRouterAdapter(

private fun openCustomTabsIntent(session: CustomTabsSession, uri: Uri, completionHandler: (Boolean) -> Unit) {
val customTabsIntent = buildCustomTabsIntent(session)
customTabsIntent.intent.data = uri

var eventsJob: Job? = null
eventsJob = flowHelper.listenToEvents(browserId, lifecycleScope) { event ->
when (event) {
is OSIABEvents.OSIABCustomTabsEvent -> {
if(event.action == OSIABCustomTabsControllerActivity.EVENT_CUSTOM_TABS_READY) {
try {
event.context?.let { ctx ->
customTabsIntent.launchUrl(ctx, uri)
completionHandler(true)
} ?: completionHandler(false)
} catch (e: Exception) {
completionHandler(false)
}
}
else if(event.action == OSIABCustomTabsControllerActivity.EVENT_CUSTOM_TABS_DESTROYED) {
if(event.action == OSIABCustomTabsControllerActivity.EVENT_CUSTOM_TABS_DESTROYED) {
isFinished = true
onBrowserFinished()
eventsJob?.cancel()
Expand All @@ -200,19 +149,30 @@ class OSIABCustomTabsRouterAdapter(
isFirstLoad = false
}
}
is OSIABEvents.BrowserFinished -> {
// Ensure that custom tabs controller activity is fully destroyed
startCustomTabsControllerActivity(true)
isFinished = true
onBrowserFinished()
eventsJob?.cancel()
}
else -> {}
}
}

try {
val (startEnter, startExit) = resolveStartAnimationRes(options.startAnimation)
startCustomTabsControllerActivity(
customTabsIntent = customTabsIntent.intent,
startEnterAnimRes = startEnter,
startExitAnimRes = startExit
)
completionHandler(true)
} catch (e: Exception) {
eventsJob?.cancel()
completionHandler(false)
}
}

private fun startCustomTabsControllerActivity(doClose: Boolean = false) {
private fun startCustomTabsControllerActivity(
doClose: Boolean = false,
customTabsIntent: Intent? = null,
startEnterAnimRes: Int = 0,
startExitAnimRes: Int = 0
) {
val intent = Intent(context, OSIABCustomTabsControllerActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
putExtra(OSIABEvents.EXTRA_BROWSER_ID, browserId)
Expand All @@ -223,6 +183,12 @@ class OSIABCustomTabsRouterAdapter(
intent.putExtra(OSIABCustomTabsControllerActivity.ACTION_CLOSE_CUSTOM_TABS, true)
}

if (customTabsIntent != null) {
intent.putExtra(OSIABCustomTabsControllerActivity.EXTRA_CUSTOM_TABS_INTENT, customTabsIntent)
intent.putExtra(OSIABCustomTabsControllerActivity.EXTRA_START_ENTER_ANIM_RES, startEnterAnimRes)
intent.putExtra(OSIABCustomTabsControllerActivity.EXTRA_START_EXIT_ANIM_RES, startExitAnimRes)
}

context.startActivity(intent)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ package com.outsystems.plugins.inappbrowser.osinappbrowserlib.views
import android.content.Intent
import android.os.Bundle
import android.view.WindowManager
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityOptionsCompat
import androidx.core.content.IntentCompat
import androidx.lifecycle.lifecycleScope
import com.outsystems.plugins.inappbrowser.osinappbrowserlib.OSIABEvents
import com.outsystems.plugins.inappbrowser.osinappbrowserlib.OSIABEvents.OSIABCustomTabsEvent
Expand All @@ -18,12 +22,16 @@ import kotlinx.coroutines.launch
class OSIABCustomTabsControllerActivity: AppCompatActivity() {
companion object {
const val EVENT_CUSTOM_TABS_DESTROYED = "com.outsystems.plugins.inappbrowser.osinappbrowserlib.EVENT_CUSTOM_TABS_DESTROYED"
const val EVENT_CUSTOM_TABS_READY = "com.outsystems.plugins.inappbrowser.osinappbrowserlib.EVENT_CUSTOM_TABS_READY"
const val EVENT_CUSTOM_TABS_PAUSED = "com.outsystems.plugins.inappbrowser.osinappbrowserlib.EVENT_CUSTOM_TABS_PAUSED"
const val EVENT_CUSTOM_TABS_RESUMED = "com.outsystems.plugins.inappbrowser.osinappbrowserlib.EVENT_CUSTOM_TABS_RESUMED"
const val ACTION_CLOSE_CUSTOM_TABS = "com.outsystems.plugins.inappbrowser.osinappbrowserlib.ACTION_CLOSE_CUSTOM_TABS"
const val EXTRA_CUSTOM_TABS_INTENT = "com.outsystems.plugins.inappbrowser.osinappbrowserlib.EXTRA_CUSTOM_TABS_INTENT"
const val EXTRA_START_ENTER_ANIM_RES = "com.outsystems.plugins.inappbrowser.osinappbrowserlib.EXTRA_START_ENTER_ANIM_RES"
const val EXTRA_START_EXIT_ANIM_RES = "com.outsystems.plugins.inappbrowser.osinappbrowserlib.EXTRA_START_EXIT_ANIM_RES"
}

private var customTabsLauncher: ActivityResultLauncher<Intent>? = null
private var hasLaunchedCustomTabs = false


private fun setup(intent: Intent) {
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
Expand All @@ -32,16 +40,30 @@ class OSIABCustomTabsControllerActivity: AppCompatActivity() {

if (intent.getBooleanExtra(ACTION_CLOSE_CUSTOM_TABS, false)) {
finish()
return
}
else {
intent.getStringExtra(OSIABEvents.EXTRA_BROWSER_ID)?.let { browserId ->
sendCustomTabsEvent(lifecycleScope, browserId, EVENT_CUSTOM_TABS_READY)

if (!hasLaunchedCustomTabs) {
val customTabsIntent = IntentCompat.getParcelableExtra(intent, EXTRA_CUSTOM_TABS_INTENT, Intent::class.java)
if (customTabsIntent != null) {
hasLaunchedCustomTabs = true
val enterAnimRes = intent.getIntExtra(EXTRA_START_ENTER_ANIM_RES, 0)
val exitAnimRes = intent.getIntExtra(EXTRA_START_EXIT_ANIM_RES, 0)
val options = if (enterAnimRes != 0 && exitAnimRes != 0) {
ActivityOptionsCompat.makeCustomAnimation(this, enterAnimRes, exitAnimRes)
} else {
null
}
customTabsLauncher?.launch(customTabsIntent, options)
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
customTabsLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
finish()
}
setup(intent)
}

Expand All @@ -50,20 +72,6 @@ class OSIABCustomTabsControllerActivity: AppCompatActivity() {
setup(intent)
}

override fun onPause() {
super.onPause()
intent.getStringExtra(OSIABEvents.EXTRA_BROWSER_ID)?.let { browserId ->
sendCustomTabsEvent(lifecycleScope, browserId, EVENT_CUSTOM_TABS_PAUSED)
}
}

override fun onResume() {
super.onResume()
intent.getStringExtra(OSIABEvents.EXTRA_BROWSER_ID)?.let { browserId ->
sendCustomTabsEvent(lifecycleScope, browserId, EVENT_CUSTOM_TABS_RESUMED)
}
}

override fun onDestroy() {
intent.getStringExtra(OSIABEvents.EXTRA_BROWSER_ID)?.let { browserId ->
val customScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
Expand Down Expand Up @@ -95,4 +103,4 @@ class OSIABCustomTabsControllerActivity: AppCompatActivity() {
scope.cancel()
}
}
}
}
Loading
Loading