提交 72f77e4b authored 作者: JarvanMo's avatar JarvanMo

Merge branch 'dev'

# Conflicts: # CHANGELOG.md # android/src/main/kotlin/com/jarvan/fluwx/handlers/FluwxRequestHandler.kt # pubspec.yaml
## 2.6.0
* Android支持通过H5冷启动app传递<wx-open-launch-app>中的extinfo数据
* Android新加<meta-data>handleWeChatRequestByFluwx</meta-data>
## 2.5.0+1 ## 2.5.0+1
* Fix trailing , issue. * Fix trailing , issue.
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
- Launch mini program in WeChat. - Launch mini program in WeChat.
- Subscribe Message. - Subscribe Message.
- Just open WeChat app. - Just open WeChat app.
- Launch app From wechat link.
## Preparation ## Preparation
...@@ -72,6 +73,7 @@ And you have to understand the difference between debug signature and release si ...@@ -72,6 +73,7 @@ And you have to understand the difference between debug signature and release si
- [Share](./doc/SHARE.md) - [Share](./doc/SHARE.md)
- [Payment](./doc/PAYMENT.md) - [Payment](./doc/PAYMENT.md)
- [Auth](./doc/AUTH.md) - [Auth](./doc/AUTH.md)
- [Launch app from h5](./doc/LAUNCH_APP_FROM_H5.md)
For more capabilities, you can read the public functions of `fluwx`. For more capabilities, you can read the public functions of `fluwx`.
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
- 拉起小程序. - 拉起小程序.
- 订阅消息. - 订阅消息.
- 打开微信. - 打开微信.
- 从微信标签打开应用
## 准备 ## 准备
...@@ -70,7 +71,7 @@ registerWxApi(appId: "wxd930ea5d5a228f5f",universalLink: "https://your.univerall ...@@ -70,7 +71,7 @@ registerWxApi(appId: "wxd930ea5d5a228f5f",universalLink: "https://your.univerall
- [分享](./doc/SHARE_CN.md) - [分享](./doc/SHARE_CN.md)
- [支付](./doc/PAYMENT_CN.md) - [支付](./doc/PAYMENT_CN.md)
- [登录](./doc/AUTH_CN.md) - [登录](./doc/AUTH_CN.md)
- [从微信标签打开应用](./doc/LAUNCH_APP_FROM_H5_CN.md)
对于更多功能,可以查看源码。 对于更多功能,可以查看源码。
## QA ## QA
......
...@@ -16,7 +16,7 @@ import io.flutter.plugin.common.MethodChannel.Result ...@@ -16,7 +16,7 @@ import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry import io.flutter.plugin.common.PluginRegistry
/** FluwxPlugin */ /** FluwxPlugin */
public class FluwxPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { class FluwxPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
companion object { companion object {
@JvmStatic @JvmStatic
...@@ -39,12 +39,18 @@ public class FluwxPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { ...@@ -39,12 +39,18 @@ public class FluwxPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
private var authHandler: FluwxAuthHandler? = null private var authHandler: FluwxAuthHandler? = null
private var fluwxChannel: MethodChannel? = null
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
val channel = MethodChannel(flutterPluginBinding.binaryMessenger, "com.jarvanmo/fluwx") if (fluwxChannel == null) {
channel.setMethodCallHandler(this) fluwxChannel = MethodChannel(flutterPluginBinding.binaryMessenger, "com.jarvanmo/fluwx")
FluwxResponseHandler.setMethodChannel(channel) fluwxChannel?.setMethodCallHandler(this)
FluwxRequestHandler.setMethodChannel(channel) }
authHandler = FluwxAuthHandler(channel) fluwxChannel?.let {
FluwxResponseHandler.setMethodChannel(it)
FluwxRequestHandler.setMethodChannel(it)
authHandler = FluwxAuthHandler(it)
}
shareHandler = FluwxShareHandlerEmbedding(flutterPluginBinding.flutterAssets, flutterPluginBinding.applicationContext) shareHandler = FluwxShareHandlerEmbedding(flutterPluginBinding.flutterAssets, flutterPluginBinding.applicationContext)
} }
......
...@@ -14,26 +14,98 @@ ...@@ -14,26 +14,98 @@
* limitations under the License. * limitations under the License.
*/ */
package com.jarvan.fluwx.handlers package com.jarvan.fluwx.handlers
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import com.tencent.mm.opensdk.modelmsg.ShowMessageFromWX import com.tencent.mm.opensdk.modelmsg.ShowMessageFromWX
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import com.tencent.mm.opensdk.modelbase.BaseReq import com.tencent.mm.opensdk.modelbase.BaseReq
import java.lang.Exception
object FluwxRequestHandler { object FluwxRequestHandler {
private const val KEY_FLUWX_REQUEST_INFO_BUNDLE = "KEY_FLUWX_REQUEST_INFO_BUNDLE"
var customOnReqDelegate: ((baseReq: BaseReq, activity: Activity) -> Unit)? = null
private var channel: MethodChannel? = null private var channel: MethodChannel? = null
fun setMethodChannel(channel: MethodChannel) { fun setMethodChannel(channel: MethodChannel) {
FluwxRequestHandler.channel = channel FluwxRequestHandler.channel = channel
} }
fun handleRequest(req: BaseReq) {
fun handleRequestInfoFromIntent(intent: Intent) {
intent.getBundleExtra(KEY_FLUWX_REQUEST_INFO_BUNDLE)?.run {
val type = getInt("_wxapi_command_type", -9999)
if (type == 4) {
handleShowMessageFromWXBundle(this)
}
}
}
private fun handleShowMessageFromWXBundle(bundle: Bundle) = handleWXShowMessageFromWX(ShowMessageFromWX.Req(bundle))
private fun handleRequest(req: BaseReq) {
when (req) { when (req) {
is ShowMessageFromWX.Req -> hanleWXShowMessageFromWX(req) is ShowMessageFromWX.Req -> handleWXShowMessageFromWX(req)
} }
} }
private fun hanleWXShowMessageFromWX(req: ShowMessageFromWX.Req) { private fun handleWXShowMessageFromWX(req: ShowMessageFromWX.Req) {
val result = mapOf( val result = mapOf(
"extMsg" to req.message.messageExt) "extMsg" to req.message.messageExt,
)
channel?.invokeMethod("onWXShowMessageFromWX", result) channel?.invokeMethod("onWXShowMessageFromWX", result)
} }
private fun defaultOnReqDelegate(baseReq: BaseReq, activity: Activity) {
// FIXME: 可能是官方的Bug,从微信拉起APP的Intent类型不对,无法跳转回Flutter Activity
// 稳定复现场景:微信版本为7.0.5,小程序SDK为2.7.7
if (baseReq.type == 4) {
// com.tencent.mm.opensdk.constants.ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX = 4
if (WXAPiHandler.wxApiRegistered) {
handleRequest(baseReq)
startSpecifiedActivity(defaultFlutterActivityAction(activity), activity = activity)
} else {
startSpecifiedActivity(defaultFlutterActivityAction(activity), bundle = Bundle().apply {
baseReq.toBundle(this)
}, bundleKey = KEY_FLUWX_REQUEST_INFO_BUNDLE, activity = activity)
}
}
}
fun onReq(baseReq: BaseReq, activity: Activity) {
try {
val activityInfo = activity.packageManager.getActivityInfo(activity.componentName, PackageManager.GET_META_DATA)
val defaultHandle = activityInfo.metaData.getBoolean("handleWeChatRequestByFluwx", true)
if (defaultHandle) {
defaultOnReqDelegate(baseReq, activity)
} else {
customOnReqDelegate?.invoke(baseReq, activity)
}
} catch (e: Exception) {
Log.i("Fluwx", "can't load meta-data handleWeChatRequestByFluwx")
}
}
private fun startSpecifiedActivity(action: String, activity: Activity, bundle: Bundle? = null, bundleKey: String? = null) {
Intent(action).run {
bundleKey?.let {
putExtra(bundleKey, bundle)
}
addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
activity.packageManager?.let {
resolveActivity(it)?.also {
activity.startActivity(this)
activity.finish()
}
}
}
}
private fun defaultFlutterActivityAction(context: Context): String = "$context.packageName.FlutterActivity"
} }
\ No newline at end of file
...@@ -30,6 +30,18 @@ object WXAPiHandler { ...@@ -30,6 +30,18 @@ object WXAPiHandler {
private var context: Context? = null private var context: Context? = null
private var registered: Boolean = false
val wxApiRegistered get() = registered
fun setupWxApi(appId: String, context: Context, force: Boolean = true): Boolean {
if (force || !registered) {
setContext(context)
registerWxAPIInternal(appId, context)
}
return registered
}
fun setContext(context: Context?) { fun setContext(context: Context?) {
WXAPiHandler.context = context WXAPiHandler.context = context
} }
...@@ -51,9 +63,9 @@ object WXAPiHandler { ...@@ -51,9 +63,9 @@ object WXAPiHandler {
return return
} }
val api = WXAPIFactory.createWXAPI(context?.applicationContext, appId) context?.let {
val registered = api.registerApp(appId) registerWxAPIInternal(appId, it)
wxApi = api }
result.success(registered) result.success(registered)
} }
...@@ -64,6 +76,11 @@ object WXAPiHandler { ...@@ -64,6 +76,11 @@ object WXAPiHandler {
} else { } else {
result.success(wxApi?.isWXAppInstalled) result.success(wxApi?.isWXAppInstalled)
} }
}
private fun registerWxAPIInternal(appId: String, context: Context) {
val api = WXAPIFactory.createWXAPI(context.applicationContext, appId)
registered = api.registerApp(appId)
wxApi = api
} }
} }
\ No newline at end of file
...@@ -23,7 +23,6 @@ import com.jarvan.fluwx.handlers.FluwxRequestHandler ...@@ -23,7 +23,6 @@ import com.jarvan.fluwx.handlers.FluwxRequestHandler
import com.jarvan.fluwx.handlers.WXAPiHandler import com.jarvan.fluwx.handlers.WXAPiHandler
import com.tencent.mm.opensdk.modelbase.BaseReq import com.tencent.mm.opensdk.modelbase.BaseReq
import com.tencent.mm.opensdk.modelbase.BaseResp import com.tencent.mm.opensdk.modelbase.BaseResp
import com.tencent.mm.opensdk.modelmsg.ShowMessageFromWX
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler
...@@ -38,7 +37,7 @@ open class FluwxWXEntryActivity : Activity(), IWXAPIEventHandler { ...@@ -38,7 +37,7 @@ open class FluwxWXEntryActivity : Activity(), IWXAPIEventHandler {
WXAPiHandler.wxApi?.handleIntent(intent, this) WXAPiHandler.wxApi?.handleIntent(intent, this)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
startSpecifiedActivity() startSpecifiedActivity(defaultFlutterActivityAction())
finish() finish()
} }
} }
...@@ -52,7 +51,7 @@ open class FluwxWXEntryActivity : Activity(), IWXAPIEventHandler { ...@@ -52,7 +51,7 @@ open class FluwxWXEntryActivity : Activity(), IWXAPIEventHandler {
WXAPiHandler.wxApi?.handleIntent(intent, this) WXAPiHandler.wxApi?.handleIntent(intent, this)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
startSpecifiedActivity() startSpecifiedActivity(defaultFlutterActivityAction())
finish() finish()
} }
} }
...@@ -61,11 +60,7 @@ open class FluwxWXEntryActivity : Activity(), IWXAPIEventHandler { ...@@ -61,11 +60,7 @@ open class FluwxWXEntryActivity : Activity(), IWXAPIEventHandler {
override fun onReq(baseReq: BaseReq) { override fun onReq(baseReq: BaseReq) {
// FIXME: 可能是官方的Bug,从微信拉起APP的Intent类型不对,无法跳转回Flutter Activity // FIXME: 可能是官方的Bug,从微信拉起APP的Intent类型不对,无法跳转回Flutter Activity
// 稳定复现场景:微信版本为7.0.5,小程序SDK为2.7.7 // 稳定复现场景:微信版本为7.0.5,小程序SDK为2.7.7
if (baseReq.type == 4) { FluwxRequestHandler.onReq(baseReq,this)
// com.tencent.mm.opensdk.constants.ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX = 4
FluwxRequestHandler.handleRequest(baseReq)
startSpecifiedActivity()
}
} }
// 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法 // 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法
...@@ -74,11 +69,20 @@ open class FluwxWXEntryActivity : Activity(), IWXAPIEventHandler { ...@@ -74,11 +69,20 @@ open class FluwxWXEntryActivity : Activity(), IWXAPIEventHandler {
finish() finish()
} }
private fun startSpecifiedActivity() { private fun startSpecifiedActivity(action: String, bundle: Bundle? = null, bundleKey: String? = null) {
Intent("$packageName.FlutterActivity").run { Intent(action).run {
bundleKey?.let {
putExtra(bundleKey, bundle)
}
addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
packageManager?.let {
resolveActivity(packageManager)?.also {
startActivity(this) startActivity(this)
}
finish() finish()
} }
}
}
}
private fun defaultFlutterActivityAction(): String = "$packageName.FlutterActivity"
} }
\ No newline at end of file
## Launch App from H5
Fluwx supports launch app from `<wx-open-launch-app>`, and pass `extInfo` to your app.
For Android side, you need add the following action for your FlutterActivity in `AndroidManifest.xml`:
```
<action android:name="${applicationId}.FlutterActivity" />
```
If you want to pass `extInfo` to Flutter, you need to add the following code in `MainActivity.kt`:
```kotlin
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
//If you didn't configure WxAPI, add the following code
WXAPiHandler.setupWxApi("wxd930ea5d5a258f4f",this)
//Get Ext-Info from Intent.
FluwxRequestHandler.handleRequestInfoFromIntent(intent)
}
```
If you want to custom your request logic, you need add the `<meta-data>` in host activity:
```xml
<meta-data
android:name="handleWeChatRequestByFluwx"
android:value="flase" />
```
And then, set `FluwxRequestHandler.customOnReqDelegate` on your own.
\ No newline at end of file
## 从H5启动app
Fluwx 支持从`<wx-open-launch-app>`启动你的app, 并且支持传递`extInfo`给你的app.
对于Android来说,你要在`AndroidManifest.xml`中给你的宿主`Activty`加上一个标签:
```
<action android:name="${applicationId}.FlutterActivity" />
```
如果你想把`extInfo`传给Flutter, 你要在`MainActivity`加上如下代码:
```kotlin
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
//If you didn't configure WxAPI, add the following code
WXAPiHandler.setupWxApi("wxd930ea5d5a258f4f",this)
//Get Ext-Info from Intent.
FluwxRequestHandler.handleRequestInfoFromIntent(intent)
}
```
如果你想自定义你的调用逻辑, 你需要在宿主Activity中加上`<meta-data>`:
```xml
<meta-data
android:name="handleWeChatRequestByFluwx"
android:value="flase" />
```
然后, 自己实现 `FluwxRequestHandler.customOnReqDelegate`.
\ No newline at end of file
...@@ -5,23 +5,27 @@ ...@@ -5,23 +5,27 @@
In most cases you can leave this as-is, but you if you want to provide In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. --> FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application <application
android:name="io.flutter.app.FlutterApplication" android:name="io.flutter.app.FlutterApplication"
android:label="fluwx_example" android:icon="@mipmap/ic_launcher"
android:icon="@mipmap/ic_launcher"> android:label="fluwx_example">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN" />
<action android:name="${applicationId}.FlutterActivity"/> <action android:name="${applicationId}.FlutterActivity" />
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<meta-data
android:name="handleWeChatRequestByFluwx"
android:value="false" />
</activity> </activity>
<!-- Don't delete the meta-data below. <!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
......
package com.jarvan.fluwx_example package com.jarvan.fluwx_example
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.jarvan.fluwx.handlers.FluwxRequestHandler
import com.jarvan.fluwx.handlers.WXAPiHandler
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant import io.flutter.plugins.GeneratedPluginRegistrant
...@@ -8,5 +10,9 @@ import io.flutter.plugins.GeneratedPluginRegistrant ...@@ -8,5 +10,9 @@ import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() { class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine); GeneratedPluginRegistrant.registerWith(flutterEngine);
//If you didn't configure WxAPI, add the following code
WXAPiHandler.setupWxApi("wxd930ea5d5a258f4f",this)
//Get Ext-Info from Intent.
FluwxRequestHandler.handleRequestInfoFromIntent(intent)
} }
} }
name: fluwx name: fluwx
description: The capability of implementing WeChat SDKs in Flutter. With Fluwx, developers can use WeChatSDK easily, such as sharing, payment, lanuch mini program and etc. description: The capability of implementing WeChat SDKs in Flutter. With Fluwx, developers can use WeChatSDK easily, such as sharing, payment, lanuch mini program and etc.
version: 2.5.0+1 version: 2.6.0
homepage: https://github.com/JarvanMo/fluwx homepage: https://github.com/JarvanMo/fluwx
environment: environment:
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论