diff --git a/android/src/main/kotlin/com/jarvan/fluwx/FluwxPlugin.kt b/android/src/main/kotlin/com/jarvan/fluwx/FluwxPlugin.kt index 5c7d09c6..1b46992b 100644 --- a/android/src/main/kotlin/com/jarvan/fluwx/FluwxPlugin.kt +++ b/android/src/main/kotlin/com/jarvan/fluwx/FluwxPlugin.kt @@ -29,6 +29,8 @@ 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 +import java.util.concurrent.atomic.AtomicBoolean + /** FluwxPlugin */ class FluwxPlugin : FlutterPlugin, MethodCallHandler, ActivityAware, @@ -47,6 +49,9 @@ class FluwxPlugin : FlutterPlugin, MethodCallHandler, ActivityAware, private var fluwxChannel: MethodChannel? = null private var context: Context? = null + private val attemptToResumeMsgFromWxFlag = AtomicBoolean(false) + + private var activityPluginBinding: ActivityPluginBinding? = null private fun handelIntent(intent: Intent) { intent.getStringExtra(KEY_FLUWX_REQUEST_INFO_EXT_MSG)?.let { @@ -96,10 +101,22 @@ class FluwxPlugin : FlutterPlugin, MethodCallHandler, ActivityAware, call.method == "openWeChatInvoice" -> openWeChatInvoice(call, result) call.method == "openUrl" -> openUrl(call, result) call.method == "openRankList" -> openRankList(result) + call.method == "attemptToResumeMsgFromWx" -> attemptToResumeMsgFromWx(result) else -> result.notImplemented() } } + private fun attemptToResumeMsgFromWx(result: Result) { + if (attemptToResumeMsgFromWxFlag.compareAndSet(false, true)) { + activityPluginBinding?.activity?.intent?.let { + FluwxRequestHandler.handleRequestInfoFromIntent(it) + } + result.success(null) + } else { + result.error("attemptToResumeMsgFromWx error", null, null) + } + } + private fun openWeChatInvoice(call: MethodCall, result: Result) { if (WXAPiHandler.wxApi == null) { result.error("Unassigned WxApi", "please config wxapi first", null) @@ -127,6 +144,7 @@ class FluwxPlugin : FlutterPlugin, MethodCallHandler, ActivityAware, override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { shareHandler?.onDestroy() authHandler?.removeAllListeners() + activityPluginBinding = null } override fun onDetachedFromActivity() { @@ -141,6 +159,7 @@ class FluwxPlugin : FlutterPlugin, MethodCallHandler, ActivityAware, override fun onAttachedToActivity(binding: ActivityPluginBinding) { // WXAPiHandler.setContext(binding.activity.applicationContext) + activityPluginBinding = binding handelIntent(binding.activity.intent) FluwxRequestHandler.handleRequestInfoFromIntent(binding.activity.intent) shareHandler?.permissionHandler = PermissionHandler(binding.activity) @@ -287,6 +306,7 @@ class FluwxPlugin : FlutterPlugin, MethodCallHandler, ActivityAware, result.success(false) } } + private fun openRankList(result: Result) { val req = OpenRankList.Req() WXAPiHandler.wxApi?.sendReq(req, SendReqCallback { diff --git a/android/src/main/kotlin/com/jarvan/fluwx/handlers/FluwxRequestHandler.kt b/android/src/main/kotlin/com/jarvan/fluwx/handlers/FluwxRequestHandler.kt index 2a00d27f..db873396 100644 --- a/android/src/main/kotlin/com/jarvan/fluwx/handlers/FluwxRequestHandler.kt +++ b/android/src/main/kotlin/com/jarvan/fluwx/handlers/FluwxRequestHandler.kt @@ -29,6 +29,7 @@ import com.jarvan.fluwx.utils.KEY_FLUWX_REQUEST_INFO_BUNDLE import com.jarvan.fluwx.utils.KEY_FLUWX_REQUEST_INFO_EXT_MSG import com.jarvan.fluwx.utils.startFlutterActivity import com.tencent.mm.opensdk.modelbase.BaseReq +import com.tencent.mm.opensdk.modelmsg.LaunchFromWX import com.tencent.mm.opensdk.modelmsg.ShowMessageFromWX import java.security.cert.Extension @@ -42,6 +43,8 @@ object FluwxRequestHandler { val type = getInt("_wxapi_command_type", -9999) if (type == 4) { handleShowMessageFromWXBundle(this) + } else if (type == 6) { + handleWXLaunchFromWXBundle(this) } } } @@ -49,45 +52,65 @@ object FluwxRequestHandler { private fun handleShowMessageFromWXBundle(bundle: Bundle) = handleWXShowMessageFromWX(ShowMessageFromWX.Req(bundle)) + private fun handleWXLaunchFromWXBundle(bundle: Bundle) = + handleWXLaunchFromWX(LaunchFromWX.Req(bundle)) + private fun handleRequest(req: BaseReq) { when (req) { is ShowMessageFromWX.Req -> handleWXShowMessageFromWX(req) + is LaunchFromWX.Req -> handleWXLaunchFromWX(req) } } private fun handleWXShowMessageFromWX(req: ShowMessageFromWX.Req) { val result = mapOf( - "extMsg" to req.message.messageExt + "extMsg" to req.message.messageExt, + "messageAction" to req.message.messageAction, + "description" to req.message.description, + "lang" to req.lang, + "description" to req.country, ) - FluwxPlugin.extMsg = req.message.messageExt; + + FluwxPlugin.extMsg = req.message.messageExt FluwxPlugin.callingChannel?.invokeMethod("onWXShowMessageFromWX", result) } + private fun handleWXLaunchFromWX(req: LaunchFromWX.Req) { + val result = mapOf( + "extMsg" to req.messageExt, + "messageAction" to req.messageAction, + "lang" to req.lang, + "country" to req.country, + ) + + FluwxPlugin.callingChannel?.invokeMethod("onWXLaunchFromWX", 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.coolBoot) { - handleRequest(baseReq) - activity.startFlutterActivity() - } else { - when (baseReq) { - is ShowMessageFromWX.Req -> { - activity.startFlutterActivity( - wxRequestBundle = Bundle().apply { - baseReq.toBundle(this) - }, - bundle = Bundle().apply { - putString( - KEY_FLUWX_REQUEST_INFO_EXT_MSG, - baseReq.message.messageExt - ) - }) - WXAPiHandler.coolBoot = false - } + + // com.tencent.mm.opensdk.constants.ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX = 4 + if (!WXAPiHandler.coolBoot) { + handleRequest(baseReq) + activity.startFlutterActivity() + } else { + when (baseReq) { + is ShowMessageFromWX.Req -> { + activity.startFlutterActivity( + wxRequestBundle = Bundle().apply { + baseReq.toBundle(this) + }, + bundle = Bundle().apply { + putString( + KEY_FLUWX_REQUEST_INFO_EXT_MSG, + baseReq.message.messageExt + ) + }) + WXAPiHandler.coolBoot = false } } + } } diff --git a/ios/Classes/FluwxPlugin.m b/ios/Classes/FluwxPlugin.m index 891588b6..aef605d3 100644 --- a/ios/Classes/FluwxPlugin.m +++ b/ios/Classes/FluwxPlugin.m @@ -42,7 +42,13 @@ @interface FluwxPlugin() typedef void(^FluwxWXReqRunnable)(void); -@implementation FluwxPlugin +@implementation FluwxPlugin { + FlutterMethodChannel *_channel; + WechatAuthSDK *_qrauth; + BOOL _isRunning; + BOOL _attemptToResumeMsgFromWxFlag; + FluwxWXReqRunnable _attemptToResumeMsgFromWxRunnable; +} const NSString *errStr = @"errStr"; const NSString *errCode = @"errCode"; @@ -53,35 +59,14 @@ @implementation FluwxPlugin const NSString *description = @"description"; -BOOL _isRunning; FluwxWXReqRunnable _initialWXReqRunnable; BOOL handleOpenURLByFluwx = YES; -FlutterMethodChannel *channel = nil; -WechatAuthSDK *_qrauth; NSObject *_fluwxRegistrar; -+ (void)registerWithRegistrar:(NSObject *)registrar { - -#if TARGET_OS_IPHONE - if (channel == nil) { -#endif - channel = [FlutterMethodChannel - methodChannelWithName:@"com.jarvanmo/fluwx" - binaryMessenger:[registrar messenger]]; - FluwxPlugin *instance = [[FluwxPlugin alloc] initWithRegistrar:registrar methodChannel:channel]; - [registrar addMethodCallDelegate:instance channel:channel]; - - [registrar addApplicationDelegate:instance]; -#if TARGET_OS_IPHONE - } -#endif - -} - - (instancetype)initWithRegistrar:(NSObject *)registrar methodChannel:(FlutterMethodChannel *)flutterMethodChannel { self = [super init]; if (self) { @@ -90,8 +75,8 @@ - (instancetype)initWithRegistrar:(NSObject *)registrar _qrauth = [[WechatAuthSDK alloc] init]; _qrauth.delegate = self; thumbnailWidth = 150; - channel = flutterMethodChannel; - + _channel = flutterMethodChannel; + _attemptToResumeMsgFromWxFlag = false; #if WECHAT_LOGGING [WXApi startLogByLevel:WXLogLevelDetail logBlock:^(NSString *log) { [self logToFlutterWithDetail:log]; @@ -142,6 +127,17 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [self handleOpenUrlCall:call result:result]; } else if([@"openWeChatInvoice" isEqualToString:call.method]) { [self openWeChatInvoice:call result:result]; + } else if([@"" isEqualToString:call.method]){ + if (!_attemptToResumeMsgFromWxFlag) { + _attemptToResumeMsgFromWxFlag = YES; + if (_attemptToResumeMsgFromWxRunnable != nil) { + _attemptToResumeMsgFromWxRunnable(); + _attemptToResumeMsgFromWxRunnable = nil; + } + result(nil); + } else { + result([FlutterError errorWithCode:@"attemptToResumeMsgFromWx error" message:nil details:nil]); + } } else if ([@"payWithFluwx" isEqualToString:call.method]) { #ifndef NO_PAY @@ -161,6 +157,16 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } } ++ (void)registerWithRegistrar:(nonnull NSObject *)registrar { + <#code#> +} + + ++ (void)registerWithRegistrar:(nonnull NSObject *)registrar { + <#code#> +} + + - (void)openWeChatInvoice:(FlutterMethodCall *)call result:(FlutterResult)result { NSString *appId = call.arguments[@"appId"]; @@ -314,12 +320,16 @@ - (void)handleLaunchMiniProgram:(FlutterMethodCall *)call result:(FlutterResult) - (void)handleSubscribeWithCall:(FlutterMethodCall *)call result:(FlutterResult)result { NSDictionary *params = call.arguments; NSString *appId = [params valueForKey:@"appId"]; - int scene = [[params valueForKey:@"scene"] intValue]; + NSNumber *scene = [params valueForKey:@"scene"]; NSString *templateId = [params valueForKey:@"templateId"]; NSString *reserved = [params valueForKey:@"reserved"]; WXSubscribeMsgReq *req = [WXSubscribeMsgReq new]; - req.scene = (UInt32) scene; + #if __LP64__ + req.scene = [scene unsignedIntValue]; + #else + req.scene = [scene unsignedLongValue]; + #endif req.templateId = templateId; req.reserved = reserved; req.openID = appId; @@ -419,11 +429,11 @@ - (BOOL)handleOpenURL:(NSNotification *)aNotification { } - (void)logToFlutterWithDetail:(NSString *) detail { - if(channel != nil){ + if(_channel != nil){ NSDictionary *result = @{ @"detail":detail }; - [channel invokeMethod:@"wechatLog" arguments:result]; + [_channel invokeMethod:@"wechatLog" arguments:result]; } } @@ -805,8 +815,8 @@ - (void)onResp:(BaseResp *)resp { type: @(messageResp.type), country: messageResp.country == nil ? @"" : messageResp.country, lang: messageResp.lang == nil ? @"" : messageResp.lang}; - if(channel != nil){ - [channel invokeMethod:@"onShareResponse" arguments:result]; + if(_channel != nil){ + [_channel invokeMethod:@"onShareResponse" arguments:result]; } @@ -825,8 +835,8 @@ - (void)onResp:(BaseResp *)resp { }; - if(channel != nil){ - [channel invokeMethod:@"onAuthResponse" arguments:result]; + if(_channel != nil){ + [_channel invokeMethod:@"onAuthResponse" arguments:result]; } } else if ([resp isKindOfClass:[AddCardToWXCardPackageResp class]]) { @@ -870,9 +880,9 @@ - (void)onResp:(BaseResp *)resp { @"cardItemList":cardItemList }; - if(channel != nil){ + if(_channel != nil){ - [channel invokeMethod:@"onOpenWechatInvoiceResponse" arguments:result]; + [_channel invokeMethod:@"onOpenWechatInvoiceResponse" arguments:result]; } } else if ([resp isKindOfClass:[WXSubscribeMsgResp class]]) { @@ -901,8 +911,8 @@ - (void)onResp:(BaseResp *)resp { UInt32 scene = subscribeMsgResp.scene; result[@"scene"] = @(scene); - if(channel != nil){ - [channel invokeMethod:@"onSubscribeMsgResp" arguments:result]; + if(_channel != nil){ + [_channel invokeMethod:@"onSubscribeMsgResp" arguments:result]; } } else if ([resp isKindOfClass:[WXLaunchMiniProgramResp class]]) { @@ -925,8 +935,8 @@ - (void)onResp:(BaseResp *)resp { // @"extMsg":miniProgramResp.extMsg == nil?@"":miniProgramResp.extMsg - if(channel != nil){ - [channel invokeMethod:@"onLaunchMiniProgramResponse" arguments:result]; + if(_channel != nil){ + [_channel invokeMethod:@"onLaunchMiniProgramResponse" arguments:result]; } @@ -943,8 +953,8 @@ - (void)onResp:(BaseResp *)resp { @"resultInfo": [FluwxStringUtil nilToEmpty:businessResp.result], @"businessType": @(businessResp.businessType), }; - if(channel != nil){ - [channel invokeMethod:@"onWXOpenBusinessWebviewResponse" arguments:result]; + if(_channel != nil){ + [_channel invokeMethod:@"onWXOpenBusinessWebviewResponse" arguments:result]; } } else if ([resp isKindOfClass:[WXOpenCustomerServiceResp class]]) @@ -958,8 +968,8 @@ - (void)onResp:(BaseResp *)resp { type: @(customerResp.type), @"extMsg":[FluwxStringUtil nilToEmpty:customerResp.extMsg] }; - if(channel != nil){ - [channel invokeMethod:@"onWXOpenBusinessWebviewResponse" arguments:result]; + if(_channel != nil){ + [_channel invokeMethod:@"onWXOpenBusinessWebviewResponse" arguments:result]; } // 相关错误信息 @@ -975,8 +985,8 @@ - (void)onResp:(BaseResp *)resp { type: @(openBusinessViewResp.type), @"extMsg":[FluwxStringUtil nilToEmpty:openBusinessViewResp.extMsg] }; - if(channel != nil){ - [channel invokeMethod:@"onOpenBusinessViewResponse" arguments:result]; + if(_channel != nil){ + [_channel invokeMethod:@"onOpenBusinessViewResponse" arguments:result]; } // 相关错误信息 @@ -997,8 +1007,8 @@ - (void)onResp:(BaseResp *)resp { @"returnKey": [FluwxStringUtil nilToEmpty:payResp.returnKey], }; [FluwxDelegate defaultManager].extData = nil; - if(channel != nil){ - [channel invokeMethod:@"onPayResponse" arguments:result]; + if(_channel != nil){ + [_channel invokeMethod:@"onPayResponse" arguments:result]; } } else if ([resp isKindOfClass:[WXNontaxPayResp class]]) { @@ -1010,24 +1020,54 @@ - (void)onReq:(BaseReq *)req { if ([req isKindOfClass:[GetMessageFromWXReq class]]) { } else if ([req isKindOfClass:[ShowMessageFromWXReq class]]) { +//onWXLaunchFromWX + ShowMessageFromWXReq *showMessageFromWXReq = (ShowMessageFromWXReq *) req; + WXMediaMessage *wmm = showMessageFromWXReq.message; + + + NSDictionary *result = @{ + @"extMsg": wmm.messageExt, + @"messageAction": wmm.messageAction, + @"lang": showMessageFromWXReq.lang, + @"country": showMessageFromWXReq.country, + }; + + [FluwxDelegate defaultManager].extMsg= wmm.messageExt; + + if (_isRunning) { + [_channel invokeMethod:@"onWXShowMessageFromWX" arguments:result]; + } else { + __weak typeof(self) weakSelf = self; + _initialWXReqRunnable = ^() { + __strong typeof(weakSelf) strongSelf = weakSelf; + [strongSelf->_channel invokeMethod:@"onWXShowMessageFromWX" arguments:result]; + }; + } } else if ([req isKindOfClass:[LaunchFromWXReq class]]) { LaunchFromWXReq *launchFromWXReq = (LaunchFromWXReq *) req; WXMediaMessage *wmm = launchFromWXReq.message; - NSString *msg = @""; - if (wmm == nil || wmm == NULL || [wmm isKindOfClass:[NSNull class]]) { - msg = @""; - }else { - msg = wmm.messageExt; - if (msg == nil || msg == NULL || [msg isKindOfClass:[NSNull class]]) { - msg = @""; - } - } + NSDictionary *result = @{ - @"extMsg": msg + @"extMsg": wmm.messageExt, + @"messageAction": wmm.messageAction, + @"lang": launchFromWXReq.lang, + @"country": launchFromWXReq.country, }; + [FluwxDelegate defaultManager].extMsg= wmm.messageExt; + + if (_isRunning) { + [_channel invokeMethod:@"onWXLaunchFromWX" arguments:result]; + } else { + __weak typeof(self) weakSelf = self; + _initialWXReqRunnable = ^() { + __strong typeof(weakSelf) strongSelf = weakSelf; + [strongSelf->_channel invokeMethod:@"onWXLaunchFromWX" arguments:result]; + }; + } + if(channel != nil){ [channel invokeMethod:@"onWXShowMessageFromWX" arguments:result]; } @@ -1462,8 +1502,8 @@ - (void)stopAuthByQRCode:(FlutterMethodCall *)call result:(FlutterResult)result } - (void)onQrcodeScanned { - if(channel != nil){ - [channel invokeMethod:@"onQRCodeScanned" arguments:@{@"errCode": @0}]; + if(_channel != nil){ + [_channel invokeMethod:@"onQRCodeScanned" arguments:@{@"errCode": @0}]; } } @@ -1472,8 +1512,8 @@ - (void)onAuthGotQrcode:(UIImage *)image { // if (imageData == nil) { // imageData = UIImageJPEGRepresentation(image, 1); // } - if(channel != nil){ - [channel invokeMethod:@"onAuthGotQRCode" arguments:@{@"errCode": @0, @"qrCode": imageData}]; + if(_channel != nil){ + [_channel invokeMethod:@"onAuthGotQRCode" arguments:@{@"errCode": @0, @"qrCode": imageData}]; } } @@ -1483,8 +1523,8 @@ - (void)onAuthFinish:(int)errCode AuthCode:(nullable NSString *)authCode { if (authCode != nil) { result[@"authCode"] = authCode; } - if(channel != nil){ - [channel invokeMethod:@"onAuthByQRCodeFinished" arguments:result]; + if(_channel != nil){ + [_channel invokeMethod:@"onAuthByQRCodeFinished" arguments:result]; } } diff --git a/ios/fluwx.podspec b/ios/fluwx.podspec index 204dfd9f..fb0f02fb 100644 --- a/ios/fluwx.podspec +++ b/ios/fluwx.podspec @@ -69,7 +69,7 @@ The capability of implementing WeChat SDKs in Flutter. With Fluwx, developers ca end s.subspec 'no_pay' do |sp| - sp.dependency 'OpenWeChatSDKNoPay','~> 2.0.2+1' + sp.dependency 'OpenWeChatSDKNoPay','~> 2.0.2+2' sp.frameworks = 'CoreGraphics', 'Security', 'WebKit' sp.libraries = 'c++', 'z', 'sqlite3.0' if debug_logging diff --git a/lib/src/fluwx.dart b/lib/src/fluwx.dart index ec21e7e5..64ac27fe 100644 --- a/lib/src/fluwx.dart +++ b/lib/src/fluwx.dart @@ -94,6 +94,12 @@ class Fluwx { return FluwxPlatform.instance.pay(which); } + /// Try to reload data from cold boot. For example, the app is launched by mini program and + /// we can get ext message by calling this. + Future attemptToResumeMsgFromWx() async { + return FluwxPlatform.instance.attemptToResumeMsgFromWx(); + } + /// Subscribe responses from WeChat subscribeResponse(Function(WeChatResponse response) listener) { _responseListeners.add(listener); diff --git a/lib/src/method_channel/fluwx_method_channel.dart b/lib/src/method_channel/fluwx_method_channel.dart index 1e8cd2dc..05df2b5a 100644 --- a/lib/src/method_channel/fluwx_method_channel.dart +++ b/lib/src/method_channel/fluwx_method_channel.dart @@ -183,9 +183,7 @@ class MethodChannelFluwx extends FluwxPlatform { switch (which) { case Payment(): return await methodChannel.invokeMethod( - 'payWithFluwx', - which.arguments - ); + 'payWithFluwx', which.arguments); case HongKongWallet(): return await methodChannel.invokeMethod( 'payWithHongKongWallet', which.arguments); @@ -205,6 +203,11 @@ class MethodChannelFluwx extends FluwxPlatform { return await methodChannel.invokeMethod('stopAuthByQRCode'); } + @override + Future attemptToResumeMsgFromWx() async { + return await methodChannel.invokeMethod("attemptToResumeMsgFromWx"); + } + @override Future get isSupportOpenBusinessView async => await methodChannel.invokeMethod("checkSupportOpenBusinessView"); diff --git a/lib/src/method_channel/fluwx_platform_interface.dart b/lib/src/method_channel/fluwx_platform_interface.dart index 7f8923eb..3211ecf7 100644 --- a/lib/src/method_channel/fluwx_platform_interface.dart +++ b/lib/src/method_channel/fluwx_platform_interface.dart @@ -113,6 +113,10 @@ abstract class FluwxPlatform extends PlatformInterface { throw UnimplementedError('authBy() has not been implemented.'); } + Future attemptToResumeMsgFromWx() { + throw UnimplementedError('authBy() has not been implemented.'); + } + Future get isSupportOpenBusinessView async { throw UnimplementedError( 'isSupportOpenBusinessView() has not been implemented.'); diff --git a/lib/src/response/wechat_response.dart b/lib/src/response/wechat_response.dart index b3311f7e..721199a9 100644 --- a/lib/src/response/wechat_response.dart +++ b/lib/src/response/wechat_response.dart @@ -48,6 +48,8 @@ Map _nameAndResponseMapper = { WeChatOpenBusinessViewResponse.fromMap(argument), "onOpenWechatInvoiceResponse": (Map argument) => WeChatOpenInvoiceResponse.fromMap(argument), + "onWXLaunchFromWX": (Map argument) => + WeChatLaunchFromWXRequest.fromMap(argument), }; sealed class WeChatResponse { @@ -213,8 +215,32 @@ class WeChatQRCodeScannedResponse extends WeChatResponse { // 获取微信打开App时携带的参数 class WeChatShowMessageFromWXRequest extends WeChatResponse { + final String? country; + final String? lang; + final String? messageAction; + final String? description; + WeChatShowMessageFromWXRequest.fromMap(Map map) : extMsg = map['extMsg'], + country = map['country'], + messageAction = map['messageAction'], + description = map["description"], + lang = map["lang"], + super._(0, ''); + + final String? extMsg; +} + +class WeChatLaunchFromWXRequest extends WeChatResponse { + final String? country; + final String? lang; + final String? messageAction; + + WeChatLaunchFromWXRequest.fromMap(Map map) + : extMsg = map['extMsg'], + country = map['country'], + messageAction = map['messageAction'], + lang = map["lang"], super._(0, ''); final String? extMsg; diff --git a/test/fluwx_test.dart b/test/fluwx_test.dart index e3171f5c..abebd2dc 100644 --- a/test/fluwx_test.dart +++ b/test/fluwx_test.dart @@ -90,6 +90,12 @@ class MockFluwxPlatform throw UnimplementedError(); } + @override + Future attemptToResumeMsgFromWx() { + // TODO: implement attemptToResumeMsgFromWx + throw UnimplementedError(); + } + } void main() {