SAF测试阶段,验证中

This commit is contained in:
2026-07-05 00:32:28 +08:00
parent dff0f6fb6b
commit 45c69c8ec4
12 changed files with 301 additions and 211 deletions
+22 -25
View File
@@ -6,7 +6,7 @@ plugins {
android {
namespace = "com.lxh.battery_health"
compileSdk = flutter.compileSdkVersion
compileSdk = 34
ndkVersion = flutter.ndkVersion
compileOptions {
@@ -21,38 +21,39 @@ android {
defaultConfig {
applicationId = "com.lxh.battery_health"
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
targetSdk = 34
versionCode = flutter.versionCode
versionName = flutter.versionName
multiDexEnabled = true
}
signingConfigs {
create("release") {
// 这里配置你正式发布的签名
// 如果还没有正式签名,debug 可以用 debug 签名替代
keyAlias = "your_key_alias"
keyPassword = "your_key_password"
storeFile = file("your_keystore.jks")
storePassword = "your_store_password"
// 如果没有正式签名,可以用 debug 签名代替(测试用)
// 正式发布时请替换为自己的密钥
getByName("debug") {
// debug 签名已经存在,无需额外配置
}
create("release") {
// 如果有正式签名,在这里配置
// keyAlias = "..."
// keyPassword = "..."
// storeFile = file("...")
// storePassword = "..."
}
}
signingConfigs {
// 如果没有正式签名,可以暂时用 debug 签名
// 正式发布时再替换
}
buildTypes {
debug {
// 🟢 关键:debug 版本包名加 .dev 后缀
applicationIdSuffix = ".dev"
signingConfig = signingConfigs.getByName("debug")
isDebuggable = true
isMinifyEnabled = false
isShrinkResources = false
}
release {
applicationIdSuffix = "" // 保持原包名
// 🟢 如果还没有正式签名,先用 debug 签名替代
signingConfig = signingConfigs.getByName("debug")
// release 版本不加后缀,保持原包名
signingConfig = signingConfigs.getByName("debug") // 若没有正式签名,先用 debug 签名
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
@@ -61,16 +62,12 @@ android {
)
}
}
// 如果有 productFlavors,可以在这里配置
// 如果没有,忽略即可
}
}
flutter {
source = "../.."
}
dependencies {
// 如果项目中有其他依赖,添加在这里
// 注意:sqflite、permission_handler 等 Flutter 插件会自动包含
}
// 无需额外添加 Activity KTX,因为已改用 startActivityForResult
}
@@ -4,19 +4,34 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.BatteryManager
import android.os.Build
import android.os.Bundle
import android.provider.DocumentsContract
import android.provider.OpenableColumns
import androidx.activity.ComponentActivity
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MethodChannel
import java.io.BufferedReader
import java.io.InputStreamReader
class MainActivity : FlutterActivity() {
// ---------- 充电状态 ----------
private val CHARGE_CHANNEL = "com.lxh.battery_health/charge"
private val EVENT_CHANNEL = "com.lxh.battery_health/charge_events"
private var eventSink: EventChannel.EventSink? = null
// ---------- SAF 相关 ----------
private val SAF_CHANNEL = "com.lxh.battery_health/saf"
private var safResult: MethodChannel.Result? = null
private var safUri: Uri? = null
private val FOLDER_PICKER_REQUEST = 1001
// ---------- 充电广播接收器 ----------
private val chargeReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
intent ?: return
@@ -44,53 +59,198 @@ class MainActivity : FlutterActivity() {
eventSink?.success(mapOf("isCharging" to isCharging, "chargeType" to chargeType))
}
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHARGE_CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "getChargeState") {
val isCharging = getBatteryStatus()
val chargeType = if (isCharging) {
val batteryIntent = registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
val plug = batteryIntent?.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) ?: -1
when (plug) {
BatteryManager.BATTERY_PLUGGED_AC -> "AC"
BatteryManager.BATTERY_PLUGGED_USB -> "USB"
BatteryManager.BATTERY_PLUGGED_WIRELESS -> "WIRELESS"
else -> "UNKNOWN"
}
} else {
"NONE"
}
result.success(mapOf("isCharging" to isCharging, "chargeType" to chargeType))
} else {
result.notImplemented()
}
}
EventChannel(flutterEngine.dartExecutor.binaryMessenger, EVENT_CHANNEL).setStreamHandler(
object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
eventSink = events
val filter = IntentFilter().apply {
addAction(Intent.ACTION_POWER_CONNECTED)
addAction(Intent.ACTION_POWER_DISCONNECTED)
}
registerReceiver(chargeReceiver, filter)
}
override fun onCancel(arguments: Any?) {
eventSink = null
unregisterReceiver(chargeReceiver)
}
}
)
}
private fun getBatteryStatus(): Boolean {
val batteryIntent = registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
val status = batteryIntent?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1
return status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL
}
// ---------- SAF 方法 ----------
private fun openFolderPicker() {
try {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
val downloadsUri = DocumentsContract.buildDocumentUri(
"com.android.externalstorage.documents",
"primary:Downloads"
)
putExtra(DocumentsContract.EXTRA_INITIAL_URI, downloadsUri)
} catch (e: Exception) {
// 忽略
}
}
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}
startActivityForResult(intent, FOLDER_PICKER_REQUEST)
} catch (e: Exception) {
android.util.Log.e("BatteryHealth", "打开文件夹选择器失败: ${e.message}")
safResult?.error("SELECT_FOLDER_FAILED", e.message, null)
safResult = null
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == FOLDER_PICKER_REQUEST && resultCode == ComponentActivity.RESULT_OK) {
val uri = data?.data
if (uri != null) {
try {
val takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
contentResolver.takePersistableUriPermission(uri, takeFlags)
safUri = uri
android.util.Log.d("BatteryHealth", "SAF URI: $uri")
safResult?.success(uri.toString())
} catch (e: Exception) {
android.util.Log.e("BatteryHealth", "SAF 授权失败: ${e.message}")
safResult?.error("SAF_FAILED", e.message, null)
}
} else {
safResult?.success(null)
}
safResult = null
}
}
private fun getTreeDocId(): String? {
return safUri?.let { DocumentsContract.getTreeDocumentId(it) }
}
private fun listFiles(): List<String> {
val result = mutableListOf<String>()
val docId = getTreeDocId()
if (docId == null || docId.isEmpty()) return result
try {
val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(safUri!!, docId)
contentResolver.query(childrenUri, null, null, null, null)?.use { cursor ->
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
while (cursor.moveToNext()) {
val name = cursor.getString(nameIndex)
if (name != null) {
result.add(name)
}
}
}
} catch (e: Exception) {
android.util.Log.e("BatteryHealth", "列出文件失败: ${e.message}")
}
return result
}
private fun getFileUri(fileName: String): Uri? {
val docId = getTreeDocId() ?: return null
try {
val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(safUri!!, docId)
contentResolver.query(childrenUri, null, null, null, null)?.use { cursor ->
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
val idIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_DOCUMENT_ID)
while (cursor.moveToNext()) {
val name = cursor.getString(nameIndex)
if (name == fileName) {
val fileDocId = cursor.getString(idIndex)
return DocumentsContract.buildDocumentUriUsingTree(safUri!!, fileDocId)
}
}
}
} catch (e: Exception) {
android.util.Log.e("BatteryHealth", "获取文件URI失败: ${e.message}")
}
return null
}
private fun readFile(uri: Uri): String? {
return try {
contentResolver.openInputStream(uri)?.use { inputStream ->
BufferedReader(InputStreamReader(inputStream)).use { reader ->
reader.readText()
}
}
} catch (e: Exception) {
android.util.Log.e("BatteryHealth", "读取文件失败: ${e.message}")
null
}
}
private fun readLogFile(fileName: String): String? {
val fileUri = getFileUri(fileName)
return fileUri?.let { readFile(it) }
}
// ---------- Flutter 通道配置 ----------
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
// 充电状态通道
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHARGE_CHANNEL)
.setMethodCallHandler { call, result ->
if (call.method == "getChargeState") {
val isCharging = getBatteryStatus()
val chargeType = if (isCharging) {
val batteryIntent = registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
val plug = batteryIntent?.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) ?: -1
when (plug) {
BatteryManager.BATTERY_PLUGGED_AC -> "AC"
BatteryManager.BATTERY_PLUGGED_USB -> "USB"
BatteryManager.BATTERY_PLUGGED_WIRELESS -> "WIRELESS"
else -> "UNKNOWN"
}
} else {
"NONE"
}
result.success(mapOf("isCharging" to isCharging, "chargeType" to chargeType))
} else {
result.notImplemented()
}
}
// SAF 通道
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, SAF_CHANNEL)
.setMethodCallHandler { call, result ->
when (call.method) {
"selectFolder" -> {
safResult = result
openFolderPicker()
}
"readLogFile" -> {
val fileName = call.argument<String>("fileName")
if (fileName != null) {
val content = readLogFile(fileName)
result.success(content)
} else {
result.error("INVALID_ARGUMENT", "fileName is required", null)
}
}
"listFiles" -> {
val files = listFiles()
result.success(files)
}
"getUri" -> {
result.success(safUri?.toString())
}
else -> result.notImplemented()
}
}
// 充电状态事件通道
EventChannel(flutterEngine.dartExecutor.binaryMessenger, EVENT_CHANNEL)
.setStreamHandler(
object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
eventSink = events
val filter = IntentFilter().apply {
addAction(Intent.ACTION_POWER_CONNECTED)
addAction(Intent.ACTION_POWER_DISCONNECTED)
}
registerReceiver(chargeReceiver, filter)
}
override fun onCancel(arguments: Any?) {
eventSink = null
unregisterReceiver(chargeReceiver)
}
}
)
}
}
+3 -1
View File
@@ -20,7 +20,9 @@ class MyApp extends StatelessWidget {
title: '电池健康度',
theme: ThemeData(
fontFamily: 'HarmonyOS_Sans_SC',
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
colorScheme: ColorScheme.fromSeed(
seedColor: const Color.fromARGB(255, 255, 255, 255),
),
useMaterial3: true,
),
home: const BatteryHealthPage(),
+12 -6
View File
@@ -283,18 +283,23 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
),
ElevatedButton(
onPressed: () async {
final ctx = context;
Navigator.pop(ctx);
// 触发关闭
Navigator.pop(context);
// 延迟确保动画完成
await Future.delayed(const Duration(milliseconds: 150));
final result = await _safService.requestPermission();
if (!mounted) return;
if (result.success) {
if (!mounted) return;
setState(() {
_safState = SafPermissionState.authorized;
});
readBatteryCapacity();
} else {
if (!mounted) return;
ScaffoldMessenger.of(ctx).showSnackBar(
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(result.errorMessage ?? '授权失败,请重试'),
backgroundColor: Colors.red,
@@ -303,7 +308,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
_showSafAuthorizationDialog();
}
},
child: const Text('选择文件夹'), // 🟢 加这行
child: const Text('选择文件夹'),
),
],
),
@@ -774,6 +779,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage>
WidgetsBinding.instance.addPostFrameCallback((_) async {
await _safService.init();
_safState = await _safService.getPermissionState();
if (_safState == SafPermissionState.unauthorized ||
_safState == SafPermissionState.expired) {
if (mounted) _showSafAuthorizationDialog();
+59 -51
View File
@@ -1,4 +1,3 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
@@ -12,55 +11,49 @@ class SafStorageService {
static const MethodChannel _channel = MethodChannel(
'com.lxh.battery_health/saf',
);
static const String _prefKeySafPath = 'saf_storage_path';
String? _cachedPath;
static const String _prefKeySafUri = 'saf_storage_uri';
String? _cachedUri;
// 🟢 初始化时从 SharedPreferences 恢复 URI
Future<void> init() async {
final prefs = await SharedPreferences.getInstance();
_cachedPath = prefs.getString(_prefKeySafPath);
if (kDebugMode) {
print('[SAF] 初始化,缓存路径: $_cachedPath');
try {
final prefs = await SharedPreferences.getInstance();
_cachedUri = prefs.getString(_prefKeySafUri);
if (kDebugMode) {
print('[SAF] 初始化,缓存 URI: $_cachedUri');
}
} catch (e) {
if (kDebugMode) {
print('[SAF] 初始化失败: $e');
}
_cachedUri = null;
}
}
Future<SafPermissionState> getPermissionState() async {
if (_cachedPath == null || _cachedPath!.isEmpty) {
if (_cachedUri == null || _cachedUri!.isEmpty) {
return SafPermissionState.unauthorized;
}
try {
final dir = Directory(_cachedPath!);
if (!await dir.exists()) {
_clearCache();
return SafPermissionState.expired;
}
return SafPermissionState.authorized;
} catch (e) {
_clearCache();
return SafPermissionState.expired;
}
// 🟢 简化:直接返回 authorized,相信本地缓存的 URI
return SafPermissionState.authorized;
}
Future<SafAuthorizationResult> requestPermission() async {
try {
final String? selectedPath = await _channel.invokeMethod('selectFolder');
final String? uriString = await _channel.invokeMethod('selectFolder');
if (selectedPath == null || selectedPath.isEmpty) {
if (uriString == null || uriString.isEmpty) {
return SafAuthorizationResult.denied();
}
// 验证路径是否包含 mbattery_charger
if (!selectedPath.contains('mbattery_charger')) {
return SafAuthorizationResult.error('请选择 mbattery_charger 文件夹');
}
_cachedPath = selectedPath;
await _savePath(selectedPath);
_cachedUri = uriString;
await _saveUri(uriString);
if (kDebugMode) {
print('[SAF] 授权成功,路径: $selectedPath');
print('[SAF] 授权成功,URI: $uriString');
}
return SafAuthorizationResult.success(selectedPath);
return SafAuthorizationResult.success(uriString);
} catch (e) {
if (kDebugMode) {
print('[SAF] 授权失败: $e');
@@ -73,8 +66,11 @@ class SafStorageService {
final state = await getPermissionState();
if (state != SafPermissionState.authorized) return false;
try {
final file = File('${_cachedPath!}/$fileName');
return await file.exists();
final files = await _channel.invokeMethod('listFiles');
if (files is List) {
return files.contains(fileName);
}
return false;
} catch (e) {
return false;
}
@@ -84,9 +80,11 @@ class SafStorageService {
final state = await getPermissionState();
if (state != SafPermissionState.authorized) return [];
try {
final file = File('${_cachedPath!}/$fileName');
if (!await file.exists()) return [];
return await file.readAsLines();
final String? content = await _channel.invokeMethod('readLogFile', {
'fileName': fileName,
});
if (content == null || content.isEmpty) return [];
return content.split('\n');
} catch (e) {
if (kDebugMode) {
print('[SAF] 读取文件失败: $e');
@@ -99,13 +97,11 @@ class SafStorageService {
final state = await getPermissionState();
if (state != SafPermissionState.authorized) return [];
try {
final dir = Directory(_cachedPath!);
if (!await dir.exists()) return [];
final entities = await dir.list().toList();
return entities
.where((e) => e is File)
.map((e) => e.path.split(Platform.pathSeparator).last)
.toList();
final result = await _channel.invokeMethod('listFiles');
if (result is List) {
return result.cast<String>();
}
return [];
} catch (e) {
if (kDebugMode) {
print('[SAF] 列出文件失败: $e');
@@ -120,18 +116,30 @@ class SafStorageService {
}
void _clearCache() {
_cachedPath = null;
_savePath(null);
_cachedUri = null;
_saveUri(null);
}
Future<void> _savePath(String? path) async {
final prefs = await SharedPreferences.getInstance();
if (path != null && path.isNotEmpty) {
await prefs.setString(_prefKeySafPath, path);
} else {
await prefs.remove(_prefKeySafPath);
Future<void> _saveUri(String? uri) async {
try {
final prefs = await SharedPreferences.getInstance();
if (uri != null && uri.isNotEmpty) {
await prefs.setString(_prefKeySafUri, uri);
if (kDebugMode) {
print('[SAF] 保存 URI 成功: $uri');
}
} else {
await prefs.remove(_prefKeySafUri);
if (kDebugMode) {
print('[SAF] 清除 URI');
}
}
} catch (e) {
if (kDebugMode) {
print('[SAF] 保存 URI 失败: $e');
}
}
}
String? get cachedPath => _cachedPath;
String? get cachedUri => _cachedUri;
}
@@ -6,10 +6,6 @@
#include "generated_plugin_registrant.h"
#include <file_selector_linux/file_selector_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
}
-1
View File
@@ -3,7 +3,6 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
file_selector_linux
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
@@ -6,13 +6,11 @@ import FlutterMacOS
import Foundation
import device_info_plus
import file_selector_macos
import shared_preferences_foundation
import sqflite_darwin
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
}
-72
View File
@@ -57,14 +57,6 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.19.1"
cross_file:
dependency: transitive
description:
name: cross_file
sha256: "92c9c43c383bfa1c32079d3bc492d55d6d4318044b7b47edaff8971cbb555c51"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.5+4"
crypto:
dependency: transitive
description:
@@ -121,70 +113,6 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "7.0.1"
file_selector:
dependency: "direct main"
description:
name: file_selector
sha256: bd15e43e9268db636b53eeaca9f56324d1622af30e5c34d6e267649758c84d9a
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
file_selector_android:
dependency: transitive
description:
name: file_selector_android
sha256: "6a26687fa65cbc28a5345c7ae6f227e89f0b47740978a4c475b1a625da7a331b"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.5.2+8"
file_selector_ios:
dependency: transitive
description:
name: file_selector_ios
sha256: e2ecf2885c121691ce13b60db3508f53c01f869fb6e8dc5c1cfa771e4c46aeca
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.5.3+5"
file_selector_linux:
dependency: transitive
description:
name: file_selector_linux
sha256: "2567f398e06ac72dcf2e98a0c95df2a9edd03c2c2e0cacd4780f20cdf56263a0"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.4"
file_selector_macos:
dependency: transitive
description:
name: file_selector_macos
sha256: "5e0bbe9c312416f1787a68259ea1505b52f258c587f12920422671807c4d618a"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.5"
file_selector_platform_interface:
dependency: transitive
description:
name: file_selector_platform_interface
sha256: "35e0bd61ebcdb91a3505813b055b09b79dfdc7d0aee9c09a7ba59ae4bb13dc85"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.7.0"
file_selector_web:
dependency: transitive
description:
name: file_selector_web
sha256: "73181fbc5257776d8ecaa6a94ab3c8e920ad143b9132a6d984a9271dfc6928d3"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.5"
file_selector_windows:
dependency: transitive
description:
name: file_selector_windows
sha256: "62197474ae75893a62df75939c777763d39c2bc5f73ce5b88497208bc269abfd"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.3+5"
flutter:
dependency: "direct main"
description: flutter
+2 -2
View File
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.3.0-dev.2
version: 1.3.0-dev.4
environment:
sdk: ^3.9.2
@@ -38,7 +38,7 @@ dependencies:
path: ^1.9.0
flutter_svg: ^2.0.10+1
shared_preferences: ^2.2.0
file_selector: ^1.0.0 # 🟢 新增
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
@@ -6,12 +6,9 @@
#include "generated_plugin_registrant.h"
#include <file_selector_windows/file_selector_windows.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
}
-1
View File
@@ -3,7 +3,6 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
file_selector_windows
permission_handler_windows
)