Toggle navigation
Toggle navigation
This project
Loading...
Sign in
flutter_package
/
auto_track_plugin
Go to a project
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
顾海波
2025-02-08 16:24:26 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
e786d2ffeda81632cbd46504d4d35ad247e452a3
e786d2ff
1 parent
95344cbc
【需求】针对大数据平台兼容,todo保存数据库恢复
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
575 additions
and
111 deletions
README.md
example/android/build.gradle
example/android/gradle/wrapper/gradle-wrapper.properties
example/lib/main.dart
example/pubspec.lock
lib/auto_track/config/config.dart
lib/auto_track/config/manager.dart
lib/auto_track/config/queue.dart
lib/auto_track/listener/page_view/page_stack.dart
lib/auto_track/track/track.dart
lib/auto_track/utils/sign.dart
pubspec.yaml
README.md
View file @
e786d2f
...
...
@@ -173,3 +173,44 @@ class PageA extends StatelessWidget {
}
```
```
{
"_track_id": 2102988140,
"time": 1738981685455,
"type": "track",
"distinct_id": "afa4c7a98b3f6467",
"anonymous_id": "afa4c7a98b3f6467",
"event": "$AppEnd",
"properties": {
"$carrier": "NONE",
"$os_version": "13",
"$model": "C310CS",
"$os": "Android",
"$screen_width": 1200,
"$brand": "BOE",
"$screen_height": 1920,
"$app_version": "2.0.2",
"$lib": "Android",
"$device_id": "afa4c7a98b3f6467",
"$app_name": "Ewin Reading",
"$lib_version": "5.3.3",
"$timezone_offset": -480,
"$app_id": "com.ewin.tech.reading",
"$mac": "020000000000",
"$manufacturer": "BOE",
"$sn": "C310CS014820000006",
"$wifi": true,
"$network_type": "WIFI",
"$screen_orientation": "portrait",
"$screen_brightness": 204,
"$screen_name": "com.boe.usercenterlibrary.LoginActivity",
"$title": "Ewin Reading",
"$event_duration": 0,
"$lib_method": "autoTrack",
"$is_first_day": true
}
}
```
...
...
example/android/build.gradle
View file @
e786d2f
buildscript
{
ext
.
kotlin_version
=
'1.7.10'
repositories
{
maven
{
url
'https://maven.aliyun.com/repository/google/'
}
maven
{
url
'https://maven.aliyun.com/repository/public'
}
maven
{
url
'https://maven.aliyun.com/repository/central'
}
google
()
mavenCentral
()
}
...
...
@@ -12,6 +16,9 @@ buildscript {
allprojects
{
repositories
{
maven
{
url
'https://maven.aliyun.com/repository/google/'
}
maven
{
url
'https://maven.aliyun.com/repository/public'
}
maven
{
url
'https://maven.aliyun.com/repository/central'
}
google
()
mavenCentral
()
}
...
...
example/android/gradle/wrapper/gradle-wrapper.properties
View file @
e786d2f
...
...
@@ -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-7.5-all.zip
distributionUrl
=
https
\:
//
mirrors.cloud.tencent.com/gradle
/gradle-7.5-all.zip
...
...
example/lib/main.dart
View file @
e786d2f
...
...
@@ -19,20 +19,29 @@ class _MyAppState extends State<MyApp> {
void
initState
()
{
AutoTrack
()
.
config
(
AutoTrackConfig
(
samplingRate:
0.9
,
// 采样率
host:
"https://sitigrs.boeart.cn"
,
appKey:
"KEY_oVfNOQLQ"
,
appSecret:
"w21tRLJt7LBVYJtD"
,
samplingRate:
1
,
// 采样率
enableUpload
:
true
,
uploadInterval:
5
,
eventHandler:
(
model
)
=>
{
print
(
'event handler
${model.type}
'
)},
pageConfigs:
[
AutoTrackPageConfig
<
Home
>(
pageID:
'home'
,
),
AutoTrackPageConfig
<
PageA
>(
pageID:
'page_a'
,
),
]))
// .enablePageLeave()
// .enablePageView()
// .enableClick()
// .enableDrag()
// .enableIgnoreNullKey()
.
enableLog
()
.
enable
()
.
enablePageLeave
()
.
enablePageView
()
.
enableClick
()
.
enableDrag
()
.
enableIgnoreNullKey
()
.
enableLog
();
;
super
.
initState
();
// AutoTrack().updateSampleRate(0.5); 更新采样率
...
...
example/pubspec.lock
View file @
e786d2f
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
android_id:
dependency: transitive
description:
name: android_id
sha256: "748ba5f93dd5c497e675d8eaa1404346ce4d1794464ea654576ff192d153b92a"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.4.0"
archive:
dependency: transitive
description:
name: archive
sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.6.1"
async:
dependency: transitive
description:
name: async
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "2.11.0"
auto_track:
...
...
@@ -15,13 +31,13 @@ packages:
path: ".."
relative: true
source: path
version: "0.
0.1
"
version: "0.
1.0
"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "2.1.1"
characters:
...
...
@@ -29,7 +45,7 @@ packages:
description:
name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "1.3.0"
clock:
...
...
@@ -37,7 +53,7 @@ packages:
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "1.1.1"
collection:
...
...
@@ -45,57 +61,74 @@ packages:
description:
name: collection
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "1.18.0"
crypto:
dependency: transitive
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
url: "https://pub.dev"
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.
3
"
version: "3.0.
6
"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
url: "https://pub.dev"
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.6"
dio:
version: "1.0.8"
device_info_plus:
dependency: transitive
description:
path: "packages/device_info_plus/device_info_plus"
ref: HEAD
resolved-ref: ff774d947bd15d9be08629e3ccfb29dda2e864bd
url: "https://gitee.com/openharmony-sig/flutter_plus_plugins"
source: git
version: "9.1.0"
device_info_plus_platform_interface:
dependency: transitive
description:
name: dio
sha256: "49af28382aefc53562459104f64d16b9dfd1e8ef68c862d5af436cc8356ce5a8"
url: "https://pub.dev"
name: device_info_plus_platform_interface
sha256: "0b04e02b30791224b31969eb1b50d723498f402971bff3630bca2ba839bd1ed2"
url: "https://pub.flutter-io.cn"
source: hosted
version: "
5.4.1
"
version: "
7.0.2
"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "1.3.1"
ffi:
dependency: transitive
description:
name: ffi
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.3"
file:
dependency: transitive
description:
name: file
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
url: "https://pub.dev"
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
url: "https://pub.flutter-io.cn"
source: hosted
version: "
6.1.4
"
version: "
7.0.0
"
fixnum:
dependency: transitive
description:
name: fixnum
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
url: "https://pub.dev"
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.
0
"
version: "1.1.
1
"
flutter:
dependency: "direct main"
description: flutter
...
...
@@ -111,7 +144,7 @@ packages:
description:
name: flutter_lints
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "2.0.3"
flutter_test:
...
...
@@ -119,17 +152,30 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
fuchsia_remote_debug_protocol:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
http:
dependency: transitive
description:
name: http
sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "4.0.2"
integration_test:
...
...
@@ -137,70 +183,111 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
url: "https://pub.flutter-io.cn"
source: hosted
version: "10.0.4"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.3"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "2.1.1"
matcher:
dependency: transitive
description:
name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev"
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.16"
version: "0.12.16
+1
"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev"
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.
5
.0"
version: "0.
8
.0"
meta:
dependency: transitive
description:
name: meta
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
url: "https://pub.dev"
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.10.0"
version: "1.12.0"
package_info_plus:
dependency: transitive
description:
path: "packages/package_info_plus/package_info_plus"
ref: HEAD
resolved-ref: ff774d947bd15d9be08629e3ccfb29dda2e864bd
url: "https://gitee.com/openharmony-sig/flutter_plus_plugins"
source: git
version: "4.2.0"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.1"
path:
dependency: transitive
description:
name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.dev"
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.
8.3
"
version: "1.
9.0
"
platform:
dependency: transitive
description:
name: platform
sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102
url: "https://pub.dev"
sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.
2
"
version: "3.1.
4
"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "2.1.8"
process:
dependency: transitive
description:
name: process
sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
url: "https://pub.dev"
sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32"
url: "https://pub.flutter-io.cn"
source: hosted
version: "
4.2.4
"
version: "
5.0.2
"
sky_engine:
dependency: transitive
description: flutter
...
...
@@ -211,7 +298,7 @@ packages:
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "1.10.0"
sprintf:
...
...
@@ -219,7 +306,7 @@ packages:
description:
name: sprintf
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "7.0.0"
stack_trace:
...
...
@@ -227,7 +314,7 @@ packages:
description:
name: stack_trace
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "1.11.1"
stream_channel:
...
...
@@ -235,7 +322,7 @@ packages:
description:
name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "2.1.2"
string_scanner:
...
...
@@ -243,7 +330,7 @@ packages:
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "1.2.0"
sync_http:
...
...
@@ -251,7 +338,7 @@ packages:
description:
name: sync_http
sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "0.3.1"
term_glyph:
...
...
@@ -259,65 +346,81 @@ packages:
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
url: "https://pub.dev"
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.
6.1
"
version: "0.
7.0
"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "1.3.2"
uuid:
dependency: transitive
description:
name: uuid
sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8
url: "https://pub.dev"
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.
3.3
"
version: "4.
5.1
"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
url: "https://pub.
dev
"
url: "https://pub.
flutter-io.cn
"
source: hosted
version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583
url: "https://pub.dev"
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1
1.10.0
"
version: "1
4.2.1
"
web:
dependency: transitive
description:
name: web
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
url: "https://pub.dev"
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
url: "https://pub.flutter-io.cn"
source: hosted
version: "
0.3
.0"
version: "
1.1
.0"
webdriver:
dependency: transitive
description:
name: webdriver
sha256: "3c923e918918feeb90c4c9fdf1fe39220fa4c0e8e2c0fffaded174498ef86c49"
url: "https://pub.dev"
sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.3"
win32:
dependency: transitive
description:
name: win32
sha256: "68d1e89a91ed61ad9c370f9f8b6effed9ae5e0ede22a270bdfa6daf79fc2290a"
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.5.4"
win32_registry:
dependency: transitive
description:
name: win32_registry
sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852"
url: "https://pub.flutter-io.cn"
source: hosted
version: "
3.0.2
"
version: "
1.1.5
"
sdks:
dart: ">=3.2.3 <4.0.0"
flutter: ">=3.3.0"
dart: ">=3.4.0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"
...
...
lib/auto_track/config/config.dart
View file @
e786d2f
...
...
@@ -24,9 +24,9 @@ class AutoTrackConfig {
this
.
useCustomRoute
=
false
,
// 使用自定义路由
this
.
ignoreElementKeys
=
const
[],
// 忽略key列表
this
.
ignoreElementStringKeys
=
const
[],
this
.
enablePageView
=
tru
e
,
// 监听页面进入事件
this
.
enablePageView
=
fals
e
,
// 监听页面进入事件
this
.
enablePageLeave
=
false
,
// 监听页面离开事件
this
.
enableClick
=
tru
e
,
// 监听点击事件
this
.
enableClick
=
fals
e
,
// 监听点击事件
this
.
enableDrag
=
false
,
// 监听拖拽事件
this
.
enableIgnoreNullKey
=
false
,
// 忽略空key事件
this
.
httpRequestConfig
,
...
...
@@ -43,6 +43,7 @@ class AutoTrackConfig {
String
?
trackId
;
String
?
userId
;
String
?
uniqueId
;
String
?
token
;
/// 采样率,默认 1 (100%)
double
samplingRate
;
...
...
lib/auto_track/config/manager.dart
View file @
e786d2f
...
...
@@ -6,16 +6,25 @@ import 'package:crypto/crypto.dart';
import
'package:device_info_plus/device_info_plus.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:package_info_plus/package_info_plus.dart'
;
import
'package:http/http.dart'
as
http
;
// 使用 http 包
import
'../log/logger.dart'
;
import
'../utils/sign.dart'
;
import
'config.dart'
;
typedef
UpdateConfigFunc
=
AutoTrackConfig
Function
(
AutoTrackConfig
);
const
String
GET_TOKEN
=
"/equipment-auth/equipment/getToken/v1"
;
const
String
UPLOAD
=
"/bd-datapoint/equipment/dataPoint/zip"
;
class
AutoTrackConfigManager
{
static
final
AutoTrackConfigManager
instance
=
AutoTrackConfigManager
.
_
();
AutoTrackConfigManager
.
_
()
{
PackageInfo
.
fromPlatform
().
then
((
value
)
=>
_appVersion
=
value
.
version
);
PackageInfo
.
fromPlatform
().
then
(
(
value
)
{
_appVersion
=
value
.
version
;
_appName
=
value
.
appName
;
});
DeviceInfoPlugin
().
deviceInfo
.
then
((
value
)
{
_deviceInfo
=
value
.
data
;
_baseDeviceInfo
=
value
;
...
...
@@ -26,7 +35,14 @@ class AutoTrackConfigManager {
String
_appVersion
=
''
;
String
get
appVersion
=>
_appVersion
;
String
_appName
=
''
;
String
get
appName
=>
_appName
;
BaseDeviceInfo
?
_baseDeviceInfo
;
BaseDeviceInfo
?
get
baseDeviceInfo
=>
_baseDeviceInfo
;
String
?
_deviceId
;
String
?
get
deviceId
=>
_deviceId
;
...
...
@@ -67,6 +83,9 @@ class AutoTrackConfigManager {
}
else
if
(
_baseDeviceInfo
is
MacOsDeviceInfo
)
{
_deviceId
=
'
${(_baseDeviceInfo as MacOsDeviceInfo).hostName}
-
${(_baseDeviceInfo as MacOsDeviceInfo).computerName}
'
;
}
else
if
(
_baseDeviceInfo
is
OhosDeviceInfo
)
{
_deviceId
=
'
${(_baseDeviceInfo as OhosDeviceInfo).odID}${config.appKey}
'
;
}
else
{
_deviceId
=
null
;
}
...
...
@@ -74,8 +93,72 @@ class AutoTrackConfigManager {
void
enableAutoTrack
(
bool
enable
)
{
_autoTrackEnable
=
enable
;
//获取token
getToken
(
false
);
}
bool
_isGetting
=
false
;
void
getToken
(
bool
refreshToken
)
async
{
if
(
_isGetting
)
{
return
;
}
_isGetting
=
true
;
AutoTrackLogger
.
getInstance
().
debug
(
'track getToken => start'
);
await
Future
.
delayed
(
const
Duration
(
milliseconds:
2000
));
try
{
int
currentSeconds
=
DateTime
.
now
().
millisecondsSinceEpoch
;
Map
<
String
,
String
>
sParams
=
{
"productKey"
:
_config
.
appKey
??
''
,
"equipmentId"
:
_deviceId
??
''
,
"otherInfo"
:
_appName
,
"time"
:
currentSeconds
.
toString
(),
};
AutoTrackLogger
.
getInstance
().
debug
(
'track getToken => param
$sParams
'
);
String
sign
=
SignUtil
.
sign
(
sParams
,
_config
.
appSecret
!);
sParams
[
"sign"
]
=
sign
;
// 发送 POST 请求(使用 http 包)
final
response
=
await
http
.
post
(
Uri
.
parse
(
_config
.
host
!
+
GET_TOKEN
),
body:
sParams
,
)
.
timeout
(
const
Duration
(
seconds:
10
));
// 添加超时
// 处理响应
if
(
response
.
statusCode
==
200
)
{
final
jsonResponse
=
jsonDecode
(
response
.
body
)
as
Map
<
String
,
dynamic
>;
final
code
=
jsonResponse
[
'code'
]
as
int
;
if
(
code
==
200
)
{
final
tokenValue
=
jsonResponse
[
'data'
]
as
String
;
AutoTrackLogger
.
getInstance
().
debug
(
'track getToken => success
$tokenValue
'
);
_config
.
token
=
tokenValue
;
}
else
{
AutoTrackLogger
.
getInstance
().
debug
(
'track getToken => fail
$code
'
);
_reGetToken
(
refreshToken
);
// 重试
}
}
else
{
AutoTrackLogger
.
getInstance
().
debug
(
'track getToken => failCode:
${response.statusCode}
'
);
_reGetToken
(
refreshToken
);
// 非 200 状态码重试
}
}
catch
(
e
)
{
print
(
'BoeDataAPI Error:
$e
'
);
_reGetToken
(
refreshToken
);
// 异常重试
}
finally
{
_isGetting
=
false
;
// 无论成功与否,重置标志
}
}
void
_reGetToken
(
bool
refreshToken
)
{
Future
.
delayed
(
const
Duration
(
seconds:
2
),
()
=>
getToken
(
refreshToken
));
}
List
<
AutoTrackPageConfig
>
get
pageConfigs
=>
_config
.
pageConfigs
;
bool
get
useCustomRoute
=>
_config
.
useCustomRoute
;
...
...
@@ -119,3 +202,4 @@ class AutoTrackConfigManager {
bool
get
ignoreNullKeyEnable
=>
_config
.
enableIgnoreNullKey
;
}
...
...
lib/auto_track/config/queue.dart
View file @
e786d2f
...
...
@@ -5,6 +5,8 @@ import 'dart:math';
import
'package:auto_track/auto_track/config/manager.dart'
;
import
'package:auto_track/auto_track/utils/track_model.dart'
;
import
'package:archive/archive.dart'
;
import
'package:device_info_plus/device_info_plus.dart'
;
import
'../log/logger.dart'
;
...
...
@@ -39,11 +41,17 @@ class AutoTrackQueue {
_timer
=
null
;
}
/**
* todo 存储数据库,目前会丢失数据
*/
void
flush
()
{
AutoTrackLogger
.
getInstance
().
debug
(
'start flush
${_queue.length}
'
);
if
(
_queue
.
isEmpty
)
return
;
final
uploadList
=
List
.
from
(
_queue
);
final
List
<
TrackModel
>
uploadList
=
List
.
from
(
_queue
);
_queue
.
clear
();
final
config
=
AutoTrackConfigManager
.
instance
.
config
;
final
baseDeviceInfo
=
AutoTrackConfigManager
.
instance
.
baseDeviceInfo
;
final
host
=
config
.
host
;
if
(
config
.
samplingRate
!=
1
)
{
if
(
Random
().
nextDouble
()
>
config
.
samplingRate
)
{
...
...
@@ -51,31 +59,156 @@ class AutoTrackQueue {
return
;
}
}
String
?
token
=
config
.
token
;
if
(
token
==
null
)
{
return
;
}
if
(
host
!=
null
)
{
final
t
=
DateTime
.
now
().
millisecondsSinceEpoch
;
httpClient
.
postUrl
(
Uri
.
parse
(
host
)).
then
((
request
)
{
request
.
headers
.
contentType
=
ContentType
.
json
;
request
.
write
(
json
.
encode
({
'app_key'
:
config
.
appKey
??
''
,
'signature'
:
config
.
signature
!(
t
),
't'
:
t
,
'user_id'
:
config
.
userId
??
''
,
'track_id'
:
config
.
trackId
??
''
,
'unique_id'
:
config
.
uniqueId
??
AutoTrackConfigManager
.
instance
.
deviceId
,
'device_id'
:
AutoTrackConfigManager
.
instance
.
deviceId
,
'data_list'
:
uploadList
.
map
((
e
)
=>
e
.
toMap
()).
toList
(),
'app_version'
:
AutoTrackConfigManager
.
instance
.
appVersion
,
'device_info'
:
AutoTrackConfigManager
.
instance
.
deviceInfo
}));
List
<
Map
>
datas
=
[];
uploadList
.
forEach
((
event
)
{
Random
random
=
Random
.
secure
();
int
id
=
random
.
nextInt
(
1
<<
32
);
// 模拟 Java 的 nextInt()
final
t
=
DateTime
.
now
().
millisecondsSinceEpoch
;
String
os
=
""
;
String
os_version
=
""
;
String
model
=
""
;
String
manufacturer
=
""
;
if
(
baseDeviceInfo
!=
null
)
{
if
(
baseDeviceInfo
is
AndroidDeviceInfo
)
{
os
=
'android'
;
os_version
=
baseDeviceInfo
.
version
.
release
;
model
=
baseDeviceInfo
.
model
;
manufacturer
=
baseDeviceInfo
.
manufacturer
;
}
else
if
(
baseDeviceInfo
is
IosDeviceInfo
)
{
os
=
'ios'
;
os_version
=
baseDeviceInfo
.
systemVersion
;
model
=
baseDeviceInfo
.
model
;
manufacturer
=
'apple'
;
}
else
if
(
baseDeviceInfo
is
OhosDeviceInfo
)
{
os
=
'ohos'
;
os_version
=
baseDeviceInfo
.
versionId
??
""
;
model
=
baseDeviceInfo
.
productModel
??
""
;
manufacturer
=
'huawei'
;
}
}
final
properties
=
{
'
\
$os
'
:
os
,
'
\
$os_version
'
:
os_version
,
'
\
$model
'
:
model
,
'
\
$lib
'
:
"Flutter"
,
'
\
$app_name
'
:
AutoTrackConfigManager
.
instance
.
appName
,
'
\
$app_version
'
:
AutoTrackConfigManager
.
instance
.
appVersion
,
'
\
$device_id
'
:
AutoTrackConfigManager
.
instance
.
deviceId
,
'
\
$timezone_offset
'
:
getZoneOffset
(),
"
\
$manufacturer
"
:
manufacturer
,
// "$carrier": "NONE",
// "$os_version": "13",
// "$model": "C310CS",
// "$os": "Android",
// "$screen_width": 1200,
// "$brand": "BOE",
// "$screen_height": 1920,
// "$device_id": "afa4c7a98b3f6467",
// "$app_name": "Ewin Reading",
// "$lib_version": "5.3.3",
// "$timezone_offset": -480,
// "$app_id": "com.ewin.tech.reading",
// "$mac": "020000000000",
// "$manufacturer": "BOE",
// "$sn": "C310CS014820000006",
// "$wifi": true,
// "$network_type": "WIFI",
// "$screen_orientation": "portrait",
// "$screen_brightness": 204,
// "$event_duration": 0,
// "$lib_method": "autoTrack",
// "$is_first_day": true
};
event
.
params
.
forEach
((
k
,
v
){
properties
[
k
]
=
v
;
});
datas
.
add
({
'_track_id'
:
id
,
'time'
:
t
,
'type'
:
'track'
,
'distinct_id'
:
config
.
userId
??
AutoTrackConfigManager
.
instance
.
deviceId
,
'anonymous_id'
:
AutoTrackConfigManager
.
instance
.
deviceId
,
'event'
:
event
.
type
,
'properties'
:
properties
});
AutoTrackLogger
.
getInstance
().
debug
(
'upload => data =>
$datas
'
);
});
httpClient
.
postUrl
(
Uri
.
parse
(
host
+
UPLOAD
))
.
then
((
HttpClientRequest
request
)
{
request
.
headers
.
set
(
HttpHeaders
.
contentTypeHeader
,
"application/json"
);
request
.
headers
.
set
(
"token"
,
token
);
// 设置 header
// 对数据进行压缩并进行 Base64 编码
final
compressedData
=
encodeData
(
jsonEncode
(
datas
));
final
jsonPayload
=
jsonEncode
({
"base64Str"
:
compressedData
});
print
(
"压缩数据:
$jsonPayload
"
);
request
.
write
(
jsonPayload
);
return
request
.
close
();
}).
then
((
response
)
{
AutoTrackLogger
.
getInstance
()
.
debug
(
'upload status =>
${response.statusCode}
'
);
}).
catchError
((
error
)
{
AutoTrackLogger
.
getInstance
().
error
(
error
);
}).
then
((
HttpClientResponse
response
)
{
final
responseCode
=
response
.
statusCode
;
print
(
"responseCode:
$responseCode
"
);
response
.
transform
(
utf8
.
decoder
).
join
().
then
((
responseBody
)
{
if
(
responseCode
>=
HttpStatus
.
ok
&&
responseCode
<
HttpStatus
.
multipleChoices
)
{
// 状态码 200 - 300 认为是成功
print
(
"response:
$responseBody
"
);
AutoTrackLogger
.
getInstance
().
debug
(
'upload => success ret_code:
$responseCode
ret_content:
$responseBody
'
);
try
{
final
jsonResponse
=
jsonDecode
(
responseBody
);
if
(
jsonResponse
[
"code"
]
==
4005
)
{
AutoTrackConfigManager
.
instance
.
getToken
(
true
);
}
}
catch
(
e
)
{
print
(
"JSON 解析错误:
$e
"
);
}
}
else
{
AutoTrackLogger
.
getInstance
().
debug
(
'upload => fail ret_code:
$responseCode
ret_content:
$responseBody
'
);
}
if
(
responseCode
<
HttpStatus
.
ok
||
responseCode
>=
HttpStatus
.
multipleChoices
)
{
AutoTrackLogger
.
getInstance
().
debug
(
'upload => fail ret_code:
$responseCode
ret_content:
$responseBody
'
);
}
});
});
}
}
int
getZoneOffset
()
{
final
now
=
DateTime
.
now
();
final
localOffset
=
now
.
timeZoneOffset
.
inMinutes
;
// 获取时区偏移量(分钟)
return
-
localOffset
;
// 取反,保持与 Java 代码一致
}
String
encodeData
(
String
rawMessage
)
{
try
{
// 使用 GZip 压缩
List
<
int
>
compressed
=
GZipEncoder
().
encode
(
utf8
.
encode
(
rawMessage
))!;
// Base64 编码
return
base64
.
encode
(
compressed
);
}
catch
(
e
)
{
throw
FormatException
(
'Invalid data:
${e.toString()}
'
);
}
}
}
...
...
lib/auto_track/listener/page_view/page_stack.dart
View file @
e786d2f
...
...
@@ -185,6 +185,7 @@ class _PageTask {
if
(
leavePage
!=
null
&&
!
leavePage
.
pageInfo
.
ignore
)
{
leavePage
.
pageInfo
.
timer
.
end
();
Track
.
instance
.
pageLeave
(
leavePage
.
pageInfo
);
Track
.
instance
.
pageDuration
(
leavePage
.
pageInfo
);
}
if
(
enterPage
!=
null
&&
!
enterPage
.
pageInfo
.
ignore
)
{
enterPage
.
pageInfo
.
timer
.
start
();
...
...
lib/auto_track/track/track.dart
View file @
e786d2f
...
...
@@ -15,9 +15,9 @@ class Track {
Map
<
String
,
dynamic
>
_appendPageInfo
(
Map
<
String
,
dynamic
>
params
,
PageInfo
pageInfo
)
{
params
[
'page_key'
]
=
pageInfo
.
pageKey
;
params
[
'
page_
title'
]
=
pageInfo
.
pageTitle
;
params
[
'
\
$
title
'
]
=
pageInfo
.
pageTitle
;
params
[
'page_manual_key'
]
=
pageInfo
.
pageManualKey
;
params
[
'
page_path'
]
=
pageInfo
.
pagePath
;
params
[
'
\
$screen_name
'
]
=
pageInfo
.
pageKey
;
params
[
'is_back'
]
=
pageInfo
.
isBack
?
1
:
0
;
return
params
;
}
...
...
@@ -37,6 +37,19 @@ class Track {
AutoTrackLogger
.
getInstance
().
debug
(
'track page_view =>
$params
'
);
}
void
pageDuration
(
PageInfo
pageInfo
)
{
if
(!
AutoTrackConfigManager
.
instance
.
autoTrackEnable
)
{
return
;
}
Map
<
String
,
dynamic
>
params
=
_appendPageInfo
({},
pageInfo
);
params
[
'use_time'
]
=
pageInfo
.
timer
.
duration
.
inMilliseconds
;
params
[
'use_name'
]
=
pageInfo
.
pageKey
;
_TrackPlugin
.
pageDuration
(
params
);
AutoTrackLogger
.
getInstance
().
debug
(
'track page_leave =>
$params
'
);
}
void
pageLeave
(
PageInfo
pageInfo
)
{
if
(!
AutoTrackConfigManager
.
instance
.
autoTrackEnable
)
{
return
;
...
...
@@ -130,8 +143,15 @@ class _TrackPlugin {
AutoTrackQueue
.
instance
.
appendQueue
(
model
);
}
static
void
pageDuration
(
Map
<
String
,
dynamic
>
params
)
{
var
model
=
TrackModel
(
'page_duration_event'
,
DateTime
.
now
().
millisecondsSinceEpoch
,
params
,
params
[
'page_manual_key'
]);
AutoTrackConfigManager
.
instance
.
config
.
eventHandler
?.
call
(
model
);
AutoTrackQueue
.
instance
.
appendQueue
(
model
);
}
static
void
click
(
Map
<
String
,
dynamic
>
params
)
{
var
model
=
TrackModel
(
'
c
lick'
,
DateTime
.
now
().
millisecondsSinceEpoch
,
params
,
params
[
'element_manual_key'
]);
var
model
=
TrackModel
(
'
\
$AppC
lick
'
,
DateTime
.
now
().
millisecondsSinceEpoch
,
params
,
params
[
'element_manual_key'
]);
AutoTrackConfigManager
.
instance
.
config
.
eventHandler
?.
call
(
model
);
AutoTrackQueue
.
instance
.
appendQueue
(
model
);
}
...
...
lib/auto_track/utils/sign.dart
0 → 100644
View file @
e786d2f
import
'dart:convert'
;
import
'package:crypto/crypto.dart'
;
class
SignUtil
{
/// 签名方法
static
String
sign
(
Map
<
String
,
String
>
sPara
,
String
appecret
)
{
String
prestr
=
createLinkString
(
paraFilter
(
sPara
));
// 把数组所有元素,
String
mysign
=
md5Sign
(
prestr
,
appecret
,
"utf-8"
);
return
mysign
;
}
/// 除去数组中的空值和签名参数
static
Map
<
String
,
String
>
paraFilter
(
Map
<
String
,
String
>
sArray
)
{
Map
<
String
,
String
>
result
=
{};
if
(
sArray
==
null
||
sArray
.
isEmpty
)
{
return
result
;
}
sArray
.
forEach
((
key
,
value
)
{
if
(
value
==
null
||
value
.
isEmpty
||
key
.
toLowerCase
()
==
"sign"
||
key
.
toLowerCase
()
==
"sign_type"
)
{
return
;
}
result
[
key
]
=
value
;
});
return
result
;
}
/// 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
static
String
createLinkString
(
Map
<
String
,
String
>
params
)
{
List
<
String
>
keys
=
params
.
keys
.
toList
();
keys
.
sort
();
String
prestr
=
""
;
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++)
{
String
key
=
keys
[
i
];
String
value
=
params
[
key
]!;
if
(
i
==
keys
.
length
-
1
)
{
// 拼接时,不包括最后一个&字符
prestr
=
"
$prestr$key
=
$value
"
;
}
else
{
prestr
=
"
$prestr$key
=
$value
&"
;
}
}
return
prestr
;
}
/// MD5签名
static
String
md5Sign
(
String
prestr
,
String
secret
,
String
encoding
)
{
String
toSign
=
prestr
+
secret
;
var
bytes
=
utf8
.
encode
(
toSign
);
var
digest
=
md5
.
convert
(
bytes
);
return
digest
.
toString
();
}
}
...
...
pubspec.yaml
View file @
e786d2f
...
...
@@ -10,12 +10,24 @@ environment:
dependencies
:
android_id
:
^0.4.0
crypto
:
^3.0.3
device_info_plus
:
^10.1.2
# device_info_plus: ^10.1.2
device_info_plus
:
git
:
url
:
https://gitee.com/openharmony-sig/flutter_plus_plugins
path
:
packages/device_info_plus/device_info_plus
flutter
:
sdk
:
flutter
package_info_plus
:
^8.0.1
# package_info_plus: ^8.0.1
package_info_plus
:
git
:
url
:
https://gitee.com/openharmony-sig/flutter_plus_plugins
path
:
packages/package_info_plus/package_info_plus
plugin_platform_interface
:
^2.0.2
uuid
:
^4.3.3
archive
:
^3.3.7
# 确保使用最新版本
dev_dependencies
:
flutter_test
:
...
...
Please
register
or
login
to post a comment