import 'package:flutter/cupertino.dart'; import 'package:injectable/injectable.dart'; import 'package:location/data/api/atmob_api.dart'; import 'package:location/di/get_it.dart'; import 'package:location/utils/async_util.dart'; import 'package:location/utils/date_util.dart'; import 'package:mobile_use_statistics/flutter_mobile_statistics.dart'; import 'package:battery_plus/battery_plus.dart'; import '../../utils/atmob_log.dart'; import '../../utils/http_handler.dart'; import '../api/request/electric_request.dart'; import '../api/request/location_phone_event_request.dart'; import '../bean/phone_event_bean.dart'; import 'account_repository.dart'; import 'dart:async'; @lazySingleton class PhoneEventRepository { final AtmobApi atmobApi; static final String tag = 'PhoneEventRepository'; Duration _taskIntervalTime = Duration(minutes: 5); Timer? _reportTimer; CancelableFuture? lockScreenCancelableFuture; CancelableFuture? batteryCancelableFuture; final battery = Battery(); PhoneEventRepository(this.atmobApi) { startReportPhoneEvent(); } static PhoneEventRepository getInstance() { return getIt.get(); } static Future hasUseStatisticsPermission() { return MobileUseStatistics.hasUseStatisticsPermission(); } static Future requestUseStatisticsPermission() async { final hasPermission = await MobileUseStatistics.requestUseStatisticsPermission(); if (hasPermission) { PhoneEventRepository.getInstance().startReportPhoneEvent(); } return hasPermission; } void setTaskIntervalTime(Duration duration) { _taskIntervalTime = duration; if (_reportTimer != null && _reportTimer!.isActive) { _reportTimer!.cancel(); _schedulePeriodicReport(); } } //开始事件上报 ,锁屏事件以及手机电量等 void startReportPhoneEvent() { if (AccountRepository.token == null || AccountRepository.token?.isEmpty == true) { return; } _runReportTasks(); _schedulePeriodicReport(); } void _schedulePeriodicReport() { AtmobLog.d(tag, '_schedulePeriodicReport'); _reportTimer?.cancel(); _reportTimer = Timer.periodic(_taskIntervalTime, (_) => _runReportTasks()); } void _runReportTasks() { //上报手机锁屏事件上报 _startLockScreenEvent(); //上报手机电量 _startPhoneElectricEvent(); } void _startPhoneElectricEvent() { AtmobLog.d(tag, '_startPhoneElectricEvent'); batteryCancelableFuture?.cancel(); batteryCancelableFuture = AsyncUtil.retryWithExponentialBackoff( () => _commitBatteryEvent(), 4, initialInterval: Duration(seconds: 3)); batteryCancelableFuture!.catchError((error) { AtmobLog.d(tag, ' startPhoneElectricEvent 重试最大次数 异常 error:$error'); _startPhoneElectricEvent(); }); } Future _commitBatteryEvent() async { int batteryValue = await getBatteryLevel(); return _electricReport(batteryValue); } ///停止事件上报 /// void stopReportPhoneEvent() { AtmobLog.d(tag, 'stopReportPhoneEvent'); _reportTimer?.cancel(); lockScreenCancelableFuture?.cancel(); batteryCancelableFuture?.cancel(); } void _startLockScreenEvent() async { //判断是否有事件上报权限 if (!await hasUseStatisticsPermission()) { return; } AtmobLog.d(tag, '_startLockScreenEvent'); lockScreenCancelableFuture?.cancel(); lockScreenCancelableFuture = AsyncUtil.retryWithExponentialBackoff( () => _commitLockScreenEvent(), 4, initialInterval: Duration(seconds: 3)); lockScreenCancelableFuture!.catchError((error) { AtmobLog.d(tag, 'startLockScreenEvent 重试最大次数 异常 error:$error'); startReportPhoneEvent(); }); } Future _commitLockScreenEvent() async { //收集手机事件数据上报 DateTime now = DateUtil.getNow(); final startTime = DateUtil.getStartOfDayTimestamp(now).millisecondsSinceEpoch; final endTime = DateUtil.getEndOfDayTimestamp(now).millisecondsSinceEpoch; final eventList = await MobileUseStatistics.getLockScreenStatistics( startTime: startTime, endTime: endTime); final events = eventList ?.map((event) => PhoneEventBean(startTime: event.startTime, endTime: event.endTime)) .toList(); if (events == null || events.isEmpty) { return; } return _locationPhoneEvent(events); } // 获取电量百分比 Future getBatteryLevel() async { final level = await battery.batteryLevel; debugPrint('Battery level: $level%'); return level; } Future _locationPhoneEvent(List events) { return atmobApi .locationPhoneEvent(LocationPhoneEventRequest(events)) .then(HttpHandler.handle(true)); } Future _electricReport(int electric) { return atmobApi .electricReport(ElectricRequest(electric)) .then(HttpHandler.handle(true)); } }