From 495dcd166d712b77d807a64a405078cf29e05e56 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Mon, 1 Dec 2025 17:38:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=8B=E8=BD=BD=E8=AF=AD?= =?UTF-8?q?=E9=9F=B3=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/data/services/network/dio_manager.dart | 100 ------------------ .../controllers/wakeup_voice_controller.dart | 33 +++--- .../yunqiinnovation/ble_service/BleService.kt | 4 +- 3 files changed, 14 insertions(+), 123 deletions(-) diff --git a/lib/data/services/network/dio_manager.dart b/lib/data/services/network/dio_manager.dart index e4c92c11d..0496c11f9 100644 --- a/lib/data/services/network/dio_manager.dart +++ b/lib/data/services/network/dio_manager.dart @@ -1,10 +1,6 @@ import 'package:dio/dio.dart'; -import 'package:dio/io.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:get/get.dart' hide Response; -import 'package:flutter/foundation.dart'; -import 'dart:io'; -import 'package:path/path.dart' as p; import 'auth_interceptor.dart'; import 'nw_method.dart'; @@ -58,100 +54,4 @@ class DioManager { ); return response.data; } - - /// 下载二进制字节(支持可选忽略证书,仅限移动/桌面端) - Future> downloadBytes(String url, {bool allowInsecure = false}) async { - // 使用独立 Dio,避免全局适配器被修改 - final client = Dio(BaseOptions( - responseType: ResponseType.bytes, - followRedirects: true, - receiveTimeout: const Duration(seconds: 60), - connectTimeout: const Duration(seconds: 60), - )); - client.interceptors.add(AuthInterceptor()); - - // 仅在非Web端尝试忽略证书 - if (allowInsecure && !kIsWeb) { - client.httpClientAdapter = IOHttpClientAdapter(createHttpClient: () { - // ignore: unnecessary_new - final ioClient = new HttpClient(); - ioClient.badCertificateCallback = (cert, host, port) => true; - return ioClient; - }); - } - - final resp = await client.get(url); - final status = resp.statusCode ?? 0; - if (status >= 200 && status < 300) { - // Dio v5 将 bytes 直接作为 List 返回 - final data = resp.data; - if (data is List) return data; - // 某些平台可能返回 Uint8List - if (data is List) { - return List.from(data); - } - throw Exception('下载返回格式异常'); - } - throw Exception('下载失败($status)'); - } - - /// 按 .env 配置决定是否允许忽略证书 - Future> downloadBytesWithEnv(String url) async { - final allow = (dotenv.env['ALLOW_INSECURE_SSL'] ?? 'false').toLowerCase() == 'true'; - return downloadBytes(url, allowInsecure: allow); - } - - /// 使用 Dio 的 download API 下载到临时文件并读出字节 - Future> downloadBytesUsingDownload(String url, {bool allowInsecure = false}) async { - final client = Dio(BaseOptions( - followRedirects: true, - receiveTimeout: const Duration(seconds: 120), - connectTimeout: const Duration(seconds: 60), - )); - client.interceptors.add(AuthInterceptor()); - - if (allowInsecure && !kIsWeb) { - client.httpClientAdapter = IOHttpClientAdapter(createHttpClient: () { - final ioClient = HttpClient(); - ioClient.badCertificateCallback = (cert, host, port) => true; - return ioClient; - }); - } - - final tmpDir = await Directory.systemTemp.createTemp('voice_pkg_'); - final baseName = _fileNameFromUrl(url); - final savePath = p.join(tmpDir.path, baseName); - - await client.download( - url, - savePath, - options: Options(responseType: ResponseType.bytes), - ); - - final file = File(savePath); - final bytes = await file.readAsBytes(); - // 清理临时文件 - try { - await file.delete(); - await tmpDir.delete(recursive: true); - } catch (_) {} - return bytes; - } - - /// 读取 .env 决定是否忽略证书,使用 download API - Future> downloadBytesUsingDownloadWithEnv(String url) async { - final allow = (dotenv.env['ALLOW_INSECURE_SSL'] ?? 'false').toLowerCase() == 'true'; - return downloadBytesUsingDownload(url, allowInsecure: allow); - } - - String _fileNameFromUrl(String url) { - try { - final clean = url.split('?').first; - final last = clean.split('/').last; - if (last.isEmpty) return 'voice.pkg'; - return last; - } catch (_) { - return 'voice.pkg'; - } - } } diff --git a/lib/modules/wakeupvoice/controllers/wakeup_voice_controller.dart b/lib/modules/wakeupvoice/controllers/wakeup_voice_controller.dart index 3d5c4c63c..3934b4908 100644 --- a/lib/modules/wakeupvoice/controllers/wakeup_voice_controller.dart +++ b/lib/modules/wakeupvoice/controllers/wakeup_voice_controller.dart @@ -1,11 +1,8 @@ import 'package:get/get.dart'; +import 'package:dio/dio.dart'; import '../../../core/utils/logger.dart'; import '../../../data/services/ble_manager.dart'; import '../../../data/services/network/api.dart'; -import '../../../data/services/network/dio_manager.dart'; -import 'dart:convert'; -import 'dart:typed_data'; -import 'package:http/http.dart' as http; class WakeupVoiceController extends GetxController { // 是否启用唤醒词(原有本地词功能,可保留) @@ -256,23 +253,18 @@ class WakeupVoiceController extends GetxController { Future> _downloadVoiceBytes(String url) async { try { - // 优先使用 Dio 的 download API(写入临时文件后读字节) - return await DioManager().downloadBytesUsingDownloadWithEnv(url); + final dio = Dio(); + final response = await dio.get>( + url, + options: Options( + responseType: ResponseType.bytes, + receiveTimeout: const Duration(seconds: 60), + ), + ); + return response.data ?? []; } catch (e) { - // 降级为直接 GET bytes(同样带鉴权/证书忽略) - Logger.info('Dio download 失败,尝试直接 bytes GET: $e'); - try { - return await DioManager().downloadBytesWithEnv(url); - } catch (e2) { - // 最后再回退到 http 包 - Logger.info('Dio bytes GET 失败,回退 http: $e2'); - final uri = Uri.parse(url); - final resp = await http.get(uri); - if (resp.statusCode == 200) { - return resp.bodyBytes; - } - throw Exception('下载失败(${resp.statusCode})'); - } + Logger.error('下载语音包失败: $url', e); + return []; } } @@ -321,7 +313,6 @@ class WakeupVoiceController extends GetxController { } Future saveChanges() async { - // TODO: 接入设备/SDK的唤醒词设置接口(本地词) Get.snackbar('保存成功', '唤醒词设置已更新'); } } diff --git a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt index ce2bbd8d6..7238c700a 100644 --- a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt +++ b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt @@ -883,8 +883,8 @@ object BleService { // 获取主服务特征 val primarySvc = g.getService(BleConst.PRIMARY_SERVICE_UUID) - notifyChar = primarySvc?.getCharacteristic(BleConst.WakeupVoices_NOTIFY_UUID) - writeChar = primarySvc?.getCharacteristic(BleConst.WakeupVoices_WRITE_UUID) + notifyChar = primarySvc?.getCharacteristic(BleConst.NOTIFY_CHAR_UUID) + writeChar = primarySvc?.getCharacteristic(BleConst.WRITE_CHAR_UUID) // 获取音频服务特征