Skip to content

Optimisation plugin for usage with Flutter module. #97

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
14 changes: 7 additions & 7 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,44 @@ group 'com.linusu.flutter_web_auth'
version '1.0-SNAPSHOT'

buildscript {
ext.kotlin_version = '1.3.72'
ext.kotlin_version = '1.5.21'
repositories {
google()
jcenter()
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath 'com.android.tools.build:gradle:3.6.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

rootProject.allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
compileSdkVersion 28
compileSdkVersion 31

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
minSdkVersion 16
minSdkVersion 23
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}

dependencies {
implementation 'androidx.browser:browser:1.0.0'
implementation 'androidx.browser:browser:1.3.0'
}
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,74 +1,179 @@
package com.linusu.flutter_web_auth

import android.content.Context
import android.app.Activity
import android.app.Application
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri

import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import androidx.browser.customtabs.CustomTabsIntent

import io.flutter.embedding.android.FlutterActivity
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 io.flutter.plugin.common.PluginRegistry.Registrar
import io.flutter.plugin.common.PluginRegistry

class FlutterWebAuthPlugin(
private var channel: MethodChannel? = null,
private var activityBinding: ActivityPluginBinding? = null
) : MethodCallHandler, FlutterPlugin, ActivityAware, PluginRegistry.NewIntentListener {

private lateinit var lifecycleListener: ActivityLifecycleListener

private val activity: Activity
get() = activityBinding!!.activity

class FlutterWebAuthPlugin(private var context: Context? = null, private var channel: MethodChannel? = null): MethodCallHandler, FlutterPlugin {
companion object {
val callbacks = mutableMapOf<String, Result>()
companion object {
val callbacks = mutableMapOf<String, Result>()
}

private fun initInstance(messenger: BinaryMessenger) {
channel = MethodChannel(messenger, "flutter_web_auth")
channel?.setMethodCallHandler(this)
}

override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
initInstance(binding.binaryMessenger)
}

@JvmStatic
fun registerWith(registrar: Registrar) {
val plugin = FlutterWebAuthPlugin()
plugin.initInstance(registrar.messenger(), registrar.context())
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
activityBinding = binding.apply {
addOnNewIntentListener(this@FlutterWebAuthPlugin)
lifecycleListener = ActivityLifecycleListener(activity.javaClass.name) {
cleanUpDanglingCalls()
}
activity.application.registerActivityLifecycleCallbacks(lifecycleListener)
}
}

}
override fun onDetachedFromActivityForConfigChanges() {
activityBinding?.apply {
removeOnNewIntentListener(this@FlutterWebAuthPlugin)
activity.application.unregisterActivityLifecycleCallbacks(lifecycleListener)
}
activityBinding = null
}

fun initInstance(messenger: BinaryMessenger, context: Context) {
this.context = context
channel = MethodChannel(messenger, "flutter_web_auth")
channel?.setMethodCallHandler(this)
}
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
activityBinding = binding.apply {
addOnNewIntentListener(this@FlutterWebAuthPlugin)
activity.application.registerActivityLifecycleCallbacks(lifecycleListener)
}
}

override public fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
initInstance(binding.getBinaryMessenger(), binding.getApplicationContext())
}
override fun onDetachedFromActivity() {
activityBinding?.apply {
removeOnNewIntentListener(this@FlutterWebAuthPlugin)
activity.application.unregisterActivityLifecycleCallbacks(lifecycleListener)
}
activityBinding = null
}

override public fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
context = null
channel = null
}

override fun onMethodCall(call: MethodCall, resultCallback: Result) {
when (call.method) {
"authenticate" -> {
val url = Uri.parse(call.argument("url"))
val callbackUrlScheme = call.argument<String>("callbackUrlScheme")!!
val preferEphemeral = call.argument<Boolean>("preferEphemeral")!!
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel = null
}

callbacks[callbackUrlScheme] = resultCallback
override fun onMethodCall(call: MethodCall, resultCallback: Result) {
when (call.method) {
"authenticate" -> {
val url = Uri.parse(call.argument("url"))
val callbackUrlScheme = call.argument<String>("callbackUrlScheme")!!
val preferEphemeral = call.argument<Boolean>("preferEphemeral")!!

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

intent.intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
if (preferEphemeral) {
intent.intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
}
intent.intent.putExtra("android.support.customtabs.extra.KEEP_ALIVE", keepAliveIntent)
val intent = CustomTabsIntent.Builder().build()
val keepAliveIntent = Intent(activity, KeepAliveService::class.java)

intent.launchUrl(context, url)
intent.intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
if (preferEphemeral) {
intent.intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
}
intent.intent.putExtra(
"android.support.customtabs.extra.KEEP_ALIVE",
keepAliveIntent
)
intent.intent.data = url
val CHROME_PACKAGE_NAME = "com.android.chrome"
val resolveInfoList = activity.packageManager.queryIntentActivities(intent
.intent, PackageManager.MATCH_ALL)
for (resolveInfo in resolveInfoList) {
val packageName = resolveInfo.activityInfo.packageName
if (TextUtils.equals(packageName, CHROME_PACKAGE_NAME))
intent.intent.setPackage(CHROME_PACKAGE_NAME)
}
intent.launchUrl(activity, url)
}
else -> resultCallback.notImplemented()
}
"cleanUpDanglingCalls" -> {
callbacks.forEach{ (_, danglingResultCallback) ->
danglingResultCallback.error("CANCELED", "User canceled login", null)
}
callbacks.clear()
resultCallback.success(null)
}

private fun cleanUpDanglingCalls() {
if (callbacks.isNotEmpty()) {
callbacks.forEach { (_, danglingResultCallback) ->
danglingResultCallback.error("CANCELED", "User canceled login", null)
}
callbacks.clear()
}
else -> resultCallback.notImplemented()
}
}

override fun onNewIntent(intent: Intent): Boolean {
if (intent.action == Intent.ACTION_VIEW &&
intent.hasCategory(Intent.CATEGORY_BROWSABLE)
) {
val url = intent.data
val scheme = url?.scheme
callbacks.remove(scheme)?.success(url?.toString())
return true
}
return false
}
}

private class ActivityLifecycleListener(
val appActivityName: String,
val onReturnFromBrowser: () -> Unit
) : Application.ActivityLifecycleCallbacks {

var paused: Boolean = false

override fun onActivityPaused(activity: Activity) {
verifyActivity(activity) {
paused = true
}
}

override fun onActivityStopped(activity: Activity) {}

override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}

override fun onActivityDestroyed(activity: Activity) {}

override fun onActivityResumed(activity: Activity) {
verifyActivity(activity) {
if (paused) {
Log.d("FlutterWebAuthPlugin", "onReturnFromBrowser")
onReturnFromBrowser()
paused = false
}
}
}

fun verifyActivity(activity: Activity, success: () -> Unit) {
if (activity.javaClass.name == appActivityName && activity is FlutterActivity) {
success()
}
}

override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}

override fun onActivityStarted(activity: Activity) {}
}
6 changes: 3 additions & 3 deletions example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion 28
compileSdkVersion 29

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
Expand All @@ -40,7 +40,7 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.linusu.flutter_web_auth_example"
minSdkVersion 16
targetSdkVersion 28
targetSdkVersion 29
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
Expand All @@ -61,7 +61,7 @@ flutter {

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
13 changes: 0 additions & 13 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_web_auth_example"
android:icon="@mipmap/ic_launcher">
<activity
Expand All @@ -21,23 +20,11 @@
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>

<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" >
<intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="foobar" />
</intent-filter>
</activity>

</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
package com.linusu.flutter_web_auth_example

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity

import io.flutter.app.FlutterActivity
import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
}
}
class MainActivity: FlutterActivity()
4 changes: 2 additions & 2 deletions example/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
buildscript {
ext.kotlin_version = '1.3.72'
ext.kotlin_version = '1.5.21'
repositories {
google()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath 'com.android.tools.build:gradle:3.6.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Expand Down
1 change: 0 additions & 1 deletion example/android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
android.enableR8=true
Loading