From adb36ce8bae9b5b6fcf7c825616a1427c2f231fa Mon Sep 17 00:00:00 2001 From: Sean Date: Wed, 21 Aug 2024 09:26:56 +0800 Subject: [PATCH] 2.45.5 --- README.md | 64 +++++---- .../org.eclipse.buildship.core.prefs | 6 +- android/build.gradle | 4 +- .../mop/api/mop/AppletHandlerModule.java | 2 +- .../mop/api/mop/AppletManageModule.java | 2 +- .../finogeeks/mop/api/mop/AppletModule.java | 28 +++- .../finogeeks/mop/api/mop/InitSDKModule.java | 9 ++ .../org.eclipse.buildship.core.prefs | 4 +- example/android/app/build.gradle | 4 +- example/ios/Podfile.lock | 20 +-- example/ios/Runner.xcodeproj/project.pbxproj | 13 +- .../xcshareddata/WorkspaceSettings.xcsettings | 8 -- example/lib/main.dart | 70 ++++++--- example/lib/test_page.dart | 136 ++++++++++++++++++ example/pubspec.lock | 37 +++-- ios/Classes/Api/MOP_clearApplets.m | 7 +- ios/Classes/Api/MOP_closeAllApplets.m | 2 +- ios/Classes/Api/MOP_initSDK.m | 2 + ios/Classes/Api/MOP_qrcodeOpenApplet.h | 1 + ios/Classes/Api/MOP_qrcodeOpenApplet.m | 1 + ios/Classes/Api/MOP_registerExtensionApi.m | 3 - ios/Classes/Api/MOP_startApplet.h | 5 +- ios/Classes/Api/MOP_startApplet.m | 1 + ios/Classes/MopPlugin.m | 1 + ios/mop.podspec | 4 +- ios/mop.podspec.tpl | 1 + lib/mop.dart | 35 ++++- pubspec.lock | 37 +++-- pubspec.yaml | 2 +- 29 files changed, 384 insertions(+), 125 deletions(-) delete mode 100644 example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 example/lib/test_page.dart diff --git a/README.md b/README.md index 51d6040..3d775d1 100644 --- a/README.md +++ b/README.md @@ -82,19 +82,24 @@ class _MyAppState extends State { // Platform messages are asynchronous, so we initialize in an async method. Future init() async { - if (Platform.isiOS) { - //com.finogeeks.mopExample - final res = await Mop.instance.initialize( - '22LyZEib0gLTQdU3MUauARlLry7JL/2fRpscC9kpGZQA', '1c11d7252c53e0b6', - apiServer: 'https://api.finclip.com', apiPrefix: '/api/v1/mop'); - print(res); - } else if (Platform.isAndroid) { - //com.finogeeks.mopexample - final res = await Mop.instance.initialize( - '22LyZEib0gLTQdU3MUauARjmmp6QmYgjGb3uHueys1oA', '98c49f97a031b555', - apiServer: 'https://api.finclip.com', apiPrefix: '/api/v1/mop'); - print(res); - } + //多服务器配置 + FinStoreConfig storeConfigA = FinStoreConfig( + "22LyZEib0gLTQdU3MUauAfJ/xujwNfM6OvvEqQyH4igA", + "703b9026be3d6bc5", + "https://api.finclip.com", + cryptType: "SM", + ); + List storeConfigs = [storeConfigA]; + Config config = Config(storeConfigs); + config.language = LanguageType.English; + config.userId = "abc12345"; + config.channel = "finclip"; + config.phone = "12345678901"; + config.appletDebugMode = BOOLState.BOOLStateTrue; + + UIConfig uiconfig = UIConfig(); + uiconfig.isHideBackHome = true; + final res = await Mop.instance.initSDK(config, uiConfig: uiconfig); if (!mounted) return; } @@ -170,24 +175,29 @@ class _MyAppState extends State { 在使用 SDK 提供的 API 之前必须要初始化 SDK ,初始化 SDK 的接口如下 ``` - /// - /// initialize mop miniprogram engine. - /// 初始化小程序 - /// [appkey] is required. it can be getted from api.finclip.com - /// [secret] is required. it can be getted from api.finclip.com - /// [apiServer] is optional. the mop server address. default is https://mp.finogeek.com - /// [apiPrefix] is optional. the mop server prefix. default is /api/v1/mop - /// - /// - Future initialize(String appkey, String secret, - {String apiServer, String apiPrefix}) +/// +/// initialize FinClip SDK. +/// 初始化SDK(推荐使用) +/// [config] is required. sdk配置 +/// [uiConfig] is optional. UI配置 +Future initSDK(Config config, {UIConfig? uiConfig}) ``` 使用示例: ``` -final res = await Mop.instance.initialize( - '22LyZEib0gLTQdU3MUauARlLry7JL/2fRpscC9kpGZQA', '1c11d7252c53e0b6', - apiServer: 'https://api.finclip.com', apiPrefix: '/api/v1/mop'); +// 1.创建Config +// 1.1 配置服务器1的参数 +FinStoreConfig finclip_store = FinStoreConfig('22LyZEib0gLTQdU3MUauATBwgfnTCJjdr7FCnywmAEM=', 'bdfd76cae24d4313', 'https://api.finclip.com'); +// 1.2 配置服务器2的参数 +FinStoreConfig test_store = FinStoreConfig('sdkKey2', 'sdkSecret2', '测试服务器'); +Config config = Config([finclip_store, test_store]); +config.userId = '您app的用户唯一标识'; + +// 2.创建UIConfig +UIConfig uiConfig = UIConfig(); +uiConfig.isHideAddToDesktopMenu = true; +uiConfig.isHideFeedbackAndComplaints = true; +final res = await Mop.instance.initSDK(config, uiConfig: uiConfig); ``` ### 2. 打开小程序 diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs index 41f5edb..124b3b1 100644 --- a/android/.settings/org.eclipse.buildship.core.prefs +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -1,11 +1,11 @@ -arguments=--init-script /var/folders/tv/dbm7kt650fvdxrtf0k7xgxcm0000gn/T/d146c9752a26f79b52047fb6dc6ed385d064e120494f96f08ca63a317c41f94c.gradle --init-script /var/folders/tv/dbm7kt650fvdxrtf0k7xgxcm0000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle +arguments=--init-script /var/folders/tx/98mydjws12b717spn4mx1wd80000gn/T/db3b08fc4a9ef609cb16b96b200fa13e563f396e9bb1ed0905fdab7bc3bc513b.gradle --init-script /var/folders/tx/98mydjws12b717spn4mx1wd80000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle auto.sync=false build.scans.enabled=false -connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(7.4.2)) +connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) connection.project.dir= eclipse.preferences.version=1 gradle.user.home= -java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_261.jdk/Contents/Home +java.home=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home jvm.arguments= offline.mode=false override.workspace.settings=true diff --git a/android/build.gradle b/android/build.gradle index 7812323..7158907 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -91,6 +91,6 @@ kapt { } dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'com.finogeeks.lib:finapplet:2.44.5' - implementation 'com.finogeeks.mop:plugins:2.44.5' + implementation 'com.finogeeks.lib:finapplet:2.45.5' + implementation 'com.finogeeks.mop:plugins:2.45.5' } \ No newline at end of file diff --git a/android/src/main/java/com/finogeeks/mop/api/mop/AppletHandlerModule.java b/android/src/main/java/com/finogeeks/mop/api/mop/AppletHandlerModule.java index edae73e..331d2b2 100644 --- a/android/src/main/java/com/finogeeks/mop/api/mop/AppletHandlerModule.java +++ b/android/src/main/java/com/finogeeks/mop/api/mop/AppletHandlerModule.java @@ -158,7 +158,7 @@ public class AppletHandlerModule extends BaseApi { }.getType())); if (bitmap != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos); byte[] data = baos.toByteArray(); params.put("bitmap", data); } diff --git a/android/src/main/java/com/finogeeks/mop/api/mop/AppletManageModule.java b/android/src/main/java/com/finogeeks/mop/api/mop/AppletManageModule.java index d83b49d..8e154e1 100644 --- a/android/src/main/java/com/finogeeks/mop/api/mop/AppletManageModule.java +++ b/android/src/main/java/com/finogeeks/mop/api/mop/AppletManageModule.java @@ -95,7 +95,7 @@ public class AppletManageModule extends BaseApi { callback.onFail(null); } } else if (event.equals("clearApplets")) { - FinAppClient.INSTANCE.getAppletApiManager().clearApplets(); + FinAppClient.INSTANCE.getAppletApiManager().finishAllRunningApplets(); callback.onSuccess(null); } else if (event.equals("removeUsedApplet")) { Log.d("MopPlugin", "removeUsedApplet:params:" + param); diff --git a/android/src/main/java/com/finogeeks/mop/api/mop/AppletModule.java b/android/src/main/java/com/finogeeks/mop/api/mop/AppletModule.java index a5350f1..a24159b 100644 --- a/android/src/main/java/com/finogeeks/mop/api/mop/AppletModule.java +++ b/android/src/main/java/com/finogeeks/mop/api/mop/AppletModule.java @@ -4,6 +4,7 @@ import android.content.Context; import android.text.TextUtils; import android.util.Log; +import androidx.annotation.NonNull; import com.finogeeks.lib.applet.client.FinAppClient; import com.finogeeks.lib.applet.client.FinAppInfo; import com.finogeeks.lib.applet.interfaces.FinCallback; @@ -176,7 +177,7 @@ public class AppletModule extends BaseApi { } else { taskMode = IFinAppletRequest.TaskMode.MULTI; } - + IFinAppletRequest.ReLaunchMode mode = getReLaunchMode(param); Log.d("MopPlugin", "startApplet (appId=" + appId + ", sequence=" + sequence + ", apiServer=" + apiServer + ", isSingleProcess:" + isSingleProcess); // mContext是FlutterActivity, // 在Android 6.0、7.0系统的部分设备中热启动小程序时,如果context参数用mContext,会出现无法启动小程序的问题 @@ -192,7 +193,8 @@ public class AppletModule extends BaseApi { .setStartParams(params) .setOfflineParams(offlineFrameworkZipPath, offlineMiniprogramZipPath) .setProcessMode(processMode) - .setTaskMode(taskMode), + .setTaskMode(taskMode) + .setReLaunchMode(mode), null); // 改成通过request来启动小程序 // FinAppClient.INSTANCE.getAppletApiManager().startApplet(context, IFinAppletRequest.Companion.fromAppId("apiServer", "appId") @@ -238,8 +240,9 @@ public class AppletModule extends BaseApi { } else { taskMode = IFinAppletRequest.TaskMode.MULTI; } + IFinAppletRequest.ReLaunchMode mode = getReLaunchMode(param); FinAppClient.INSTANCE.getAppletApiManager().startApplet(mContext, IFinAppletRequest.Companion.fromQrCode(qrcode) - .setProcessMode(processMode).setTaskMode(taskMode), new FinCallback() { + .setProcessMode(processMode).setTaskMode(taskMode).setReLaunchMode(mode), new FinCallback() { @Override public void onSuccess(String s) { callback.onSuccess(new HashMap()); @@ -277,6 +280,25 @@ public class AppletModule extends BaseApi { });*/ } + @NonNull + private static IFinAppletRequest.ReLaunchMode getReLaunchMode(Map param) { + IFinAppletRequest.ReLaunchMode mode = IFinAppletRequest.ReLaunchMode.PARAMS_EXIST; + Object modeValue = param.get("reLaunchMode"); + if (modeValue != null) { + if (modeValue instanceof Integer) { + int reLaunchMode = (Integer) modeValue; + if (reLaunchMode == 1) { + mode = IFinAppletRequest.ReLaunchMode.ONLY_PARAMS_DIFF; + } else if (reLaunchMode == 2) { + mode = IFinAppletRequest.ReLaunchMode.ALWAYS; + } else if (reLaunchMode == 3) { + mode = IFinAppletRequest.ReLaunchMode.NEVER; + } + } + } + return mode; + } + private void changeUserId(Map param, ICallback callback) { String userId = String.valueOf(param.get("userId")); if (FinAppClient.INSTANCE.getFinAppConfig() != null) { diff --git a/android/src/main/java/com/finogeeks/mop/api/mop/InitSDKModule.java b/android/src/main/java/com/finogeeks/mop/api/mop/InitSDKModule.java index a4b2a7d..a4f457e 100644 --- a/android/src/main/java/com/finogeeks/mop/api/mop/InitSDKModule.java +++ b/android/src/main/java/com/finogeeks/mop/api/mop/InitSDKModule.java @@ -80,6 +80,15 @@ public class InitSDKModule extends BaseApi { if (userId != null) { configBuilder.setUserId(userId); } + String channel = (String) configMap.get("channel"); + if (channel != null) { + configBuilder.setChannel(channel); + } + String phone = (String) configMap.get("phone"); + if (phone != null) { + configBuilder.setPhone(phone); + } + String productIdentification = (String) configMap.get("productIdentification"); if (productIdentification != null) { configBuilder.setProductIdentification(productIdentification); diff --git a/example/android/.settings/org.eclipse.buildship.core.prefs b/example/android/.settings/org.eclipse.buildship.core.prefs index 26ccfb0..445ffa1 100644 --- a/example/android/.settings/org.eclipse.buildship.core.prefs +++ b/example/android/.settings/org.eclipse.buildship.core.prefs @@ -1,11 +1,11 @@ -arguments=--init-script /var/folders/tv/dbm7kt650fvdxrtf0k7xgxcm0000gn/T/d146c9752a26f79b52047fb6dc6ed385d064e120494f96f08ca63a317c41f94c.gradle --init-script /var/folders/tv/dbm7kt650fvdxrtf0k7xgxcm0000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle +arguments=--init-script /var/folders/tx/98mydjws12b717spn4mx1wd80000gn/T/d146c9752a26f79b52047fb6dc6ed385d064e120494f96f08ca63a317c41f94c.gradle --init-script /var/folders/tx/98mydjws12b717spn4mx1wd80000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle auto.sync=false build.scans.enabled=false connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) connection.project.dir= eclipse.preferences.version=1 gradle.user.home= -java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_261.jdk/Contents/Home +java.home=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home jvm.arguments= offline.mode=false override.workspace.settings=true diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index c1d619b..c55ac0e 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -70,7 +70,7 @@ flutter { } dependencies { - def sdk_version = "2.41.3" - compileOnly "com.finogeeks.lib:finapplet:2.41.4-dev20230721v13" + def sdk_version = "2.45.1" + compileOnly "com.finogeeks.lib:finapplet:${sdk_version}" implementation "com.finogeeks.mop:plugins:${sdk_version}" } diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 4fa39cb..9d56ccb 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,11 +1,11 @@ PODS: - - FinApplet (2.40.12-dev20230615v03) - - FinAppletExt (2.40.12-dev20230615v03): - - FinApplet (= 2.40.12-dev20230615v03) + - FinApplet (2.45.1) + - FinAppletExt (2.45.1): + - FinApplet (= 2.45.1) - Flutter (1.0.0) - mop (0.1.1): - - FinApplet (= 2.40.12-dev20230615v03) - - FinAppletExt (= 2.40.12-dev20230615v03) + - FinApplet (= 2.45.1) + - FinAppletExt (= 2.45.1) - Flutter DEPENDENCIES: @@ -13,7 +13,7 @@ DEPENDENCIES: - mop (from `.symlinks/plugins/mop/ios`) SPEC REPOS: - ssh://gitlab.finogeeks.club/finclip-ios/DevPods: + ssh://gitlab.finogeeks.club/finclip-ios/FinPods: - FinApplet - FinAppletExt @@ -24,11 +24,11 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/mop/ios" SPEC CHECKSUMS: - FinApplet: 8c14ee57dcefca25074fc4ae5ff047d0636d9116 - FinAppletExt: b6356d98e0897017611a402aaf97f24686652d93 + FinApplet: eea27894485c871a94b2ded79a8fe1e84d7ffcc9 + FinAppletExt: 231dde4c4ed3862b70179c3dfac7406090ace955 Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a - mop: 2610a14e951144088f87aea5881db9c5d58a5995 + mop: afa40651ec188a85a27c068d5afa2a97c6a53a01 PODFILE CHECKSUM: 2da0220ee5ba22a2dfcec42dfe5b17d05f3c3da9 -COCOAPODS: 1.11.3 +COCOAPODS: 1.15.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index a038787..7b0d422 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -367,6 +367,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 9QCKYFU5M4; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = finclip_example; @@ -377,6 +378,7 @@ MARKETING_VERSION = 1.0.0; PRODUCT_BUNDLE_IDENTIFIER = com.finogeeks.finosprite; PRODUCT_NAME = "$(TARGET_NAME)"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = wild_all; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -495,8 +497,10 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 9QCKYFU5M4; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 9QCKYFU5M4; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = finclip_example; @@ -507,6 +511,8 @@ MARKETING_VERSION = 1.0.0; PRODUCT_BUNDLE_IDENTIFIER = com.finogeeks.finosprite; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = wild_all; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -520,8 +526,10 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 9QCKYFU5M4; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 9QCKYFU5M4; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = finclip_example; @@ -532,6 +540,7 @@ MARKETING_VERSION = 1.0.0; PRODUCT_BUNDLE_IDENTIFIER = com.finogeeks.finosprite; PRODUCT_NAME = "$(TARGET_NAME)"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = wild_all; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c..0000000 --- a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/example/lib/main.dart b/example/lib/main.dart index e1afd19..d320e0c 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,13 +1,11 @@ // ignore_for_file: prefer_const_constructors -import 'dart:ffi'; - import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:mop/api.dart'; import 'dart:async'; -import 'dart:io'; import 'package:mop/mop.dart'; +import 'package:mop_example/test_page.dart'; void main() => runApp(MyApp()); @@ -22,7 +20,10 @@ class _MyAppState extends State { @override void initState() { super.initState(); - init(); + + Future.delayed(const Duration(seconds: 3), () { + init(); + }); } // Platform messages are asynchronous, so we initialize in an async method. @@ -45,6 +46,9 @@ class _MyAppState extends State { Config config = Config(storeConfigs); config.language = LanguageType.English; config.baseLoadingViewClass = "LoadingView"; + config.userId = "18607180143"; + config.channel = "finclip"; + config.phone = "1234567890"; config.appletDebugMode = BOOLState.BOOLStateTrue; UIConfig uiconfig = UIConfig(); @@ -143,7 +147,7 @@ class _MyAppState extends State { ); } - Widget _buildAppletWidget(String appletId, String appletName) { + Widget _buildAppletWidget(String appletId, String appletName, int index, Map? startParams) { return Container( margin: EdgeInsets.only(left: 20, top: 30, right: 20), child: Column( @@ -159,31 +163,43 @@ class _MyAppState extends State { Container( height: 100, child: GridView.count( - crossAxisCount: 3, + crossAxisCount: 4, childAspectRatio: 2, - crossAxisSpacing: 30, + crossAxisSpacing: 10, // physics: NeverScrollableScrollPhysics(), children: [ - _buildAppletItem(appletId, "打开小程序", () { + _buildAppletItem(appletId, "open", () { TranstionStyle style = TranstionStyle.TranstionStyleUp; - if (appletId == "5f72e3559a6a7900019b5baa") { + FCReLaunchMode mode = FCReLaunchMode.PARAMS_EXIST; + if (index == 1) { + mode = FCReLaunchMode.ONLY_PARAMS_DIFF; style = TranstionStyle.TranstionStylePush; + } else if (index == 2) { + mode = FCReLaunchMode.ALWAYS; + } else if (index == 3) { + mode = FCReLaunchMode.NEVER; } - RemoteAppletRequest request = RemoteAppletRequest(apiServer: 'https://api.finclip.com', appletId: appletId, transitionStyle: style); + + RemoteAppletRequest request = RemoteAppletRequest( + apiServer: 'https://api.finclip.com', + appletId: appletId, + transitionStyle: style, + reLaunchMode: mode, + startParams: startParams); Mop.instance.startApplet(request); // Mop.instance.qrcodeOpenApplet('https://api.finclip.com/api/v1/mop/runtime/applet/-f-MGYzN2Q1YTYzMmI2MWIyZg--'); }), - _buildAppletItem(appletId, "finishRunningApplet", () { + _buildAppletItem(appletId, "finish", () { Mop.instance.finishRunningApplet(appletId, true); }), - _buildAppletItem(appletId, "removeUsedApplet", () { + _buildAppletItem(appletId, "remove", () { Mop.instance.removeUsedApplet(appletId); }), - // _buildAppletItem(appletId, "removeUsedApplet", () { - // Mop.instance.removeUsedApplet(appletId); - // }), + _buildAppletItem(appletId, "finishAll", () { + Mop.instance.clearApplets(); + }), ], ), ) @@ -199,13 +215,29 @@ class _MyAppState extends State { home: Scaffold( appBar: AppBar( title: const Text('凡泰极客小程序 Flutter 插件'), + actions: [ + Builder( + builder: (context) { + return IconButton( + icon: Icon(Icons.more_horiz), + tooltip: 'More', + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => TestPage()), + ); + }, + ); + }, + ), + ], ), body: Column( children: [ - _buildAppletWidget("5facb3a52dcbff00017469bd", "画图小程序"), - _buildAppletWidget("5f72e3559a6a7900019b5baa", "官方小程序"), - _buildAppletWidget("5f17f457297b540001e06ebb", "api测试小程序"), - _buildAppletWidget("61386f6484dd160001d3e1ab", "测试小程序"), + _buildAppletWidget("5facb3a52dcbff00017469bd", "画图小程序", 0, {'query':'ramdom='+context.hashCode.toString()}), + _buildAppletWidget("5f72e3559a6a7900019b5baa", "官方小程序", 1, {'query':'key=value'}), + _buildAppletWidget("5f17f457297b540001e06ebb", "api测试小程序", 2, null), + _buildAppletWidget("61386f6484dd160001d3e1ab", "测试小程序", 3, {'query':'ramdom='+context.hashCode.toString()}), ], ), diff --git a/example/lib/test_page.dart b/example/lib/test_page.dart new file mode 100644 index 0000000..7a4fe77 --- /dev/null +++ b/example/lib/test_page.dart @@ -0,0 +1,136 @@ +import 'package:flutter/material.dart'; +import 'package:mop/mop.dart'; + +class TestPage extends StatefulWidget { + @override + _TestPageState createState() => _TestPageState(); +} + +class _TestPageState extends State { + final TextEditingController _controller1 = TextEditingController(text: '5f72e3559a6a7900019b5baa'); + final TextEditingController _controller2 = TextEditingController(); + final TextEditingController _controller3 = TextEditingController(text: 'key1=value2&name=zhangsan'); + final TextEditingController _controller4 = TextEditingController(text: 'https://api.finclip.com/api/v1/mop/runtime/applet/-f-f1362bb056a265aa--'); + + int _selectedRadio = 0; + + void _handleRadioValueChange(int? value) { + setState(() { + _selectedRadio = value!; + }); + } + + void _handleButtonPress() { + // 在这里处理按钮点击事件 + String appId = _controller1.text.trim(); + String path = _controller2.text.trim(); + String query = _controller3.text.trim(); + + int index = _selectedRadio; + FCReLaunchMode mode = FCReLaunchMode.PARAMS_EXIST; + if (index == 1) { + mode = FCReLaunchMode.ONLY_PARAMS_DIFF; + } else if (index == 2) { + mode = FCReLaunchMode.ALWAYS; + } else if (index == 3) { + mode = FCReLaunchMode.NEVER; + } + + Map? startParams = {}; + if (path.length > 0) { + startParams["path"] = path; + } + if (query.length > 0) { + startParams["query"] = query; + } + + RemoteAppletRequest request = RemoteAppletRequest( + apiServer: 'https://api.finclip.com', + appletId: appId, + reLaunchMode: mode, + startParams: startParams); + Mop.instance.startApplet(request); + } + + void _handleqrCodeButtonPress() { + String qrcode = _controller4.text.trim(); + int index = _selectedRadio; + FCReLaunchMode mode = FCReLaunchMode.PARAMS_EXIST; + if (index == 1) { + mode = FCReLaunchMode.ONLY_PARAMS_DIFF; + } else if (index == 2) { + mode = FCReLaunchMode.ALWAYS; + } else if (index == 3) { + mode = FCReLaunchMode.NEVER; + } + QRCodeAppletRequest qrcodeRequest = QRCodeAppletRequest(qrcode, reLaunchMode: mode); + Mop.instance.qrcodeStartApplet(qrcodeRequest); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('测试页面'), + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + _buildTextField(_controller1, '小程序id'), + _buildTextField(_controller2, '输入path'), + _buildTextField(_controller3, '输入query'), + _buildTextField(_controller4, '二维码地址'), + SizedBox(height: 10), + Column( + children: [ + _buildRadioTile(0, 'ParamExist'), + _buildRadioTile(1, 'OnlyParamDiff'), + _buildRadioTile(2, 'Always'), + _buildRadioTile(3, 'Never'), + ], + ), + SizedBox(height: 10), + ElevatedButton( + onPressed: _handleButtonPress, + child: Text('打开小程序'), + ), + SizedBox(height: 10), + ElevatedButton( + onPressed: _handleqrCodeButtonPress, + child: Text('二维码打开小程序'), + ), + ], + ), + ), + ); + } + + Widget _buildTextField(TextEditingController controller, String hintText) { + return TextField( + controller: controller, + decoration: InputDecoration( + hintText: hintText, + border: OutlineInputBorder(), + contentPadding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0), + ), + ); + } + + Widget _buildRadioTile(int value, String title) { + return GestureDetector( + onTap: () => _handleRadioValueChange(value), + child: Row( + children: [ + Radio( + value: value, + groupValue: _selectedRadio, + onChanged: _handleRadioValueChange, + ), + Text(title), + ], + ), + ); + } + +} diff --git a/example/pubspec.lock b/example/pubspec.lock index ee91b9b..c64b873 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.flutter-io.cn" source: hosted - version: "2.9.0" + version: "2.8.2" boolean_selector: dependency: transitive description: @@ -21,14 +21,21 @@ packages: name: characters url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.1" + version: "1.2.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.1" clock: dependency: transitive description: name: clock url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.1" + version: "1.1.0" collection: dependency: transitive description: @@ -49,7 +56,7 @@ packages: name: fake_async url: "https://pub.flutter-io.cn" source: hosted - version: "1.3.1" + version: "1.3.0" flutter: dependency: "direct main" description: flutter @@ -68,7 +75,7 @@ packages: name: flutter_plugin_android_lifecycle url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.9" + version: "2.0.14" flutter_test: dependency: "direct dev" description: flutter @@ -87,35 +94,35 @@ packages: name: matcher url: "https://pub.flutter-io.cn" source: hosted - version: "0.12.12" + version: "0.12.11" material_color_utilities: dependency: transitive description: name: material_color_utilities url: "https://pub.flutter-io.cn" source: hosted - version: "0.1.5" + version: "0.1.4" meta: dependency: transitive description: name: meta url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.0" + version: "1.7.0" mop: dependency: "direct main" description: path: ".." relative: true source: path - version: "2.41.1" + version: "2.45.1" path: dependency: transitive description: name: path url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.2" + version: "1.8.1" sky_engine: dependency: transitive description: flutter @@ -127,7 +134,7 @@ packages: name: source_span url: "https://pub.flutter-io.cn" source: hosted - version: "1.9.0" + version: "1.8.2" stack_trace: dependency: transitive description: @@ -148,21 +155,21 @@ packages: name: string_scanner url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.1" + version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.1" + version: "1.2.0" test_api: dependency: transitive description: name: test_api url: "https://pub.flutter-io.cn" source: hosted - version: "0.4.12" + version: "0.4.9" vector_math: dependency: transitive description: @@ -171,5 +178,5 @@ packages: source: hosted version: "2.1.2" sdks: - dart: ">=2.17.0-0 <3.0.0" + dart: ">=2.17.0 <3.0.0" flutter: ">=3.0.0" diff --git a/ios/Classes/Api/MOP_clearApplets.m b/ios/Classes/Api/MOP_clearApplets.m index e4f22a0..3c06da0 100644 --- a/ios/Classes/Api/MOP_clearApplets.m +++ b/ios/Classes/Api/MOP_clearApplets.m @@ -13,9 +13,10 @@ - (void)setupApiWithSuccess:(void (^)(NSDictionary * _Nonnull))success failure:(void (^)(id _Nullable))failure cancel:(void (^)(void))cancel { NSLog(@"clearApplets"); - [[FATClient sharedClient]clearMemoryCache]; - [[FATClient sharedClient]clearLocalApplets]; - success(@{}); + [[FATClient sharedClient] closeAllAppletsWithCompletion:^{ + [[FATClient sharedClient] clearMemoryCache]; + success(@{}); + }]; } @end diff --git a/ios/Classes/Api/MOP_closeAllApplets.m b/ios/Classes/Api/MOP_closeAllApplets.m index b737361..dd22274 100644 --- a/ios/Classes/Api/MOP_closeAllApplets.m +++ b/ios/Classes/Api/MOP_closeAllApplets.m @@ -13,7 +13,7 @@ - (void)setupApiWithSuccess:(void (^)(NSDictionary * _Nonnull))success failure:(void (^)(id _Nullable))failure cancel:(void (^)(void))cancel { NSLog(@"closeAllApplets"); - [[FATClient sharedClient] closeAllApplets]; + [[FATClient sharedClient] closeAllAppletsWithCompletion:nil]; success(@{}); } diff --git a/ios/Classes/Api/MOP_initSDK.m b/ios/Classes/Api/MOP_initSDK.m index 0b39479..773b091 100644 --- a/ios/Classes/Api/MOP_initSDK.m +++ b/ios/Classes/Api/MOP_initSDK.m @@ -47,6 +47,8 @@ } config.currentUserId = self.config[@"userId"]; + config.channel = self.config[@"channel"]; + config.phone = self.config[@"phone"]; config.productIdentification = self.config[@"productIdentification"]; config.disableAuthorize = [self.config[@"disableRequestPermissions"] boolValue]; config.appletAutoAuthorize = [self.config[@"appletAutoAuthorize"] boolValue]; diff --git a/ios/Classes/Api/MOP_qrcodeOpenApplet.h b/ios/Classes/Api/MOP_qrcodeOpenApplet.h index f9fdbf0..f2511a4 100644 --- a/ios/Classes/Api/MOP_qrcodeOpenApplet.h +++ b/ios/Classes/Api/MOP_qrcodeOpenApplet.h @@ -12,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN @interface MOP_qrcodeOpenApplet : MOPBaseApi @property (nonatomic,copy) NSString *qrcode; +@property (nonatomic,copy) NSString *reLaunchMode; @end diff --git a/ios/Classes/Api/MOP_qrcodeOpenApplet.m b/ios/Classes/Api/MOP_qrcodeOpenApplet.m index 14d49bc..bc92124 100644 --- a/ios/Classes/Api/MOP_qrcodeOpenApplet.m +++ b/ios/Classes/Api/MOP_qrcodeOpenApplet.m @@ -15,6 +15,7 @@ NSLog(@"MOP_qrcodeOpenApplet:%@", self.qrcode); FATAppletQrCodeRequest *qrcodeRequest = [[FATAppletQrCodeRequest alloc] init]; qrcodeRequest.qrCode = self.qrcode; + qrcodeRequest.reLaunchMode = [self.reLaunchMode intValue]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ UIViewController *currentVC = [MOPTools topViewController]; diff --git a/ios/Classes/Api/MOP_registerExtensionApi.m b/ios/Classes/Api/MOP_registerExtensionApi.m index b66094d..9b27607 100644 --- a/ios/Classes/Api/MOP_registerExtensionApi.m +++ b/ios/Classes/Api/MOP_registerExtensionApi.m @@ -30,12 +30,9 @@ } // 再判断回调是否为失败 BOOL hasError = [[result allKeys] containsObject:@"errMsg"]; - if (hasError) { NSString *errMsg = result[@"errMsg"]; NSString *errPrefix = [NSString stringWithFormat:@"%@:fail", name]; - NSLog(@"extensionApi2 [%@] reslut:%@", errPrefix, errMsg); - BOOL isFail = [errMsg hasPrefix:errPrefix]; if (isFail) { NSLog(@"extensionApi reslut:fail"); diff --git a/ios/Classes/Api/MOP_startApplet.h b/ios/Classes/Api/MOP_startApplet.h index 27c6b3c..3187ed0 100644 --- a/ios/Classes/Api/MOP_startApplet.h +++ b/ios/Classes/Api/MOP_startApplet.h @@ -17,8 +17,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy) NSDictionary *startParams; @property (nonatomic, copy) NSString *offlineMiniprogramZipPath; @property (nonatomic, copy) NSString *offlineFrameworkZipPath; -@property (nonatomic, strong) NSString *animated; -@property (nonatomic, strong) NSString *transitionStyle; +@property (nonatomic, copy) NSString *animated; +@property (nonatomic, copy) NSString *transitionStyle; +@property (nonatomic, copy) NSString *reLaunchMode; @end diff --git a/ios/Classes/Api/MOP_startApplet.m b/ios/Classes/Api/MOP_startApplet.m index 744db0a..06dbb8b 100644 --- a/ios/Classes/Api/MOP_startApplet.m +++ b/ios/Classes/Api/MOP_startApplet.m @@ -26,6 +26,7 @@ request.offlineFrameworkZipPath = self.offlineFrameworkZipPath; request.animated = [self.animated boolValue]; request.transitionStyle = [self.transitionStyle intValue]; + request.reLaunchMode = [self.reLaunchMode intValue]; // 启动小程序 [[FATClient sharedClient] startAppletWithRequest:request InParentViewController:currentVC completion:^(BOOL result, NSError *error) { diff --git a/ios/Classes/MopPlugin.m b/ios/Classes/MopPlugin.m index 7040596..facdd99 100644 --- a/ios/Classes/MopPlugin.m +++ b/ios/Classes/MopPlugin.m @@ -154,6 +154,7 @@ static MopPlugin *_instance; request.command = call.method; request.param = (NSDictionary*)call.arguments; MOPBaseApi* api = [MOPApiConverter apiWithRequest: request]; + NSLog(@"method:%@, param:%@", request.command, request.param); if (api) { [api setupApiWithSuccess:^(NSDictionary * _Nonnull data) { result(@{@"retMsg":@"ok",@"success":@(YES),@"data": data ? : @{}}); diff --git a/ios/mop.podspec b/ios/mop.podspec index 5a76724..e74f586 100644 --- a/ios/mop.podspec +++ b/ios/mop.podspec @@ -21,8 +21,8 @@ A finclip miniprogram flutter sdk. s.vendored_libraries = 'Classes/FinAppletExt/Vendor/Lame/libmp3lame.a' s.static_framework = true - s.dependency 'FinApplet' , '2.44.5' + s.dependency 'FinApplet' , '2.45.5' # s.dependency 'FinAppletExt' - s.dependency 'FinAppletBLE' , '2.44.5' + s.dependency 'FinAppletBLE' , '2.45.5' end diff --git a/ios/mop.podspec.tpl b/ios/mop.podspec.tpl index 49c8ec9..be33034 100644 --- a/ios/mop.podspec.tpl +++ b/ios/mop.podspec.tpl @@ -22,6 +22,7 @@ A finclip miniprogram flutter sdk. s.static_framework = true s.dependency 'FinApplet' , '__finapplet_version__' +# s.dependency 'FinAppletExt' , '__finapplet_version__' s.dependency 'FinAppletBLE' end diff --git a/lib/mop.dart b/lib/mop.dart index ae6cb48..252719c 100644 --- a/lib/mop.dart +++ b/lib/mop.dart @@ -74,6 +74,11 @@ class Config { /// 小程序缓存信息会存储在以userId命名的不同目录下。 String? userId; + // 渠道标识,如果未设置则取应用bundleId + String? channel; + // 手机号,也可以是一个token。 + String? phone; + /// 产品的标识,非必传,默认为存储目录里的finclip,finogeeks和userAgent里的finogeeks String? productIdentification; @@ -250,6 +255,8 @@ class Config { return { "finStoreConfigs": storeConfigs, "userId": userId, + "channel": channel, + "phone": phone, "productIdentification": productIdentification, "disableRequestPermissions": disableRequestPermissions, "appletAutoAuthorize": appletAutoAuthorize, @@ -849,6 +856,9 @@ class RemoteAppletRequest { // 是否以单任务模式运行,仅限android,默认为false bool isSingTask; + // 触发reLaunch的条件模式 + FCReLaunchMode reLaunchMode; + RemoteAppletRequest({ required this.apiServer, required this.appletId, @@ -860,6 +870,7 @@ class RemoteAppletRequest { this.transitionStyle = TranstionStyle.TranstionStyleUp, this.isSingleProcess = false, this.isSingTask = false, + this.reLaunchMode = FCReLaunchMode.PARAMS_EXIST, }); Map toMap() { @@ -870,6 +881,7 @@ class RemoteAppletRequest { "isSingleProcess": isSingleProcess, "isSingTask": isSingTask, "transitionStyle": transitionStyle.index, + "reLaunchMode": reLaunchMode.index, }; if (startParams != null) result["startParams"] = startParams; if (offlineMiniprogramZipPath != null) @@ -895,15 +907,19 @@ class QRCodeAppletRequest { // 是否以单任务模式运行,仅限android,默认为false bool isSingTask; + // 触发reLaunch的条件模式 + FCReLaunchMode reLaunchMode; + QRCodeAppletRequest(this.qrCode, - {this.isSingleProcess = false, this.isSingTask = false}); + {this.isSingleProcess = false, this.isSingTask = false, this.reLaunchMode = FCReLaunchMode.PARAMS_EXIST}); Map toMap() { return { - "apiServer": qrCode, + "qrcode": qrCode, "animated": animated, "isSingleProcess": isSingleProcess, "isSingTask": isSingTask, + "reLaunchMode": reLaunchMode.index, }; } } @@ -949,6 +965,13 @@ enum LogLevel { LEVEL_NONE } +enum FCReLaunchMode { + PARAMS_EXIST, // 只要有启动参数(path、query),热启动就会执行reLaunch + ONLY_PARAMS_DIFF, // 只有启动参数与上一次不同,热启动时才会执行reLaunch + ALWAYS, // 每次热启动均执行reLaunch + NEVER // 永远不执行reLaunch,每次热启动均复用页面栈 +} + class Mop { static final Mop _instance = new Mop._internal(); late MethodChannel _channel; @@ -1142,6 +1165,12 @@ class Mop { return await _channel.invokeMapMethod("qrcodeOpenApplet", params); } + Future qrcodeStartApplet(QRCodeAppletRequest qrcodeRequest) async { + Map params = qrcodeRequest.toMap(); + final Map ret = await _channel.invokeMethod("qrcodeOpenApplet", params); + return ret; + } + /// (扫码后)解密-鉴权-打开小程序 Future scanOpenApplet(String info, {bool isSingleProcess = false, bool isSingTask = false}) async { @@ -1186,7 +1215,7 @@ class Mop { } /// clear applets cache - /// 清除缓存的小程序 + /// 结束所有小程序 Future clearApplets() async { return await _channel.invokeMethod("clearApplets"); } diff --git a/pubspec.lock b/pubspec.lock index e3f3961..a842077 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.flutter-io.cn" source: hosted - version: "2.9.0" + version: "2.8.2" boolean_selector: dependency: transitive description: @@ -21,14 +21,21 @@ packages: name: characters url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.1" + version: "1.2.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.1" clock: dependency: transitive description: name: clock url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.1" + version: "1.1.0" collection: dependency: transitive description: @@ -42,7 +49,7 @@ packages: name: fake_async url: "https://pub.flutter-io.cn" source: hosted - version: "1.3.1" + version: "1.3.0" flutter: dependency: "direct main" description: flutter @@ -61,7 +68,7 @@ packages: name: flutter_plugin_android_lifecycle url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.6" + version: "2.0.14" flutter_test: dependency: "direct dev" description: flutter @@ -80,28 +87,28 @@ packages: name: matcher url: "https://pub.flutter-io.cn" source: hosted - version: "0.12.12" + version: "0.12.11" material_color_utilities: dependency: transitive description: name: material_color_utilities url: "https://pub.flutter-io.cn" source: hosted - version: "0.1.5" + version: "0.1.4" meta: dependency: transitive description: name: meta url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.0" + version: "1.7.0" path: dependency: transitive description: name: path url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.2" + version: "1.8.1" sky_engine: dependency: transitive description: flutter @@ -113,7 +120,7 @@ packages: name: source_span url: "https://pub.flutter-io.cn" source: hosted - version: "1.9.0" + version: "1.8.2" stack_trace: dependency: transitive description: @@ -134,21 +141,21 @@ packages: name: string_scanner url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.1" + version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.1" + version: "1.2.0" test_api: dependency: transitive description: name: test_api url: "https://pub.flutter-io.cn" source: hosted - version: "0.4.12" + version: "0.4.9" vector_math: dependency: transitive description: @@ -157,5 +164,5 @@ packages: source: hosted version: "2.1.2" sdks: - dart: ">=2.17.0-0 <3.0.0" - flutter: ">=2.2.3" + dart: ">=2.17.0 <3.0.0" + flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index ae7daab..49d2792 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: mop description: A Finogeeks MiniProgram Flutter SDK. -version: '2.44.5' +version: '2.45.5' homepage: https://github.com/finogeeks/mop-flutter-sdk environment: