Skip to content
Merged
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
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,5 @@ sdk-flutter-analyze:
flutter analyze --no-fatal-infos

.PHONY: sdk-dart-format
sdk-dart-format:
dart format --set-exit-if-changed lib
75 changes: 37 additions & 38 deletions android/src/main/kotlin/com/authgear/flutter/AuthgearPlugin.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.authgear.flutter

import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.content.pm.PackageInfo
import android.graphics.Color
Expand All @@ -20,6 +22,7 @@ import androidx.annotation.NonNull
import androidx.annotation.RequiresApi
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
Expand All @@ -46,26 +49,18 @@ class AuthgearPlugin: FlutterPlugin, ActivityAware, MethodCallHandler, PluginReg
private lateinit var channel: MethodChannel
private var pluginBinding: FlutterPlugin.FlutterPluginBinding? = null
private var activityBinding: ActivityPluginBinding? = null
private val startActivityHandles = StartActivityHandles<Result>()
private val startActivityHandles = StartActivityHandles<Handle>()

private class Handle(val result: Result) {
var broadcastReceiver: BroadcastReceiver? = null
}

companion object {
private const val LOGTAG = "AuthgearPlugin"
private const val ENCRYPTED_SHARED_PREFERENCES_NAME = "authgear_encrypted_shared_preferences"
private const val TAG_AUTHENTICATION = 1
private const val TAG_OPEN_URL = 2

private val wechat: HashMap<String, MethodChannel> = hashMapOf()

internal fun onWechatRedirectURI(uri: Uri): Boolean {
val uriWithoutQuery = uri.buildUpon().clearQuery().fragment("").build().toString()
val methodChannel = wechat.remove(uriWithoutQuery)
if (methodChannel == null) {
return false
}
methodChannel.invokeMethod("onWechatRedirectURI", uri.toString())
return true
}

fun wechatErrorResult(errCode: Int, errStr: String, result: Result) {
if (errCode == -2) {
result.cancel()
Expand Down Expand Up @@ -113,19 +108,22 @@ class AuthgearPlugin: FlutterPlugin, ActivityAware, MethodCallHandler, PluginReg
if (handle == null) {
return false
}
if (handle.value.broadcastReceiver != null) {
this.pluginBinding?.applicationContext?.unregisterReceiver(handle.value.broadcastReceiver)
}

return when (handle.tag) {
TAG_AUTHENTICATION -> {
when (resultCode) {
Activity.RESULT_CANCELED -> handle.value.cancel()
Activity.RESULT_OK -> handle.value.success(data?.data.toString())
Activity.RESULT_CANCELED -> handle.value.result.cancel()
Activity.RESULT_OK -> handle.value.result.success(data?.data.toString())
}
true
}
TAG_OPEN_URL -> {
when (resultCode) {
Activity.RESULT_CANCELED -> handle.value.success(null)
Activity.RESULT_OK -> handle.value.success(null)
Activity.RESULT_CANCELED -> handle.value.result.success(null)
Activity.RESULT_OK -> handle.value.result.success(null)
}
true
}
Expand All @@ -135,16 +133,12 @@ class AuthgearPlugin: FlutterPlugin, ActivityAware, MethodCallHandler, PluginReg

override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
when (call.method) {
"registerWechatRedirectURI" -> {
this.storeWechat(call)
result.success(null)
}
"openAuthorizeURL" -> {
val url = Uri.parse(call.argument("url"))
val redirectURI = Uri.parse(call.argument("redirectURI"))
// Custom tabs do not support incognito mode for now.
// val preferEphemeral: Boolean = call.argument("preferEphemeral")!!
val requestCode = startActivityHandles.push(StartActivityHandle(TAG_AUTHENTICATION, result))
val requestCode = startActivityHandles.push(StartActivityHandle(TAG_AUTHENTICATION, Handle(result)))
val activity = activityBinding?.activity
if (activity == null) {
result.noActivity()
Expand All @@ -155,15 +149,34 @@ class AuthgearPlugin: FlutterPlugin, ActivityAware, MethodCallHandler, PluginReg
activity.startActivityForResult(intent, requestCode)
}
"openAuthorizeURLWithWebView" -> {
val methodChannelName = call.argument<String>("methodChannelName")!!
val url = Uri.parse(call.argument("url"))
val redirectURI = Uri.parse(call.argument("redirectURI"))
val actionBarBackgroundColor = this.readColorInt(call, "actionBarBackgroundColor")
val actionBarButtonTintColor = this.readColorInt(call, "actionBarButtonTintColor")
val wechatRedirectURIString = call.argument<String>("androidWechatRedirectURI")
val options = WebKitWebViewActivity.Options(url, redirectURI)
options.actionBarBackgroundColor = actionBarBackgroundColor
options.actionBarButtonTintColor = actionBarButtonTintColor
val handle = Handle(result)
wechatRedirectURIString?.let {
val wechatRedirectURI = Uri.parse(it)
val intentAction = "com.authgear.flutter.$methodChannelName"
handle.broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val methodChannel = MethodChannel(this@AuthgearPlugin.pluginBinding?.binaryMessenger!!, methodChannelName)
val u = intent?.getParcelableExtra<Uri>(WebKitWebViewActivity.KEY_WECHAT_REDIRECT_URI)!!
methodChannel.invokeMethod("unimportant", u.toString())
}
}
val intentFilter = IntentFilter(intentAction)
options.wechatRedirectURI = wechatRedirectURI
options.wechatRedirectURIIntentAction = intentAction
val ctx = pluginBinding?.applicationContext!!
ContextCompat.registerReceiver(ctx, handle.broadcastReceiver, intentFilter, ContextCompat.RECEIVER_NOT_EXPORTED)
}

val requestCode = startActivityHandles.push(StartActivityHandle(TAG_AUTHENTICATION, result))
val requestCode = startActivityHandles.push(StartActivityHandle(TAG_AUTHENTICATION, handle))
val activity = activityBinding?.activity
if (activity == null) {
result.noActivity()
Expand All @@ -174,7 +187,7 @@ class AuthgearPlugin: FlutterPlugin, ActivityAware, MethodCallHandler, PluginReg
}
"openURL" -> {
val url = Uri.parse(call.argument("url"))
val requestCode = startActivityHandles.push(StartActivityHandle(TAG_OPEN_URL, result))
val requestCode = startActivityHandles.push(StartActivityHandle(TAG_OPEN_URL, Handle(result)))
val activity = activityBinding?.activity
if (activity == null) {
result.noActivity()
Expand Down Expand Up @@ -262,20 +275,6 @@ class AuthgearPlugin: FlutterPlugin, ActivityAware, MethodCallHandler, PluginReg
}
}

private fun storeWechat(call: MethodCall) {
val wechatRedirectURI = call.argument<String>("wechatRedirectURI")
val wechatMethodChannel = call.argument<String>("wechatMethodChannel")
if (wechatRedirectURI == null || wechatMethodChannel == null) {
return
}
val binaryMessenger = pluginBinding?.binaryMessenger
if (binaryMessenger == null) {
return
}
val channel = MethodChannel(binaryMessenger, wechatMethodChannel)
wechat[wechatRedirectURI] = channel
}

private fun getDeviceInfo(result: Result) {
var baseOS: String? = ""
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ class OAuthRedirectActivity: Activity() {
super.onCreate(savedInstanceState)
val uri = intent.data
if (uri != null) {
if (AuthgearPlugin.onWechatRedirectURI(uri)) {
// handled
} else if (isRedirectURI(uri)) {
if (isRedirectURI(uri)) {
startActivity(OAuthCoordinatorActivity.createRedirectIntent(this, uri))
redirectURI = null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class WebKitWebViewActivity: AppCompatActivity() {
private const val KEY_OPTIONS = "KEY_OPTIONS"
private const val KEY_WEB_VIEW_STATE = "KEY_WEB_VIEW_STATE"
private const val TAG_FILE_CHOOSER = 1
internal const val KEY_WECHAT_REDIRECT_URI = "KEY_WECHAT_REDIRECT_URI"

fun createIntent(ctx: Context, options: Options): Intent {
val intent = Intent(ctx, WebKitWebViewActivity::class.java)
Expand All @@ -44,6 +45,8 @@ class WebKitWebViewActivity: AppCompatActivity() {
var redirectURI: Uri
var actionBarBackgroundColor: Int? = null
var actionBarButtonTintColor: Int? = null
var wechatRedirectURI: Uri? = null
var wechatRedirectURIIntentAction: String? = null

constructor(url: Uri, redirectURI: Uri) {
this.url = url
Expand All @@ -59,6 +62,12 @@ class WebKitWebViewActivity: AppCompatActivity() {
if (bundle.containsKey("actionBarButtonTintColor")) {
this.actionBarButtonTintColor = bundle.getInt("actionBarButtonTintColor")
}
if (bundle.containsKey("wechatRedirectURI")) {
this.wechatRedirectURI = bundle.getParcelable("wechatRedirectURI")
}
if (bundle.containsKey("wechatRedirectURIIntentAction")) {
this.wechatRedirectURIIntentAction = bundle.getString("wechatRedirectURIIntentAction")
}
}

fun toBundle(): Bundle {
Expand All @@ -71,6 +80,12 @@ class WebKitWebViewActivity: AppCompatActivity() {
this.actionBarButtonTintColor?.let {
bundle.putInt("actionBarButtonTintColor", it)
}
this.wechatRedirectURI?.let {
bundle.putParcelable("wechatRedirectURI", it)
}
this.wechatRedirectURIIntentAction?.let {
bundle.putString("wechatRedirectURIIntentAction", it)
}
return bundle
}
}
Expand Down Expand Up @@ -115,21 +130,27 @@ class WebKitWebViewActivity: AppCompatActivity() {
}

private fun shouldOverrideUrlLoading(uri: Uri): Boolean {
if (this.checkRedirectURI(uri)) {
return true;
}
return false;
}
val withoutQuery = this.removeQueryAndFragment(uri)

private fun checkRedirectURI(uri: Uri): Boolean {
val redirectURI = this.activity.getOptions().redirectURI
val withoutQuery = this.removeQueryAndFragment(uri)
if (withoutQuery.toString() == redirectURI.toString()) {
this.activity.result = uri
this.activity.callSetResult()
this.activity.finish()
return true
}

val wechatRedirectURI = this.activity.getOptions().wechatRedirectURI
if (wechatRedirectURI != null) {
if (withoutQuery.toString() == wechatRedirectURI.toString()) {
val intent = Intent(this.activity.getOptions().wechatRedirectURIIntentAction)
intent.setPackage(this.activity.applicationContext.packageName)
intent.putExtra(KEY_WECHAT_REDIRECT_URI, uri)
this.activity.applicationContext.sendBroadcast(intent)
return true
}
}

return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,10 @@ class WebViewActivity: AppCompatActivity() {
view: WebView?,
request: WebResourceRequest?
): Boolean {
val url = request?.url
if (url != null && AuthgearPlugin.onWechatRedirectURI(url)) {
return true
}
return super.shouldOverrideUrlLoading(view, request)
}

override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
if (url != null && AuthgearPlugin.onWechatRedirectURI(Uri.parse(url))) {
return true
}
return super.shouldOverrideUrlLoading(view, url)
}
}
Expand Down
2 changes: 1 addition & 1 deletion example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,5 @@ flutter {
}

dependencies {
implementation "com.tencent.mm.opensdk:wechat-sdk-android:6.8.0"
implementation "com.tencent.mm.opensdk:wechat-sdk-android:6.8.34"
}
10 changes: 10 additions & 0 deletions example/android/app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,13 @@
-dontwarn com.google.errorprone.annotations.RestrictedApi
-dontwarn javax.annotation.Nullable
-dontwarn javax.annotation.concurrent.GuardedBy

-keep class com.tencent.mm.opensdk.** {
*;
}
-keep class com.tencent.wxop.** {
*;
}
-keep class com.tencent.mm.sdk.** {
*;
}
7 changes: 3 additions & 4 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@
android:host="host"
android:pathPrefix="/path"
android:scheme="com.authgear.exampleapp.flutter" />
<data
android:host="host"
android:pathPrefix="/open_wechat_app"
android:scheme="com.authgear.exampleapp.flutter" />
</intent-filter>
</activity>
<activity
Expand All @@ -59,4 +55,7 @@
android:name="flutterEmbedding"
android:value="2" />
</application>
<queries>
<package android:name="com.tencent.mm" />
</queries>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class MainActivity: FlutterFragmentActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)

api = WXAPIFactory.createWXAPI(this, WECHAT_APP_ID)
api = WXAPIFactory.createWXAPI(this, WECHAT_APP_ID, true)
api?.registerApp(WECHAT_APP_ID)

MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
Expand Down
27 changes: 27 additions & 0 deletions example/ios/Add-OTHER_LDFLAGS-ObjC/Add-OTHER_LDFLAGS-ObjC.podspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Pod::Spec.new do |s|
s.name = 'Add-OTHER_LDFLAGS-ObjC'
s.version = '1.0.0'
s.summary = 'Add -ObjC by stating this is a static_framework'
s.description = 'Add -ObjC by stating this is a static_framework'
s.platforms = { :ios => '8.0' }
s.authors = {
'dummy' => 'user@example.com',
}
s.license = 'MIT'
s.homepage = 'https://example.com'
s.source = {
:type => 'zip',
:http => 'http://dldir1.qq.com/WechatWebDev/opensdk/XCFramework/OpenSDK2.0.4.zip',
}
# This is why this file exists.
# The project needs at least one static_framework so that Cocoapods
# will include -ObjC in OTHER_LDFLAGS.
# Note that -ObjC is so special that you cannot add it with post_install hook.
# -ObjC can only be added this way.
#
# The reason why -ObjC is needed is documented here.
# https://developers.weixin.qq.com/community/develop/article/doc/000e8e316d4590c7ef92ec1a366c13
s.static_framework = true
# Yes, this file does not actually exist, but Cocoapods does not complain.
s.source_files = 'dummy.h'
end
1 change: 1 addition & 0 deletions example/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ target 'Runner' do
# Use WechatOpenSDK-XCFramework instead of WechatOpenSDK
# See https://developers.weixin.qq.com/community/develop/doc/000c62b9b0ccf8c1d65fa90b751001?blockType=1
pod 'WechatOpenSDK-XCFramework', '~> 2.0.4'
pod 'Add-OTHER_LDFLAGS-ObjC', :podspec => './Add-OTHER_LDFLAGS-ObjC/Add-OTHER_LDFLAGS-ObjC.podspec'
end

post_install do |installer|
Expand Down
7 changes: 6 additions & 1 deletion example/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
PODS:
- Add-OTHER_LDFLAGS-ObjC (1.0.0)
- Flutter (1.0.0)
- flutter_authgear (0.1.0):
- Flutter
Expand All @@ -8,6 +9,7 @@ PODS:
- WechatOpenSDK-XCFramework (2.0.4)

DEPENDENCIES:
- Add-OTHER_LDFLAGS-ObjC (from `./Add-OTHER_LDFLAGS-ObjC/Add-OTHER_LDFLAGS-ObjC.podspec`)
- Flutter (from `Flutter`)
- flutter_authgear (from `.symlinks/plugins/flutter_authgear/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
Expand All @@ -18,6 +20,8 @@ SPEC REPOS:
- WechatOpenSDK-XCFramework

EXTERNAL SOURCES:
Add-OTHER_LDFLAGS-ObjC:
:podspec: "./Add-OTHER_LDFLAGS-ObjC/Add-OTHER_LDFLAGS-ObjC.podspec"
Flutter:
:path: Flutter
flutter_authgear:
Expand All @@ -26,11 +30,12 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"

SPEC CHECKSUMS:
Add-OTHER_LDFLAGS-ObjC: 5f8f0f83c16738a7f9954268aef665b10f5c5b81
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_authgear: 91b45db8689e711cb672a39d77e4662d4fcc2998
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
WechatOpenSDK-XCFramework: 36fb2bea0754266c17184adf4963d7e6ff98b69f

PODFILE CHECKSUM: a223dddfd171e1c2eb444b4e549ee6ab3f96bcae
PODFILE CHECKSUM: 38144be7857f60194b0e96460fe073ee7263422e

COCOAPODS: 1.16.2
Loading
Loading