尝试解决二次启动时文件读取问题

This commit is contained in:
2026-07-05 00:59:41 +08:00
parent c7ee563e84
commit 8e93cbeed2
3 changed files with 182 additions and 61 deletions
@@ -4,6 +4,7 @@ import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.os.BatteryManager import android.os.BatteryManager
import android.os.Build import android.os.Build
@@ -20,18 +21,17 @@ import java.io.BufferedReader
import java.io.InputStreamReader import java.io.InputStreamReader
class MainActivity : FlutterActivity() { class MainActivity : FlutterActivity() {
// ---------- 充电状态 ----------
private val CHARGE_CHANNEL = "com.lxh.battery_health/charge" private val CHARGE_CHANNEL = "com.lxh.battery_health/charge"
private val EVENT_CHANNEL = "com.lxh.battery_health/charge_events" private val EVENT_CHANNEL = "com.lxh.battery_health/charge_events"
private var eventSink: EventChannel.EventSink? = null private var eventSink: EventChannel.EventSink? = null
// ---------- SAF 相关 ----------
private val SAF_CHANNEL = "com.lxh.battery_health/saf" private val SAF_CHANNEL = "com.lxh.battery_health/saf"
private var safResult: MethodChannel.Result? = null private var safResult: MethodChannel.Result? = null
private var safUri: Uri? = null private var safUri: Uri? = null
private val FOLDER_PICKER_REQUEST = 1001 private val FOLDER_PICKER_REQUEST = 1001
private val PREF_NAME = "battery_health_prefs"
private val KEY_SAF_URI = "saf_uri"
// ---------- 充电广播接收器 ----------
private val chargeReceiver = object : BroadcastReceiver() { private val chargeReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
intent ?: return intent ?: return
@@ -42,6 +42,46 @@ class MainActivity : FlutterActivity() {
} }
} }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
android.util.Log.d("BatteryHealth", "onCreate 开始")
try {
val prefs: SharedPreferences = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
val uriString = prefs.getString(KEY_SAF_URI, null)
android.util.Log.d("BatteryHealth", "SharedPreferences URI: $uriString")
if (uriString != null) {
safUri = Uri.parse(uriString)
android.util.Log.d("BatteryHealth", "恢复 SAF URI 成功: $safUri")
}
} catch (e: Exception) {
android.util.Log.e("BatteryHealth", "恢复 URI 异常: ${e.message}")
}
android.util.Log.d("BatteryHealth", "onCreate 结束,safUri = $safUri")
}
private fun saveUri(uri: Uri) {
try {
val prefs: SharedPreferences = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
prefs.edit().putString(KEY_SAF_URI, uri.toString()).apply()
android.util.Log.d("BatteryHealth", "保存 SAF URI: $uri")
} catch (e: Exception) {
android.util.Log.e("BatteryHealth", "保存 URI 失败: ${e.message}")
}
}
private fun restoreUri(uriString: String) {
try {
safUri = Uri.parse(uriString)
android.util.Log.d("BatteryHealth", "通过 MethodChannel 恢复 URI: $safUri")
// 同时保存到 SharedPreferences
val prefs: SharedPreferences = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
prefs.edit().putString(KEY_SAF_URI, uriString).apply()
} catch (e: Exception) {
android.util.Log.e("BatteryHealth", "restoreUri 失败: ${e.message}")
}
}
private fun sendChargeState(isCharging: Boolean) { private fun sendChargeState(isCharging: Boolean) {
val chargeType = if (isCharging) { val chargeType = if (isCharging) {
val batteryIntent = registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) val batteryIntent = registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
@@ -66,7 +106,6 @@ class MainActivity : FlutterActivity() {
status == BatteryManager.BATTERY_STATUS_FULL status == BatteryManager.BATTERY_STATUS_FULL
} }
// ---------- SAF 方法 ----------
private fun openFolderPicker() { private fun openFolderPicker() {
try { try {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
@@ -100,7 +139,8 @@ class MainActivity : FlutterActivity() {
val takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION val takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
contentResolver.takePersistableUriPermission(uri, takeFlags) contentResolver.takePersistableUriPermission(uri, takeFlags)
safUri = uri safUri = uri
android.util.Log.d("BatteryHealth", "SAF URI: $uri") saveUri(uri)
android.util.Log.d("BatteryHealth", "SAF 授权成功 URI: $uri")
safResult?.success(uri.toString()) safResult?.success(uri.toString())
} catch (e: Exception) { } catch (e: Exception) {
android.util.Log.e("BatteryHealth", "SAF 授权失败: ${e.message}") android.util.Log.e("BatteryHealth", "SAF 授权失败: ${e.message}")
@@ -118,9 +158,13 @@ class MainActivity : FlutterActivity() {
} }
private fun listFiles(): List<String> { private fun listFiles(): List<String> {
android.util.Log.d("BatteryHealth", "listFiles 被调用,safUri = $safUri")
val result = mutableListOf<String>() val result = mutableListOf<String>()
val docId = getTreeDocId() val docId = getTreeDocId()
if (docId == null || docId.isEmpty()) return result if (docId == null || docId.isEmpty()) {
android.util.Log.e("BatteryHealth", "docId 为空")
return result
}
try { try {
val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(safUri!!, docId) val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(safUri!!, docId)
@@ -134,7 +178,7 @@ class MainActivity : FlutterActivity() {
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
android.util.Log.e("BatteryHealth", "列出文件失败: ${e.message}") android.util.Log.e("BatteryHealth", "列出文件失败: ${e.message}", e)
} }
return result return result
} }
@@ -178,11 +222,9 @@ class MainActivity : FlutterActivity() {
return fileUri?.let { readFile(it) } return fileUri?.let { readFile(it) }
} }
// ---------- Flutter 通道配置 ----------
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine) super.configureFlutterEngine(flutterEngine)
// 充电状态通道
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHARGE_CHANNEL) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHARGE_CHANNEL)
.setMethodCallHandler { call, result -> .setMethodCallHandler { call, result ->
if (call.method == "getChargeState") { if (call.method == "getChargeState") {
@@ -205,10 +247,18 @@ class MainActivity : FlutterActivity() {
} }
} }
// SAF 通道
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, SAF_CHANNEL) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, SAF_CHANNEL)
.setMethodCallHandler { call, result -> .setMethodCallHandler { call, result ->
when (call.method) { when (call.method) {
"restoreUri" -> {
val uriString = call.argument<String>("uri")
if (uriString != null) {
restoreUri(uriString)
result.success(true)
} else {
result.error("INVALID_ARGUMENT", "uri is required", null)
}
}
"selectFolder" -> { "selectFolder" -> {
safResult = result safResult = result
openFolderPicker() openFolderPicker()
@@ -233,7 +283,6 @@ class MainActivity : FlutterActivity() {
} }
} }
// 充电状态事件通道
EventChannel(flutterEngine.dartExecutor.binaryMessenger, EVENT_CHANNEL) EventChannel(flutterEngine.dartExecutor.binaryMessenger, EVENT_CHANNEL)
.setStreamHandler( .setStreamHandler(
object : EventChannel.StreamHandler { object : EventChannel.StreamHandler {
+121 -49
View File
@@ -1,5 +1,5 @@
import 'dart:io';
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'dart:developer' as dev; import 'dart:developer' as dev;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@@ -8,6 +8,7 @@ import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
//import 'package:shared_preferences/shared_preferences.dart';
import '../models/device_matching.dart'; import '../models/device_matching.dart';
import '../utils/charge_utils.dart'; import '../utils/charge_utils.dart';
@@ -84,8 +85,10 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
} }
Future<Database> _initDatabase() async { Future<Database> _initDatabase() async {
dev.log('🔵 _initDatabase 开始', name: 'BatteryHealth');
Directory appDocDir = await getApplicationDocumentsDirectory(); Directory appDocDir = await getApplicationDocumentsDirectory();
String dbPath = path.join(appDocDir.path, 'battery_health.db'); String dbPath = path.join(appDocDir.path, 'battery_health.db');
dev.log('🔵 数据库路径: $dbPath', name: 'BatteryHealth');
return await openDatabase( return await openDatabase(
dbPath, dbPath,
version: 2, version: 2,
@@ -136,15 +139,18 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
// ---------- 设备信息 ---------- // ---------- 设备信息 ----------
Future<void> _getDeviceInfo() async { Future<void> _getDeviceInfo() async {
dev.log('🔵 _getDeviceInfo 开始', name: 'BatteryHealth');
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
try { try {
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
String model = androidInfo.model; String model = androidInfo.model;
dev.log('🔵 设备型号: $model', name: 'BatteryHealth');
setState(() { setState(() {
_deviceModel = DeviceMatching.getModelName(model); _deviceModel = DeviceMatching.getModelName(model);
_designCap = DeviceMatching.getDesignCapacity(model); _designCap = DeviceMatching.getDesignCapacity(model);
}); });
} catch (e) { } catch (e) {
dev.log('🔵 获取设备信息失败: $e', name: 'BatteryHealth');
setState(() { setState(() {
_deviceModel = '魅族21 Pro (默认)'; _deviceModel = '魅族21 Pro (默认)';
_designCap = 5050; _designCap = 5050;
@@ -152,23 +158,25 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
} }
} }
// ---------- 扫描目录 (SAF 模式) ---------- // ---------- 扫描目录 (SAF) ----------
Future<void> _scanAndUpdateDB() async { Future<void> _scanAndUpdateDB() async {
// 检查 SAF 授权状态 dev.log('🔵 _scanAndUpdateDB 开始', name: 'BatteryHealth');
_safState = await _safService.getPermissionState(); _safState = await _safService.getPermissionState();
if (_safState != SafPermissionState.authorized) { if (_safState != SafPermissionState.authorized) {
_showSafAuthorizationDialog(); dev.log('🔵 _scanAndUpdateDB: 未授权', name: 'BatteryHealth');
return; return;
} }
try { try {
final files = await _safService.listFiles(); final files = await _safService.listFiles();
dev.log('🔵 扫描文件列表: $files', name: 'BatteryHealth');
RegExp filePattern = RegExp(r'mbattery_charger_log_(\d{4}_\d{2}_\d{2})$'); RegExp filePattern = RegExp(r'mbattery_charger_log_(\d{4}_\d{2}_\d{2})$');
for (String fileName in files) { for (String fileName in files) {
Match? match = filePattern.firstMatch(fileName); Match? match = filePattern.firstMatch(fileName);
if (match != null) { if (match != null) {
String dateStr = match.group(1)!.replaceAll('_', '-'); String dateStr = match.group(1)!.replaceAll('_', '-');
dev.log('🔵 处理文件: $fileName, 日期: $dateStr', name: 'BatteryHealth');
try { try {
List<String> lines = await _safService.readLogFile(fileName); List<String> lines = await _safService.readLogFile(fileName);
if (lines.isEmpty) continue; if (lines.isEmpty) continue;
@@ -197,11 +205,14 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
if (maxVolt == null || minVolt == null) continue; if (maxVolt == null || minVolt == null) continue;
await _insertOrUpdate(dateStr, cap, maxVolt, minVolt); await _insertOrUpdate(dateStr, cap, maxVolt, minVolt);
} catch (_) {} dev.log('🔵 插入数据库: $dateStr, cap=$cap', name: 'BatteryHealth');
} catch (e) {
dev.log('🔵 处理文件 $fileName 异常: $e', name: 'BatteryHealth');
}
} }
} }
} catch (e) { } catch (e) {
dev.log('[_scanAndUpdateDB] ❌ 扫描异常: $e', name: 'BatteryHealth'); dev.log('🔵 _scanAndUpdateDB 异常: $e', name: 'BatteryHealth');
} }
} }
@@ -211,7 +222,9 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
String year = nowUtc.year.toString(); String year = nowUtc.year.toString();
String month = nowUtc.month.toString().padLeft(2, '0'); String month = nowUtc.month.toString().padLeft(2, '0');
String day = nowUtc.day.toString().padLeft(2, '0'); String day = nowUtc.day.toString().padLeft(2, '0');
return 'mbattery_charger_log_${year}_${month}_$day'; String fileName = 'mbattery_charger_log_${year}_${month}_$day';
dev.log('🔵 getTodayFileName: $fileName', name: 'BatteryHealth');
return fileName;
} }
// ---------- 时间戳工具方法 ---------- // ---------- 时间戳工具方法 ----------
@@ -250,9 +263,10 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
// ---------- SAF 授权引导 ---------- // ---------- SAF 授权引导 ----------
void _showSafAuthorizationDialog() { void _showSafAuthorizationDialog() {
dev.log('🔵 _showSafAuthorizationDialog 被调用', name: 'BatteryHealth');
if (!mounted) return; if (!mounted) return;
showDialog( showDialog<String>(
context: context, context: context,
barrierDismissible: false, barrierDismissible: false,
builder: (context) => AlertDialog( builder: (context) => AlertDialog(
@@ -274,7 +288,8 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
actions: [ actions: [
TextButton( TextButton(
onPressed: () { onPressed: () {
Navigator.pop(context); dev.log('🔵 用户取消授权', name: 'BatteryHealth');
Navigator.pop(context, 'cancel');
setState(() { setState(() {
_safState = SafPermissionState.denied; _safState = SafPermissionState.denied;
}); });
@@ -282,48 +297,44 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
child: const Text('取消'), child: const Text('取消'),
), ),
ElevatedButton( ElevatedButton(
onPressed: () async { onPressed: () {
// 保存 context 引用 dev.log('🔵 用户点击选择文件夹', name: 'BatteryHealth');
final ctx = context; Navigator.pop(context, 'select');
// 尝试关闭对话框
Navigator.of(ctx, rootNavigator: true).pop();
// 等待动画完成
await Future.delayed(const Duration(milliseconds: 200));
final result = await _safService.requestPermission();
if (!mounted) return;
if (result.success) {
setState(() {
_safState = SafPermissionState.authorized;
});
// 🟢 兜底:在下一帧再次尝试关闭
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
Navigator.of(ctx, rootNavigator: true).pop();
}
});
readBatteryCapacity();
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(result.errorMessage ?? '授权失败,请重试'),
backgroundColor: Colors.red,
),
);
_showSafAuthorizationDialog();
}
}, },
child: const Text('选择文件夹'), child: const Text('选择文件夹'),
), ),
], ],
), ),
); ).then((result) async {
dev.log('🔵 对话框关闭,result: $result', name: 'BatteryHealth');
if (result == 'select') {
dev.log('🔵 开始请求授权', name: 'BatteryHealth');
final authResult = await _safService.requestPermission();
dev.log(
'🔵 授权结果: success=${authResult.success}, state=${authResult.state}',
name: 'BatteryHealth',
);
if (!mounted) return;
if (authResult.success) {
dev.log('🔵 授权成功,调用 readBatteryCapacity', name: 'BatteryHealth');
setState(() {
_safState = SafPermissionState.authorized;
});
readBatteryCapacity();
} else {
dev.log('🔵 授权失败: ${authResult.errorMessage}', name: 'BatteryHealth');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(authResult.errorMessage ?? '授权失败,请重试'),
backgroundColor: Colors.red,
),
);
_showSafAuthorizationDialog();
}
}
});
} }
// ---------- 核心:系统API定调 ---------- // ---------- 核心:系统API定调 ----------
@@ -531,10 +542,9 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
} }
} }
// 检查 SAF 授权
_safState = await _safService.getPermissionState(); _safState = await _safService.getPermissionState();
if (_safState != SafPermissionState.authorized) { if (_safState != SafPermissionState.authorized) {
if (mounted) _showSafAuthorizationDialog(); dev.log('[_fetchChargeDataFromLog] 未授权,跳过', name: 'BatteryHealth');
return; return;
} }
@@ -620,9 +630,17 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
// ---------- 读取当前数据 ---------- // ---------- 读取当前数据 ----------
Future<void> readBatteryCapacity() async { Future<void> readBatteryCapacity() async {
dev.log(
'🔵 ========== readBatteryCapacity 开始 ==========',
name: 'BatteryHealth',
);
// 检查 SAF 授权 // 检查 SAF 授权
_safState = await _safService.getPermissionState(); _safState = await _safService.getPermissionState();
dev.log('🔵 SAF状态: $_safState', name: 'BatteryHealth');
if (_safState != SafPermissionState.authorized) { if (_safState != SafPermissionState.authorized) {
dev.log('🔵 未授权,弹窗', name: 'BatteryHealth');
if (mounted) _showSafAuthorizationDialog(); if (mounted) _showSafAuthorizationDialog();
return; return;
} }
@@ -631,11 +649,16 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
await _scanAndUpdateDB(); await _scanAndUpdateDB();
final fileName = getTodayFileName(); final fileName = getTodayFileName();
dev.log('🔵 今日文件名: $fileName', name: 'BatteryHealth');
final exists = await _safService.logFileExists(fileName); final exists = await _safService.logFileExists(fileName);
dev.log('🔵 文件存在: $exists', name: 'BatteryHealth');
if (!exists) { if (!exists) {
dev.log('🔵 文件不存在,尝试从数据库读取', name: 'BatteryHealth');
List<Map<String, dynamic>> recent = await _queryRecentData(1); List<Map<String, dynamic>> recent = await _queryRecentData(1);
if (recent.isNotEmpty) { if (recent.isNotEmpty) {
dev.log('🔵 数据库有数据: ${recent.first}', name: 'BatteryHealth');
setState(() { setState(() {
_currentCap = recent.first['capacity'].toDouble(); _currentCap = recent.first['capacity'].toDouble();
_maxVolt = recent.first['volt_max'] ?? 0; _maxVolt = recent.first['volt_max'] ?? 0;
@@ -644,6 +667,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
}); });
await _updateTrendChart(); await _updateTrendChart();
} else { } else {
dev.log('🔵 数据库无数据', name: 'BatteryHealth');
setState(() => _hasData = false); setState(() => _hasData = false);
} }
if (_isCharging) _fetchChargeDataFromLog(); if (_isCharging) _fetchChargeDataFromLog();
@@ -654,7 +678,9 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
try { try {
final lines = await _safService.readLogFile(fileName); final lines = await _safService.readLogFile(fileName);
dev.log('🔵 读取到 ${lines.length}', name: 'BatteryHealth');
if (lines.isEmpty) { if (lines.isEmpty) {
dev.log('🔵 文件为空', name: 'BatteryHealth');
setState(() => _hasData = false); setState(() => _hasData = false);
if (_isCharging) _fetchChargeDataFromLog(); if (_isCharging) _fetchChargeDataFromLog();
_chargeAnimationController.reset(); _chargeAnimationController.reset();
@@ -662,12 +688,23 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
return; return;
} }
// 打印前几行
if (lines.isNotEmpty) {
dev.log('🔵 第一行: ${lines.first}', name: 'BatteryHealth');
if (lines.length > 1) {
dev.log('🔵 第二行: ${lines[1]}', name: 'BatteryHealth');
}
}
if (_isCharging) _parseChargeDataFromLog(lines); if (_isCharging) _parseChargeDataFromLog(lines);
List<String> validLines = lines List<String> validLines = lines
.where((line) => line.contains('tbat=')) .where((line) => line.contains('tbat='))
.toList(); .toList();
dev.log('🔵 有效行数 (含tbat): ${validLines.length}', name: 'BatteryHealth');
if (validLines.isEmpty) { if (validLines.isEmpty) {
dev.log('🔵 无有效数据行', name: 'BatteryHealth');
setState(() => _hasData = false); setState(() => _hasData = false);
_chargeAnimationController.reset(); _chargeAnimationController.reset();
_updateChargeState(); _updateChargeState();
@@ -675,6 +712,8 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
} }
String lastLine = validLines.last; String lastLine = validLines.last;
dev.log('🔵 最后一行: $lastLine', name: 'BatteryHealth');
RegExp capReg = RegExp(r'learned_cap=(\d+)'); RegExp capReg = RegExp(r'learned_cap=(\d+)');
RegExp cycleReg = RegExp(r'cycle=(\d+)'); RegExp cycleReg = RegExp(r'cycle=(\d+)');
RegExp tempReg = RegExp(r'tbat=(\d+)'); RegExp tempReg = RegExp(r'tbat=(\d+)');
@@ -685,7 +724,13 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
String? tempStr = tempReg.firstMatch(lastLine)?.group(1); String? tempStr = tempReg.firstMatch(lastLine)?.group(1);
String? voltStr = voltageReg.firstMatch(lastLine)?.group(1); String? voltStr = voltageReg.firstMatch(lastLine)?.group(1);
dev.log(
'🔵 capStr=$capStr, cycleStr=$cycleStr, tempStr=$tempStr, voltStr=$voltStr',
name: 'BatteryHealth',
);
if (capStr == null) { if (capStr == null) {
dev.log('🔵 未找到 learned_cap', name: 'BatteryHealth');
setState(() => _hasData = false); setState(() => _hasData = false);
_chargeAnimationController.reset(); _chargeAnimationController.reset();
_updateChargeState(); _updateChargeState();
@@ -697,6 +742,11 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
double temp = double.parse(tempStr ?? '0'); double temp = double.parse(tempStr ?? '0');
double volt = double.parse(voltStr ?? '0') / 1000000; double volt = double.parse(voltStr ?? '0') / 1000000;
dev.log(
'🔵 解析结果: capMah=$capMah, cycle=$cycle, temp=$temp, volt=$volt',
name: 'BatteryHealth',
);
List<double> temps = []; List<double> temps = [];
for (String line in validLines) { for (String line in validLines) {
RegExpMatch? match = tempReg.firstMatch(line); RegExpMatch? match = tempReg.firstMatch(line);
@@ -731,10 +781,20 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
_hasData = true; _hasData = true;
}); });
dev.log(
'🔵 数据更新完成: _currentCap=$_currentCap, _cycleCount=$_cycleCount',
name: 'BatteryHealth',
);
await _updateTrendChart(); await _updateTrendChart();
_chargeAnimationController.reset(); _chargeAnimationController.reset();
_updateChargeState(); _updateChargeState();
dev.log(
'🔵 ========== readBatteryCapacity 完成 ==========',
name: 'BatteryHealth',
);
} catch (e) { } catch (e) {
dev.log('🔵 readBatteryCapacity 异常: $e', name: 'BatteryHealth');
setState(() => _hasData = false); setState(() => _hasData = false);
_chargeAnimationController.reset(); _chargeAnimationController.reset();
_updateChargeState(); _updateChargeState();
@@ -752,6 +812,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
@override @override
void initState() { void initState() {
super.initState(); super.initState();
dev.log('🔵 ========== initState 开始 ==========', name: 'BatteryHealth');
_chargeAnimationController = AnimationController( _chargeAnimationController = AnimationController(
vsync: this, vsync: this,
@@ -786,18 +847,29 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
} }
}); });
// 延迟初始化 SAF 并读取数据
WidgetsBinding.instance.addPostFrameCallback((_) async { WidgetsBinding.instance.addPostFrameCallback((_) async {
dev.log('🔵 initState -> addPostFrameCallback 开始', name: 'BatteryHealth');
await _safService.init(); await _safService.init();
dev.log(
'🔵 _safService.init() 完成,cachedUri: ${_safService.cachedUri}',
name: 'BatteryHealth',
);
_safState = await _safService.getPermissionState(); _safState = await _safService.getPermissionState();
dev.log('🔵 _safState: $_safState', name: 'BatteryHealth');
if (_safState == SafPermissionState.unauthorized || if (_safState == SafPermissionState.unauthorized ||
_safState == SafPermissionState.expired) { _safState == SafPermissionState.expired) {
dev.log('🔵 需要授权,弹窗', name: 'BatteryHealth');
if (mounted) _showSafAuthorizationDialog(); if (mounted) _showSafAuthorizationDialog();
} else { } else {
dev.log('🔵 已有授权,调用 readBatteryCapacity', name: 'BatteryHealth');
readBatteryCapacity(); readBatteryCapacity();
} }
}); });
dev.log('🔵 ========== initState 结束 ==========', name: 'BatteryHealth');
} }
@override @override
+1 -1
View File
@@ -34,7 +34,7 @@ class SafStorageService {
if (_cachedUri == null || _cachedUri!.isEmpty) { if (_cachedUri == null || _cachedUri!.isEmpty) {
return SafPermissionState.unauthorized; return SafPermissionState.unauthorized;
} }
// 🟢 简化:直接返回 authorized,相信本地缓存的 URI // 🟢 直接返回 authorized,相信缓存
return SafPermissionState.authorized; return SafPermissionState.authorized;
} }