Przeglądaj źródła

feat: 接入airbridge

Destiny 10 miesięcy temu
rodzic
commit
da9937b422

+ 15 - 0
airbridge.json

@@ -0,0 +1,15 @@
+{
+  "sdkEnabled": true,
+  "logLevel": "debug",
+  "autoStartTrackingEnabled": true,
+  "autoDetermineTrackingAuthorizationTimeoutInSecond": 30,
+  "trackMetaDeferredAppLinkEnabled": false,
+  "sessionTimeoutInSecond": 300,
+  "metaInstallReferrerAppID": "",
+  "trackAirbridgeDeeplinkOnlyEnabled": true,
+  "trackInSessionLifecycleEventEnabled": true,
+  "hashUserInformationEnabled": true,
+  "clearEventBufferOnInitializeEnabled": false,
+  "eventTransmitIntervalInSecond": 0,
+  "isHandleAirbridgeDeeplinkOnly": true
+}

+ 31 - 0
ios/Podfile.lock

@@ -1,4 +1,8 @@
 PODS:
+  - airbridge-ios-sdk (4.2.2)
+  - airbridge_flutter_sdk (4.2.1):
+    - airbridge-ios-sdk (= 4.2.2)
+    - Flutter
   - app_tracking_transparency (0.0.1):
     - Flutter
   - apple_pay (0.0.1):
@@ -40,14 +44,24 @@ PODS:
   - sqflite_darwin (0.0.4):
     - Flutter
     - FlutterMacOS
+  - UMCommon (7.5.2):
+    - UMDevice
+  - UMDevice (3.4.0)
+  - umeng_common_sdk (0.0.1):
+    - Flutter
+    - UMCommon
+    - UMDevice
   - video_player_avfoundation (0.0.1):
     - Flutter
     - FlutterMacOS
+  - wakelock_plus (0.0.1):
+    - Flutter
   - webview_flutter_wkwebview (0.0.1):
     - Flutter
     - FlutterMacOS
 
 DEPENDENCIES:
+  - airbridge_flutter_sdk (from `.symlinks/plugins/airbridge_flutter_sdk/ios`)
   - app_tracking_transparency (from `.symlinks/plugins/app_tracking_transparency/ios`)
   - apple_pay (from `.symlinks/plugins/apple_pay/ios`)
   - camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
@@ -65,15 +79,22 @@ DEPENDENCIES:
   - photo_manager (from `.symlinks/plugins/photo_manager/ios`)
   - sensors_plus (from `.symlinks/plugins/sensors_plus/ios`)
   - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
+  - umeng_common_sdk (from `.symlinks/plugins/umeng_common_sdk/ios`)
   - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
+  - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
   - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
 
 SPEC REPOS:
   trunk:
+    - airbridge-ios-sdk
     - MMKV
     - MMKVCore
+    - UMCommon
+    - UMDevice
 
 EXTERNAL SOURCES:
+  airbridge_flutter_sdk:
+    :path: ".symlinks/plugins/airbridge_flutter_sdk/ios"
   app_tracking_transparency:
     :path: ".symlinks/plugins/app_tracking_transparency/ios"
   apple_pay:
@@ -108,12 +129,18 @@ EXTERNAL SOURCES:
     :path: ".symlinks/plugins/sensors_plus/ios"
   sqflite_darwin:
     :path: ".symlinks/plugins/sqflite_darwin/darwin"
+  umeng_common_sdk:
+    :path: ".symlinks/plugins/umeng_common_sdk/ios"
   video_player_avfoundation:
     :path: ".symlinks/plugins/video_player_avfoundation/darwin"
+  wakelock_plus:
+    :path: ".symlinks/plugins/wakelock_plus/ios"
   webview_flutter_wkwebview:
     :path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
 
 SPEC CHECKSUMS:
+  airbridge-ios-sdk: dc9373851397d23b5930966454af805929102c3d
+  airbridge_flutter_sdk: 297265f08d31fbdec608e9cc0434f7ab48c826e8
   app_tracking_transparency: e169b653478da7bb15a6c61209015378ca73e375
   apple_pay: 631cbd73016e371a5f3f31c1d9fa2444740e80be
   camera_avfoundation: dd002b0330f4981e1bbcb46ae9b62829237459a4
@@ -133,7 +160,11 @@ SPEC CHECKSUMS:
   photo_manager: ff695c7a1dd5bc379974953a2b5c0a293f7c4c8a
   sensors_plus: 7229095999f30740798f0eeef5cd120357a8f4f2
   sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
+  UMCommon: 72513a01ebca2dead52f2112b4d7c6196dbbe412
+  UMDevice: dcdf7ec167387837559d149fbc7d793d984faf82
+  umeng_common_sdk: a8abd7f86dfd013dbbeeae587ee143760c6582f2
   video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3
+  wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56
   webview_flutter_wkwebview: 0982481e3d9c78fd5c6f62a002fcd24fc791f1e4
 
 PODFILE CHECKSUM: 5e1afdb9869de7eeb6b0abacc114654ae68d56ef

+ 38 - 0
ios/Runner.xcodeproj/project.pbxproj

@@ -201,6 +201,8 @@
 				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
 				A8EA13BF7346A66478B5F40B /* [CP] Embed Pods Frameworks */,
 				159DABA5C7E8C2C8DEDB2134 /* [CP] Copy Pods Resources */,
+				F2B20345ED2A3FE673969348 /* [Airbridge] Copy airbridge.json */,
+				597B1AD32C38AF4B2823484E /* [Airbridge] Create LibraryInfo.json */,
 			);
 			buildRules = (
 			);
@@ -327,6 +329,24 @@
 			shellPath = /bin/sh;
 			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
 		};
+		597B1AD32C38AF4B2823484E /* [Airbridge] Create LibraryInfo.json */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+			);
+			name = "[Airbridge] Create LibraryInfo.json";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "echo '{\"wrapperName\": \"airbridge-flutter-sdk\", \"wrapperVersion\": \"4.2.1\"}' > \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/LibraryInfo.json\"\n";
+		};
 		9740EEB61CF901F6004384FC /* Run Script */ = {
 			isa = PBXShellScriptBuildPhase;
 			alwaysOutOfDate = 1;
@@ -381,6 +401,24 @@
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
+		F2B20345ED2A3FE673969348 /* [Airbridge] Copy airbridge.json */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+			);
+			name = "[Airbridge] Copy airbridge.json";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "if [ -r \"${SRCROOT}/../airbridge.json\" ]; then\n    cp \"${SRCROOT}/../airbridge.json\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/airbridge.json\"\nfi";
+		};
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */

+ 2 - 0
ios/Runner/AppDelegate.swift

@@ -1,6 +1,7 @@
 import Flutter
 import StoreKit
 import UIKit
+import airbridge_flutter_sdk
 
 @main
 @objc class AppDelegate: FlutterAppDelegate {
@@ -9,6 +10,7 @@ import UIKit
     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
   ) -> Bool {
     GeneratedPluginRegistrant.register(with: self)
+      AirbridgeFlutter.initializeSDK(name: "cleanpro", token: "649deecf9821441da88270073b5cf8d0")
     return super.application(application, didFinishLaunchingWithOptions: launchOptions)
   }
 }

+ 27 - 0
lib/data/api/event_api.dart

@@ -0,0 +1,27 @@
+import 'package:clean/data/api/request/attr_push_request.dart';
+import 'package:clean/data/api/request/event_push_request.dart';
+import 'package:dio/dio.dart';
+import 'package:retrofit/error_logger.dart';
+import 'package:retrofit/http.dart';
+
+import '../../base/base_request.dart';
+import '../../base/base_response.dart';
+import '../consts/constants.dart';
+import 'network_module.dart';
+
+part 'event_api.g.dart';
+
+@RestApi()
+abstract class EventApi {
+  factory EventApi(Dio dio, {String baseUrl}) = _EventApi;
+
+  @POST("/central/open/v1/event/push")
+  Future<BaseResponse> eventPush(
+      @Body() EventPushRequest request);
+
+  @POST("/central/open/v1/promotion/attribution/push/airbridge")
+  Future<BaseResponse> attrPush(
+      @Body() AttrPushRequest request);
+}
+
+final eventApi = EventApi(eventDio, baseUrl: Constants.centralUrl);

+ 21 - 0
lib/data/api/network_module.dart

@@ -137,6 +137,20 @@ class _NetworkModule {
     ));
     return dio;
   }
+
+  static Dio _createEventDio() {
+    Dio dio = Dio(BaseOptions(
+        headers: httpHeaders,
+    ));
+    dio.interceptors.add(PrettyDioLogger(
+      requestHeader: true,
+      requestBody: true,
+      responseBody: true,
+      responseHeader: true,
+      enabled: BuildConfig.isDebug,
+    ));
+    return dio;
+  }
 }
 
 final defaultDio = _NetworkModule._createDefaultDio();
@@ -144,3 +158,10 @@ final defaultDio = _NetworkModule._createDefaultDio();
 final streamDio = _NetworkModule._createStreamDio();
 
 final fileDio = _NetworkModule._createFileDio();
+
+final eventDio = _NetworkModule._createEventDio();
+
+/// 自定义Header
+Map<String, dynamic> httpHeaders = {
+  'AppKey': '4808237ea7d1462a8de80c8ce7ae5c06',
+};

+ 21 - 0
lib/data/api/request/attr_push_request.dart

@@ -0,0 +1,21 @@
+import 'package:clean/base/base_request.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+part 'attr_push_request.g.dart';
+
+@JsonSerializable()
+class AttrPushRequest extends BaseRequest {
+  @JsonKey(name: 'clientType')
+  String clientType;
+
+  @JsonKey(name: 'clientId')
+  String clientId;
+
+  @JsonKey(name: 'resultJson')
+  String resultJson;
+
+  AttrPushRequest(this.resultJson, this.clientId, this.clientType);
+
+  @override
+  Map<String, dynamic> toJson() => _$AttrPushRequestToJson(this);
+}

+ 41 - 0
lib/data/api/request/event_push_request.dart

@@ -0,0 +1,41 @@
+import 'package:clean/base/base_request.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+part 'event_push_request.g.dart';
+
+@JsonSerializable()
+class EventPushRequest {
+  @JsonKey(name: 'ak')
+  late String ak;
+
+  @JsonKey(name: 'cp')
+  late Map<String, dynamic> cp;
+
+  @JsonKey(name: 'es')
+  List<Map<String, dynamic>> es;
+
+  @JsonKey(name: 'pr')
+  Map<String, dynamic>? pr;
+
+  @JsonKey(name: 'ft')
+  late int ft;
+
+  EventPushRequest(this.ft, this.es, Map<String, dynamic>? pr) {
+    ak = "4808237ea7d1462a8de80c8ce7ae5c06";
+    cp = <String, dynamic>{};
+    cp["\$pkg"] = BaseRequest().packageName;
+    cp["\$aplf"] = BaseRequest().appPlatform;
+    cp["\$chnl"] = BaseRequest().channelName;
+    cp["\$aver"] = BaseRequest().appVersionName;
+    cp["\$avec"] = BaseRequest().appVersionCode;
+    cp["\$Idfa"] = BaseRequest().idfa;
+    cp["\$idfv"] = BaseRequest().idfv;
+    cp["\$tplf"] = BaseRequest().tgPlatform;
+    cp["\$osv"] = BaseRequest().tgPlatform;
+    cp["\$modl"] = BaseRequest().model;
+    cp["\$brnd"] = BaseRequest().brand;
+  }
+
+  @override
+  Map<String, dynamic> toJson() => _$EventPushRequestToJson(this);
+}

+ 1 - 0
lib/data/consts/constants.dart

@@ -27,6 +27,7 @@ class Constants {
   static const String isIntro = 'isIntroduction';
   static const String isFirstClickHomeClean = 'isFirstClickClean';
   static String baseUrl = getBaseUrl();
+  static String centralUrl = "https://central-os-api.atmob.com";
 
   static const String appDefaultChannel = "Android";
   static const int appDefaultAppId = 0;

+ 22 - 0
lib/data/repositories/event_repository.dart

@@ -0,0 +1,22 @@
+import 'package:clean/base/base_request.dart';
+import 'package:clean/data/api/event_api.dart';
+import 'package:clean/data/api/request/attr_push_request.dart';
+import 'package:clean/data/api/request/event_push_request.dart';
+import 'package:clean/utils/http_handler.dart';
+
+class EventRepository {
+
+  EventRepository._();
+
+  Future<void> eventPush(
+      int ft, List<Map<String, dynamic>> es, {Map<String, dynamic>? pr}) {
+    return eventApi.eventPush(EventPushRequest(ft, es, pr)).then(HttpHandler.handle(true));
+  }
+
+  Future<void> attrPush(
+      String clientId, String clientType, String resultJson) {
+    return eventApi.attrPush(AttrPushRequest(resultJson, clientId, clientType)).then(HttpHandler.handle(true));
+  }
+}
+
+final EventRepository eventRepository = EventRepository._();

+ 47 - 2
lib/handler/event_handler.dart

@@ -1,4 +1,6 @@
+import 'package:airbridge_flutter_sdk/airbridge_flutter_sdk.dart';
 import 'package:clean/data/consts/event_report_id.dart';
+import 'package:clean/data/repositories/event_repository.dart';
 import 'package:clean/sdk/umeng/umeng_helper.dart';
 
 import '../data/consts/constants.dart';
@@ -17,7 +19,20 @@ class EventHandler {
         ToastUtil.show('$eventId ${params.toString()}');
       }
     }
-    UmengHelper.onEvent(eventId, params ?? {"defaultKey": "default"});
+    Airbridge.trackEvent(category: eventId, customAttributes: params);
+    var time = DateTime.now().millisecondsSinceEpoch;
+    List<Map<String, dynamic>> es = <Map<String, dynamic>>[];
+    Map<String, dynamic> esItem = <String, dynamic>{};
+    esItem["ty"] = "track";
+    esItem["ev"] = eventId;
+    esItem["ti"] = time;
+    es.add(esItem);
+    if (params != null) {
+      eventRepository.eventPush(time, es, pr: params);
+    } else {
+      eventRepository.eventPush(time, es);
+    }
+    // UmengHelper.onEvent(eventId, params ?? {"defaultKey": "default"});
   }
 
   static void reportPay(
@@ -38,6 +53,36 @@ class EventHandler {
       ToastUtil.show(
           'PAY: 金额:$priceFen 订单号:$orderId 商品名:$itemName 支付方式:$payWayStr');
     }
-    UmengHelper.onEvent(EventId.event_02007,  {"price": priceFen, "orderId": orderId, "itemName": itemName, "payWay": payWay});
+    // UmengHelper.onEvent(EventId.event_02007,  {"price": priceFen, "orderId": orderId, "itemName": itemName, "payWay": payWay});
+
+    var time = DateTime.now().millisecondsSinceEpoch;
+    List<Map<String, dynamic>> es = <Map<String, dynamic>>[];
+    Map<String, dynamic> esItem = <String, dynamic>{};
+    esItem["ty"] = "track";
+    esItem["ev"] = "\$payment";
+    esItem["ti"] = time;
+    es.add(esItem);
+    Map<String, dynamic> params = <String, dynamic>{};
+    params["\$pitem"] = itemName;
+    params["\$pmon"] = orderId;
+    params["\$pcur"] = "USD";
+    params["\$pamt"] = priceFen;
+    params["\$pmtd"] = "appstore";
+    eventRepository.eventPush(time, es, pr: params);
+  }
+
+  // 首次启动应用
+  static void pushInstall() {
+
+    if (isFirstIntoApp()) {
+      var time = DateTime.now().millisecondsSinceEpoch;
+      List<Map<String, dynamic>> es = <Map<String, dynamic>>[];
+      Map<String, dynamic> esItem = <String, dynamic>{};
+      esItem["ty"] = "track";
+      esItem["ev"] = "\$install";
+      esItem["ti"] = time;
+      es.add(esItem);
+      eventRepository.eventPush(time, es);
+    }
   }
 }

+ 15 - 0
lib/module/home/home_controller.dart

@@ -1,8 +1,11 @@
+import 'dart:convert';
 import 'dart:io';
 
+import 'package:airbridge_flutter_sdk/airbridge_flutter_sdk.dart';
 import 'package:classify_photo/classify_photo.dart';
 import 'package:clean/base/base_controller.dart';
 import 'package:clean/data/consts/constants.dart';
+import 'package:clean/data/repositories/event_repository.dart';
 import 'package:clean/data/repositories/user_repository.dart';
 import 'package:clean/module/image_picker/image_picker_util.dart';
 import 'package:clean/module/locations_photo/locations_photo_view.dart';
@@ -87,6 +90,18 @@ class HomeController extends BaseController {
 
     await userRepository.getUserInfo();
 
+    if (userRepository.userInfo.value != null) {
+       Airbridge.setUserID(userRepository.userInfo.value!.ssid);
+       
+       // 接收归因结果
+       Airbridge.setOnAttributionReceived((result) {
+         print(result);
+         eventRepository.attrPush(userRepository.userInfo.value!.ssid, "airbridge", jsonEncode(result));
+       });
+    }
+    
+    EventHandler.pushInstall();
+
     if (!isFirstIntoApp() && !userRepository.isVip()) {
       Get.toNamed(RoutePath.discount);
     }

+ 57 - 1
pubspec.lock

@@ -14,6 +14,14 @@ packages:
     description: dart
     source: sdk
     version: "0.3.3"
+  airbridge_flutter_sdk:
+    dependency: "direct main"
+    description:
+      name: airbridge_flutter_sdk
+      sha256: "81396932d540bf3fa29c4e59f205dc40d2ee167a20555e8392fc4793fcabcafc"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "4.2.1"
   analyzer:
     dependency: transitive
     description:
@@ -69,6 +77,14 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.11.0"
+  atmob_channel_reader:
+    dependency: "direct main"
+    description:
+      name: atmob_channel_reader
+      sha256: e855cd64162fcb37f7f1f5ae9ee71418ba36c2d9f1b4d58e540afb576bab6888
+      url: "http://pub.v8dashen.com"
+    source: hosted
+    version: "0.0.2"
   boolean_selector:
     dependency: transitive
     description:
@@ -221,6 +237,14 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.0.3"
+  chewie:
+    dependency: "direct main"
+    description:
+      name: chewie
+      sha256: "645fbca3f22309381edb5af59a4c8aa544a3d3872d7b7b7c986c2b18b3bdd265"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "1.10.0"
   classify_photo:
     dependency: "direct main"
     description:
@@ -324,6 +348,14 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.2.0"
+  dbus:
+    dependency: transitive
+    description:
+      name: dbus
+      sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "0.7.11"
   device_info_plus:
     dependency: "direct main"
     description:
@@ -1301,6 +1333,14 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.4.0"
+  umeng_common_sdk:
+    dependency: "direct main"
+    description:
+      name: umeng_common_sdk
+      sha256: ba4ac629987f88cb42cb89a0a885be1a93cce8080bb6134014fe2ce4df7bac88
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "1.2.8"
   uuid:
     dependency: transitive
     description:
@@ -1334,7 +1374,7 @@ packages:
     source: hosted
     version: "2.1.4"
   video_player:
-    dependency: transitive
+    dependency: "direct main"
     description:
       name: video_player
       sha256: "4a8c3492d734f7c39c2588a3206707a05ee80cef52e8c7f3b2078d430c84bc17"
@@ -1389,6 +1429,22 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "14.3.0"
+  wakelock_plus:
+    dependency: transitive
+    description:
+      name: wakelock_plus
+      sha256: "36c88af0b930121941345306d259ec4cc4ecca3b151c02e3a9e71aede83c615e"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "1.2.10"
+  wakelock_plus_platform_interface:
+    dependency: transitive
+    description:
+      name: wakelock_plus_platform_interface
+      sha256: "70e780bc99796e1db82fe764b1e7dcb89a86f1e5b3afb1db354de50f2e41eb7a"
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "1.2.2"
   watcher:
     dependency: transitive
     description:

+ 3 - 0
pubspec.yaml

@@ -126,6 +126,9 @@ dependencies:
 
   #友盟
   umeng_common_sdk: ^1.2.8
+
+  airbridge_flutter_sdk: ^4.2.1
+
   #渠道包信息
   atmob_channel_reader:
     version: ^0.0.2