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-11 16:09:39 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
c05ca8cd7e707333cc341055597a6004e6057c09
c05ca8cd
1 parent
e786d2ff
【需求】添加数据缓存和上报
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
162 additions
and
42 deletions
example/pubspec.lock
lib/auto_track/config/queue.dart
lib/auto_track/utils/track_model.dart
pubspec.yaml
example/pubspec.lock
View file @
c05ca8c
...
...
@@ -309,6 +309,22 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "7.0.0"
sqflite:
dependency: transitive
description:
name: sqflite
sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.3.3+1"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.5.4"
stack_trace:
dependency: transitive
description:
...
...
@@ -341,6 +357,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.1"
synchronized:
dependency: transitive
description:
name: synchronized
sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.0+1"
term_glyph:
dependency: transitive
description:
...
...
lib/auto_track/config/queue.dart
View file @
c05ca8c
...
...
@@ -3,27 +3,64 @@ import 'dart:convert';
import
'dart:io'
;
import
'dart:math'
;
import
'package:archive/archive.dart'
;
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
'package:path/path.dart'
as
path
;
import
'package:sqflite/sqflite.dart'
;
import
'../log/logger.dart'
;
class
AutoTrackQueue
{
static
final
AutoTrackQueue
instance
=
AutoTrackQueue
.
_
();
late
Database
database
;
Future
<
void
>
_lastTask
=
Future
.
value
();
void
post
(
Future
<
void
>
Function
()
task
)
{
_lastTask
=
_lastTask
.
then
((
_
)
=>
task
());
}
AutoTrackQueue
.
_
()
{
httpClient
.
badCertificateCallback
=
(
X509Certificate
cert
,
String
host
,
int
port
)
=>
true
;
//异步任务
post
(()
async
{
database
=
await
openTrackDatabase
();
});
}
Future
<
Database
>
openTrackDatabase
()
async
{
final
databasePath
=
await
getDatabasesPath
();
final
pathString
=
path
.
join
(
databasePath
,
'track.db'
);
return
openDatabase
(
pathString
,
onCreate:
(
db
,
version
)
{
return
db
.
execute
(
"CREATE TABLE track("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"event TEXT, "
"date DATE"
")"
,
);
},
version:
1
,
);
}
Timer
?
_timer
;
final
List
<
TrackModel
>
_queue
=
[];
final
httpClient
=
HttpClient
();
void
appendQueue
(
TrackModel
model
)
{
if
(
_timer
==
null
)
return
;
_queue
.
add
(
model
);
if
(
database
==
null
)
return
;
post
(()
async
{
await
database
.
insert
(
"track"
,
Track
(
event:
jsonEncode
(
model
.
toMap
()),
date:
DateTime
.
now
())
.
toMap
());
});
}
void
start
()
{
...
...
@@ -32,7 +69,7 @@ class AutoTrackQueue {
Duration
(
seconds:
AutoTrackConfigManager
.
instance
.
config
.
uploadInterval
??
10
),
(
timer
)
{
flush
(
);
post
(
flush
);
});
}
...
...
@@ -41,15 +78,24 @@ class AutoTrackQueue {
_timer
=
null
;
}
/**
* todo 存储数据库,目前会丢失数据
*/
void
flush
()
{
AutoTrackLogger
.
getInstance
().
debug
(
'start flush
${_queue.length}
'
);
Future
<
void
>
flush
()
async
{
AutoTrackLogger
.
getInstance
().
debug
(
"@@@start flush"
);
if
(
database
==
null
)
{
AutoTrackLogger
.
getInstance
().
debug
(
'数据库未初始化,跳过 flush'
);
return
;
}
final
List
<
TrackModel
>
uploadList
=
[];
List
<
Map
<
String
,
dynamic
>>
events
=
await
database
.
query
(
"track"
,
columns:
[
"id"
,
"event"
,
"date"
],
limit:
100
);
for
(
var
event
in
events
)
{
Track
model
=
Track
.
fromMap
(
event
);
uploadList
.
add
(
TrackModel
.
fromMap
(
jsonDecode
(
model
.
event
)));
}
if
(
_queue
.
isEmpty
)
return
;
final
List
<
TrackModel
>
uploadList
=
List
.
from
(
_queue
);
_queue
.
clear
();
final
config
=
AutoTrackConfigManager
.
instance
.
config
;
final
baseDeviceInfo
=
AutoTrackConfigManager
.
instance
.
baseDeviceInfo
;
final
host
=
config
.
host
;
...
...
@@ -64,14 +110,12 @@ class AutoTrackQueue {
return
;
}
if
(
host
!=
null
)
{
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
=
""
;
...
...
@@ -90,8 +134,8 @@ class AutoTrackQueue {
manufacturer
=
'apple'
;
}
else
if
(
baseDeviceInfo
is
OhosDeviceInfo
)
{
os
=
'ohos'
;
os_version
=
baseDeviceInfo
.
versionId
??
""
;
model
=
baseDeviceInfo
.
productModel
??
""
;
os_version
=
baseDeviceInfo
.
versionId
??
""
;
model
=
baseDeviceInfo
.
productModel
??
""
;
manufacturer
=
'huawei'
;
}
}
...
...
@@ -129,11 +173,10 @@ class AutoTrackQueue {
// "$is_first_day": true
};
event
.
params
.
forEach
((
k
,
v
)
{
event
.
params
.
forEach
((
k
,
v
)
{
properties
[
k
]
=
v
;
});
datas
.
add
({
'_track_id'
:
id
,
'time'
:
t
,
...
...
@@ -141,57 +184,63 @@ class AutoTrackQueue {
'distinct_id'
:
config
.
userId
??
AutoTrackConfigManager
.
instance
.
deviceId
,
'anonymous_id'
:
AutoTrackConfigManager
.
instance
.
deviceId
,
'event'
:
event
.
type
,
'properties'
:
properties
'event'
:
event
.
type
,
'properties'
:
properties
});
AutoTrackLogger
.
getInstance
().
debug
(
'upload => data =>
$datas
'
);
});
try
{
final
httpClient
=
HttpClient
();
final
request
=
await
httpClient
.
postUrl
(
Uri
.
parse
(
host
+
UPLOAD
));
httpClient
.
postUrl
(
Uri
.
parse
(
host
+
UPLOAD
))
.
then
((
HttpClientRequest
request
)
{
request
.
headers
.
set
(
HttpHeaders
.
contentTypeHeader
,
"application/json"
);
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
"
);
AutoTrackLogger
.
getInstance
().
debug
(
"压缩数据:
$jsonPayload
"
);
request
.
write
(
jsonPayload
);
return
request
.
close
();
}).
then
((
HttpClientResponse
response
)
{
final
response
=
await
request
.
close
();
final
responseCode
=
response
.
statusCode
;
print
(
"responseCode:
$responseCode
"
);
response
.
transform
(
utf8
.
decoder
).
join
().
then
((
responseBody
)
{
AutoTrackLogger
.
getInstance
().
debug
(
"responseCode:
$responseCode
"
);
final
responseBody
=
await
response
.
transform
(
utf8
.
decoder
).
join
();
if
(
responseCode
>=
HttpStatus
.
ok
&&
responseCode
<
HttpStatus
.
multipleChoices
)
{
// 状态码 200 - 300 认为是成功
print
(
"response:
$responseBody
"
);
AutoTrackLogger
.
getInstance
().
debug
(
'upload => success ret_code:
$responseCode
ret_content:
$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
);
}
else
{
//批量删除
for
(
var
event
in
events
)
{
await
database
.
delete
(
"track"
,
where:
"id = ?"
,
whereArgs:
[
event
[
'id'
]]);
}
}
}
catch
(
e
)
{
print
(
"JSON 解析错误:
$e
"
);
AutoTrackLogger
.
getInstance
().
debug
(
"JSON 解析错误:
$e
"
);
}
}
else
{
AutoTrackLogger
.
getInstance
().
debug
(
'upload => fail ret_code:
$responseCode
ret_content:
$responseBody
'
);
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
'
);
}
catch
(
e
)
{
AutoTrackLogger
.
getInstance
().
debug
(
"网络请求错误:
$e
"
);
}
});
});
}
}
...
...
@@ -212,3 +261,39 @@ class AutoTrackQueue {
}
}
}
class
Track
{
final
int
?
id
;
final
String
event
;
final
DateTime
date
;
Track
({
this
.
id
,
required
this
.
event
,
required
this
.
date
,
});
// 从 Map 中创建 Track 对象
factory
Track
.
fromMap
(
Map
<
String
,
dynamic
>
map
)
{
return
Track
(
id:
map
[
'id'
]
as
int
,
event:
map
[
'event'
]
as
String
,
date:
DateTime
.
fromMillisecondsSinceEpoch
(
map
[
'date'
]
as
int
),
);
}
// 将 Track 对象转换为 Map
Map
<
String
,
dynamic
>
toMap
()
{
return
{
'id'
:
id
,
'event'
:
event
,
'date'
:
date
.
millisecondsSinceEpoch
,
};
}
// 用于调试的 toString 方法
@override
String
toString
()
{
return
'Track{id:
$id
, event:
$event
, date:
$date
}'
;
}
}
...
...
lib/auto_track/utils/track_model.dart
View file @
c05ca8c
...
...
@@ -13,4 +13,14 @@ class TrackModel {
'params'
:
params
,
};
}
//frommap
factory
TrackModel
.
fromMap
(
Map
<
String
,
dynamic
>
map
)
{
return
TrackModel
(
map
[
'type'
]
as
String
,
map
[
'time'
]
as
int
,
map
[
'params'
]
as
Map
<
String
,
dynamic
>,
map
[
'key'
]
as
String
,
);
}
}
...
...
pubspec.yaml
View file @
c05ca8c
...
...
@@ -25,6 +25,7 @@ dependencies:
plugin_platform_interface
:
^2.0.2
uuid
:
^4.3.3
archive
:
^3.3.7
# 确保使用最新版本
sqflite
:
^2.3.0
...
...
Please
register
or
login
to post a comment