first commit
This commit is contained in:
182
lib/services/time_tracking_service.dart
Normal file
182
lib/services/time_tracking_service.dart
Normal file
@@ -0,0 +1,182 @@
|
||||
import 'package:flutter/services.dart';
|
||||
import '../models/app_usage.dart';
|
||||
import '../database/app_usage_dao.dart';
|
||||
import 'category_service.dart';
|
||||
import 'statistics_service.dart';
|
||||
|
||||
class TimeTrackingService {
|
||||
static const MethodChannel _channel = MethodChannel('autotime_tracker/time_tracking');
|
||||
|
||||
final AppUsageDao _appUsageDao = AppUsageDao();
|
||||
final CategoryService _categoryService = CategoryService();
|
||||
final StatisticsService _statisticsService = StatisticsService();
|
||||
|
||||
/// 检查权限状态
|
||||
Future<bool> hasPermission() async {
|
||||
try {
|
||||
final result = await _channel.invokeMethod<bool>('hasPermission');
|
||||
return result ?? false;
|
||||
} catch (e) {
|
||||
print('Error checking permission: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 请求权限
|
||||
Future<bool> requestPermission() async {
|
||||
try {
|
||||
final result = await _channel.invokeMethod<bool>('requestPermission');
|
||||
return result ?? false;
|
||||
} catch (e) {
|
||||
print('Error requesting permission: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取应用使用数据(从系统 API)
|
||||
Future<List<AppUsageData>> getAppUsageFromSystem({
|
||||
required DateTime startTime,
|
||||
required DateTime endTime,
|
||||
}) async {
|
||||
try {
|
||||
final result = await _channel.invokeMethod<List<dynamic>>('getAppUsage', {
|
||||
'startTime': startTime.millisecondsSinceEpoch,
|
||||
'endTime': endTime.millisecondsSinceEpoch,
|
||||
});
|
||||
|
||||
if (result == null) return [];
|
||||
|
||||
return result
|
||||
.map((item) => AppUsageData.fromMap(Map<String, dynamic>.from(item)))
|
||||
.toList();
|
||||
} catch (e) {
|
||||
print('Error getting app usage from system: $e');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/// 同步应用使用数据到数据库
|
||||
Future<void> syncAppUsageToDatabase({
|
||||
required DateTime startTime,
|
||||
required DateTime endTime,
|
||||
}) async {
|
||||
try {
|
||||
// 1. 从系统获取数据
|
||||
final systemData = await getAppUsageFromSystem(
|
||||
startTime: startTime,
|
||||
endTime: endTime,
|
||||
);
|
||||
|
||||
if (systemData.isEmpty) {
|
||||
print('No app usage data from system');
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 转换为 AppUsage 模型并分类
|
||||
final appUsages = <AppUsage>[];
|
||||
for (final data in systemData) {
|
||||
// 获取分类
|
||||
final category = await _categoryService.getCategory(data.packageName);
|
||||
|
||||
// 创建 AppUsage 对象
|
||||
final usage = AppUsage(
|
||||
packageName: data.packageName,
|
||||
appName: data.appName,
|
||||
startTime: data.startTime,
|
||||
endTime: data.endTime,
|
||||
duration: data.duration,
|
||||
category: category,
|
||||
deviceUnlockCount: data.deviceUnlockCount ?? 0,
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
);
|
||||
|
||||
appUsages.add(usage);
|
||||
}
|
||||
|
||||
// 3. 批量插入数据库
|
||||
if (appUsages.isNotEmpty) {
|
||||
await _appUsageDao.batchInsertAppUsages(appUsages);
|
||||
print('Synced ${appUsages.length} app usage records to database');
|
||||
}
|
||||
|
||||
// 4. 更新今日统计
|
||||
await _statisticsService.refreshTodayStats();
|
||||
} catch (e) {
|
||||
print('Error syncing app usage to database: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// 同步今日数据
|
||||
Future<void> syncTodayData() async {
|
||||
final now = DateTime.now();
|
||||
final startOfDay = DateTime(now.year, now.month, now.day);
|
||||
final endOfDay = startOfDay.add(const Duration(days: 1));
|
||||
|
||||
await syncAppUsageToDatabase(
|
||||
startTime: startOfDay,
|
||||
endTime: endOfDay,
|
||||
);
|
||||
}
|
||||
|
||||
/// 启动后台追踪
|
||||
Future<void> startBackgroundTracking() async {
|
||||
try {
|
||||
await _channel.invokeMethod('startBackgroundTracking');
|
||||
} catch (e) {
|
||||
print('Error starting background tracking: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// 停止后台追踪
|
||||
Future<void> stopBackgroundTracking() async {
|
||||
try {
|
||||
await _channel.invokeMethod('stopBackgroundTracking');
|
||||
} catch (e) {
|
||||
print('Error stopping background tracking: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// 检查后台追踪状态
|
||||
Future<bool> isBackgroundTrackingActive() async {
|
||||
try {
|
||||
final result = await _channel.invokeMethod<bool>('isBackgroundTrackingActive');
|
||||
return result ?? false;
|
||||
} catch (e) {
|
||||
print('Error checking background tracking status: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 系统返回的应用使用数据模型
|
||||
class AppUsageData {
|
||||
final String packageName;
|
||||
final String appName;
|
||||
final DateTime startTime;
|
||||
final DateTime endTime;
|
||||
final int duration; // 秒
|
||||
final int? deviceUnlockCount;
|
||||
|
||||
AppUsageData({
|
||||
required this.packageName,
|
||||
required this.appName,
|
||||
required this.startTime,
|
||||
required this.endTime,
|
||||
required this.duration,
|
||||
this.deviceUnlockCount,
|
||||
});
|
||||
|
||||
factory AppUsageData.fromMap(Map<String, dynamic> map) {
|
||||
return AppUsageData(
|
||||
packageName: map['packageName'] as String,
|
||||
appName: map['appName'] as String,
|
||||
startTime: DateTime.fromMillisecondsSinceEpoch(map['startTime'] as int),
|
||||
endTime: DateTime.fromMillisecondsSinceEpoch(map['endTime'] as int),
|
||||
duration: map['duration'] as int,
|
||||
deviceUnlockCount: map['deviceUnlockCount'] as int?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user