Skip to content

Commit

Permalink
Keep full authentication proedure on the same task stack for better u…
Browse files Browse the repository at this point in the history
…x on android
  • Loading branch information
Mino5531 committed Feb 13, 2025
1 parent 8057fa8 commit af583aa
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.linusu.flutter_web_auth_2

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.browser.customtabs.CustomTabsIntent

class AuthenticationManagementActivity(
) : Activity() {
companion object {
const val KEY_AUTH_STARTED: String = "authStarted"
const val KEY_AUTH_URI: String = "authUri"
const val KEY_AUTH_OPTION_INTENT_FLAGS: String = "authOptionsIntentFlags"
const val KEY_AUTH_OPTION_TARGET_PACKAGE: String = "authOptionsTargetPackage"

fun createResponseHandlingIntent(context: Context): Intent {
val intent = Intent(context, AuthenticationManagementActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
return intent
}
}
private var authStarted: Boolean = false
private lateinit var authenticationUri: Uri
private var intentFlags: Int = 0
private var targetPackage: String? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
extractState(intent.extras)
} else {
extractState(savedInstanceState)
}
}

override fun onResume() {
super.onResume()

if (!authStarted) {
val intent = CustomTabsIntent.Builder().build()
intent.intent.addFlags(intentFlags)

if (targetPackage != null) {
intent.intent.setPackage(targetPackage)
}
intent.launchUrl(this, authenticationUri)
authStarted = true
return
}
/* If the authentication was already started and we've returned here, the user either
* completed or cancelled authentication.
* Either way we want to return to our original flutter activity, so just finish here
*/
finish()
}

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
setIntent(intent);
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putBoolean(KEY_AUTH_STARTED, authStarted)
outState.putParcelable(KEY_AUTH_URI, authenticationUri)
outState.putInt(KEY_AUTH_OPTION_INTENT_FLAGS, intentFlags)
outState.putString(
KEY_AUTH_OPTION_TARGET_PACKAGE,
targetPackage
)
}

private fun extractState(state: Bundle?) {
if (state == null) {
finish()
return
}
authStarted = state.getBoolean(KEY_AUTH_STARTED, false)
authenticationUri = state.getParcelable(KEY_AUTH_URI)!!
intentFlags = state.getInt(KEY_AUTH_OPTION_INTENT_FLAGS, 0)
targetPackage = state.getString(KEY_AUTH_OPTION_TARGET_PACKAGE)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class CallbackActivity : Activity() {
if (scheme != null) {
FlutterWebAuth2Plugin.callbacks.remove(scheme)?.success(url.toString())
}
finishAndRemoveTask()
startActivity(AuthenticationManagementActivity.createResponseHandlingIntent(this))
finish()
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.linusu.flutter_web_auth_2

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
Expand All @@ -9,16 +10,20 @@ import androidx.browser.customtabs.CustomTabsClient
import androidx.browser.customtabs.CustomTabsIntent

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import java.util.ArrayList

class FlutterWebAuth2Plugin(
private var context: Context? = null,
private var channel: MethodChannel? = null
) : MethodCallHandler, FlutterPlugin {
private var channel: MethodChannel? = null,
private var activity: Activity? = null,
) : MethodCallHandler, FlutterPlugin, ActivityAware {
companion object {
val callbacks = mutableMapOf<String, Result>()
}
Expand Down Expand Up @@ -46,17 +51,11 @@ class FlutterWebAuth2Plugin(
val options = call.argument<Map<String, Any>>("options")!!

callbacks[callbackUrlScheme] = resultCallback
val intent = CustomTabsIntent.Builder().build()
val keepAliveIntent = Intent(context, KeepAliveService::class.java)

intent.intent.addFlags(options["intentFlags"] as Int)
intent.intent.putExtra("android.support.customtabs.extra.KEEP_ALIVE", keepAliveIntent)

val targetPackage = findTargetBrowserPackageName(options)
if (targetPackage != null) {
intent.intent.setPackage(targetPackage)
}
intent.launchUrl(context!!, url)
activity?.startActivity(Intent(activity,AuthenticationManagementActivity::class.java).apply {
putExtra(AuthenticationManagementActivity.KEY_AUTH_URI,url)
putExtra(AuthenticationManagementActivity.KEY_AUTH_OPTION_INTENT_FLAGS, options["intentFlags"] as Int)
putExtra(AuthenticationManagementActivity.KEY_AUTH_OPTION_TARGET_PACKAGE, findTargetBrowserPackageName(options))
})
}

"cleanUpDanglingCalls" -> {
Expand All @@ -71,6 +70,22 @@ class FlutterWebAuth2Plugin(
}
}

override fun onAttachedToActivity(binding: ActivityPluginBinding) {
activity = binding.activity
}

override fun onDetachedFromActivityForConfigChanges() {
onDetachedFromActivity()
}

override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
onAttachedToActivity(binding)
}

override fun onDetachedFromActivity() {
activity = null
}

/**
* Find Support CustomTabs Browser.
*
Expand Down Expand Up @@ -145,5 +160,4 @@ class FlutterWebAuth2Plugin(
)
return value == packageName
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<activity android:name="com.linusu.flutter_web_auth_2.AuthenticationManagementActivity">
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
Expand Down
7 changes: 2 additions & 5 deletions flutter_web_auth_2/lib/src/options.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
/// Default intent flags for opening the custom tabs intent on Android.
/// This is essentially the same as
/// `FLAG_ACTIVITY_SINGLE_TOP | FLAG_ACTIVITY_NEW_TASK`.
const defaultIntentFlags = 1 << 29 | 1 << 28;
const defaultIntentFlags = 0;

/// "Ephemeral" intent flags for opening the custom tabs intent on Android.
/// This is essentially the same as
/// `FLAG_ACTIVITY_SINGLE_TOP | FLAG_ACTIVITY_NEW_TASK
/// | FLAG_ACTIVITY_NO_HISTORY`.
/// FLAG_ACTIVITY_NO_HISTORY`.
const ephemeralIntentFlags = defaultIntentFlags | 1 << 30;

/// Default HTML code that generates a nice callback page.
Expand Down

0 comments on commit af583aa

Please sign in to comment.