Commit af0efb47 authored by 汪林玲's avatar 汪林玲

Initial commit

parents
# Created by https://www.toptal.com/developers/gitignore/api/flutter,androidstudio
# Edit at https://www.toptal.com/developers/gitignore?templates=flutter,androidstudio
### Flutter ###
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.fvm/
.packages
.pub-cache/
.pub/
build/
coverage/
lib/generated_plugin_registrant.dart
# For library packages, don’t commit the pubspec.lock file.
# Regenerating the pubspec.lock file lets you test your package against the latest compatible versions of its dependencies.
# See https://dart.dev/guides/libraries/private-files#pubspeclock
#pubspec.lock
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/key.properties
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
# 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/.last_build_id
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Flutter.podspec
**/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.*
# 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
### AndroidStudio ###
# Covers files to be ignored for android development using Android Studio.
# Built application files
*.apk
*.ap_
*.aab
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Gradle files
.gradle
.gradle/
# Signing files
.signing/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio
/*/build/
/*/local.properties
/*/out
/*/*/build
/*/*/production
captures/
.navigation/
*.ipr
*~
*.swp
# Keystore files
*.jks
*.keystore
# Google Services (e.g. APIs or Firebase)
# google-services.json
# Android Patch
gen-external-apklibs
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
# NDK
obj/
# IntelliJ IDEA
*.iml
*.iws
/out/
# User-specific configurations
.idea/caches/
.idea/libraries/
.idea/shelf/
.idea/workspace.xml
.idea/tasks.xml
.idea/.name
.idea/compiler.xml
.idea/copyright/profiles_settings.xml
.idea/encodings.xml
.idea/misc.xml
.idea/modules.xml
.idea/scopes/scope_settings.xml
.idea/dictionaries
.idea/vcs.xml
.idea/jsLibraryMappings.xml
.idea/datasources.xml
.idea/dataSources.ids
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml
.idea/assetWizardSettings.xml
.idea/gradle.xml
.idea/jarRepositories.xml
.idea/navEditor.xml
# OS-specific files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Legacy Eclipse project files
.classpath
.project
.cproject
.settings/
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.war
*.ear
# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
hs_err_pid*
## Plugin-specific files:
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Mongo Explorer plugin
.idea/mongoSettings.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### AndroidStudio Patch ###
!/gradle/wrapper/gradle-wrapper.jar
# End of https://www.toptal.com/developers/gitignore/api/flutter,androidstudio
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
</set>
</option>
</component>
</project>
\ No newline at end of file
## 1.5.5
- 更新iOS SDK 2.3.2
## 1.5.4
- 更新Android SDK 2.1.3
## 1.5.3
- 更新Android SDK 2.1.2
## 1.5.2
- 更新Android SDK 2.1.1, 优化Android请求性能
## 1.5.1
- 修正Android请求超时问题(注: 原1.5.0版本用户需升级至1.5.1以上)
## 1.5.0
- 更新Android SDK 2.1.0, iOS SDK 2.3.0
## 1.4.0
- 修正iOS无法调起问题以及避免与其他插件冲突
## 1.3.1
- Gradle build tools version 4.1.0
## 1.3.0
- 完善文档,更新Android SDK 2.0.8, iOS SDK 2.2.0
- 返回数据移除resumePage
## 1.2.0
完善文档,更新Android SDK 2.0.3
## 1.1.0
完善文档,更新Android SDK 2.0.1
## 1.0.3
增加一键调起支持
## 1.0.2
兼容低版本flutter
## 1.0.1
更新文档和相关示例
## 1.0.0
支持flutter plugin
MIT License
Copyright (c) 2020 射手科技(珠海)有限公司
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# sharetrace_flutter_plugin
请先从[ShareTrace控制台](https://www.sharetrace.com/)获取`AppKey`
### 一、安装
#### 1.1 添加依赖
在项目的pubspec.yaml文件中添加以下内容:
``` xml
dependencies:
sharetrace_flutter_plugin: ^1.4.0
```
#### 1.2 安装
通过命令行安装
```cmd
flutter pub get
```
### 二、配置
#### Android配置
找到项目的`AndroidManifest.xml`文件,在`<application>...</application>`中增加以下配置
```xml
<meta-data
android:name="com.sharetrace.APP_KEY"
android:value="SHARETRACE_APPKEY"/>
```
> **请将 SHARETRACE_APPKEY 替换成 sharetrace 为应用分配的 appkey**
#### iOS配置
在Info.plist中增加以下配置
```xml
<key>com.sharetrace.APP_KEY</key>
<string> SHARETRACE_APPKEY </string>
```
> **请将 SHARETRACE_APPKEY 替换成 sharetrace 为应用分配的 appkey**
### 三、获取安装携带的参数
#### 3.1. 导入接口定义
```dart
import 'package:sharetrace_flutter_plugin/sharetrace_flutter_plugin.dart';
```
#### 3.2. 定义结果回调
```dart
Future responseHandler(Map<String, String> data) async {
setState(() {
result = "getInstallTrace: \n\n"
+ "code= " + data['code'] + "\n"
+ "msg= " + data['msg'] + "\n"
+ "paramsData= " + data['paramsData'] + "\n"
+ "channel= " + data['channel'];
});
}
```
#### 3.3. 请求获取参数
```dart
SharetraceFlutterPlugin _sharetraceFlutterPlugin = SharetraceFlutterPlugin.getInstance();
_sharetraceFlutterPlugin.getInstallTrace(responseHandler);
```
### 四、一键调起
Sharetrace支持通过标准的Scheme和Universal Links(iOS>=9),接入Sharetrace SDK后,在各种浏览器,包括微信,微博等内置浏览器一键调起app,并传递网页配置等自定义动态参数。配置只需简单几个步骤即可,如下:
#### 4.1 开启一键调起功能
登录Sharetrace的管理后台,找到iOS配置,开启相关功能和填入配置
![5_apple_config_on.png](https://res.sharetrace.com/img/5_apple_config_on.png)
其中Team Id可以在[Apple开发者](https://developer.apple.com/account/#/membership/)后台查看
#### 4.2 开启Associated Domains服务
##### 方法一(推荐):Xcode一键开启
(这里以Xcode 12为例,其他Xcode版本类似)
![5_1_domains.png](https://res.sharetrace.com/img/5_1_domains.png)
在如下图所示位置填入Sharetrace后台提供的applinks
![5_applinks_value.png](https://res.sharetrace.com/img/5_applinks_value.png)
##### 方法二:通过Apple开发者管理后台手动开启
登录到[Apple管理后台](https://developer.apple.com/account),在Identifiers找到所需开启到App ID
![5_apple_dev_config.png](https://res.sharetrace.com/img/5_apple_dev_config.png)
#### 4.3 Scheme配置
找到项目Info配置,填入后台分配的Scheme, 如下图:
![ios_scheme_value.png](https://res.sharetrace.com/img/ios_scheme_value.png)
#### 4.4 代码配置
从Sharetrace flutter plugin 1.4.0 开始,一键调起逻辑由插件内部处理以解决与其他插件冲突的问题,则可以跳过该步骤。
若plugin版本 < 1.4.0,依然需要在AppDelegate进行配置,如下所示:
##### iOS 配置
找到AppDelegate文件,参考以下配置
**Objective-C**
``` objc
#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"
#import <sharetrace_flutter_plugin/SharetraceFlutterPlugin.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];
}
// Universal Link
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
[SharetraceFlutterPlugin handleUniversalLink:userActivity];
//其他代码
return YES;
}
//iOS9以下 Scheme
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
[SharetraceFlutterPlugin handleSchemeLinkURL:url];
//其他代码
return YES;
}
//iOS9以上 Scheme
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(nonnull NSDictionary *)options {
[SharetraceFlutterPlugin handleSchemeLinkURL:url];
//其他代码
return YES;
}
@end
```
**Swift**
``` swift
import UIKit
import Flutter
import sharetrace_flutter_plugin
@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)
}
override func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
SharetraceFlutterPlugin.handleSchemeLinkURL(url)
return true
}
override func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
SharetraceFlutterPlugin.handleSchemeLinkURL(url)
return true
}
override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
SharetraceFlutterPlugin.handleUniversalLink(userActivity)
return true
}
}
```
#### 4.5 获取一键调起参数
``` dart
class _MyAppState extends State<MyApp> {
String result;
SharetraceFlutterPlugin _sharetraceFlutterPlugin;
@override
void initState() {
super.initState();
initPlatformState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
_sharetraceFlutterPlugin = SharetraceFlutterPlugin.getInstance();
_sharetraceFlutterPlugin.registerWakeupHandler(wakeupHandler);
setState(() {
result = "";
});
}
Future wakeupHandler(Map<String, String> data) async {
setState(() {
result = "wakeupTrace: \n\n"
+ "code= " + data['code'] + "\n"
+ "msg= " + data['msg'] + "\n"
+ "paramsData= " + data['paramsData'] + "\n"
+ "channel= " + data['channel'];
});
}
}
```
### 五、配置安装方式
SDK 集成完成后,按照`sharetrace`控制台接入流程完成后续的配置。
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
group 'com.sharetrace.sharetrace_flutter_plugin'
version '1.0'
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
}
}
rootProject.allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 16
}
lintOptions {
disable 'InvalidPackage'
}
}
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation 'com.sharetrace:sharetrace-android-sdk:2.1.3'
}
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip
rootProject.name = 'sharetrace_flutter_plugin'
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sharetrace.sharetrace_flutter_plugin">
</manifest>
package com.sharetrace.sharetrace_flutter_plugin;
import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import java.util.HashMap;
import java.util.Map;
import cn.net.shoot.sharetracesdk.AppData;
import cn.net.shoot.sharetracesdk.ShareTrace;
import cn.net.shoot.sharetracesdk.ShareTraceInstallListener;
import cn.net.shoot.sharetracesdk.ShareTraceWakeUpListener;
import io.flutter.embedding.engine.FlutterEngine;
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.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.Registrar;
/**
* SharetraceFlutterPlugin
*/
public class SharetraceFlutterPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private static final String TAG = "SharetraceFlutterPlugin";
private static MethodChannel channel;
private static AppData cacheAppData = null;
private static boolean hasWakeupRegisted = false;
private static final String KEY_CODE = "code";
private static final String KEY_MSG = "msg";
private static final String KEY_PARAMSDATA = "paramsData";
private static final String KEY_CHANNEL = "channel";
public static Application application;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
FlutterEngine flutterEngine = flutterPluginBinding.getFlutterEngine();
channel = new MethodChannel(flutterEngine.getDartExecutor(), "sharetrace_flutter_plugin");
channel.setMethodCallHandler(this);
application = (Application) flutterPluginBinding.getApplicationContext();
}
// This static function is optional and equivalent to onAttachedToEngine. It supports the old
// pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
// plugin registration via this function while apps migrate to use the new Android APIs
// post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
//
// It is encouraged to share logic between onAttachedToEngine and registerWith to keep
// them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
// depending on the user's project. onAttachedToEngine or registerWith must both be defined
// in the same class.
public static void registerWith(Registrar registrar) {
application = (Application) registrar.context();
channel = new MethodChannel(registrar.messenger(), "sharetrace_flutter_plugin");
channel.setMethodCallHandler(new SharetraceFlutterPlugin());
registrar.addNewIntentListener(newIntentListener);
Activity activity = registrar.activity();
if (activity != null) {
ShareTrace.getWakeUpTrace(activity.getIntent(), shareTraceWakeUpListener);
}
}
private static final PluginRegistry.NewIntentListener newIntentListener = new PluginRegistry.NewIntentListener() {
@Override
public boolean onNewIntent(Intent intent) {
return ShareTrace.getWakeUpTrace(intent, shareTraceWakeUpListener);
}
};
private static final ShareTraceWakeUpListener shareTraceWakeUpListener = new ShareTraceWakeUpListener() {
@Override
public void onWakeUp(AppData appData) {
if (hasWakeupRegisted) {
Map<String, String> ret = parseToSuccessMap(appData);
wakeupResponse(ret);
cacheAppData = null;
} else {
cacheAppData = appData;
}
}
};
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if("init".equals(call.method)){
ShareTrace.init(application);
result.success(true);
}else if (call.method.equals("getInstallTrace")) {
result.success("call getInstallTrace success.");
int defaultTimeout = 10;
try {
String timeoutSeconds = call.argument("timeoutSeconds");
if (timeoutSeconds != null && !TextUtils.isEmpty(timeoutSeconds)) {
int timeout = Integer.parseInt(timeoutSeconds);
if (timeout > 0) {
defaultTimeout = timeout;
}
}
} catch (Throwable e) {
// ignore
Log.d(TAG, "timeoutSeconds parsed error: " + e.getMessage());
}
ShareTrace.getInstallTrace(new ShareTraceInstallListener() {
@Override
public void onInstall(AppData appData) {
if (appData == null) {
Map<String, String> ret = parseToResult(-1, "Extract data fail.", "", "");
installResponse(ret);
return;
}
Map<String, String> ret = parseToSuccessMap(appData);
installResponse(ret);
}
@Override
public void onError(int code, String message) {
Map<String, String> ret = parseToResult(code, message, "", "");
installResponse(ret);
}
}, defaultTimeout * 1000);
} else if (call.method.equals("registerWakeup")) {
hasWakeupRegisted = true;
if (cacheAppData != null) {
Map<String, String> ret = parseToSuccessMap(cacheAppData);
wakeupResponse(ret);
}
result.success("call registerWakeup success");
} else {
result.notImplemented();
}
}
private static Map<String, String> parseToSuccessMap(AppData appData) {
if (appData == null) {
return new HashMap<>();
}
String paramsData = (appData.getParamsData() == null) ? "" : appData.getParamsData();
String channel = (appData.getChannel() == null) ? "" : appData.getChannel();
return parseToResult(200, "Success", paramsData, channel);
}
private static void wakeupResponse(Map<String, String> ret) {
if (channel == null) {
return;
}
channel.invokeMethod("onWakeupResponse", ret);
}
private static void installResponse(Map<String, String> ret) {
if (channel == null) {
return;
}
channel.invokeMethod("onInstallResponse", ret);
}
private static Map<String, String> parseToResult(int code, String msg, String paramsData, String channel) {
Map<String, String> result = new HashMap<>();
result.put(KEY_CODE, String.valueOf(code));
result.put(KEY_MSG, msg);
result.put(KEY_PARAMSDATA, paramsData);
result.put(KEY_CHANNEL, channel);
return result;
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
Intent intent = binding.getActivity().getIntent();
if (intent != null) {
ShareTrace.getWakeUpTrace(intent, shareTraceWakeUpListener);
}
binding.addOnNewIntentListener(newIntentListener);
}
@Override
public void onDetachedFromActivityForConfigChanges() {
}
@Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
}
@Override
public void onDetachedFromActivity() {
}
}
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
/Flutter/Generated.xcconfig
/Flutter/flutter_export_environment.sh
\ No newline at end of file
#import <Flutter/Flutter.h>
@interface SharetraceFlutterPlugin : NSObject<FlutterPlugin>
/**
* 处理 URI Schemes 逻辑
* @param url 通过Schemes调起时,系统回调回来的URL
* @return bool Sharetrace是否成功识别该URL
*/
+ (BOOL)handleSchemeLinkURL:(NSURL * _Nullable)url;
/**
* 处理 Universal link 逻辑
* @param userActivity 通过Universal link调起时,包含系统回调回来的URL信息的NSUserActivity
* @return bool Sharetrace是否成功识别该URL
*/
+ (BOOL)handleUniversalLink:(NSUserActivity * _Nullable)userActivity;
@end
#import "SharetraceFlutterPlugin.h"
#import <SharetraceSDK/SharetraceSDK.h>
@interface SharetraceFlutterPlugin ()<SharetraceDelegate>
@property (strong, nonatomic) FlutterMethodChannel * flutterMethodChannel;
@property (nonatomic, strong)NSDictionary *wakeUpTraceDict;
@property (nonatomic, assign)BOOL hasLoad;
@end
@implementation SharetraceFlutterPlugin
static NSString * const key_code = @"code";
static NSString * const key_msg = @"msg";
static NSString * const key_paramsData = @"paramsData";
static NSString * const key_channel = @"channel";
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"sharetrace_flutter_plugin"
binaryMessenger:[registrar messenger]];
SharetraceFlutterPlugin* instance = [[SharetraceFlutterPlugin alloc] init];
[registrar addApplicationDelegate:instance];
instance.flutterMethodChannel = channel;
[registrar addMethodCallDelegate:instance channel:channel];
}
- (instancetype)init {
self = [super init];
if (self) {
}
return self;
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if ([@"init" isEqualToString:call.method]) {
[Sharetrace initWithDelegate:self];
result(@YES);
}else if ([@"getInstallTrace" isEqualToString:call.method]) {
NSTimeInterval timeout = 10;
if (call.arguments != nil) {
id timeoutSeconds = call.arguments[@"timeoutSeconds"];
if (timeoutSeconds != nil) {
NSString *targetTime = [NSString stringWithString:timeoutSeconds];
NSTimeInterval targetTimeInterval = [targetTime doubleValue];
if (targetTimeInterval > 0) {
timeout = targetTimeInterval;
}
}
}
NSTimeInterval targetTimeout = timeout * 1000;
[Sharetrace getInstallTraceWithTimeout:targetTimeout success:^(AppData * _Nullable appData) {
if (appData == nil) {
NSDictionary *ret = [SharetraceFlutterPlugin parseToResultDict:-1 :@"Extract data fail." :@"" :@""];
[self response:ret];
return;
}
NSDictionary *ret = [SharetraceFlutterPlugin parseToResultDict:200 :@"Success" :appData.paramsData :appData.channel];
[self response:ret];
} fail:^(NSInteger code, NSString * _Nonnull msg) {
NSDictionary *ret = [SharetraceFlutterPlugin parseToResultDict:code :msg :@"" :@""];
[self response:ret];
}];
} else if ([@"registerWakeup" isEqualToString:call.method]) {
self.hasLoad = YES;
if (self.wakeUpTraceDict != nil && self.wakeUpTraceDict.count > 0) {
[self wakeupResponse:self.wakeUpTraceDict];
self.wakeUpTraceDict = nil;
}
} else {
result(FlutterMethodNotImplemented);
}
}
- (void)response:(NSDictionary *) ret {
[self.flutterMethodChannel invokeMethod:@"onInstallResponse" arguments:ret];
}
- (void)wakeupResponse:(NSDictionary *) ret {
[self.flutterMethodChannel invokeMethod:@"onWakeupResponse" arguments:ret];
}
+ (NSDictionary*)parseToResultDict:(NSInteger)code :(NSString*)msg :(NSString*)paramsData :(NSString*)channel {
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
dict[key_code] = [[NSNumber numberWithInteger:code] stringValue];
dict[key_msg] = msg;
dict[key_paramsData] = paramsData;
dict[key_channel] = channel;
return dict;
}
- (void)getWakeUpTrace:(AppData *)appData {
if (appData == nil) {
return;
}
NSDictionary *ret = [SharetraceFlutterPlugin parseToResultDict:200 :@"Success" :appData.paramsData :appData.channel];
if (self.hasLoad) {
[self wakeupResponse:ret];
self.wakeUpTraceDict = nil;
} else {
@synchronized(self){
self.wakeUpTraceDict = ret;
}
}
}
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {
[Sharetrace handleSchemeLinkURL:url];
return NO;
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
[Sharetrace handleSchemeLinkURL:url];
return NO;
}
- (BOOL)application:(UIApplication*)application continueUserActivity:(NSUserActivity*)userActivity restorationHandler:(void (^)(NSArray*))restorationHandler {
[Sharetrace handleUniversalLink:userActivity];
return NO;
}
+ (BOOL)handleSchemeLinkURL:(NSURL * _Nullable)url {
return [Sharetrace handleSchemeLinkURL:url];
}
+ (BOOL)handleUniversalLink:(NSUserActivity * _Nullable)userActivity {
return [Sharetrace handleUniversalLink:userActivity];
}
@end
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint sharetrace_flutter_plugin.podspec' to validate before publishing.
#
Pod::Spec.new do |s|
s.name = 'sharetrace_flutter_plugin'
s.version = '1.0.4'
s.summary = 'Sharetrace flutter plugin.'
s.description = <<-DESC
Sharetrace flutter plugin.
DESC
s.homepage = 'https://www.sharetrace.com/'
s.license = { :file => '../LICENSE' }
s.author = { "ShareTrace" => "sharetrace@shoot.net.cn" }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.platform = :ios, '8.0'
s.dependency 'SharetraceSDK', "~> 2.3.2"
# Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
end
import 'dart:async';
import 'package:flutter/services.dart';
typedef Future<dynamic> ResponseHandler(Map<String, String> data);
class SharetraceFlutterPlugin {
static const MethodChannel _channel = const MethodChannel('sharetrace_flutter_plugin');
static SharetraceFlutterPlugin _instance;
SharetraceFlutterPlugin._internal() {
_channel.setMethodCallHandler(_onMethodHandle);
}
factory SharetraceFlutterPlugin.getInstance() => _getInstance();
static _getInstance() {
if (_instance == null) {
_instance = SharetraceFlutterPlugin._internal();
}
return _instance;
}
Future defaultHandler() async {}
ResponseHandler _installRespHandler;
ResponseHandler _wakeupRespHandler;
Future<Null> _onMethodHandle(MethodCall call) async {
if (call.method == "onInstallResponse") {
if (_installRespHandler != null) {
return _installRespHandler(call.arguments.cast<String, String>());
}
return defaultHandler();
} else if (call.method == "onWakeupResponse") {
if (_wakeupRespHandler != null) {
return _wakeupRespHandler(call.arguments.cast<String, String>());
}
return defaultHandler();
}
}
void init(){
_channel.invokeMethod("init");
}
void registerWakeupHandler(ResponseHandler responseHandler) {
_wakeupRespHandler = responseHandler;
_channel.invokeMethod("registerWakeup");
}
void getInstallTrace(ResponseHandler responseHandler, [int timeoutSeconds = 10]) {
var args = new Map();
args["timeoutSeconds"] = timeoutSeconds.toString();
this._installRespHandler = responseHandler;
_channel.invokeMethod("getInstallTrace", args);
}
}
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.5.0-nullsafety.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0-nullsafety.1"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0-nullsafety.3"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0-nullsafety.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0-nullsafety.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.15.0-nullsafety.3"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0-nullsafety.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.10-nullsafety.1"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0-nullsafety.3"
path:
dependency: transitive
description:
name: path
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.8.0-nullsafety.1"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.8.0-nullsafety.2"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.10.0-nullsafety.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0-nullsafety.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0-nullsafety.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0-nullsafety.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.19-nullsafety.2"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0-nullsafety.3"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0-nullsafety.3"
sdks:
dart: ">=2.10.0-110 <2.11.0"
flutter: ">=1.10.0"
name: sharetrace_flutter_plugin
description: Sharetrace flutter plugin.
version: 1.5.5
homepage: https://www.sharetrace.com/
environment:
sdk: ">=2.7.0 <3.0.0"
flutter: ">=1.10.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
# 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:
# This section identifies this Flutter project as a plugin project.
# The 'pluginClass' and Android 'package' identifiers should not ordinarily
# be modified. They are used by the tooling to maintain consistency when
# adding or updating assets for this project.
plugin:
platforms:
android:
package: com.sharetrace.sharetrace_flutter_plugin
pluginClass: SharetraceFlutterPlugin
ios:
pluginClass: SharetraceFlutterPlugin
# To add assets to your plugin package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.dev/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# To add custom fonts to your plugin package, 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
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts in packages, see
# https://flutter.dev/custom-fonts/#from-packages
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
const MethodChannel channel = MethodChannel('sharetrace_flutter_plugin');
TestWidgetsFlutterBinding.ensureInitialized();
setUp(() {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
return '42';
});
});
tearDown(() {
channel.setMockMethodCallHandler(null);
});
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment