Merge branch 'feat/newApi'

# Conflicts:
#	android/src/main/java/com/finogeeks/mop/api/mop/AppletModule.java
#	example/.flutter-plugins-dependencies
#	ios/Classes/Api/MOP_initialize.h
#	ios/mop.podspec
master
kangxuyao 2022-01-10 09:50:55 +08:00
commit 776f5a621e
93 changed files with 1905 additions and 1037 deletions

17
.gitignore vendored
View File

@ -5,13 +5,9 @@
.packages
.pub/
build/
# See https://www.dartlang.org/guides/libraries/private-files
# Files and directories created by pub
.dart_tool/
.packages
build/
# If you're building an application, you may want to check-in your pubspec.lock
pubspec.lock
@ -27,3 +23,16 @@ doc/api/
*.js_
*.js.deps
*.js.map
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
android/bin/
android/.project

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>

View File

@ -0,0 +1,13 @@
arguments=
auto.sync=false
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(7.0-rc-1))
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=
java.home=C\:/Program Files/Eclipse Foundation/jdk-11.0.12.7-hotspot
jvm.arguments=
offline.mode=false
override.workspace.settings=true
show.console.view=true
show.executions.view=true

View File

@ -31,7 +31,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61"
}
@ -68,6 +68,7 @@ android {
minSdkVersion 21
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false

View File

@ -1,96 +0,0 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
group 'com.finogeeks.mop'
version '1.0'
buildscript {
repositories {
google()
jcenter()
maven {
url "https://gradle.finogeeks.club/repository/finogeeks/"
credentials {
username "finclip"
password "Abcd@@1234"
}
}
maven {
url "https://gradle.finogeeks.club/repository/applet/"
credentials {
username "finclip"
password "Abcd@@1234"
}
}
maven { url "https://jitpack.io" }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61"
}
}
rootProject.allprojects {
repositories {
google()
jcenter()
maven {
url "https://gradle.finogeeks.club/repository/finogeeks/"
credentials {
username "finclip"
password "Abcd@@1234"
}
}
maven {
url "https://gradle.finogeeks.club/repository/applet/"
credentials {
username "finclip"
password "Abcd@@1234"
}
}
maven { url "https://jitpack.io" }
}
}
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 21
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
disable 'InvalidPackage'
}
}
kapt {
arguments {
arg("moduleName", project.getName())
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.finogeeks.lib:finapplet:__finapplet_version__'
implementation 'com.finogeeks.mop:plugins:__finapplet_version__'
}

View File

@ -1,3 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true

Binary file not shown.

View File

@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip

160
android/gradlew vendored
View File

@ -1,160 +0,0 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
android/gradlew.bat vendored
View File

@ -1,90 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -5,9 +5,9 @@ import java.util.Map;
import io.flutter.plugin.common.EventChannel;
public class MopEventStream implements EventChannel.StreamHandler {
public class MopEventStream implements EventChannel.StreamHandler {
EventChannel.EventSink mEventSlink;
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
mEventSlink = eventSink;
@ -17,12 +17,13 @@ public class MopEventStream implements EventChannel.StreamHandler {
public void onCancel(Object o) {
mEventSlink = null;
}
public void send(String channel,String event,Object body) {
public void send(String channel, String event, Object body) {
if (mEventSlink != null) {
Map<String,Object> map = new HashMap<>();
map.put("channel",channel);
map.put("event",event);
map.put("body",body);
Map<String, Object> map = new HashMap<>();
map.put("channel", channel);
map.put("event", event);
map.put("body", body);
mEventSlink.success(map);
}
}

View File

@ -1,7 +1,9 @@
package com.finogeeks.mop;
import android.app.Activity;
import android.content.Intent;
import android.util.Log;
import androidx.lifecycle.Lifecycle;
import com.finogeeks.mop.interfaces.Event;
import com.finogeeks.mop.interfaces.FlutterInterface;
@ -11,6 +13,10 @@ import com.finogeeks.mop.service.MopPluginService;
import java.util.HashMap;
import java.util.Map;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.embedding.engine.plugins.lifecycle.FlutterLifecycleAdapter;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
@ -22,78 +28,125 @@ import io.flutter.plugin.common.PluginRegistry.Registrar;
/**
* MopPlugin
*/
public class MopPlugin implements MethodCallHandler {
private static final String LOG_TAG = MopPlugin.class.getSimpleName();
public class MopPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
private static final String LOG_TAG = MopPlugin.class.getSimpleName();
private static final String CHANNEL = "mop";
private PluginRegistry.Registrar registrar;
private FlutterInterface flutterInterface;
private MopPluginDelegate delegate;
private static final String CHANNEL = "mop";
private static final String EVENT_CHANNEL = "plugins.mop.finogeeks.com/mop_event";
private final FlutterInterface flutterInterface = new FlutterInterface();
private final MopPluginDelegate delegate = new MopPluginDelegate();
private final MopEventStream mopEventStream = new MopEventStream();
/**
* Plugin registration.
*/
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL);
final MopPluginDelegate delegate = new MopPluginDelegate(registrar.activity());
final MopPlugin instance = new MopPlugin(registrar, delegate);
channel.setMethodCallHandler(instance);
final EventChannel eventChannel = new EventChannel(registrar.messenger(), "plugins.mop.finogeeks.com/mop_event");
MopEventStream mopEventStream = new MopEventStream();
eventChannel.setStreamHandler(mopEventStream);
MopPluginService.getInstance().initialize(registrar.activity(), mopEventStream, channel);
// These are null when not using v2 embedding.
private FlutterPluginBinding flutterPluginBinding;
private MethodChannel channel;
private EventChannel eventChannel;
private Lifecycle lifecycle;
}
/**
* Plugin registration.
*/
@SuppressWarnings("deprecation")
public static void registerWith(Registrar registrar) {
MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL);
MopPluginDelegate delegate = new MopPluginDelegate();
final MopPlugin plugin = new MopPlugin();
channel.setMethodCallHandler(plugin);
registrar.addActivityResultListener(delegate);
MopPlugin(PluginRegistry.Registrar registrar, MopPluginDelegate delegate) {
this.registrar = registrar;
this.flutterInterface = new FlutterInterface();
this.delegate = delegate;
}
EventChannel eventChannel = new EventChannel(registrar.messenger(), EVENT_CHANNEL);
final MopEventStream mopEventStream = new MopEventStream();
eventChannel.setStreamHandler(mopEventStream);
MopPluginService.getInstance().initialize(registrar.activity(), mopEventStream, channel);
}
@Override
public void onMethodCall(MethodCall call, final Result result) {
registrar.addActivityResultListener(delegate);
ICallback callback = new ICallback<Object>() {
@Override
public void onSuccess(Object data) {
Map<String, Object> obj = new HashMap<String, Object>();
@Override
public void onMethodCall(MethodCall call, final Result result) {
ICallback callback = new ICallback<Object>() {
@Override
public void onSuccess(Object data) {
Map<String, Object> obj = new HashMap<String, Object>();
obj.put("success", true);
if (data != null)
obj.put("data", data);
obj.put("retMsg", "ok");
result.success(obj);
}
obj.put("success", true);
if (data != null)
obj.put("data", data);
obj.put("retMsg", "ok");
result.success(obj);
}
@Override
public void onFail(Object error) {
Map<String, Object> obj = new HashMap<String, Object>();
obj.put("success", false);
obj.put("retMsg", error == null ? "" : error);
result.success(obj);
}
@Override
public void onFail(Object error) {
Map<String, Object> obj = new HashMap<String, Object>();
obj.put("success", false);
obj.put("retMsg", error == null ? "" : error);
result.success(obj);
}
@Override
public void onCancel(Object cancel) {
result.notImplemented();
}
@Override
public void onCancel(Object cancel) {
result.notImplemented();
}
@Override
public void startActivityForResult(Intent intent, int requestCode) {
@Override
public void startActivityForResult(Intent intent, int requestCode) {
}
};
Log.d(LOG_TAG, "mopplugin: invoke " + call.method);
Event event = new Event(call.method, call.arguments, callback);
delegate.setEvent(event);
this.flutterInterface.invokeHandler(event);
// if (call.method.equals("getPlatformVersion")) {
// result.success("Android " + android.os.Build.VERSION.RELEASE);
// } else {
// result.notImplemented();
// }
}
}
};
Log.d(LOG_TAG, "mopplugin: invoke " + call.method);
Event event = new Event(call.method, call.arguments, callback);
delegate.setEvent(event);
this.flutterInterface.invokeHandler(event);
// if (call.method.equals("getPlatformVersion")) {
// result.success("Android " + android.os.Build.VERSION.RELEASE);
// } else {
// result.notImplemented();
// }
}
@Override
public void onAttachedToEngine(FlutterPluginBinding binding) {
this.flutterPluginBinding = binding;
channel = new MethodChannel(binding.getFlutterEngine().getDartExecutor(), CHANNEL);
channel.setMethodCallHandler(this);
EventChannel eventChannel = new EventChannel(binding.getFlutterEngine().getDartExecutor(), EVENT_CHANNEL);
eventChannel.setStreamHandler(mopEventStream);
}
@Override
public void onDetachedFromEngine(FlutterPluginBinding binding) {
this.flutterPluginBinding = null;
}
@Override
public void onAttachedToActivity(ActivityPluginBinding binding) {
binding.addActivityResultListener(delegate);
lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding);
setServicesFromActivity(binding.getActivity());
channel.setMethodCallHandler(this);
}
@Override
public void onDetachedFromActivityForConfigChanges() {
lifecycle = null;
}
@Override
public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
binding.addActivityResultListener(delegate);
lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding);
setServicesFromActivity(binding.getActivity());
}
@Override
public void onDetachedFromActivity() {
lifecycle = null;
channel.setMethodCallHandler(null);
}
private void setServicesFromActivity(Activity activity) {
if (activity == null)
return;
MopPluginService.getInstance().initialize(activity, mopEventStream, channel);
}
}

View File

@ -9,11 +9,8 @@ import com.finogeeks.mop.service.MopPluginService;
import io.flutter.plugin.common.PluginRegistry;
public class MopPluginDelegate implements PluginRegistry.ActivityResultListener {
private Event mEvent;
private final Activity activity;
public Event getEvent() {
return mEvent;
@ -23,16 +20,11 @@ public class MopPluginDelegate implements PluginRegistry.ActivityResultListener
this.mEvent = event;
}
public MopPluginDelegate(final Activity activity) {
this.activity = activity;
}
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == Constants.REQUEST_CODE_CHOOSE
|| requestCode == Constants.REQUEST_CODE_LOCATION_CHOOSE
) {
MopPluginService.getInstance().getApisManager().getApiInstance(mEvent).onActivityResult(requestCode, resultCode, data, mEvent.getCallback());
if (requestCode == Constants.REQUEST_CODE_CHOOSE || requestCode == Constants.REQUEST_CODE_LOCATION_CHOOSE) {
MopPluginService.getInstance().getApisManager().getApiInstance(mEvent).onActivityResult(requestCode,
resultCode, data, mEvent.getCallback());
}
return true;
}

View File

@ -1,11 +1,20 @@
package com.finogeeks.mop.api.mop;
import android.content.Context;
import android.util.Log;
import com.finogeeks.lib.applet.anim.FadeInAnim;
import com.finogeeks.lib.applet.anim.NoneAnim;
import com.finogeeks.lib.applet.anim.SlideFromBottomToTopAnim;
import com.finogeeks.lib.applet.anim.SlideFromLeftToRightAnim;
import com.finogeeks.lib.applet.anim.SlideFromRightToLeftAnim;
import com.finogeeks.lib.applet.anim.SlideFromTopToBottomAnim;
import com.finogeeks.lib.applet.client.FinAppClient;
import com.finogeeks.lib.applet.db.entity.FinApplet;
import com.finogeeks.lib.applet.interfaces.FinCallback;
import com.finogeeks.mop.api.BaseApi;
import com.finogeeks.mop.interfaces.ICallback;
import com.google.gson.Gson;
import java.util.HashMap;
import java.util.Map;
@ -13,13 +22,16 @@ import java.util.Map;
public class AppletManageModule extends BaseApi {
private static final String TAG = "AppletManageModule";
public AppletManageModule(Context context) {
super(context);
}
@Override
public String[] apis() {
return new String[]{"currentApplet", "closeAllApplets", "clearApplets", "removeUsedApplet"};
return new String[]{"currentApplet", "closeAllApplets", "clearApplets", "removeUsedApplet",
"setActivityTransitionAnim", "sendCustomEvent", "callJS"};
}
@Override
@ -57,6 +69,70 @@ public class AppletManageModule extends BaseApi {
} else {
callback.onFail(null);
}
} else if (event.equals("setActivityTransitionAnim")) {
String anim = (String) param.get("anim");
Log.d(TAG, "setActivityTransitionAnim:" + anim);
if ("SlideFromLeftToRightAnim".equals(anim)) {
FinAppClient.INSTANCE.getAppletApiManager().setActivityTransitionAnim(SlideFromLeftToRightAnim.INSTANCE);
} else if ("SlideFromRightToLeftAnim".equals(anim)) {
FinAppClient.INSTANCE.getAppletApiManager().setActivityTransitionAnim(SlideFromRightToLeftAnim.INSTANCE);
} else if ("SlideFromTopToBottomAnim".equals(anim)) {
FinAppClient.INSTANCE.getAppletApiManager().setActivityTransitionAnim(SlideFromTopToBottomAnim.INSTANCE);
} else if ("SlideFromBottomToTopAnim".equals(anim)) {
FinAppClient.INSTANCE.getAppletApiManager().setActivityTransitionAnim(SlideFromBottomToTopAnim.INSTANCE);
} else if ("FadeInAnim".equals(anim)) {
FinAppClient.INSTANCE.getAppletApiManager().setActivityTransitionAnim(FadeInAnim.INSTANCE);
} else if ("NoneAnim".equals(anim)) {
FinAppClient.INSTANCE.getAppletApiManager().setActivityTransitionAnim(NoneAnim.INSTANCE);
}
callback.onSuccess(null);
} else if (event.equals("sendCustomEvent")) {
String appId = (String) param.get("appId");
Map eventData = (Map) param.get("eventData");
Log.d(TAG, "sendCustomEvent:" + appId);
if (appId != null) {
FinAppClient.INSTANCE.getAppletApiManager().sendCustomEvent(appId, eventData == null ? "" : new Gson().toJson(eventData));
callback.onSuccess(null);
} else {
callback.onFail(null);
}
} else if (event.equals("callJS")) {
String appId = (String) param.get("appId");
String eventName = (String) param.get("eventName");
String nativeViewId = (String) param.get("nativeViewId");
int viewId = 0;
if (nativeViewId != null && !nativeViewId.equals("")) {
try {
viewId = Integer.parseInt(nativeViewId);
} catch (Exception e) {
e.printStackTrace();
}
}
Map eventData = (Map) param.get("eventData");
Log.d(TAG, "callJS:" + appId);
if (appId != null && eventName != null) {
FinAppClient.INSTANCE.getAppletApiManager().callJS(appId, eventName, eventData == null ? "" : new Gson().toJson(eventData),
viewId, new FinCallback<String>() {
@Override
public void onSuccess(String s) {
Map<String, Object> res = new HashMap<>();
res.put("data", s);
callback.onSuccess(res);
}
@Override
public void onError(int i, String s) {
callback.onFail(null);
}
@Override
public void onProgress(int i, String s) {
}
});
} else {
callback.onFail(null);
}
}
}
}

View File

@ -6,6 +6,7 @@ import android.util.Log;
import com.finogeeks.lib.applet.client.FinAppClient;
import com.finogeeks.lib.applet.interfaces.FinCallback;
import com.finogeeks.lib.applet.client.FinAppInfo;
import com.finogeeks.lib.applet.sdk.model.StartAppletDecryptRequest;
import com.finogeeks.mop.api.BaseApi;
import com.finogeeks.mop.interfaces.ICallback;
@ -56,19 +57,20 @@ public class AppletModule extends BaseApi {
String appId = String.valueOf(param.get("appId"));
Integer sequence = (Integer) param.get("sequence");
Map<String, String> params = (Map) param.get("params");
String apiServer = (String) param.get("apiServer");
// mContextFlutterActivity
// Android 6.07.0contextmContext
// 使Application Context
Context context = mContext.getApplicationContext();
if (params == null) {
if (sequence == null) {
FinAppClient.INSTANCE.getAppletApiManager().startApplet(context, appId);
} else {
FinAppClient.INSTANCE.getAppletApiManager().startApplet(context, appId, sequence, null);
}
FinAppInfo.StartParams startParams = params == null ? null : new FinAppInfo.StartParams(params.get("path"), params.get("query"), params.get("scene"));
Log.d(TAG, "openApplet:" + appId + "," + param + "," + sequence + "," + apiServer);
if (apiServer != null) {
FinAppClient.INSTANCE.getAppletApiManager().startApplet(context, apiServer, appId, sequence, startParams);
} else {
FinAppClient.INSTANCE.getAppletApiManager().startApplet(context, appId, params);
FinAppClient.INSTANCE.getAppletApiManager().startApplet(context, appId, sequence, startParams);
}
// String apiServer = (String) param.get("apiServer");
// String apiPrefix = (String) param.get("apiPrefix");
// if (apiServer == null || apiServer.isEmpty() || apiPrefix == null || apiPrefix.isEmpty()) {

View File

@ -2,6 +2,7 @@ package com.finogeeks.mop.api.mop;
import android.app.Application;
import android.content.Context;
import android.util.Log;
import com.finogeeks.lib.applet.BuildConfig;
import com.finogeeks.lib.applet.client.FinAppClient;
@ -11,6 +12,8 @@ import com.finogeeks.lib.applet.interfaces.FinCallback;
import com.finogeeks.mop.api.BaseApi;
import com.finogeeks.mop.interfaces.ICallback;
import com.finogeeks.mop.service.MopPluginService;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.util.ArrayList;
import java.util.List;
@ -74,7 +77,22 @@ public class BaseModule extends BaseApi {
Boolean bindAppletWithMainProcess = (Boolean) param.get("bindAppletWithMainProcess");
if (bindAppletWithMainProcess == null) bindAppletWithMainProcess = false;
FinAppConfig config = new FinAppConfig.Builder()
String customWebViewUserAgent = (String) param.get("customWebViewUserAgent");
Integer appletIntervalUpdateLimit = (Integer) param.get("appletIntervalUpdateLimit");
Integer maxRunningApplet = (Integer) param.get("maxRunningApplet");
Gson gson = new Gson();
List<FinStoreConfig> finStoreConfigs = null;
if (param.get("finStoreConfigs") != null) {
finStoreConfigs = gson.fromJson(gson.toJson(param.get("finStoreConfigs")), new TypeToken<List<FinStoreConfig>>() {
}.getType());
}
FinAppConfig.UIConfig uiConfig = null;
if (param.get("uiConfig") != null) {
uiConfig = gson.fromJson(gson.toJson(param.get("uiConfig")), FinAppConfig.UIConfig.class);
}
FinAppConfig.Builder builder = new FinAppConfig.Builder()
.setSdkKey(appkey)
.setSdkSecret(secret)
.setApiUrl(apiServer)
@ -84,8 +102,18 @@ public class BaseModule extends BaseApi {
.setUserId(userId)
.setDebugMode(debug)
.setDisableRequestPermissions(disablePermission)
.setBindAppletWithMainProcess(bindAppletWithMainProcess)
.build();
.setBindAppletWithMainProcess(bindAppletWithMainProcess);
if (customWebViewUserAgent != null)
builder.setCustomWebViewUserAgent(customWebViewUserAgent);
if (appletIntervalUpdateLimit != null)
builder.setAppletIntervalUpdateLimit(appletIntervalUpdateLimit);
if (maxRunningApplet != null) builder.setMaxRunningApplet(maxRunningApplet);
if (finStoreConfigs != null) builder.setFinStoreConfigs(finStoreConfigs);
if (uiConfig != null) builder.setUiConfig(uiConfig);
FinAppConfig config = builder.build();
Log.d(TAG, "config:" + gson.toJson(config));
final Application application = MopPluginService.getInstance().getActivity().getApplication();
// SDKSDK

View File

@ -33,66 +33,126 @@ public class ExtensionApiModule extends BaseApi {
@Override
public String[] apis() {
return new String[]{"registerExtensionApi"};
return new String[]{"registerExtensionApi","addWebExtentionApi"};
}
@Override
public void invoke(String s, Map param, ICallback iCallback) {
MethodChannel channel = MopPluginService.getInstance().getMethodChannel();
String name = (String) param.get("name");
FinAppClient.INSTANCE.getExtensionApiManager().registerApi(new com.finogeeks.lib.applet.api.BaseApi(getContext()) {
@Override
public String[] apis() {
return new String[]{name};
}
if(s.equals("registerExtensionApi")) {
MethodChannel channel = MopPluginService.getInstance().getMethodChannel();
String name = (String) param.get("name");
Log.d(TAG, "registerExtensionApi:" + name);
FinAppClient.INSTANCE.getExtensionApiManager().registerApi(new com.finogeeks.lib.applet.api.BaseApi(getContext()) {
@Override
public String[] apis() {
return new String[]{name};
}
@Override
public void invoke(String s, JSONObject jsonObject, com.finogeeks.lib.applet.interfaces.ICallback iCallback) {
Log.d("MopPlugin", "invoke extensionApi:" + s + ",params:" + jsonObject);
Map params = GsonUtil.gson.fromJson(jsonObject.toString(), HashMap.class);
handler.post(() -> {
channel.invokeMethod("extensionApi:" + name, params, new MethodChannel.Result() {
@Override
public void success(Object result) {
String json = GsonUtil.gson.toJson(result);
FinAppTrace.d(ExtensionApiModule.TAG, "channel invokeMethod:" + name
+ " success, result=" + result + ", json=" + json);
JSONObject ret = null;
if (json != null && !json.equals("null")) {
try {
ret = new JSONObject(json);
if (ret.has("errMsg")) {
String errMsg = ret.getString("errMsg");
if (errMsg.startsWith(name + ":fail")) {
iCallback.onFail(ret);
return;
@Override
public void invoke(String s, JSONObject jsonObject, com.finogeeks.lib.applet.interfaces.ICallback iCallback) {
Log.d("MopPlugin", "invoke extensionApi:" + s + ",params:" + jsonObject);
Map params = GsonUtil.gson.fromJson(jsonObject.toString(), HashMap.class);
handler.post(() -> {
channel.invokeMethod("extensionApi:" + name, params, new MethodChannel.Result() {
@Override
public void success(Object result) {
String json = GsonUtil.gson.toJson(result);
FinAppTrace.d(ExtensionApiModule.TAG, "channel invokeMethod:" + name
+ " success, result=" + result + ", json=" + json);
JSONObject ret = null;
if (json != null && !json.equals("null")) {
try {
ret = new JSONObject(json);
if (ret.has("errMsg")) {
String errMsg = ret.getString("errMsg");
if (errMsg.startsWith(name + ":fail")) {
iCallback.onFail(ret);
return;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
} catch (JSONException e) {
e.printStackTrace();
}
iCallback.onSuccess(ret);
}
iCallback.onSuccess(ret);
}
@Override
public void error(String errorCode, String errorMessage, Object errorDetails) {
FinAppTrace.e(ExtensionApiModule.TAG, "channel invokeMethod:" + name
+ " error, errorCode=" + errorCode
+ ", errorMessage=" + errorMessage
+ ", errorDetails=" + errorDetails);
iCallback.onFail();
}
@Override
public void error(String errorCode, String errorMessage, Object errorDetails) {
FinAppTrace.e(ExtensionApiModule.TAG, "channel invokeMethod:" + name
+ " error, errorCode=" + errorCode
+ ", errorMessage=" + errorMessage
+ ", errorDetails=" + errorDetails);
iCallback.onFail();
}
@Override
public void notImplemented() {
iCallback.onFail();
}
@Override
public void notImplemented() {
iCallback.onFail();
}
});
});
});
}
});
}
});
}else if(s.equals("addWebExtentionApi")){
MethodChannel channel = MopPluginService.getInstance().getMethodChannel();
String name = (String) param.get("name");
Log.d(TAG, "addWebExtentionApi:" + name);
FinAppClient.INSTANCE.getExtensionWebApiManager().registerApi(new com.finogeeks.lib.applet.api.BaseApi(getContext()) {
@Override
public String[] apis() {
return new String[]{name};
}
@Override
public void invoke(String s, JSONObject jsonObject, com.finogeeks.lib.applet.interfaces.ICallback iCallback) {
Log.d("MopPlugin", "invoke webextensionApi:" + s + ",params:" + jsonObject);
Map params = GsonUtil.gson.fromJson(jsonObject.toString(), HashMap.class);
handler.post(() -> {
channel.invokeMethod("webExtentionApi:" + name, params, new MethodChannel.Result() {
@Override
public void success(Object result) {
String json = GsonUtil.gson.toJson(result);
FinAppTrace.d(ExtensionApiModule.TAG, "channel invokeMethod:" + name
+ " success, result=" + result + ", json=" + json);
JSONObject ret = null;
if (json != null && !json.equals("null")) {
try {
ret = new JSONObject(json);
if (ret.has("errMsg")) {
String errMsg = ret.getString("errMsg");
if (errMsg.startsWith(name + ":fail")) {
iCallback.onFail(ret);
return;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
iCallback.onSuccess(ret);
}
@Override
public void error(String errorCode, String errorMessage, Object errorDetails) {
FinAppTrace.e(ExtensionApiModule.TAG, "channel invokeMethod:" + name
+ " error, errorCode=" + errorCode
+ ", errorMessage=" + errorMessage
+ ", errorDetails=" + errorDetails);
iCallback.onFail();
}
@Override
public void notImplemented() {
iCallback.onFail();
}
});
});
}
});
}
}
}

View File

@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"mop","path":"/Users/haley/Documents/Finogeeks/Gitlab/finclip-flutter-sdk/","dependencies":[]}],"android":[{"name":"mop","path":"/Users/haley/Documents/Finogeeks/Gitlab/finclip-flutter-sdk/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"mop","dependencies":[]}],"date_created":"2022-01-06 18:17:11.770441","version":"2.3.0-1.0.pre.169"}
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"mop","path":"/Users/kangxuyao/StudioProjects/finclip-flutter-sdk/","dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"/Users/kangxuyao/.pub-cache/hosted/pub.flutter-io.cn/flutter_plugin_android_lifecycle-2.0.5/","dependencies":[]},{"name":"mop","path":"/Users/kangxuyao/StudioProjects/finclip-flutter-sdk/","dependencies":["flutter_plugin_android_lifecycle"]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"mop","dependencies":["flutter_plugin_android_lifecycle"]}],"date_created":"2022-01-04 13:47:58.706248","version":"2.6.0-12.0.pre.553"}

53
example/.gitignore vendored
View File

@ -22,52 +22,25 @@
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
# Web related
lib/generated_plugin_registrant.dart
# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/Flutter/flutter_export_environment.sh
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
# Symbolication related
app.*.symbols
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release

View File

@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.
version:
revision: 1aedbb1835bd6eb44550293d57d4d124f19901f0
revision: ffb2ecea5223acdd139a5039be2f9c796962833d
channel: stable
project_type: app

View File

@ -0,0 +1,29 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

13
example/android/.gitignore vendored 100644
View File

@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>android</name>
<comment>Project android created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1633860434667</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

View File

@ -0,0 +1,13 @@
arguments=
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=C\:/Program Files/Eclipse Foundation/jdk-11.0.12.7-hotspot
jvm.arguments=
offline.mode=false
override.workspace.settings=true
show.console.view=true
show.executions.view=true

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>app</name>
<comment>Project app created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1633860434672</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

View File

@ -0,0 +1,2 @@
connection.project.dir=..
eclipse.preferences.version=1

View File

@ -25,20 +25,20 @@ apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 28
compileSdkVersion 30
lintOptions {
disable 'InvalidPackage'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.finogeeks.mopexample"
applicationId "com.finogeeks.mop_example"
minSdkVersion 21
targetSdkVersion 28
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@ -48,22 +48,8 @@ android {
signingConfig signingConfigs.debug
}
}
packagingOptions {
// libsdkcore.so
doNotStrip "*/x86/libsdkcore.so"
doNotStrip "*/x86_64/libsdkcore.so"
doNotStrip "*/armeabi-v7a/libsdkcore.so"
doNotStrip "*/arm64-v8a/libsdkcore.so"
}
}
flutter {
source '../..'
}
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
}

View File

@ -1,7 +0,0 @@
/*___Generated_by_IDEA___*/
package com.finogeeks.mop_example;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -1,7 +0,0 @@
/*___Generated_by_IDEA___*/
package com.finogeeks.mop_example;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -1,33 +1,41 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.finogeeks.mop_example">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
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
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
<application
android:label="mop_example"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<!-- <meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/> -->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>

View File

@ -1,7 +0,0 @@
/*___Generated_by_IDEA___*/
package com.finogeeks.mop_example;
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
public final class Manifest {
}

View File

@ -1,7 +0,0 @@
/*___Generated_by_IDEA___*/
package com.finogeeks.mop_example;
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
public final class R {
}

View File

@ -1,16 +1,6 @@
package com.finogeeks.mop_example;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -1,8 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -1,12 +1,11 @@
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.4'
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61"
}
}
@ -14,15 +13,13 @@ buildscript {
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}

View File

@ -1,5 +1,3 @@
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip

View File

@ -1,5 +0,0 @@
-keep class com.finogeeks.** {*;}
# tbs
-keep class com.tencent.smtt.** {*;}
-keep class com.tencent.tbs.** {*;}

View File

@ -1,15 +1,11 @@
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"

33
example/ios/.gitignore vendored 100644
View File

@ -0,0 +1,33 @@
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3

View File

@ -1 +0,0 @@
9b8dc99cc1898757c03a06b2261ab8de

View File

@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
<string>9.0</string>
</dict>
</plist>

View File

@ -1,2 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@ -1,18 +0,0 @@
#
# NOTE: This podspec is NOT to be published. It is only used as a local source!
#
Pod::Spec.new do |s|
s.name = 'Flutter'
s.version = '1.0.0'
s.summary = 'High-performance, high-fidelity mobile apps.'
s.description = <<-DESC
Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
DESC
s.homepage = 'https://flutter.io'
s.license = { :type => 'MIT' }
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.vendored_frameworks = 'Flutter.framework'
end

View File

@ -1,2 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

View File

@ -1,8 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
source 'https://git.finogeeks.club/finoapp-ios/FinPods'
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@ -13,63 +10,40 @@ project 'Runner', {
'Release' => :release,
}
def parse_KV_file(file, separator='=')
file_abs_path = File.expand_path(file)
if !File.exists? file_abs_path
return [];
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
pods_ary = []
skip_line_start_symbols = ["#", "/"]
File.foreach(file_abs_path) { |line|
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
plugin = line.split(pattern=separator)
if plugin.length == 2
podname = plugin[0].strip()
path = plugin[1].strip()
podpath = File.expand_path("#{path}", file_abs_path)
pods_ary.push({:name => podname, :path => podpath});
else
puts "Invalid plugin specification: #{line}"
end
}
return pods_ary
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
# referring to absolute paths on developers' machines.
system('rm -rf .symlinks')
system('mkdir -p .symlinks/plugins')
use_frameworks!
use_modular_headers!
# Flutter Pods
generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
if generated_xcode_build_settings.empty?
puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first."
end
generated_xcode_build_settings.map { |p|
if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
symlink = File.join('.symlinks', 'flutter')
File.symlink(File.dirname(p[:path]), symlink)
pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
end
}
# Plugin Pods
plugin_pods = parse_KV_file('../.flutter-plugins')
plugin_pods.map { |p|
symlink = File.join('.symlinks', 'plugins', p[:name])
File.symlink(p[:path], symlink)
pod p[:name], :path => File.join(symlink, 'ios')
}
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
install! 'cocoapods', :disable_input_output_paths => true
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
if config.name == "Debug"
config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES'
else
config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO'
end
end
end
end

View File

@ -1,3 +1,34 @@
PODFILE CHECKSUM: fa591ea0d89752dd0191ae3f82c83db034678e82
PODS:
- FinApplet (2.34.11)
- FinAppletExt (2.34.11):
- FinApplet (= 2.34.11)
- Flutter (1.0.0)
- mop (0.1.1):
- FinApplet (= 2.34.11)
- FinAppletExt (= 2.34.11)
- Flutter
COCOAPODS: 1.10.1
DEPENDENCIES:
- Flutter (from `Flutter`)
- mop (from `.symlinks/plugins/mop/ios`)
SPEC REPOS:
trunk:
- FinApplet
- FinAppletExt
EXTERNAL SOURCES:
Flutter:
:path: Flutter
mop:
:path: ".symlinks/plugins/mop/ios"
SPEC CHECKSUMS:
FinApplet: 975a76c8de4c9ddf64d6b4bfcd946ad6830f54f6
FinAppletExt: 9489276a84f908b60a75a71d09b0b4397e070bee
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
mop: 9a49a0b917e4016aa897c76656fddb69ad69b118
PODFILE CHECKSUM: 2317ba7584871ae8cd67fd0244fbd5e96fd06167
COCOAPODS: 1.11.2

View File

@ -3,19 +3,17 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
6DB2EFFFC5FD4690C06ACB3A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B691CF78BE1464D3451E07AF /* Pods_Runner.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
AF7B8F29E858B4266D8A8AD0 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ABAEB264A095769DC71DEAE1 /* libPods-Runner.a */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -32,24 +30,23 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
073CDBAAF19B6FF1EF196501 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
207F05A0BE4F11BA62008DCF /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
4F9256BFB604D1207B06C14E /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
6793BBA3F03EE46BEAD75979 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
865E64E9FAB2F680272FCE6F /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
ABAEB264A095769DC71DEAE1 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
B62C1456907598F7FC4CC93E /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
B691CF78BE1464D3451E07AF /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -57,17 +54,27 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
AF7B8F29E858B4266D8A8AD0 /* libPods-Runner.a in Frameworks */,
6DB2EFFFC5FD4690C06ACB3A /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
43950FB4B3EA29B9EA2BA804 /* Frameworks */ = {
1B5EB5EC57E12758D2A6310E /* Pods */ = {
isa = PBXGroup;
children = (
ABAEB264A095769DC71DEAE1 /* libPods-Runner.a */,
6793BBA3F03EE46BEAD75979 /* Pods-Runner.debug.xcconfig */,
207F05A0BE4F11BA62008DCF /* Pods-Runner.release.xcconfig */,
865E64E9FAB2F680272FCE6F /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
8C9832689000ED580600B3AE /* Frameworks */ = {
isa = PBXGroup;
children = (
B691CF78BE1464D3451E07AF /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -89,8 +96,8 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
9A4E54748C7B614766AAD771 /* Pods */,
43950FB4B3EA29B9EA2BA804 /* Frameworks */,
1B5EB5EC57E12758D2A6310E /* Pods */,
8C9832689000ED580600B3AE /* Frameworks */,
);
sourceTree = "<group>";
};
@ -105,37 +112,18 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
97C146F11CF9000F007C117D /* Supporting Files */ = {
isa = PBXGroup;
children = (
97C146F21CF9000F007C117D /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
9A4E54748C7B614766AAD771 /* Pods */ = {
isa = PBXGroup;
children = (
073CDBAAF19B6FF1EF196501 /* Pods-Runner.debug.xcconfig */,
4F9256BFB604D1207B06C14E /* Pods-Runner.release.xcconfig */,
B62C1456907598F7FC4CC93E /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -143,13 +131,14 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
BC8240216498EB68CEE5D926 /* [CP] Check Pods Manifest.lock */,
2DEACE28B1DB5888C31A623A /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
46BA5F59FC1A40CE8339661F /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -166,17 +155,17 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = "The Chromium Authors";
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = H48LA2V876;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
@ -200,7 +189,6 @@
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
@ -209,35 +197,7 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
BC8240216498EB68CEE5D926 /* [CP] Check Pods Manifest.lock */ = {
2DEACE28B1DB5888C31A623A /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -259,6 +219,51 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
46BA5F59FC1A40CE8339661F /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -266,8 +271,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
97C146F31CF9000F007C117D /* main.m in Sources */,
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -338,6 +342,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@ -348,23 +353,18 @@
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = H48LA2V876;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.finogeeks.mopexample;
PRODUCT_BUNDLE_IDENTIFIER = com.finogeeks.finclip.demo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
@ -468,6 +468,8 @@
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@ -478,23 +480,19 @@
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = H48LA2V876;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.finogeeks.mopexample;
PRODUCT_BUNDLE_IDENTIFIER = com.finogeeks.finclip.demo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
@ -504,23 +502,18 @@
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = H48LA2V876;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.finogeeks.mopexample;
PRODUCT_BUNDLE_IDENTIFIER = com.finogeeks.finclip.demo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -1,6 +0,0 @@
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : FlutterAppDelegate
@end

View File

@ -1,13 +0,0 @@
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end

View File

@ -0,0 +1,13 @@
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

View File

@ -15,11 +15,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>

View File

@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"

View File

@ -1,9 +0,0 @@
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

View File

@ -1,3 +1,7 @@
// ignore_for_file: prefer_const_constructors
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io';
@ -19,20 +23,120 @@ class _MyAppState extends State<MyApp> {
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> init() async {
UIConfig uiconfig = UIConfig();
//
FinStoreConfig storeConfigA = FinStoreConfig(
"2LyZEib0gLTQdU3MUauATBwgfnTCJjdr7FCnywmAEM=",
"bdfd76cae24d4313",
"https://api.finclip.com",
"https://api.finclip.com",
);
FinStoreConfig storeConfigB = FinStoreConfig(
"2LyZEib0gLTQdU3MUauATBwgfnTCJjdr7FCnywmAEM=",
"bdfd76cae24d4313",
"https://finchat-mop-b.finogeeks.club",
"https://finchat-mop-b.finogeeks.club",
);
List<FinStoreConfig> storeConfigs = [storeConfigA];
uiconfig.isAlwaysShowBackInDefaultNavigationBar = false;
uiconfig.isClearNavigationBarNavButtonBackground = false;
uiconfig.isHideFeedbackAndComplaints = true;
uiconfig.isHideBackHome = true;
uiconfig.isHideForwardMenu = true;
uiconfig.hideTransitionCloseButton = true;
uiconfig.disableSlideCloseAppletGesture = true;
CapsuleConfig capsuleConfig = CapsuleConfig();
capsuleConfig.capsuleBgLightColor = 0x33ff00ee;
capsuleConfig.capsuleRightMargin = 25;
uiconfig.capsuleConfig = capsuleConfig;
uiconfig.appletText = "applet";
if (Platform.isIOS) {
final res = await Mop.instance.initialize(
'22LyZEib0gLTQdU3MUauAZ0pZVbKTWGmNN6Lx8hXhIkA', '74bde5fad53a817c',
apiServer: 'https://api.finclip.com', apiPrefix: '/api/v1/mop');
'22LyZEib0gLTQdU3MUauATBwgfnTCJjdr7FCnywmAEM=', 'bdfd76cae24d4313',
apiServer: 'https://api.finclip.com',
apiPrefix: '/api/v1/mop',
uiConfig: uiconfig,
finStoreConfigs: storeConfigs);
print(res);
} else if (Platform.isAndroid) {
final res = await Mop.instance.initialize(
'22LyZEib0gLTQdU3MUauAZ0pZVbKTWGmNN6Lx8hXhIkA', '74bde5fad53a817c',
'22LyZEib0gLTQdU3MUauATBwgfnTCJjdr7FCnywmAEM=', 'bdfd76cae24d4313',
apiServer: 'https://api.finclip.com', apiPrefix: '/api/v1/mop');
print(res);
}
if (!mounted) return;
}
Widget _buildAppletItem(
String appletId, String itemName, VoidCallback tapAction) {
return GestureDetector(
onTap: tapAction,
child: Container(
padding: EdgeInsets.only(left: 7, right: 7),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
gradient: LinearGradient(
colors: const [Color(0xFF12767e), Color(0xFF0dabb8)],
stops: const [0.0, 1.0],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: Center(
child: Text(
itemName,
style: TextStyle(color: Colors.white),
),
),
),
);
}
Widget _buildAppletWidget(String appletId, String appletName) {
return Container(
margin: EdgeInsets.only(left: 20, top: 30, right: 20),
child: Column(
children: [
Text(
appletName,
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.w500, color: Colors.red),
),
SizedBox(
height: 10,
),
Container(
height: 100,
child: GridView.count(
crossAxisCount: 3,
childAspectRatio: 2,
crossAxisSpacing: 30,
// physics: NeverScrollableScrollPhysics(),
children: [
_buildAppletItem(appletId, "打开小程序", () {
Mop.instance.openApplet(appletId,
path: 'pages/index/index', query: '');
}),
_buildAppletItem(appletId, "finishRunningApplet", () {
Mop.instance.finishRunningApplet(appletId, true);
}),
_buildAppletItem(appletId, "removeUsedApplet", () {
Mop.instance.removeUsedApplet(appletId);
}),
// _buildAppletItem(appletId, "removeUsedApplet", () {
// Mop.instance.removeUsedApplet(appletId);
// }),
],
),
)
],
),
);
}
// 5e637a18cbfae4000170fa7a
@override
Widget build(BuildContext context) {
@ -41,82 +145,12 @@ class _MyAppState extends State<MyApp> {
appBar: AppBar(
title: const Text('凡泰极客小程序 Flutter 插件'),
),
body: Center(
child: Container(
padding: EdgeInsets.only(
top: 20,
),
child: Column(
children: <Widget>[
Container(
width: 140,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
gradient: LinearGradient(
colors: const [Color(0xFF12767e), Color(0xFF0dabb8)],
stops: const [0.0, 1.0],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: FlatButton(
onPressed: () {
Mop.instance.openApplet('5ea03fa563cb900001d73863',
path: 'pages/index/index', query: '');
},
child: Text(
'打开画图小程序',
style: TextStyle(color: Colors.white),
),
),
),
SizedBox(height: 30),
Container(
width: 140,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
gradient: LinearGradient(
colors: const [Color(0xFF12767e), Color(0xFF0dabb8)],
stops: const [0.0, 1.0],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: FlatButton(
onPressed: () {
Mop.instance.openApplet('5ea0401463cb900001d73865');
},
child: Text(
'打开官方小程序',
style: TextStyle(color: Colors.white),
),
),
),
SizedBox(height: 30),
Container(
width: 140,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
gradient: LinearGradient(
colors: const [Color(0xFF12767e), Color(0xFF0dabb8)],
stops: const [0.0, 1.0],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: FlatButton(
onPressed: () {
Mop.instance.openApplet('5ea0412663cb900001d73867');
},
child: Text(
'我的对账单',
style: TextStyle(color: Colors.white),
),
),
),
],
),
),
body: Column(
children: <Widget>[
_buildAppletWidget("5facb3a52dcbff00017469bd", "画图小程序"),
_buildAppletWidget("5fa214a29a6a7900019b5cc1", "官方小程序"),
_buildAppletWidget("5fa215459a6a7900019b5cc3", "我的对账单"),
],
),
),
);

View File

@ -7,7 +7,7 @@ packages:
name: async
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.6.1"
version: "2.8.2"
boolean_selector:
dependency: transitive
description:
@ -21,14 +21,14 @@ packages:
name: characters
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
version: "1.2.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
version: "1.3.1"
clock:
dependency: transitive
description:
@ -49,7 +49,7 @@ packages:
name: cupertino_icons
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.1.3"
version: "1.0.4"
fake_async:
dependency: transitive
description:
@ -62,27 +62,48 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.4"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.5"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.1"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.10"
version: "0.12.11"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0"
version: "1.7.0"
mop:
dependency: "direct dev"
dependency: "direct main"
description:
path: ".."
relative: true
@ -141,7 +162,7 @@ packages:
name: test_api
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.0"
version: "0.4.3"
typed_data:
dependency: transitive
description:
@ -155,7 +176,7 @@ packages:
name: vector_math
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0"
version: "2.1.1"
sdks:
dart: ">=2.12.0 <3.0.0"
flutter: ">=1.10.0"
dart: ">=2.14.0 <3.0.0"
flutter: ">=2.2.3"

View File

@ -3,39 +3,57 @@ description: Demonstrates how to use the mop plugin.
publish_to: 'none'
environment:
sdk: '>=2.1.0 <3.0.0'
sdk: '>=2.12.0 <3.0.0'
dependencies:
flutter:
sdk: flutter
mop:
# When depending on this package from a real application you should use:
# mop: ^x.y.z
# See https://dart.dev/tools/pub/dependencies#version-constraints
# The example app is bundled with the plugin so we use a path dependency on
# the parent directory to use the current plugin's version.
path: ../
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
cupertino_icons: ^1.0.2
dev_dependencies:
flutter_test:
sdk: flutter
mop:
path: ../
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^1.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a

View File

@ -19,7 +19,7 @@ void main() {
expect(
find.byWidgetPredicate(
(Widget widget) => widget is Text &&
widget.data.startsWith('Running on:'),
widget.data!.startsWith('Running on:'),
),
findsOneWidget,
);

View File

@ -0,0 +1,16 @@
//
// MOB_addWebExtentionApi.h
// mop
//
// Created by on 2021/12/21.
//
#import "MOPBaseApi.h"
NS_ASSUME_NONNULL_BEGIN
@interface MOB_addWebExtentionApi : MOPBaseApi
@property(nonatomic, copy) NSString* name;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,53 @@
//
// MOB_addWebExtentionApi.m
// mop
//
// Created by on 2021/12/21.
//
#import "MOB_addWebExtentionApi.h"
#import "MopPlugin.h"
#import <FinApplet/FinApplet.h>
@implementation MOB_addWebExtentionApi
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *,id> * _Nonnull))success failure:(void (^)(id _Nullable))failure cancel:(void (^)(void))cancel
{
NSLog(@"MOB_addWebExtentionApi");
FlutterMethodChannel *channel = [[MopPlugin instance] methodChannel];
[[FATClient sharedClient] fat_registerWebApi:self.name handle:^(id param, FATExtensionApiCallback callback) {
NSLog(@"invoke webExtentionApi:");
NSLog(@"%@",self.name);
NSLog(@"%@",param);
NSString* api = [@"webExtentionApi:" stringByAppendingString:self.name];
[channel invokeMethod:api arguments:param result:^(id _Nullable result) {
NSLog(@"webExtentionApi reslut:%@",result);
// flutter
BOOL isFlutterError = [result isKindOfClass:[FlutterError class]] || result == FlutterMethodNotImplemented;
if (isFlutterError) {
NSLog(@"webExtentionApi reslut:fail");
callback(FATExtensionCodeFailure,nil);
return;
}
//
BOOL hasError = [[result allKeys] containsObject:@"errMsg"];
if (hasError) {
NSString *errMsg = result[@"errMsg"];
NSString *errPrefix = [NSString stringWithFormat:@"%@:fail", self.name];
BOOL isFail = [errMsg hasPrefix:errPrefix];
if (isFail) {
NSLog(@"webExtentionApi reslut:fail");
callback(FATExtensionCodeFailure,nil);
return;
}
}
//
NSLog(@"webExtentionApi callback:%@",result);
callback(FATExtensionCodeSuccess,result);
}];
}];
success(@{});
}
@end

View File

@ -0,0 +1,18 @@
//
// MOP_callJS.h
// mop
//
// Created by on 2021/12/21.
//
#import "MOPBaseApi.h"
NS_ASSUME_NONNULL_BEGIN
@interface MOP_callJS : MOPBaseApi
@property (nonatomic, copy) NSString *eventName;
@property (nonatomic, copy) NSString *nativeViewId;
@property (nonatomic, copy) NSDictionary *eventData;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,28 @@
//
// MOP_callJS.m
// mop
//
// Created by on 2021/12/21.
//
#import "MOP_callJS.h"
@implementation MOP_callJS
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *,id> * _Nonnull))success failure:(void (^)(id _Nullable))failure cancel:(void (^)(void))cancel
{
if (!self.eventData || !self.eventName || !self.nativeViewId) {
failure(@{@"errMsg": @"callJS:fail"});
return;
}
NSNumber *numberId = @(_nativeViewId.integerValue);
[[FATClient sharedClient].nativeViewManager sendEvent:_eventName nativeViewId:numberId detail:_eventData completion:^(id result, NSError *error) {
if (error) {
failure(@{@"errMsg": @"sendCustomEvent:fail"});
} else {
success(result);
}
}];
}
@end

View File

@ -0,0 +1,17 @@
//
// MOP_closeApplet.h
// mop
//
// Created by on 2021/12/21.
//
#import "MOPBaseApi.h"
NS_ASSUME_NONNULL_BEGIN
@interface MOP_closeApplet : MOPBaseApi
@property (nonatomic, copy) NSString *appletId;
@property (nonatomic, assign) BOOL animated;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,25 @@
//
// MOP_closeApplet.m
// mop
//
// Created by on 2021/12/21.
//
#import "MOP_closeApplet.h"
#import <FinApplet/FinApplet.h>
@implementation MOP_closeApplet
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *,id> * _Nonnull))success failure:(void (^)(id _Nullable))failure cancel:(void (^)(void))cancel
{
if (!self.appletId || self.appletId.length < 1) {
failure(@{@"errMsg": @"closeApplet:fail"});
return;
}
[[FATClient sharedClient] closeApplet:self.appletId animated:_animated completion:^{
success(@{});
}];
}
@end

View File

@ -0,0 +1,17 @@
//
// MOP_finishRunningApplet.h
// mop
//
// Created by on 2021/12/21.
//
#import "MOPBaseApi.h"
NS_ASSUME_NONNULL_BEGIN
@interface MOP_finishRunningApplet : MOPBaseApi
@property (nonatomic, copy) NSString *appletId;
@property (nonatomic, assign) BOOL animated;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,25 @@
//
// MOP_finishRunningApplet.m
// mop
//
// Created by on 2021/12/21.
//
#import "MOP_finishRunningApplet.h"
@implementation MOP_finishRunningApplet
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *,id> * _Nonnull))success failure:(void (^)(id _Nullable))failure cancel:(void (^)(void))cancel
{
if (!self.appletId || self.appletId.length < 1) {
failure(@{@"errMsg": @"finishRunningApplet:fail"});
return;
}
[[FATClient sharedClient] closeApplet:self.appletId animated:_animated completion:^{
[[FATClient sharedClient] clearMemeryApplet:self.appletId];
success(@{});
}];
}
@end

View File

@ -16,9 +16,15 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, copy) NSString *apiServer;
@property (nonatomic, copy) NSString *apiPrefix;
@property (nonatomic, copy) NSString *cryptType;
@property (nonatomic, assign) BOOL encryptServerData;
@property (nonatomic, copy) NSString *userId;
@property (nonatomic, assign) bool disablePermission;
@property (nonatomic, assign) bool encryptServerData;
@property (nonatomic, strong) NSArray *finStoreConfigs;
@property (nonatomic, strong) NSDictionary *uiConfig;
@property (nonatomic, copy) NSString *customWebViewUserAgent;
@property (nonatomic, assign) BOOL disablePermission;
@property (nonatomic, assign) NSInteger appletIntervalUpdateLimit;
@property (nonatomic, assign) NSInteger maxRunningApplet;
@end

View File

@ -8,6 +8,7 @@
#import "MOP_initialize.h"
#import <FinApplet/FinApplet.h>
#import <FinAppletExt/FinAppletExt.h>
#import "MOPTools.h"
// #import <FinAppletWebRTC/FinAppletWebRTC.h>
@implementation MOP_initialize
@ -15,7 +16,7 @@
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *,id> * _Nonnull))success failure:(void (^)(id _Nullable))failure cancel:(void (^)(void))cancel
{
if (!self.appkey || !self.secret) {
failure(@"appkey 或 secret不能为空");
failure(@"sdkkey 或 secret不能为空");
return;
}
if (!self.apiServer || [self.apiServer isEqualToString:@""]) {
@ -24,27 +25,102 @@
if (!self.apiPrefix|| [self.apiPrefix isEqualToString:@""]) {
self.apiPrefix = @"/api/v1/mop";
}
FATConfig *config = [FATConfig configWithAppSecret:self.secret appKey:self.appkey];
config.apiServer = [self.apiServer copy];
config.apiPrefix = [self.apiPrefix copy];
if([self.cryptType isEqualToString: @"SM"])
{
config.cryptType = FATApiCryptTypeSM;
FATConfig *config;
if (_finStoreConfigs && _finStoreConfigs.count > 0) {
NSMutableArray *storeArrayM = [NSMutableArray array];
for (NSDictionary *dict in _finStoreConfigs) {
FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
storeConfig.sdkKey = dict[@"sdkKey"];
// storeConfig.sdkKey = @"22LyZEib0gLTQdU3MUauAb4V4W8Uxd/gMgmH8Hg1bGQ=";
storeConfig.sdkSecret = dict[@"sdkSecret"];
storeConfig.apiServer = dict[@"apiServer"];
storeConfig.apmServer = dict[@"apmServer"];
storeConfig.fingerprint = dict[@"fingerprint"];
if ([@"SM" isEqualToString:dict[@"cryptType"]]) {
storeConfig.cryptType = FATApiCryptTypeSM;
} else {
storeConfig.cryptType = FATApiCryptTypeMD5;
}
storeConfig.encryptServerData = [dict[@"encryptServerData"] boolValue];
[storeArrayM addObject:storeConfig];
}
config = [FATConfig configWithStoreConfigs:storeArrayM];
} else {
config = [FATConfig configWithAppSecret:self.secret appKey:self.appkey];
config.apiServer = [self.apiServer copy];
config.apiPrefix = [self.apiPrefix copy];
if([self.cryptType isEqualToString: @"SM"])
{
config.cryptType = FATApiCryptTypeSM;
}
else
{
config.cryptType = FATApiCryptTypeMD5;
}
// encryptServerData
NSLog(@"encryptServerData:%d",self.encryptServerData);
config.encryptServerData = self.encryptServerData;
}
else
{
config.cryptType = FATApiCryptTypeMD5;
}
config.currentUserId = [self.userId copy];
// encryptServerData
NSLog(@"encryptServerData:%d",self.encryptServerData);
config.encryptServerData = self.encryptServerData;
NSLog(@"disablePermission:%d",self.disablePermission);
config.disableAuthorize = self.disablePermission;
config.currentUserId = [self.userId copy];
config.appletIntervalUpdateLimit = self.appletIntervalUpdateLimit;
// bool debug = false,
// bool bindAppletWithMainProcess = false,
// List<FinStoreConfig>? finStoreConfigs,
// UIConfig? uiConfig,
// String? customWebViewUserAgent,
// int appletIntervalUpdateLimit = 0,
// int maxRunningApplet = 5,
NSError* error = nil;
FATUIConfig *uiconfig = [[FATUIConfig alloc]init];
uiconfig.autoAdaptDarkMode = YES;
if (_uiConfig) {
if (_uiConfig[@"navigationTitleTextAttributes"]) {
uiconfig.navigationTitleTextAttributes = _uiConfig[@"navigationTitleTextAttributes"];
}
if (_uiConfig[@"progressBarColor"]) {
uiconfig.progressBarColor = [MOPTools colorWithRGBHex:[_uiConfig[@"progressBarColor"] intValue]];
}
uiconfig.hideBackToHome = [_uiConfig[@"isHideBackHome"] boolValue];
uiconfig.hideFeedbackMenu = [_uiConfig[@"isHideFeedbackAndComplaints"] boolValue];
uiconfig.hideForwardMenu = [_uiConfig[@"isHideForwardMenu"] boolValue];
uiconfig.autoAdaptDarkMode = [_uiConfig[@"autoAdaptDarkMode"] boolValue];
uiconfig.appletText = _uiConfig[@"appletText"];
uiconfig.hideTransitionCloseButton = [_uiConfig[@"hideTransitionCloseButton"] boolValue];
uiconfig.disableSlideCloseAppletGesture = _uiConfig[@"disableSlideCloseAppletGesture"];
if (_uiConfig[@"capsuleConfig"]) {
NSDictionary *capsuleConfigDic = _uiConfig[@"capsuleConfig"];
FATCapsuleConfig *capsuleConfig = [[FATCapsuleConfig alloc]init];
capsuleConfig.capsuleWidth = [capsuleConfigDic[@"capsuleWidth"] floatValue];
capsuleConfig.capsuleHeight = [capsuleConfigDic[@"capsuleHeight"] floatValue];
capsuleConfig.capsuleRightMargin = [capsuleConfigDic[@"capsuleRightMargin"] floatValue];
capsuleConfig.capsuleCornerRadius = [capsuleConfigDic[@"capsuleCornerRadius"] floatValue];
capsuleConfig.capsuleBorderWidth = [capsuleConfigDic[@"capsuleBorderWidth"] floatValue];
capsuleConfig.moreBtnWidth = [capsuleConfigDic[@"moreBtnWidth"] floatValue];
capsuleConfig.moreBtnLeftMargin = [capsuleConfigDic[@"moreBtnLeftMargin"] floatValue];
capsuleConfig.closeBtnWidth = [capsuleConfigDic[@"closeBtnWidth"] floatValue];
capsuleConfig.closeBtnLeftMargin = [capsuleConfigDic[@"closeBtnLeftMargin"] floatValue];
capsuleConfig.capsuleBorderLightColor = [MOPTools colorWithRGBHex:[capsuleConfigDic[@"capsuleBorderLightColor"] intValue]];
capsuleConfig.capsuleBorderDarkColor = [MOPTools colorWithRGBHex:[capsuleConfigDic[@"capsuleBorderDarkColor"] intValue]];
capsuleConfig.capsuleBgLightColor = [MOPTools colorWithRGBHex:[capsuleConfigDic[@"capsuleBgLightColor"] intValue]];
capsuleConfig.capsuleBgDarkColor = [MOPTools colorWithRGBHex:[capsuleConfigDic[@"capsuleBgDarkColor"] intValue]];
capsuleConfig.capsuleDividerLightColor = [MOPTools colorWithRGBHex:[capsuleConfigDic[@"capsuleDividerLightColor"] intValue]];
capsuleConfig.capsuleDividerDarkColor = [MOPTools colorWithRGBHex:[capsuleConfigDic[@"capsuleDividerDarkColor"] intValue]];
uiconfig.capsuleConfig = capsuleConfig;
}
}
uiconfig.appendingCustomUserAgent = self.customWebViewUserAgent;
// uiconfig.moreMenuStyle = FATMoreViewStyleNormal;
[[FATClient sharedClient] initWithConfig:config uiConfig:uiconfig error:&error];
if (error) {

View File

@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface MOP_registerExtensionApi : MOPBaseApi
@property NSString* name;
@property(nonatomic, copy) NSString* name;
@end

View File

@ -0,0 +1,16 @@
//
// MOP_removeApplet.h
// mop
//
// Created by on 2021/12/21.
//
#import "MOPBaseApi.h"
NS_ASSUME_NONNULL_BEGIN
@interface MOP_removeApplet : MOPBaseApi
@property (nonatomic, copy) NSString *appletId;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,32 @@
//
// MOP_removeApplet.m
// mop
//
// Created by on 2021/12/21.
//
#import "MOP_removeApplet.h"
@implementation MOP_removeApplet
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *,id> * _Nonnull))success failure:(void (^)(id _Nullable))failure cancel:(void (^)(void))cancel
{
if (!self.appletId || self.appletId.length < 1) {
failure(@{@"errMsg": @"removeApplet:fail"});
return;
}
FATAppletInfo *appletInfo = [[FATClient sharedClient] currentApplet];
if (appletInfo && [appletInfo.appId isEqual:self.appletId]) {
[[FATClient sharedClient] closeApplet:self.appletId animated:NO completion:^{
[[FATClient sharedClient] removeAppletFromLocalCache:self.appletId];
success(@{});
}];
} else {
[[FATClient sharedClient] removeAppletFromLocalCache:self.appletId];
success(@{});
}
}
@end

View File

@ -0,0 +1,16 @@
//
// MOP_sendCustomEvent.h
// mop
//
// Created by on 2021/12/21.
//
#import "MOPBaseApi.h"
NS_ASSUME_NONNULL_BEGIN
@interface MOP_sendCustomEvent : MOPBaseApi
@property (nonatomic, strong) NSDictionary *eventData;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,28 @@
//
// MOP_sendCustomEvent.m
// mop
//
// Created by on 2021/12/21.
//
#import "MOP_sendCustomEvent.h"
@implementation MOP_sendCustomEvent
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *,id> * _Nonnull))success failure:(void (^)(id _Nullable))failure cancel:(void (^)(void))cancel
{
if (!self.eventData ) {
failure(@{@"errMsg": @"sendCustomEvent:fail"});
return;
}
[[FATClient sharedClient].nativeViewManager sendCustomEventWithDetail:self.eventData completion:^(id result, NSError *error) {
if (error) {
failure(@{@"errMsg": @"sendCustomEvent:fail"});
} else {
success(result);
}
}];
}
@end

View File

@ -0,0 +1,16 @@
//
// MOP_setFinStoreConfigs.h
// mop
//
// Created by on 2021/12/20.
//
#import "MOPBaseApi.h"
NS_ASSUME_NONNULL_BEGIN
@interface MOP_setFinStoreConfigs : MOPBaseApi
@property(nonatomic, strong) NSArray *storeConfigs;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,12 @@
//
// MOP_setFinStoreConfigs.m
// mop
//
// Created by on 2021/12/20.
//
#import "MOP_setFinStoreConfigs.h"
@implementation MOP_setFinStoreConfigs
@end

View File

@ -107,7 +107,9 @@ static MopPlugin *_instance;
return [[FATClient sharedClient] handleOpenURL:url];
}
-(BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
- (BOOL)application:(UIApplication*)application
continueUserActivity:(NSUserActivity*)userActivity
restorationHandler:(void (^)(NSArray*))restorationHandler
{
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
NSURL *url = userActivity.webpageURL;

View File

@ -88,9 +88,10 @@
id value = container[key];
id safetyValue = [self parseFromKeyValue:value];
if (!safetyValue)
if (!safetyValue) //safetyValuenil
{
safetyValue = @"";
// safetyValue = @"";
continue;
}
[result setObject:safetyValue forKey:key];
}

View File

@ -13,6 +13,9 @@ NS_ASSUME_NONNULL_BEGIN
+ (UIViewController *)topViewController;
+ (UIViewController *)topViewController:(UIViewController *)rootViewController;
+ (UIColor *)colorWithRGBHex:(UInt32)hex;
+ (UIColor *)fat_colorWithHexString:(NSString *)hexColor;
@end
NS_ASSUME_NONNULL_END

View File

@ -28,4 +28,89 @@
return [self topViewController:presentedViewController];
}
+ (UIColor *)colorWithRGBHex:(UInt32)hex
{
int a = (hex >> 24) & 0xFF;
int r = (hex >> 16) & 0xFF;
int g = (hex >> 8) & 0xFF;
int b = (hex) & 0xFF;
return [UIColor colorWithRed:r / 255.0f
green:g / 255.0f
blue:b / 255.0f
alpha:a / 255.0f];
}
+ (UIColor *)fat_colorWithHexString:(NSString *)hexColor {
if (!hexColor) return nil;
// blackwhite
if ([hexColor compare:@"black" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
return UIColor.blackColor;
} else if ([hexColor compare:@"white" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
return UIColor.whiteColor;
}
NSString *cString = [[hexColor stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString];
if (cString.length == 0) return nil;
if ([cString hasPrefix:@"#"]) cString = [cString substringFromIndex:1];
if ([cString containsString:@"0X"]) cString = [cString stringByReplacingOccurrencesOfString:@"0X" withString:@""];
if (cString.length == 3) { // 36
cString = [NSString stringWithFormat:@"%c%c%c%c%c%c",
[cString characterAtIndex:0],
[cString characterAtIndex:0],
[cString characterAtIndex:1],
[cString characterAtIndex:1],
[cString characterAtIndex:2],
[cString characterAtIndex:2]];
}
if (cString.length == 4) { // 48
cString = [NSString stringWithFormat:@"%c%c%c%c%c%c%c%c",
[cString characterAtIndex:0],
[cString characterAtIndex:0],
[cString characterAtIndex:1],
[cString characterAtIndex:1],
[cString characterAtIndex:2],
[cString characterAtIndex:2],
[cString characterAtIndex:3],
[cString characterAtIndex:3]];
}
NSScanner *scanner = [NSScanner scannerWithString:cString];
unsigned hexNum;
if (![scanner scanHexInt:&hexNum]) return [UIColor blackColor];
if (cString.length == 6) {
return [self fat_colorWithRGBHex:hexNum];
} else if (cString.length == 8) {
return [self fat_colorWithARGBHex:hexNum];
}
return nil;
}
+ (UIColor *)fat_colorWithRGBHex:(UInt32)hex {
int red = (hex >> 16) & 0xFF;
int green = (hex >> 8) & 0xFF;
int blue = (hex)&0xFF;
return [UIColor colorWithRed:red / 255.0f green:green / 255.0f blue:blue / 255.0f alpha:1.0f];
}
+ (UIColor *)fat_colorWithRGBAlphaHex:(UInt32)hex {
int red = (hex >> 24) & 0xFF;
int green = (hex >> 16) & 0xFF;
int blue = (hex >> 8) & 0xFF;
int alpha = hex & 0xFF;
return [UIColor colorWithRed:red / 255.0f green:green / 255.0f blue:blue / 255.0f alpha:alpha / 255.0f];
}
+ (UIColor *)fat_colorWithARGBHex:(UInt32)hex {
int alpha = (hex >> 24) & 0xFF;
int red = (hex >> 16) & 0xFF;
int green = (hex >> 8) & 0xFF;
int blue = hex & 0xFF;
return [UIColor colorWithRed:red / 255.0f green:green / 255.0f blue:blue / 255.0f alpha:alpha / 255.0f];
}
@end

View File

@ -1,5 +1,3 @@
import 'dart:typed_data';
class CustomMenu {
String menuId;
String image;
@ -8,8 +6,7 @@ class CustomMenu {
CustomMenu(this.menuId, this.image, this.title, this.type);
Map<String, dynamic> toJson() =>
{'menuId': menuId, 'image': image, 'title': title, 'type': type};
Map<String, dynamic> toJson() => {'menuId': menuId, 'image': image, 'title': title, 'type': type};
}
abstract class AppletHandler {

View File

@ -1,5 +1,7 @@
import 'dart:async';
import 'dart:ffi';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:mop/api.dart';
@ -8,27 +10,244 @@ typedef MopEventErrorCallback = void Function(dynamic event);
typedef ExtensionApiHandler = Future Function(dynamic params);
class FinStoreConfig {
///SDK Key
String sdkKey;
///SDK secret
String sdkSecret;
///
String apiServer;
///apm,apiServer
String apmServer;
///MD5 SM
String cryptType;
///SDK (https://open.fdep.cn/)
String? fingerprint;
///使YES
bool encryptServerData;
FinStoreConfig(this.sdkKey, this.sdkSecret, this.apiServer, this.apmServer,
{this.cryptType = "MD5",
this.fingerprint,
this.encryptServerData = false});
Map<String, dynamic> toMap() {
return {
"sdkKey": sdkKey,
"sdkSecret": sdkSecret,
"apiServer": apiServer,
"apmServer": apmServer,
"cryptType": cryptType,
"fingerprint": fingerprint,
"encryptServerData": encryptServerData
};
}
}
class UIConfig {
Map<String, dynamic>? navigationTitleTextAttributes; //font
///
bool isAlwaysShowBackInDefaultNavigationBar = false;
///
bool isClearNavigationBarNavButtonBackground = false;
///"更多""反馈与投诉"
bool isHideFeedbackAndComplaints = false;
///"更多""返回首页"
bool isHideBackHome = false;
///"更多""转发"
bool isHideForwardMenu = false;
/// ServiceSDK
bool hideTransitionCloseButton = false;
///
bool disableSlideCloseAppletGesture = false;
///
CapsuleConfig? capsuleConfig;
FloatWindowConfig? floatWindowConfig;
//iOS
//H5 0xFFFFAA00
int? progressBarColor;
//true
bool autoAdaptDarkMode = true;
//appletText
String? appletText;
Map<String, dynamic> toMap() {
return {
"navigationTitleTextAttributes": navigationTitleTextAttributes,
"isAlwaysShowBackInDefaultNavigationBar":
isAlwaysShowBackInDefaultNavigationBar,
"isClearNavigationBarNavButtonBackground":
isClearNavigationBarNavButtonBackground,
"isHideFeedbackAndComplaints": isHideFeedbackAndComplaints,
"isHideBackHome": isHideBackHome,
"isHideForwardMenu": isHideForwardMenu,
"hideTransitionCloseButton": hideTransitionCloseButton,
"disableSlideCloseAppletGesture": disableSlideCloseAppletGesture,
"capsuleConfig": capsuleConfig?.toMap(),
"floatWindowConfig": floatWindowConfig?.toMap(),
"progressBarColor": progressBarColor,
"autoAdaptDarkMode": autoAdaptDarkMode,
"appletText": appletText
};
}
}
///
class CapsuleConfig {
/// 88
double capsuleWidth = 88;
///32
double capsuleHeight = 32;
///
double capsuleRightMargin = 7;
///5
double capsuleCornerRadius = 5;
///0.8
double capsuleBorderWidth = 1;
///
int capsuleBgLightColor = 0x33000000;
///
int capsuleBgDarkColor = 0x80ffffff;
///
int capsuleBorderLightColor = 0x80ffffff;
///
int capsuleBorderDarkColor = 0x26000000;
///线
int capsuleDividerLightColor = 0x80ffffff;
///线
int capsuleDividerDarkColor = 0x26000000;
///使
int? moreLightImage;
///使
int? moreDarkImage;
///
double moreBtnWidth = 32;
///
double moreBtnLeftMargin = 6;
///使
int? closeLightImage;
///使
int? closeDarkImage;
///
double closeBtnWidth = 32;
///
double closeBtnLeftMargin = 6;
Map<String, dynamic> toMap() {
return {
"capsuleWidth": capsuleWidth,
"capsuleHeight": capsuleHeight,
"capsuleRightMargin": capsuleRightMargin,
"capsuleCornerRadius": capsuleCornerRadius,
"capsuleBorderWidth": capsuleBorderWidth,
"capsuleBgLightColor": capsuleBgLightColor,
"capsuleBgDarkColor": capsuleBgDarkColor,
"capsuleBorderLightColor": capsuleBorderLightColor,
"capsuleBorderDarkColor": capsuleBorderDarkColor,
"capsuleDividerLightColor": capsuleDividerLightColor,
"capsuleDividerDarkColor": capsuleDividerDarkColor,
"moreLightImage": moreLightImage,
"moreDarkImage": moreDarkImage,
"moreBtnWidth": moreBtnWidth,
"moreBtnLeftMargin": moreBtnLeftMargin,
"closeLightImage": closeLightImage,
"closeDarkImage": closeDarkImage,
"closeBtnWidth": closeBtnWidth,
"closeBtnLeftMargin": closeBtnLeftMargin,
};
}
}
class FloatWindowConfig {
bool floatMode = false;
int x;
int y;
int width;
int height;
FloatWindowConfig(this.floatMode, this.x, this.y, this.width, this.height);
Map<String, dynamic> toMap() {
return {
"floatMode": floatMode,
"x": x,
"y": y,
"width": width,
"height": height
};
}
}
enum Anim {
SlideFromLeftToRightAnim,
SlideFromRightToLeftAnim,
SlideFromTopToBottomAnim,
SlideFromBottomToTopAnim,
FadeInAnim,
NoneAnim
}
class Mop {
static final Mop _instance = new Mop._internal();
MethodChannel _channel;
EventChannel _mopEventChannel;
int eventId = 0;
List<Map<String, dynamic>> _mopEventQueye = <Map<String, dynamic>>[];
late MethodChannel _channel;
late EventChannel _mopEventChannel;
late int eventId = 0;
final List<Map<String, dynamic>> _mopEventQueye = <Map<String, dynamic>>[];
Map<String, ExtensionApiHandler> _extensionApis = {};
final Map<String, ExtensionApiHandler> _extensionApis = {};
Map<String, ExtensionApiHandler> _webExtensionApis = {};
factory Mop() {
return _instance;
}
Mop._internal() {
print('mop: _internal');
debugPrint('mop: _internal');
// init
_channel = new MethodChannel('mop');
_channel = const MethodChannel('mop');
_channel.setMethodCallHandler(_handlePlatformMethodCall);
_mopEventChannel = new EventChannel('plugins.mop.finogeeks.com/mop_event');
_mopEventChannel =
const EventChannel('plugins.mop.finogeeks.com/mop_event');
_mopEventChannel.receiveBroadcastStream().listen((dynamic value) {
print('matrix: receiveBroadcastStream $value');
debugPrint('matrix: receiveBroadcastStream $value');
for (Map m in _mopEventQueye) {
if (m['event'] == value['event']) {
m['MopEventCallback'](value['body']);
@ -47,47 +266,77 @@ class Mop {
}
Future<dynamic> _handlePlatformMethodCall(MethodCall call) async {
print("_handlePlatformMethodCall: method:${call.method}");
debugPrint("_handlePlatformMethodCall: method:${call.method}");
if (call.method.startsWith("extensionApi:")) {
final name = call.method.substring("extensionApi:".length);
final handler = _extensionApis[name];
if (handler != null) {
return await handler(call.arguments);
}
} else if (call.method.startsWith("extensionApi:")) {}
} else if (call.method.startsWith("webExtentionApi:")) {
final name = call.method.substring("webExtentionApi:".length);
final handler = _webExtensionApis[name];
if (handler != null) {
return await handler(call.arguments);
}
}
}
///
///
/// initialize mop miniprogram engine.
///
/// [appkey] is required. it can be getted from api.finclip.com
/// [sdkkey] 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
/// [cryptType] is optional. cryptType, should be MD5/SM
/// [disablePermission] is optional.
/// [encryptServerData]
/// [userId] id
/// [finStoreConfigs]
/// [uiConfig] UI
/// [debug] debug
/// [customWebViewUserAgent] webview ua
/// [appletIntervalUpdateLimit]
/// [maxRunningApplet]
///
Future<Map> initialize(String appkey, String secret,
{String apiServer,
String apiPrefix,
String cryptType,
bool disablePermission,
String userId,
bool encryptServerData = false,
bool debug = false,
bool bindAppletWithMainProcess = false}) async {
Future<Map> initialize(
String sdkkey,
String secret, {
String? apiServer,
String? apiPrefix,
String? cryptType,
bool encryptServerData = false,
bool disablePermission = false,
String? userId,
bool debug = false,
bool bindAppletWithMainProcess = false,
List<FinStoreConfig>? finStoreConfigs,
UIConfig? uiConfig,
String? customWebViewUserAgent,
int? appletIntervalUpdateLimit,
int? maxRunningApplet,
}) async {
List<Map<String, dynamic>>? storeConfigs =
finStoreConfigs?.map((e) => e.toMap()).toList();
final Map ret = await _channel.invokeMethod('initialize', {
'appkey': appkey,
'appkey': sdkkey,
'secret': secret,
'apiServer': apiServer,
'apiPrefix': apiPrefix,
'cryptType': cryptType,
"encryptServerData": encryptServerData,
'disablePermission': disablePermission,
'userId': userId,
"encryptServerData": encryptServerData,
"debug": debug,
"bindAppletWithMainProcess": bindAppletWithMainProcess
"bindAppletWithMainProcess": bindAppletWithMainProcess,
"finStoreConfigs": storeConfigs,
"uiConfig": uiConfig?.toMap(),
"customWebViewUserAgent": customWebViewUserAgent,
"appletIntervalUpdateLimit": appletIntervalUpdateLimit,
"maxRunningApplet": maxRunningApplet
});
return ret;
}
@ -104,14 +353,11 @@ class Mop {
/// [cryptType] is optional. cryptType, should be MD5/SM
Future<Map> openApplet(
final String appId, {
final String path,
final String query,
final int sequence,
final String apiServer,
final String apiPrefix,
final String fingerprint,
final String cryptType,
final String scene,
final String? path,
final String? query,
final int? sequence,
final String? apiServer,
final String? scene,
}) async {
Map<String, Object> params = {'appId': appId};
Map param = {};
@ -120,9 +366,6 @@ class Mop {
if (param.length > 0) params["params"] = param;
if (sequence != null) params["sequence"] = sequence;
if (apiServer != null) params["apiServer"] = apiServer;
if (apiPrefix != null) params["apiPrefix"] = apiPrefix;
if (fingerprint != null) params["fingerprint"] = fingerprint;
if (cryptType != null) params["cryptType"] = cryptType;
if (scene != null) param["scene"] = scene;
final Map ret = await _channel.invokeMethod('openApplet', params);
return ret;
@ -136,7 +379,7 @@ class Mop {
///
Future<Map<String, dynamic>> currentApplet() async {
final ret = await _channel.invokeMapMethod("currentApplet");
return Map<String, dynamic>.from(ret);
return Map<String, dynamic>.from(ret!);
}
///
@ -167,7 +410,7 @@ class Mop {
Future<String> sdkVersion() async {
return await _channel
.invokeMapMethod("sdkVersion")
.then((value) => value["data"]);
.then((value) => value?["data"]);
}
///
@ -190,7 +433,7 @@ class Mop {
String qrCode, String apiServer) async {
final ret = await _channel.invokeMapMethod("parseAppletInfoFromWXQrCode",
{"qrCode": qrCode, "apiServer": apiServer});
return Map<String, dynamic>.from(ret);
return Map<String, dynamic>.from(ret!);
}
///
@ -207,7 +450,7 @@ class Mop {
_extensionApis["getCustomMenus"] = (params) async {
final res = await handler.getCustomMenus(params["appId"]);
List<Map<String, dynamic>> list = [];
res?.forEach((element) {
res.forEach((element) {
Map<String, dynamic> map = Map();
map["menuId"] = element.menuId;
map["image"] = element.image;
@ -215,7 +458,7 @@ class Mop {
map["type"] = element.type;
list.add(map);
});
print("registerAppletHandler getCustomMenus list $list");
debugPrint("registerAppletHandler getCustomMenus list $list");
return list;
};
_extensionApis["onCustomMenuClick"] = (params) async {
@ -241,8 +484,8 @@ class Mop {
Future<String> getSMSign(String plainText) async {
var result =
await _channel.invokeMapMethod("smsign", {'plainText': plainText});
var data = result['data']['data'];
print(data);
var data = result?['data']['data'];
debugPrint(data);
return data;
}
@ -251,4 +494,51 @@ class Mop {
await _channel.invokeMapMethod("webViewBounces", {'bounces': bounces});
return;
}
//
Future<void> closeApplet(String appletId, bool animated) async {
await _channel.invokeMethod(
"closeApplet", {"appletId": appletId, "animated": animated});
return;
}
//
Future<void> finishRunningApplet(String appletId, bool animated) async {
await _channel.invokeMethod(
"finishRunningApplet", {"appletId": appletId, "animated": animated});
return;
}
//
Future setActivityTransitionAnim(Anim anim) async {
await _channel
.invokeMethod("setActivityTransitionAnim", {"anim": anim.name});
return;
}
//
Future<void> sendCustomEvent(
String appId, Map<String, dynamic> eventData) async {
await _channel.invokeMethod(
"sendCustomEvent", {"appId": appId, "eventData": eventData});
return;
}
//js
Future<void> callJS(String appId, String eventName, String nativeViewId,
Map<String, dynamic> eventData) async {
await _channel.invokeMethod("callJS", {
"appId": appId,
"eventName": eventName,
"nativeViewId": nativeViewId,
"eventData": eventData
});
return;
}
//h5
void addWebExtentionApi(String name, ExtensionApiHandler handler) {
_webExtensionApis[name] = handler;
_channel.invokeMethod("addWebExtentionApi", {"name": name});
}
}

View File

@ -7,7 +7,7 @@ packages:
name: async
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.6.1"
version: "2.8.2"
boolean_selector:
dependency: transitive
description:
@ -21,14 +21,14 @@ packages:
name: characters
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
version: "1.2.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
version: "1.3.1"
clock:
dependency: transitive
description:
@ -55,25 +55,46 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.4"
flutter_plugin_android_lifecycle:
dependency: "direct main"
description:
name: flutter_plugin_android_lifecycle
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.5"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.1"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.10"
version: "0.12.11"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0"
version: "1.7.0"
path:
dependency: transitive
description:
@ -127,7 +148,7 @@ packages:
name: test_api
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.0"
version: "0.4.3"
typed_data:
dependency: transitive
description:
@ -141,7 +162,7 @@ packages:
name: vector_math
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0"
version: "2.1.1"
sdks:
dart: ">=2.12.0 <3.0.0"
flutter: ">=1.10.0"
dart: ">=2.14.0 <3.0.0"
flutter: ">=2.2.3"

View File

@ -4,16 +4,18 @@ version: '__mop_flutter_sdk_version__'
homepage: https://github.com/finogeeks/mop-flutter-sdk
environment:
sdk: '>=2.1.0 <3.0.0'
flutter: '^1.10.0'
sdk: '>=2.12.0 <3.0.0'
flutter: '^2.2.3'
dependencies:
flutter:
sdk: flutter
flutter_plugin_android_lifecycle: ^2.0.3
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^1.0.0
flutter:
plugin:

View File

@ -4,16 +4,18 @@ version: '2.35.1'
homepage: https://github.com/finogeeks/mop-flutter-sdk
environment:
sdk: '>=2.1.0 <3.0.0'
flutter: '^1.10.0'
sdk: '>=2.12.0 <3.0.0'
flutter: '^2.2.3'
dependencies:
flutter:
sdk: flutter
flutter_plugin_android_lifecycle: ^2.0.3
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^1.0.0
flutter:
plugin:

View File

@ -5,6 +5,8 @@ import 'package:mop/mop.dart';
void main() {
const MethodChannel channel = MethodChannel('mop');
TestWidgetsFlutterBinding.ensureInitialized();
setUp(() {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
return '42';