diff --git a/README.md b/README.md
index 8344389..a9279b3 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,417 @@
-# app003
+# AI Chat Assistant Flutter Plugin
-A new Flutter project.
+一个功能丰富的 AI 聊天助手 Flutter 插件,专为车载系统设计,支持语音识别、AI 对话、车控命令执行、语音合成等功能。
-## Getting Started
+## 📱 功能特性
-This project is a starting point for a Flutter application.
+- 🎤 **语音识别 (ASR)**: 支持实时语音转文字,自动停止检测
+- 🤖 **AI 对话**: 基于 SSE (Server-Sent Events) 的流式 AI 对话
+- 🚗 **车控命令**: 支持 20+ 种车辆控制命令(空调、车窗、车门、座椅加热等)
+- 🔊 **语音合成 (TTS)**: 支持中英文语音播报
+- 🎨 **精美 UI**: 浮动图标、波纹动画、渐变背景
+- 📱 **多界面模式**: 支持全屏和部分屏幕聊天界面
+- 🌐 **国际化**: 支持中英文切换
+- 📊 **状态管理**: 基于 Provider 的状态管理
-A few resources to get you started if this is your first Flutter project:
+## 🏗️ 项目架构
-- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
-- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
+### 📁 目录结构
-For help getting started with Flutter development, view the
-[online documentation](https://docs.flutter.dev/), which offers tutorials,
-samples, guidance on mobile development, and a full API reference.
+```
+lib/
+├── app.dart # 主应用入口
+├── main.dart # 程序启动入口
+├── enums/ # 枚举定义
+│ ├── message_service_state.dart # 消息服务状态
+│ ├── message_status.dart # 消息状态
+│ └── vehicle_command_type.dart # 车控命令类型
+├── models/ # 数据模型
+│ ├── chat_message.dart # 聊天消息模型
+│ ├── vehicle_cmd.dart # 车控命令模型
+│ ├── vehicle_cmd_response.dart # 车控命令响应
+│ └── vehicle_status_info.dart # 车辆状态信息
+├── screens/ # 界面页面
+│ ├── full_screen.dart # 全屏聊天界面
+│ ├── main_screen.dart # 主界面
+│ └── part_screen.dart # 部分屏聊天界面
+├── services/ # 核心服务
+│ ├── audio_recorder_service.dart # 音频录制服务
+│ ├── chat_sse_service.dart # SSE 聊天服务
+│ ├── classification_service.dart # 分类服务
+│ ├── command_service.dart # 车控命令服务
+│ ├── control_recognition_service.dart # 控制识别服务
+│ ├── location_service.dart # 位置服务
+│ ├── message_service.dart # 消息管理服务
+│ ├── redis_service.dart # Redis 服务
+│ ├── tts_service.dart # 语音合成服务
+│ ├── vehicle_state_service.dart # 车辆状态服务
+│ └── voice_recognition_service.dart # 语音识别服务
+├── themes/ # 主题样式
+│ └── AppTheme.dart # 应用主题定义
+├── utils/ # 工具类
+│ ├── common_util.dart # 通用工具
+│ ├── tts_engine_manager.dart # TTS 引擎管理
+│ └── tts_util.dart # TTS 工具
+└── widgets/ # UI 组件
+ ├── assistant_avatar.dart # AI 助手头像
+ ├── chat_box.dart # 聊天框
+ ├── chat_bubble.dart # 聊天气泡
+ ├── chat_footer.dart # 聊天底部
+ ├── chat_header.dart # 聊天头部
+ ├── floating_icon.dart # 浮动图标
+ ├── floating_icon_with_wave.dart # 带波纹的浮动图标
+ ├── gradient_background.dart # 渐变背景
+ └── large_audio_wave.dart # 大音频波形
+```
+
+### 🎯 核心架构设计
+
+#### 1. 服务层架构 (Services Layer)
+
+- **MessageService**: 核心消息管理服务,负责统一管理聊天消息、语音识别、AI 对话流程
+- **ChatSseService**: SSE 流式通信服务,处理与 AI 后端的实时对话
+- **CommandService**: 车控命令处理服务,提供车辆控制命令的回调机制
+- **TTSService**: 语音合成服务,支持中英文语音播报
+- **VoiceRecognitionService**: 语音识别服务,处理音频转文字
+
+#### 2. UI 层架构 (UI Layer)
+
+- **浮动图标模式**: 主界面显示可拖拽的 AI 助手浮动图标
+- **部分屏幕模式**: 点击图标显示简化聊天界面
+- **全屏模式**: 完整的聊天界面,支持历史记录、操作按钮等
+
+#### 3. 状态管理 (State Management)
+
+基于 Provider 模式的响应式状态管理:
+- 消息状态管理
+- 语音识别状态
+- AI 对话状态
+- 车控命令执行状态
+
+## 🚗 支持的车控命令
+
+| 命令类型 | 中文描述 | 英文描述 |
+|---------|---------|---------|
+| lock | 上锁车门 | lock |
+| unlock | 解锁车门 | unlock |
+| openWindow | 打开车窗 | open window |
+| closeWindow | 关闭车窗 | close window |
+| appointAC | 预约空调 | appoint AC |
+| openAC | 打开空调 | open AC |
+| closeAC | 关闭空调 | close AC |
+| changeACTemp | 修改空调温度 | change AC temperature |
+| coolSharply | 极速降温 | cool sharply |
+| prepareCar | 一键备车 | prepare car |
+| meltSnow | 一键融雪 | melt snow |
+| openTrunk | 打开后备箱 | open trunk |
+| closeTrunk | 关闭后备箱 | close trunk |
+| honk | 鸣笛 | honk |
+| locateCar | 定位车辆 | locate car |
+| openWheelHeat | 开启方向盘加热 | open wheel heat |
+| closeWheelHeat | 关闭方向盘加热 | close wheel heat |
+| openMainSeatHeat | 开启主座椅加热 | open main seat heat |
+| closeMainSeatHeat | 关闭主座椅加热 | close main seat heat |
+| openMinorSeatHeat | 开启副座椅加热 | open minor seat heat |
+| closeMinorSeatHeat | 关闭副座椅加热 | close minor seat heat |
+
+## 🔧 技术栈
+
+### 核心依赖
+
+- **Flutter SDK**: ^3.6.2
+- **Provider**: ^6.1.5 - 状态管理
+- **HTTP**: ^1.4.0 - 网络请求
+- **Record**: ^6.0.0 - 音频录制
+- **AudioPlayers**: ^5.2.1 - 音频播放
+- **Flutter TTS**: ^4.2.0 - 语音合成
+- **Permission Handler**: ^12.0.0 - 权限管理
+- **UUID**: ^3.0.5 - 唯一标识符生成
+- **Flutter Markdown**: ^0.7.7+1 - Markdown 渲染
+- **FlutterToast**: ^8.2.12 - 消息提示
+- **Path Provider**: ^2.1.5 - 文件路径管理
+
+### 自定义包
+
+- **basic_intl**: 基础国际化支持包
+
+## 🚀 快速开始
+
+### 1. 添加依赖
+
+在您的 `pubspec.yaml` 文件中添加:
+
+```yaml
+dependencies:
+ ai_chat_assistant:
+ path: path/to/ai_chat_assistant
+```
+
+### 2. 权限配置
+
+#### Android 权限 (android/app/src/main/AndroidManifest.xml)
+
+```xml
+
+
+
+
+```
+
+### 3. 基础集成
+
+```dart
+import 'package:flutter/material.dart';
+import 'package:ai_chat_assistant/app.dart';
+import 'package:ai_chat_assistant/services/message_service.dart';
+import 'package:ai_chat_assistant/enums/vehicle_command_type.dart';
+import 'package:provider/provider.dart';
+import 'package:permission_handler/permission_handler.dart';
+
+void main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+
+ // 请求麦克风权限
+ if (!await Permission.microphone.isGranted) {
+ await Permission.microphone.request();
+ }
+
+ // 初始化 AI Chat Assistant,注册车控命令回调
+ ChatAssistantApp.initialize(
+ commandCallback: (VehicleCommandType type, Map? params) async {
+ // 处理车控命令的业务逻辑
+ print('收到车控命令: $type, 参数: $params');
+
+ // 返回执行结果
+ return (true, {'message': '命令已执行'});
+ },
+ );
+
+ runApp(
+ ChangeNotifierProvider(
+ create: (_) => MessageService(),
+ child: const MyApp(),
+ ),
+ );
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'My Car App',
+ home: const ChatAssistantApp(), // 直接使用 AI 助手
+ );
+ }
+}
+```
+
+### 4. 自定义集成
+
+如果您想在现有应用中集成聊天助手,可以使用浮动图标:
+
+```dart
+import 'package:ai_chat_assistant/widgets/floating_icon.dart';
+
+class MyHomePage extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Stack(
+ children: [
+ // 您的现有 UI
+ YourExistingWidget(),
+
+ // AI 助手浮动图标
+ const FloatingIcon(),
+ ],
+ ),
+ );
+ }
+}
+```
+
+## 📖 示例项目
+
+项目包含完整的示例应用,位于 `example/` 目录下:
+
+```bash
+cd example
+flutter run
+```
+
+示例展示了:
+- 基础集成方法
+- 车控命令处理
+- 自定义 UI 主题
+- 权限管理
+
+## 🎨 UI 组件
+
+### 浮动图标 (FloatingIcon)
+
+可拖拽的 AI 助手图标,支持:
+- 拖拽定位
+- 点击展开聊天界面
+- 动态图标切换
+- 波纹动画效果
+
+### 聊天界面组件
+
+- **ChatBubble**: 聊天气泡组件
+- **ChatBox**: 聊天输入框
+- **ChatHeader**: 聊天头部
+- **ChatFooter**: 聊天底部操作栏
+- **AssistantAvatar**: AI 助手头像
+
+### 动画组件
+
+- **FloatingIconWithWave**: 带波纹效果的浮动图标
+- **LargeAudioWave**: 大音频波形动画
+- **GradientBackground**: 渐变背景
+
+## ⚙️ 配置选项
+
+### 主题自定义
+
+```dart
+// 在 AppTheme.dart 中自定义主题
+class AppTheme {
+ static ThemeData get lightTheme => ThemeData(
+ // 自定义浅色主题
+ );
+
+ static ThemeData get darkTheme => ThemeData(
+ // 自定义深色主题
+ );
+}
+```
+
+### 资源文件
+
+确保在 `pubspec.yaml` 中包含必要的资源:
+
+```yaml
+flutter:
+ assets:
+ - assets/images/
+ fonts:
+ - family: VWHead_Bold
+ fonts:
+ - asset: assets/fonts/VWHead-Bold.otf
+ - family: VWHead_Regular
+ fonts:
+ - asset: assets/fonts/VWHead-Regular.otf
+```
+
+## 🔌 Native 平台集成
+
+### Android 平台
+
+项目包含 Android 原生代码,支持:
+- ASR (自动语音识别) 功能
+- 原生音频处理
+- 系统权限管理
+
+### 插件架构
+
+```yaml
+plugin:
+ platforms:
+ android:
+ package: com.example.ai_assistant_plugin
+ pluginClass: AiAssistantPlugin
+```
+
+## 📝 API 文档
+
+### MessageService
+
+核心消息管理服务:
+
+```dart
+class MessageService extends ChangeNotifier {
+ // 发送消息
+ Future sendMessage(String text);
+
+ // 开始语音识别
+ Future startVoiceRecognition();
+
+ // 停止语音识别
+ void stopVoiceRecognition();
+
+ // 获取聊天历史
+ List get messages;
+}
+```
+
+### CommandService
+
+车控命令服务:
+
+```dart
+class CommandService {
+ // 注册命令回调
+ static void registerCallback(CommandCallback callback);
+
+ // 执行车控命令
+ static Future<(bool, Map?)> executeCommand(
+ VehicleCommandType type,
+ {Map? params}
+ );
+}
+```
+
+## 🐛 调试和故障排除
+
+### 常见问题
+
+1. **麦克风权限问题**
+ - 确保在 AndroidManifest.xml 中添加了录音权限
+ - 在应用启动时请求权限
+
+2. **网络连接问题**
+ - 检查网络权限配置
+ - 确认 SSE 服务端地址配置正确
+
+3. **TTS 播放问题**
+ - 检查音频播放权限
+ - 确认设备支持 TTS 功能
+
+### 日志调试
+
+启用详细日志:
+
+```dart
+// 在 main.dart 中启用调试日志
+void main() {
+ debugPrint('AI Chat Assistant 启动中...');
+ // ... 其他初始化代码
+}
+```
+
+## 🤝 贡献指南
+
+欢迎提交 Issue 和 Pull Request!
+
+1. Fork 本仓库
+2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
+3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
+4. 推送到分支 (`git push origin feature/AmazingFeature`)
+5. 打开 Pull Request
+
+## 📄 许可证
+
+本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。
+
+## 🔗 相关链接
+
+- [Flutter 官方文档](https://flutter.dev/docs)
+- [Provider 状态管理](https://pub.dev/packages/provider)
+- [Flutter TTS](https://pub.dev/packages/flutter_tts)
+- [Record 插件](https://pub.dev/packages/record)
+
+---
+
+**注意**: 本插件专为车载系统设计,某些功能可能需要特定的硬件环境支持。
diff --git a/android/.gitignore b/android/.gitignore
index be3943c..9120f02 100644
--- a/android/.gitignore
+++ b/android/.gitignore
@@ -12,3 +12,5 @@ GeneratedPluginRegistrant.java
key.properties
**/*.keystore
**/*.jks
+/build/
+/src/build/
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644
index 0000000..0715030
--- /dev/null
+++ b/android/build.gradle
@@ -0,0 +1,94 @@
+group 'com.example.ai_chat_assistant'
+version '1.0-SNAPSHOT'
+
+buildscript {
+ ext.kotlin_version = '2.1.20'
+ repositories {
+ maven { url rootProject.file("../ai_chat_assistant/android/mavenLocal") }
+
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:8.11.1'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+allprojects {
+ repositories {
+ maven { url rootProject.file("../ai_chat_assistant/android/mavenLocal") }
+
+ google()
+ mavenCentral()
+ }
+}
+
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-kapt'
+
+android {
+ namespace 'com.example.ai_chat_assistant'
+
+
+ compileSdk 33
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+
+ kotlinOptions {
+ jvmTarget = "17"
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ test.java.srcDirs += 'src/test/kotlin'
+ }
+
+ defaultConfig {
+ minSdkVersion 23
+ ndk {
+ abiFilters "armeabi-v7a", "arm64-v8a"
+ }
+ }
+
+ buildFeatures {
+ dataBinding true
+ viewBinding = true
+ }
+
+ // 获取配置文件
+ def localProperties = new Properties()
+ def localPropertiesFile = rootProject.file('local.properties')
+ if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') {
+ localProperties.load(it)
+ }
+ }
+
+ // 获取flutter sdk 路径
+ def flutterRoot = localProperties.getProperty('flutter.sdk')
+ if (flutterRoot == null) {
+ throw new GradleException("Flutter SDK not found. Define location with flutter.")
+ }
+
+ repositories {
+// flatDir {
+// dirs("libs")
+// }
+ }
+
+ dependencies {
+// implementation 'com.alibaba.idst:nui-release:1.0.0'
+// implementation 'com.alibaba:fastjson:1.2.83'
+// compileOnly files("$flutterRoot/bin/cache/artifacts/engine/android-arm/flutter.jar")
+ implementation(files("libs/fastjson-1.1.46.android.jar"))
+ implementation(files("libs/nui-release-1.0.0.aar"))
+ }
+}
+
+
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index 6701377..437a291 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://mirrors.aliyun.com/macports/distfiles/gradle/gradle-8.12-all.zip
+distributionUrl=https\://mirrors.aliyun.com/macports/distfiles/gradle/gradle-8.13-all.zip
diff --git a/android/app/libs/fastjson-1.1.46.android.jar b/android/libs/fastjson-1.1.46.android.jar
similarity index 100%
rename from android/app/libs/fastjson-1.1.46.android.jar
rename to android/libs/fastjson-1.1.46.android.jar
diff --git a/android/app/libs/nuisdk-release.aar b/android/libs/nui-release-1.0.0.aar
similarity index 100%
rename from android/app/libs/nuisdk-release.aar
rename to android/libs/nui-release-1.0.0.aar
diff --git a/android/mavenLocal/com/alibaba/idst/nui-release/1.0.0/nui-release-1.0.0.aar b/android/mavenLocal/com/alibaba/idst/nui-release/1.0.0/nui-release-1.0.0.aar
new file mode 100644
index 0000000..37d6835
Binary files /dev/null and b/android/mavenLocal/com/alibaba/idst/nui-release/1.0.0/nui-release-1.0.0.aar differ
diff --git a/android/mavenLocal/com/alibaba/idst/nui-release/1.0.0/nui-release-1.0.0.pom b/android/mavenLocal/com/alibaba/idst/nui-release/1.0.0/nui-release-1.0.0.pom
new file mode 100644
index 0000000..c1dd12f
--- /dev/null
+++ b/android/mavenLocal/com/alibaba/idst/nui-release/1.0.0/nui-release-1.0.0.pom
@@ -0,0 +1,8 @@
+
+
+ 4.0.0
+ com.alibaba.idst
+ nui-release
+ 1.0.0
+ aar
+
diff --git a/android/settings.gradle b/android/settings.gradle
new file mode 100644
index 0000000..9ca8501
--- /dev/null
+++ b/android/settings.gradle
@@ -0,0 +1 @@
+ rootProject.name = 'ai_assistant_plugin'
\ No newline at end of file
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a2f47b6
--- /dev/null
+++ b/android/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/android/app/src/main/java/com/example/ai_chat_assistant/MainActivity.java b/android/src/main/java/com/example/ai_assistant_plugin/AiAssistantPlugin.java
similarity index 57%
rename from android/app/src/main/java/com/example/ai_chat_assistant/MainActivity.java
rename to android/src/main/java/com/example/ai_assistant_plugin/AiAssistantPlugin.java
index 459ec87..7651f3d 100644
--- a/android/app/src/main/java/com/example/ai_chat_assistant/MainActivity.java
+++ b/android/src/main/java/com/example/ai_assistant_plugin/AiAssistantPlugin.java
@@ -1,32 +1,32 @@
-package com.example.ai_chat_assistant;
-
-import android.media.AudioFormat;
-import android.media.AudioRecord;
-import android.media.MediaRecorder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.util.Log;
-
-import io.flutter.embedding.android.FlutterActivity;
-import io.flutter.embedding.engine.FlutterEngine;
-import io.flutter.plugin.common.MethodChannel;
-
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONException;
-import com.alibaba.fastjson.JSONObject;
-import com.alibaba.idst.nui.AsrResult;
-import com.alibaba.idst.nui.Constants;
-import com.alibaba.idst.nui.INativeNuiCallback;
-import com.alibaba.idst.nui.INativeStreamInputTtsCallback;
-import com.alibaba.idst.nui.KwsResult;
-import com.alibaba.idst.nui.NativeNui;
+package com.example.ai_assistant_plugin;
import java.util.Map;
-public class MainActivity extends FlutterActivity implements INativeNuiCallback {
- private static final String TTS_CHANNEL = "com.example.ai_chat_assistant/tts";
- private static final String ASR_CHANNEL = "com.example.ai_chat_assistant/asr";
+import io.flutter.embedding.engine.plugins.FlutterPlugin;
+import io.flutter.plugin.common.MethodCall;
+import io.flutter.plugin.common.MethodChannel;
+import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
+import io.flutter.plugin.common.MethodChannel.Result;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.alibaba.fastjson.JSONException;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.idst.nui.Constants;
+import com.alibaba.idst.nui.INativeStreamInputTtsCallback;
+import com.alibaba.idst.nui.NativeNui;
+
+/**
+ * AiAssistantPlugin
+ */
+public class AiAssistantPlugin implements FlutterPlugin, MethodCallHandler {
+
+ private static final String CHANNEL = "com.example.ai_chat_assistant/ali_sdk";
private static final String TAG = "AliyunSDK";
private static final String APP_KEY = "bXFFc1V65iYbW6EF";
private static final String ACCESS_KEY = "LTAI5t71JHxXRvt2mGuEVz9X";
@@ -37,6 +37,15 @@ public class MainActivity extends FlutterActivity implements INativeNuiCallback
private final NativeNui streamInputTtsInstance = new NativeNui(Constants.ModeType.MODE_STREAM_INPUT_TTS);
private final NativeNui asrInstance = new NativeNui();
+ /// The MethodChannel that will the communication between Flutter and native Android
+ ///
+ /// This local reference serves to register the plugin with the Flutter Engine and unregister it
+ /// when the Flutter Engine is detached from the Activity
+ private MethodChannel channel;
+ private Handler asrHandler;
+ private AsrCallBack asrCallBack;
+ private Handler handler = new Handler(Looper.getMainLooper());
+
private final AudioPlayer ttsAudioTrack = new AudioPlayer(new AudioPlayerCallback() {
@Override
public void playStart() {
@@ -53,137 +62,66 @@ public class MainActivity extends FlutterActivity implements INativeNuiCallback
}
});
- private MethodChannel asrMethodChannel;
- private final static int ASR_SAMPLE_RATE = 16000;
- private final static int ASR_WAVE_FRAM_SIZE = 20 * 2 * 1 * ASR_SAMPLE_RATE / 1000; //20ms audio for 16k/16bit/mono
- private AudioRecord asrAudioRecorder = null;
- private boolean asrStopping = false;
- private Handler asrHandler;
- private String asrText = "";
-
@Override
- public void configureFlutterEngine(FlutterEngine flutterEngine) {
- super.configureFlutterEngine(flutterEngine);
- new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), TTS_CHANNEL)
- .setMethodCallHandler((call, result) -> {
- Map args = (Map) call.arguments;
- switch (call.method) {
- case "startTts":
- Object isChinese = args.get("isChinese");
- if (isChinese == null || isChinese.toString().isBlank()) {
- return;
- }
- boolean isSuccess = startTts(Boolean.parseBoolean(isChinese.toString()));
- result.success(isSuccess);
- break;
- case "sendTts":
- Object textArg = args.get("text");
- if (textArg == null || textArg.toString().isBlank()) {
- return;
- }
- sendTts(textArg.toString());
- break;
- case "completeTts":
- completeTts();
- break;
- case "stopTts":
- stopTts();
- break;
- default:
- result.notImplemented();
- break;
- }
- });
- asrMethodChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), ASR_CHANNEL);
- asrMethodChannel.setMethodCallHandler((call, result) -> {
- switch (call.method) {
- case "startAsr":
- startAsr();
- break;
- case "stopAsr":
- stopAsr();
- break;
- default:
- result.notImplemented();
- break;
- }
- });
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ public void onAttachedToEngine(FlutterPluginBinding flutterPluginBinding) {
+ channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), CHANNEL);
+ channel.setMethodCallHandler(this);
HandlerThread asrHandlerThread = new HandlerThread("process_thread");
asrHandlerThread.start();
asrHandler = new Handler(asrHandlerThread.getLooper());
- }
-
- @Override
- protected void onStart() {
- Log.i(TAG, "onStart");
- super.onStart();
- asrInstance.initialize(this, genAsrInitParams(),
+ asrCallBack = new AsrCallBack(channel);
+ asrInstance.initialize(asrCallBack, genAsrInitParams(),
Constants.LogLevel.LOG_LEVEL_NONE, false);
}
@Override
- protected void onStop() {
- Log.i(TAG, "onStop");
- super.onStop();
-
- asrInstance.release();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
+ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
+ channel.setMethodCallHandler(null);
ttsAudioTrack.stop();
ttsAudioTrack.releaseAudioTrack();
streamInputTtsInstance.stopStreamInputTts();
+ streamInputTtsInstance.release();
+// asrInstance.release();
+// if (asrCallBack != null) {
+// asrCallBack.release();
+// asrCallBack = null;
+// }
}
- private boolean startTts(boolean isChinese) {
- int ret = streamInputTtsInstance.startStreamInputTts(new INativeStreamInputTtsCallback() {
- @Override
- public void onStreamInputTtsEventCallback(INativeStreamInputTtsCallback.StreamInputTtsEvent event, String task_id, String session_id, int ret_code, String error_msg, String timestamp, String all_response) {
- Log.i(TAG, "stream input tts event(" + event + ") session id(" + session_id + ") task id(" + task_id + ") retCode(" + ret_code + ") errMsg(" + error_msg + ")");
- if (event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_SYNTHESIS_STARTED) {
- Log.i(TAG, "STREAM_INPUT_TTS_EVENT_SYNTHESIS_STARTED");
- ttsAudioTrack.play();
- Log.i(TAG, "start play");
- } else if (event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_SENTENCE_SYNTHESIS) {
- Log.i(TAG, "STREAM_INPUT_TTS_EVENT_SENTENCE_SYNTHESIS:" + timestamp);
- } else if (event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_SYNTHESIS_COMPLETE || event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_TASK_FAILED) {
- /*
- * 提示: STREAM_INPUT_TTS_EVENT_SYNTHESIS_COMPLETE事件表示TTS已经合成完并通过回调传回了所有音频数据, 而不是表示播放器已经播放完了所有音频数据。
- */
- Log.i(TAG, "play end");
-
- // 表示推送完数据, 当播放器播放结束则会有playOver回调
- ttsAudioTrack.isFinishSend(true);
-
- if (event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_TASK_FAILED) {
- Log.e(TAG, "STREAM_INPUT_TTS_EVENT_TASK_FAILED: " + "error_code(" + ret_code + ") error_message(" + error_msg + ")");
- }
- } else if (event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_SENTENCE_BEGIN) {
- Log.i(TAG, "STREAM_INPUT_TTS_EVENT_SENTENCE_BEGIN:" + all_response);
- } else if (event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_SENTENCE_END) {
- Log.i(TAG, "STREAM_INPUT_TTS_EVENT_SENTENCE_END:" + all_response);
+ @Override
+ public void onMethodCall(MethodCall call, @NonNull Result result) {
+ Map args = call.arguments();
+ switch (call.method) {
+ case "startTts":
+ Object isChinese = args.get("isChinese");
+ if (isChinese == null || isChinese.toString().isBlank()) {
+ return;
}
- }
-
- @Override
- public void onStreamInputTtsDataCallback(byte[] data) {
- if (data.length > 0) {
- ttsAudioTrack.setAudioData(data);
+ boolean isSuccess = startTts(Boolean.parseBoolean(isChinese.toString()));
+ result.success(isSuccess);
+ break;
+ case "sendTts":
+ Object textArg = args.get("text");
+ if (textArg == null || textArg.toString().isBlank()) {
+ return;
}
- }
- }, genTtsTicket(), genTtsParameters(isChinese), "", Constants.LogLevel.toInt(Constants.LogLevel.LOG_LEVEL_NONE), false);
- if (Constants.NuiResultCode.SUCCESS != ret) {
- Log.i(TAG, "start tts failed " + ret);
- return false;
- } else {
- return true;
+ sendTts(textArg.toString());
+ break;
+ case "completeTts":
+ completeTts();
+ break;
+ case "stopTts":
+ stopTts();
+ break;
+ case "startAsr":
+ startAsr();
+ break;
+ case "stopAsr":
+ stopAsr();
+ break;
+ default:
+ result.notImplemented();
+ break;
}
}
@@ -201,7 +139,6 @@ public class MainActivity extends FlutterActivity implements INativeNuiCallback
}
private void startAsr() {
- asrText = "";
asrHandler.post(() -> {
String setParamsString = genAsrParams();
Log.i(TAG, "nui set params " + setParamsString);
@@ -213,105 +150,12 @@ public class MainActivity extends FlutterActivity implements INativeNuiCallback
private void stopAsr() {
asrHandler.post(() -> {
- asrStopping = true;
long ret = asrInstance.stopDialog();
- runOnUiThread(() -> asrMethodChannel.invokeMethod("onAsrStop", null));
+ handler.post(() -> channel.invokeMethod("onAsrStop", null));
Log.i(TAG, "cancel dialog " + ret + " end");
});
}
- @Override
- public void onNuiEventCallback(Constants.NuiEvent event, final int resultCode,
- final int arg2, KwsResult kwsResult,
- AsrResult asrResult) {
- Log.i(TAG, "event=" + event + " resultCode=" + resultCode);
- if (event == Constants.NuiEvent.EVENT_TRANSCRIBER_STARTED) {
-
- } else if (event == Constants.NuiEvent.EVENT_TRANSCRIBER_COMPLETE) {
- asrStopping = false;
- } else if (event == Constants.NuiEvent.EVENT_ASR_PARTIAL_RESULT) {
- JSONObject jsonObject = JSON.parseObject(asrResult.allResponse);
- JSONObject payload = jsonObject.getJSONObject("payload");
- String result = payload.getString("result");
- if (asrMethodChannel != null && result != null && !result.isBlank()) {
- runOnUiThread(() -> asrMethodChannel.invokeMethod("onAsrResult", asrText + result));
- }
- } else if (event == Constants.NuiEvent.EVENT_SENTENCE_END) {
- JSONObject jsonObject = JSON.parseObject(asrResult.allResponse);
- JSONObject payload = jsonObject.getJSONObject("payload");
- String result = payload.getString("result");
- if (asrMethodChannel != null && result != null && !result.isBlank()) {
- asrText += result;
- runOnUiThread(() -> asrMethodChannel.invokeMethod("onAsrResult", asrText));
- }
- } else if (event == Constants.NuiEvent.EVENT_VAD_START) {
-
- } else if (event == Constants.NuiEvent.EVENT_VAD_END) {
-
- } else if (event == Constants.NuiEvent.EVENT_ASR_ERROR) {
- asrStopping = false;
- } else if (event == Constants.NuiEvent.EVENT_MIC_ERROR) {
- asrStopping = false;
- } else if (event == Constants.NuiEvent.EVENT_DIALOG_EX) { /* unused */
- Log.i(TAG, "dialog extra message = " + asrResult.asrResult);
- }
- }
-
- //当调用NativeNui的start后,会一定时间反复回调该接口,底层会提供buffer并告知这次需要数据的长度
- //返回值告知底层读了多少数据,应该尽量保证return的长度等于需要的长度,如果返回<=0,则表示出错
- @Override
- public int onNuiNeedAudioData(byte[] buffer, int len) {
- if (asrAudioRecorder == null) {
- return -1;
- }
- if (asrAudioRecorder.getState() != AudioRecord.STATE_INITIALIZED) {
- Log.e(TAG, "audio recorder not init");
- return -1;
- }
- return asrAudioRecorder.read(buffer, 0, len);
- }
-
- //当录音状态发送变化的时候调用
- @Override
- public void onNuiAudioStateChanged(Constants.AudioState state) {
- Log.i(TAG, "onNuiAudioStateChanged");
- if (state == Constants.AudioState.STATE_OPEN) {
- Log.i(TAG, "audio recorder start");
- asrAudioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT,
- ASR_SAMPLE_RATE,
- AudioFormat.CHANNEL_IN_MONO,
- AudioFormat.ENCODING_PCM_16BIT,
- ASR_WAVE_FRAM_SIZE * 4);
- asrAudioRecorder.startRecording();
- Log.i(TAG, "audio recorder start done");
- } else if (state == Constants.AudioState.STATE_CLOSE) {
- Log.i(TAG, "audio recorder close");
- if (asrAudioRecorder != null) {
- asrAudioRecorder.release();
- }
- } else if (state == Constants.AudioState.STATE_PAUSE) {
- Log.i(TAG, "audio recorder pause");
- if (asrAudioRecorder != null) {
- asrAudioRecorder.stop();
- }
- }
- }
-
- @Override
- public void onNuiAudioRMSChanged(float val) {
-// Log.i(TAG, "onNuiAudioRMSChanged vol " + val);
- }
-
- @Override
- public void onNuiVprEventCallback(Constants.NuiVprEvent event) {
- Log.i(TAG, "onNuiVprEventCallback event " + event);
- }
-
- @Override
- public void onNuiLogTrackCallback(Constants.LogLevel level, String log) {
- Log.i(TAG, "onNuiLogTrackCallback log level:" + level + ", message -> " + log);
- }
-
private String genTtsTicket() {
String str = "";
try {
@@ -433,4 +277,51 @@ public class MainActivity extends FlutterActivity implements INativeNuiCallback
Log.i(TAG, "dialog params: " + params);
return params;
}
-}
\ No newline at end of file
+
+ private boolean startTts(boolean isChinese) {
+ int ret = streamInputTtsInstance.startStreamInputTts(new INativeStreamInputTtsCallback() {
+ @Override
+ public void onStreamInputTtsEventCallback(INativeStreamInputTtsCallback.StreamInputTtsEvent event, String task_id, String session_id, int ret_code, String error_msg, String timestamp, String all_response) {
+ Log.i(TAG, "stream input tts event(" + event + ") session id(" + session_id + ") task id(" + task_id + ") retCode(" + ret_code + ") errMsg(" + error_msg + ")");
+ if (event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_SYNTHESIS_STARTED) {
+ Log.i(TAG, "STREAM_INPUT_TTS_EVENT_SYNTHESIS_STARTED");
+ ttsAudioTrack.play();
+ Log.i(TAG, "start play");
+ } else if (event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_SENTENCE_SYNTHESIS) {
+ Log.i(TAG, "STREAM_INPUT_TTS_EVENT_SENTENCE_SYNTHESIS:" + timestamp);
+ } else if (event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_SYNTHESIS_COMPLETE || event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_TASK_FAILED) {
+ /*
+ * 提示: STREAM_INPUT_TTS_EVENT_SYNTHESIS_COMPLETE事件表示TTS已经合成完并通过回调传回了所有音频数据, 而不是表示播放器已经播放完了所有音频数据。
+ */
+ Log.i(TAG, "play end");
+
+ // 表示推送完数据, 当播放器播放结束则会有playOver回调
+ ttsAudioTrack.isFinishSend(true);
+
+ if (event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_TASK_FAILED) {
+ Log.e(TAG, "STREAM_INPUT_TTS_EVENT_TASK_FAILED: " + "error_code(" + ret_code + ") error_message(" + error_msg + ")");
+ }
+ } else if (event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_SENTENCE_BEGIN) {
+ Log.i(TAG, "STREAM_INPUT_TTS_EVENT_SENTENCE_BEGIN:" + all_response);
+ } else if (event == StreamInputTtsEvent.STREAM_INPUT_TTS_EVENT_SENTENCE_END) {
+ Log.i(TAG, "STREAM_INPUT_TTS_EVENT_SENTENCE_END:" + all_response);
+ }
+ }
+
+ @Override
+ public void onStreamInputTtsDataCallback(byte[] data) {
+ if (data.length > 0) {
+ ttsAudioTrack.setAudioData(data);
+ }
+ }
+ }, genTtsTicket(), genTtsParameters(isChinese), "", Constants.LogLevel.toInt(Constants.LogLevel.LOG_LEVEL_NONE), false);
+ if (Constants.NuiResultCode.SUCCESS != ret) {
+ Log.i(TAG, "start tts failed " + ret);
+ return false;
+ } else {
+ return true;
+ }
+
+ }
+
+}
diff --git a/android/src/main/java/com/example/ai_assistant_plugin/AsrCallBack.java b/android/src/main/java/com/example/ai_assistant_plugin/AsrCallBack.java
new file mode 100644
index 0000000..1d129ff
--- /dev/null
+++ b/android/src/main/java/com/example/ai_assistant_plugin/AsrCallBack.java
@@ -0,0 +1,139 @@
+package com.example.ai_assistant_plugin;
+
+import android.media.AudioFormat;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.idst.nui.AsrResult;
+import com.alibaba.idst.nui.Constants;
+import com.alibaba.idst.nui.INativeNuiCallback;
+import com.alibaba.idst.nui.KwsResult;
+
+import io.flutter.plugin.common.MethodChannel;
+
+public class AsrCallBack implements INativeNuiCallback {
+
+ private static final String TAG = "AliAsr";
+ private final static int ASR_SAMPLE_RATE = 16000;
+ private final static int ASR_WAVE_FRAM_SIZE = 20 * 2 * 1 * ASR_SAMPLE_RATE / 1000; //20ms audio for 16k/16bit/mono
+ private AudioRecord asrAudioRecorder = null;
+ private MethodChannel channel;
+ private String asrText = "";
+ private Handler handler = new Handler(Looper.getMainLooper());
+
+ public AsrCallBack(MethodChannel channel) {
+ this.channel = channel;
+ }
+
+ @Override
+ public void onNuiEventCallback(Constants.NuiEvent event, final int resultCode,
+ final int arg2, KwsResult kwsResult,
+ AsrResult asrResult) {
+ Log.i(TAG, "event=" + event + " resultCode=" + resultCode);
+ if (event == Constants.NuiEvent.EVENT_TRANSCRIBER_STARTED) {
+ asrText = "";
+ } else if (event == Constants.NuiEvent.EVENT_TRANSCRIBER_COMPLETE) {
+
+ } else if (event == Constants.NuiEvent.EVENT_ASR_PARTIAL_RESULT) {
+ JSONObject jsonObject = JSON.parseObject(asrResult.allResponse);
+ JSONObject payload = jsonObject.getJSONObject("payload");
+ String result = payload.getString("result");
+ if (channel != null && result != null && !result.isBlank()) {
+ handler.post(() -> channel.invokeMethod("onAsrResult", asrText + result));
+ }
+ } else if (event == Constants.NuiEvent.EVENT_SENTENCE_END) {
+ JSONObject jsonObject = JSON.parseObject(asrResult.allResponse);
+ JSONObject payload = jsonObject.getJSONObject("payload");
+ String result = payload.getString("result");
+ if (channel != null && result != null && !result.isBlank()) {
+ asrText += result;
+ handler.post(() -> channel.invokeMethod("onAsrResult", asrText));
+ }
+ } else if (event == Constants.NuiEvent.EVENT_VAD_START) {
+
+ } else if (event == Constants.NuiEvent.EVENT_VAD_END) {
+
+ } else if (event == Constants.NuiEvent.EVENT_ASR_ERROR) {
+
+ } else if (event == Constants.NuiEvent.EVENT_MIC_ERROR) {
+
+ } else if (event == Constants.NuiEvent.EVENT_DIALOG_EX) { /* unused */
+ Log.i(TAG, "dialog extra message = " + asrResult.asrResult);
+ }
+ }
+
+ //当调用NativeNui的start后,会一定时间反复回调该接口,底层会提供buffer并告知这次需要数据的长度
+ //返回值告知底层读了多少数据,应该尽量保证return的长度等于需要的长度,如果返回<=0,则表示出错
+ @Override
+ public int onNuiNeedAudioData(byte[] buffer, int len) {
+ if (asrAudioRecorder == null) {
+ return -1;
+ }
+ if (asrAudioRecorder.getState() != AudioRecord.STATE_INITIALIZED) {
+ Log.e(TAG, "audio recorder not init");
+ return -1;
+ }
+ return asrAudioRecorder.read(buffer, 0, len);
+ }
+
+ //当录音状态发送变化的时候调用
+ @Override
+ public void onNuiAudioStateChanged(Constants.AudioState state) {
+ Log.i(TAG, "onNuiAudioStateChanged");
+ if (state == Constants.AudioState.STATE_OPEN) {
+ Log.i(TAG, "audio recorder start");
+ asrAudioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT,
+ ASR_SAMPLE_RATE,
+ AudioFormat.CHANNEL_IN_MONO,
+ AudioFormat.ENCODING_PCM_16BIT,
+ ASR_WAVE_FRAM_SIZE * 4);
+ asrAudioRecorder.startRecording();
+ Log.i(TAG, "audio recorder start done");
+ } else if (state == Constants.AudioState.STATE_CLOSE) {
+ Log.i(TAG, "audio recorder close");
+ if (asrAudioRecorder != null) {
+ asrAudioRecorder.release();
+ }
+ } else if (state == Constants.AudioState.STATE_PAUSE) {
+ Log.i(TAG, "audio recorder pause");
+ if (asrAudioRecorder != null) {
+ asrAudioRecorder.stop();
+ }
+ }
+ }
+
+ @Override
+ public void onNuiAudioRMSChanged(float val) {
+// Log.i(TAG, "onNuiAudioRMSChanged vol " + val);
+ }
+
+ @Override
+ public void onNuiVprEventCallback(Constants.NuiVprEvent event) {
+ Log.i(TAG, "onNuiVprEventCallback event " + event);
+ }
+
+ @Override
+ public void onNuiLogTrackCallback(Constants.LogLevel level, String log) {
+ Log.i(TAG, "onNuiLogTrackCallback log level:" + level + ", message -> " + log);
+ }
+
+ public void release() {
+ // 释放音频录制资源
+ if (asrAudioRecorder != null) {
+ try {
+ asrAudioRecorder.stop();
+ } catch (Exception e) {
+ Log.e(TAG, "release error", e);
+ }
+ asrAudioRecorder.release();
+ asrAudioRecorder = null;
+ }
+ channel = null;
+ asrText = null;
+ }
+}
diff --git a/android/app/src/main/java/com/example/ai_chat_assistant/AudioPlayer.java b/android/src/main/java/com/example/ai_assistant_plugin/AudioPlayer.java
similarity index 99%
rename from android/app/src/main/java/com/example/ai_chat_assistant/AudioPlayer.java
rename to android/src/main/java/com/example/ai_assistant_plugin/AudioPlayer.java
index f901250..db3f415 100644
--- a/android/app/src/main/java/com/example/ai_chat_assistant/AudioPlayer.java
+++ b/android/src/main/java/com/example/ai_assistant_plugin/AudioPlayer.java
@@ -1,4 +1,4 @@
-package com.example.ai_chat_assistant;
+package com.example.ai_assistant_plugin;
import android.media.AudioFormat;
import android.media.AudioManager;
diff --git a/android/app/src/main/java/com/example/ai_chat_assistant/AudioPlayerCallback.java b/android/src/main/java/com/example/ai_assistant_plugin/AudioPlayerCallback.java
similarity index 77%
rename from android/app/src/main/java/com/example/ai_chat_assistant/AudioPlayerCallback.java
rename to android/src/main/java/com/example/ai_assistant_plugin/AudioPlayerCallback.java
index aaaefe8..e0490ca 100644
--- a/android/app/src/main/java/com/example/ai_chat_assistant/AudioPlayerCallback.java
+++ b/android/src/main/java/com/example/ai_assistant_plugin/AudioPlayerCallback.java
@@ -1,4 +1,4 @@
-package com.example.ai_chat_assistant;
+package com.example.ai_assistant_plugin;
public interface AudioPlayerCallback {
public void playStart();
diff --git a/android/app/src/main/java/com/example/ai_chat_assistant/Auth.java b/android/src/main/java/com/example/ai_assistant_plugin/Auth.java
similarity index 99%
rename from android/app/src/main/java/com/example/ai_chat_assistant/Auth.java
rename to android/src/main/java/com/example/ai_assistant_plugin/Auth.java
index ccd577b..aa06a13 100644
--- a/android/app/src/main/java/com/example/ai_chat_assistant/Auth.java
+++ b/android/src/main/java/com/example/ai_assistant_plugin/Auth.java
@@ -1,11 +1,10 @@
-package com.example.ai_chat_assistant;
+package com.example.ai_assistant_plugin;
import android.util.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
-
-import com.example.ai_chat_assistant.token.AccessToken;
+import com.example.ai_assistant_plugin.token.AccessToken;
import java.io.File;
import java.io.FileInputStream;
diff --git a/android/app/src/main/java/com/example/ai_chat_assistant/token/AccessToken.java b/android/src/main/java/com/example/ai_assistant_plugin/token/AccessToken.java
similarity index 98%
rename from android/app/src/main/java/com/example/ai_chat_assistant/token/AccessToken.java
rename to android/src/main/java/com/example/ai_assistant_plugin/token/AccessToken.java
index 08ae376..afabfe3 100644
--- a/android/app/src/main/java/com/example/ai_chat_assistant/token/AccessToken.java
+++ b/android/src/main/java/com/example/ai_assistant_plugin/token/AccessToken.java
@@ -1,4 +1,4 @@
-package com.example.ai_chat_assistant.token;
+package com.example.ai_assistant_plugin.token;
import android.util.Log;
diff --git a/android/app/src/main/java/com/example/ai_chat_assistant/token/HttpRequest.java b/android/src/main/java/com/example/ai_assistant_plugin/token/HttpRequest.java
similarity index 99%
rename from android/app/src/main/java/com/example/ai_chat_assistant/token/HttpRequest.java
rename to android/src/main/java/com/example/ai_assistant_plugin/token/HttpRequest.java
index 03ed9f5..e5c68c1 100644
--- a/android/app/src/main/java/com/example/ai_chat_assistant/token/HttpRequest.java
+++ b/android/src/main/java/com/example/ai_assistant_plugin/token/HttpRequest.java
@@ -1,4 +1,4 @@
-package com.example.ai_chat_assistant.token;
+package com.example.ai_assistant_plugin.token;
import android.util.Log;
diff --git a/android/app/src/main/java/com/example/ai_chat_assistant/token/HttpResponse.java b/android/src/main/java/com/example/ai_assistant_plugin/token/HttpResponse.java
similarity index 94%
rename from android/app/src/main/java/com/example/ai_chat_assistant/token/HttpResponse.java
rename to android/src/main/java/com/example/ai_assistant_plugin/token/HttpResponse.java
index c9b0bc9..d3f5adf 100644
--- a/android/app/src/main/java/com/example/ai_chat_assistant/token/HttpResponse.java
+++ b/android/src/main/java/com/example/ai_assistant_plugin/token/HttpResponse.java
@@ -1,4 +1,4 @@
-package com.example.ai_chat_assistant.token;
+package com.example.ai_assistant_plugin.token;
/**
* Say something
diff --git a/android/app/src/main/java/com/example/ai_chat_assistant/token/HttpUtil.java b/android/src/main/java/com/example/ai_assistant_plugin/token/HttpUtil.java
similarity index 98%
rename from android/app/src/main/java/com/example/ai_chat_assistant/token/HttpUtil.java
rename to android/src/main/java/com/example/ai_assistant_plugin/token/HttpUtil.java
index 2432570..9908477 100644
--- a/android/app/src/main/java/com/example/ai_chat_assistant/token/HttpUtil.java
+++ b/android/src/main/java/com/example/ai_assistant_plugin/token/HttpUtil.java
@@ -1,4 +1,4 @@
-package com.example.ai_chat_assistant.token;
+package com.example.ai_assistant_plugin.token;
import android.util.Log;
diff --git a/android/app/src/main/java/com/example/ai_chat_assistant/token/Signer.java b/android/src/main/java/com/example/ai_assistant_plugin/token/Signer.java
similarity index 98%
rename from android/app/src/main/java/com/example/ai_chat_assistant/token/Signer.java
rename to android/src/main/java/com/example/ai_assistant_plugin/token/Signer.java
index 0eefaca..ce89a5f 100644
--- a/android/app/src/main/java/com/example/ai_chat_assistant/token/Signer.java
+++ b/android/src/main/java/com/example/ai_assistant_plugin/token/Signer.java
@@ -1,4 +1,4 @@
-package com.example.ai_chat_assistant.token;
+package com.example.ai_assistant_plugin.token;
import android.util.Base64;
diff --git a/android/app/src/profile/AndroidManifest.xml b/android/src/profile/AndroidManifest.xml
similarity index 100%
rename from android/app/src/profile/AndroidManifest.xml
rename to android/src/profile/AndroidManifest.xml
diff --git a/example/.gitignore b/example/.gitignore
new file mode 100644
index 0000000..3820a95
--- /dev/null
+++ b/example/.gitignore
@@ -0,0 +1,45 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.build/
+.buildlog/
+.history
+.svn/
+.swiftpm/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins-dependencies
+.pub-cache/
+.pub/
+/build/
+/coverage/
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/example/.metadata b/example/.metadata
new file mode 100644
index 0000000..76fd1d0
--- /dev/null
+++ b/example/.metadata
@@ -0,0 +1,30 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: "05db9689081f091050f01aed79f04dce0c750154"
+ channel: "stable"
+
+project_type: app
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: 05db9689081f091050f01aed79f04dce0c750154
+ base_revision: 05db9689081f091050f01aed79f04dce0c750154
+ - platform: android
+ create_revision: 05db9689081f091050f01aed79f04dce0c750154
+ base_revision: 05db9689081f091050f01aed79f04dce0c750154
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/example/README.md b/example/README.md
new file mode 100644
index 0000000..2b3fce4
--- /dev/null
+++ b/example/README.md
@@ -0,0 +1,16 @@
+# example
+
+A new Flutter project.
+
+## Getting Started
+
+This project is a starting point for a Flutter application.
+
+A few resources to get you started if this is your first Flutter project:
+
+- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
+- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
+
+For help getting started with Flutter development, view the
+[online documentation](https://docs.flutter.dev/), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.
diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml
new file mode 100644
index 0000000..0d29021
--- /dev/null
+++ b/example/analysis_options.yaml
@@ -0,0 +1,28 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at https://dart.dev/lints.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/example/android/.gitignore b/example/android/.gitignore
new file mode 100644
index 0000000..be3943c
--- /dev/null
+++ b/example/android/.gitignore
@@ -0,0 +1,14 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+.cxx/
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/to/reference-keystore
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/android/app/build.gradle.kts b/example/android/app/build.gradle.kts
similarity index 77%
rename from android/app/build.gradle.kts
rename to example/android/app/build.gradle.kts
index b592c1a..cc7d3a4 100644
--- a/android/app/build.gradle.kts
+++ b/example/android/app/build.gradle.kts
@@ -6,9 +6,9 @@ plugins {
}
android {
- namespace = "com.example.ai_chat_assistant"
+ namespace = "com.example.example"
compileSdk = flutter.compileSdkVersion
- ndkVersion = "29.0.13599879"
+ ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
@@ -21,10 +21,10 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
- applicationId = "com.example.ai_chat_assistant"
+ applicationId = "com.example.example"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
- minSdk = 24
+ minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
@@ -37,18 +37,16 @@ android {
signingConfig = signingConfigs.getByName("debug")
}
}
- repositories {
- flatDir {
- dirs("libs")
- }
+ viewBinding {
+// isEnabled = viewBindingEnabled
}
+ dependenciesInfo {
+ includeInApk = includeInApk
+ includeInBundle = includeInBundle
+ }
+ ndkVersion = ndkVersion
}
flutter {
source = "../.."
}
-
-dependencies {
- implementation(files("libs/fastjson-1.1.46.android.jar"))
- implementation(files("libs/nuisdk-release.aar"))
-}
\ No newline at end of file
diff --git a/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml
similarity index 83%
rename from android/app/src/debug/AndroidManifest.xml
rename to example/android/app/src/debug/AndroidManifest.xml
index d3aa09c..399f698 100644
--- a/android/app/src/debug/AndroidManifest.xml
+++ b/example/android/app/src/debug/AndroidManifest.xml
@@ -4,5 +4,4 @@
to allow setting breakpoints, to provide hot reload, etc.
-->
-
diff --git a/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
similarity index 93%
rename from android/app/src/main/AndroidManifest.xml
rename to example/android/app/src/main/AndroidManifest.xml
index fbfedbd..74a78b9 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
-
-
-
diff --git a/example/android/app/src/main/java/com/example/example/MainActivity.java b/example/android/app/src/main/java/com/example/example/MainActivity.java
new file mode 100644
index 0000000..59f336d
--- /dev/null
+++ b/example/android/app/src/main/java/com/example/example/MainActivity.java
@@ -0,0 +1,6 @@
+package com.example.example;
+
+import io.flutter.embedding.android.FlutterActivity;
+
+public class MainActivity extends FlutterActivity {
+}
diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml
similarity index 100%
rename from android/app/src/main/res/drawable-v21/launch_background.xml
rename to example/android/app/src/main/res/drawable-v21/launch_background.xml
diff --git a/android/app/src/main/res/drawable/launch_background.xml b/example/android/app/src/main/res/drawable/launch_background.xml
similarity index 100%
rename from android/app/src/main/res/drawable/launch_background.xml
rename to example/android/app/src/main/res/drawable/launch_background.xml
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
similarity index 100%
rename from android/app/src/main/res/mipmap-hdpi/ic_launcher.png
rename to example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
similarity index 100%
rename from android/app/src/main/res/mipmap-mdpi/ic_launcher.png
rename to example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
similarity index 100%
rename from android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
rename to example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
similarity index 100%
rename from android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
rename to example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
similarity index 100%
rename from android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
rename to example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
diff --git a/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml
similarity index 100%
rename from android/app/src/main/res/values-night/styles.xml
rename to example/android/app/src/main/res/values-night/styles.xml
diff --git a/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml
similarity index 100%
rename from android/app/src/main/res/values/styles.xml
rename to example/android/app/src/main/res/values/styles.xml
diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..399f698
--- /dev/null
+++ b/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/example/android/build.gradle.kts b/example/android/build.gradle.kts
new file mode 100644
index 0000000..cec5e06
--- /dev/null
+++ b/example/android/build.gradle.kts
@@ -0,0 +1,29 @@
+allprojects {
+ repositories {
+ maven { url = uri("https://maven.aliyun.com/repository/public") }
+ maven { url = uri("https://maven.aliyun.com/repository/google") }
+ maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") }
+ maven { url = uri("https://maven.aliyun.com/repository/central") }
+
+ google()
+ mavenCentral()
+ }
+}
+
+val newBuildDir: Directory =
+ rootProject.layout.buildDirectory
+ .dir("../../build")
+ .get()
+rootProject.layout.buildDirectory.value(newBuildDir)
+
+subprojects {
+ val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
+ project.layout.buildDirectory.value(newSubprojectBuildDir)
+}
+subprojects {
+ project.evaluationDependsOn(":app")
+}
+
+tasks.register("clean") {
+ delete(rootProject.layout.buildDirectory)
+}
diff --git a/example/android/build/reports/problems/problems-report.html b/example/android/build/reports/problems/problems-report.html
new file mode 100644
index 0000000..fd2eaf0
--- /dev/null
+++ b/example/android/build/reports/problems/problems-report.html
@@ -0,0 +1,663 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Gradle Configuration Cache
+
+
+
+
+
+
+ Loading...
+
+
+
+
+
+
+
diff --git a/example/android/gradle.properties b/example/android/gradle.properties
new file mode 100644
index 0000000..f018a61
--- /dev/null
+++ b/example/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..ac3b479
--- /dev/null
+++ b/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
diff --git a/example/android/settings.gradle.kts b/example/android/settings.gradle.kts
new file mode 100644
index 0000000..1f4edca
--- /dev/null
+++ b/example/android/settings.gradle.kts
@@ -0,0 +1,31 @@
+pluginManagement {
+ val flutterSdkPath =
+ run {
+ val properties = java.util.Properties()
+ file("local.properties").inputStream().use { properties.load(it) }
+ val flutterSdkPath = properties.getProperty("flutter.sdk")
+ require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
+ flutterSdkPath
+ }
+
+ includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
+
+ repositories {
+ maven { url = uri("https://maven.aliyun.com/repository/public") }
+ maven { url = uri("https://maven.aliyun.com/repository/google") }
+ maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") }
+ maven { url = uri("https://maven.aliyun.com/repository/central") }
+
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+plugins {
+ id("dev.flutter.flutter-plugin-loader") version "1.0.0"
+ id("com.android.application") version "8.9.1" apply false
+ id("org.jetbrains.kotlin.android") version "2.1.0" apply false
+}
+
+include(":app")
diff --git a/example/lib/main.dart b/example/lib/main.dart
new file mode 100644
index 0000000..5348bce
--- /dev/null
+++ b/example/lib/main.dart
@@ -0,0 +1,58 @@
+import 'package:flutter/material.dart';
+import 'package:permission_handler/permission_handler.dart';
+import 'package:provider/provider.dart';
+import 'package:ai_chat_assistant/app.dart';
+import 'package:ai_chat_assistant/services/message_service.dart';
+import 'package:ai_chat_assistant/enums/vehicle_command_type.dart';
+
+void main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+
+ // 请求麦克风权限
+ if (!await Permission.microphone.isGranted) {
+ await Permission.microphone.request();
+ }
+
+ // 初始化 AI Chat Assistant,注册车控命令回调
+ ChatAssistantApp.initialize(
+ commandCallback: (VehicleCommandType type, Map? params) async {
+ // 这里是示例的车控命令处理逻辑
+ print('收到车控命令: $type, 参数: $params');
+ return Future.value((true, {'message': '命令已执行'}));
+ },
+ );
+
+ runApp(
+ ChangeNotifierProvider(
+ create: (_) => MessageService(),
+ child: const MyApp(),
+ ),
+ );
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'AI Chat Assistant Example',
+ theme: ThemeData(
+ primarySwatch: Colors.blue,
+ useMaterial3: true,
+ ),
+ home: const ExampleHomePage(),
+ );
+ }
+}
+
+class ExampleHomePage extends StatelessWidget {
+ const ExampleHomePage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return const Scaffold(
+ body: ChatAssistantApp(),
+ );
+ }
+}
diff --git a/example/pubspec.lock b/example/pubspec.lock
new file mode 100644
index 0000000..3e86f95
--- /dev/null
+++ b/example/pubspec.lock
@@ -0,0 +1,608 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+ ai_chat_assistant:
+ dependency: "direct main"
+ description:
+ path: ".."
+ relative: true
+ source: path
+ version: "1.0.0+1"
+ args:
+ dependency: transitive
+ description:
+ name: args
+ sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.7.0"
+ async:
+ dependency: transitive
+ description:
+ name: async
+ sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.13.0"
+ audioplayers:
+ dependency: transitive
+ description:
+ name: audioplayers
+ sha256: c05c6147124cd63e725e861335a8b4d57300b80e6e92cea7c145c739223bbaef
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "5.2.1"
+ audioplayers_android:
+ dependency: transitive
+ description:
+ name: audioplayers_android
+ sha256: b00e1a0e11365d88576320ec2d8c192bc21f1afb6c0e5995d1c57ae63156acb5
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "4.0.3"
+ audioplayers_darwin:
+ dependency: transitive
+ description:
+ name: audioplayers_darwin
+ sha256: "3034e99a6df8d101da0f5082dcca0a2a99db62ab1d4ddb3277bed3f6f81afe08"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "5.0.2"
+ audioplayers_linux:
+ dependency: transitive
+ description:
+ name: audioplayers_linux
+ sha256: "60787e73fefc4d2e0b9c02c69885402177e818e4e27ef087074cf27c02246c9e"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "3.1.0"
+ audioplayers_platform_interface:
+ dependency: transitive
+ description:
+ name: audioplayers_platform_interface
+ sha256: "365c547f1bb9e77d94dd1687903a668d8f7ac3409e48e6e6a3668a1ac2982adb"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "6.1.0"
+ audioplayers_web:
+ dependency: transitive
+ description:
+ name: audioplayers_web
+ sha256: "22cd0173e54d92bd9b2c80b1204eb1eb159ece87475ab58c9788a70ec43c2a62"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "4.1.0"
+ audioplayers_windows:
+ dependency: transitive
+ description:
+ name: audioplayers_windows
+ sha256: "9536812c9103563644ada2ef45ae523806b0745f7a78e89d1b5fb1951de90e1a"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "3.1.0"
+ basic_intl:
+ dependency: transitive
+ description:
+ path: "../packages/basic_intl"
+ relative: true
+ source: path
+ version: "0.2.0"
+ boolean_selector:
+ dependency: transitive
+ description:
+ name: boolean_selector
+ sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.1.2"
+ characters:
+ dependency: transitive
+ description:
+ name: characters
+ sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.4.0"
+ clock:
+ dependency: transitive
+ description:
+ name: clock
+ sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.1.2"
+ collection:
+ dependency: transitive
+ description:
+ name: collection
+ sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.19.1"
+ crypto:
+ dependency: transitive
+ description:
+ name: crypto
+ sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "3.0.6"
+ cupertino_icons:
+ dependency: "direct main"
+ description:
+ name: cupertino_icons
+ sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.0.8"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.3.3"
+ ffi:
+ dependency: transitive
+ description:
+ name: ffi
+ sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.1.4"
+ file:
+ dependency: transitive
+ description:
+ name: file
+ sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "7.0.1"
+ flutter:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_lints:
+ dependency: "direct dev"
+ description:
+ name: flutter_lints
+ sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "5.0.0"
+ flutter_markdown:
+ dependency: transitive
+ description:
+ name: flutter_markdown
+ sha256: "08fb8315236099ff8e90cb87bb2b935e0a724a3af1623000a9cec930468e0f27"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.7.7+1"
+ flutter_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_tts:
+ dependency: transitive
+ description:
+ name: flutter_tts
+ sha256: bdf2fc4483e74450dc9fc6fe6a9b6a5663e108d4d0dad3324a22c8e26bf48af4
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "4.2.3"
+ flutter_web_plugins:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ fluttertoast:
+ dependency: transitive
+ description:
+ name: fluttertoast
+ sha256: "25e51620424d92d3db3832464774a6143b5053f15e382d8ffbfd40b6e795dcf1"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "8.2.12"
+ http:
+ dependency: transitive
+ description:
+ name: http
+ sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.5.0"
+ http_parser:
+ dependency: transitive
+ description:
+ name: http_parser
+ sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "4.1.2"
+ js:
+ dependency: transitive
+ description:
+ name: js
+ sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.6.7"
+ leak_tracker:
+ dependency: transitive
+ description:
+ name: leak_tracker
+ sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "11.0.1"
+ leak_tracker_flutter_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_flutter_testing
+ sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "3.0.10"
+ leak_tracker_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_testing
+ sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "3.0.2"
+ lints:
+ dependency: transitive
+ description:
+ name: lints
+ sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "5.1.1"
+ markdown:
+ dependency: transitive
+ description:
+ name: markdown
+ sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "7.3.0"
+ matcher:
+ dependency: transitive
+ description:
+ name: matcher
+ sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.12.17"
+ material_color_utilities:
+ dependency: transitive
+ description:
+ name: material_color_utilities
+ sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.11.1"
+ meta:
+ dependency: transitive
+ description:
+ name: meta
+ sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.16.0"
+ nested:
+ dependency: transitive
+ description:
+ name: nested
+ sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.0.0"
+ path:
+ dependency: transitive
+ description:
+ name: path
+ sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.9.1"
+ path_provider:
+ dependency: transitive
+ description:
+ name: path_provider
+ sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.1.5"
+ path_provider_android:
+ dependency: transitive
+ description:
+ name: path_provider_android
+ sha256: "993381400e94d18469750e5b9dcb8206f15bc09f9da86b9e44a9b0092a0066db"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.2.18"
+ path_provider_foundation:
+ dependency: transitive
+ description:
+ name: path_provider_foundation
+ sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.4.2"
+ path_provider_linux:
+ dependency: transitive
+ description:
+ name: path_provider_linux
+ sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.2.1"
+ path_provider_platform_interface:
+ dependency: transitive
+ description:
+ name: path_provider_platform_interface
+ sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.1.2"
+ path_provider_windows:
+ dependency: transitive
+ description:
+ name: path_provider_windows
+ sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.3.0"
+ permission_handler:
+ dependency: transitive
+ description:
+ name: permission_handler
+ sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "12.0.1"
+ permission_handler_android:
+ dependency: transitive
+ description:
+ name: permission_handler_android
+ sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "13.0.1"
+ permission_handler_apple:
+ dependency: transitive
+ description:
+ name: permission_handler_apple
+ sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "9.4.7"
+ permission_handler_html:
+ dependency: transitive
+ description:
+ name: permission_handler_html
+ sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.1.3+5"
+ permission_handler_platform_interface:
+ dependency: transitive
+ description:
+ name: permission_handler_platform_interface
+ sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "4.3.0"
+ permission_handler_windows:
+ dependency: transitive
+ description:
+ name: permission_handler_windows
+ sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.2.1"
+ platform:
+ dependency: transitive
+ description:
+ name: platform
+ sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "3.1.6"
+ plugin_platform_interface:
+ dependency: transitive
+ description:
+ name: plugin_platform_interface
+ sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.1.8"
+ provider:
+ dependency: transitive
+ description:
+ name: provider
+ sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "6.1.5+1"
+ record:
+ dependency: transitive
+ description:
+ name: record
+ sha256: "9dbc6ff3e784612f90a9b001373c45ff76b7a08abd2bd9fdf72c242320c8911c"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "6.1.1"
+ record_android:
+ dependency: transitive
+ description:
+ name: record_android
+ sha256: "8361a791c9a3fa5c065f0b8b5adb10f12531f8538c86b19474cf7b56ea80d426"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.4.1"
+ record_ios:
+ dependency: transitive
+ description:
+ name: record_ios
+ sha256: "13e241ed9cbc220534a40ae6b66222e21288db364d96dd66fb762ebd3cb77c71"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.1.2"
+ record_linux:
+ dependency: transitive
+ description:
+ name: record_linux
+ sha256: "235b1f1fb84e810f8149cc0c2c731d7d697f8d1c333b32cb820c449bf7bb72d8"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.2.1"
+ record_macos:
+ dependency: transitive
+ description:
+ name: record_macos
+ sha256: "2849068bb59072f300ad63ed146e543d66afaef8263edba4de4834fc7c8d4d35"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.1.1"
+ record_platform_interface:
+ dependency: transitive
+ description:
+ name: record_platform_interface
+ sha256: b0065fdf1ec28f5a634d676724d388a77e43ce7646fb049949f58c69f3fcb4ed
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.4.0"
+ record_web:
+ dependency: transitive
+ description:
+ name: record_web
+ sha256: "4f0adf20c9ccafcc02d71111fd91fba1ca7b17a7453902593e5a9b25b74a5c56"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.2.0"
+ record_windows:
+ dependency: transitive
+ description:
+ name: record_windows
+ sha256: "223258060a1d25c62bae18282c16783f28581ec19401d17e56b5205b9f039d78"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.0.7"
+ sky_engine:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ source_span:
+ dependency: transitive
+ description:
+ name: source_span
+ sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.10.1"
+ stack_trace:
+ dependency: transitive
+ description:
+ name: stack_trace
+ sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.12.1"
+ stream_channel:
+ dependency: transitive
+ description:
+ name: stream_channel
+ sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.1.4"
+ string_scanner:
+ dependency: transitive
+ description:
+ name: string_scanner
+ sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.4.1"
+ synchronized:
+ dependency: transitive
+ description:
+ name: synchronized
+ sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "3.4.0"
+ term_glyph:
+ dependency: transitive
+ description:
+ name: term_glyph
+ sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.2.2"
+ test_api:
+ dependency: transitive
+ description:
+ name: test_api
+ sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.7.6"
+ typed_data:
+ dependency: transitive
+ description:
+ name: typed_data
+ sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.4.0"
+ uuid:
+ dependency: transitive
+ description:
+ name: uuid
+ sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "3.0.7"
+ vector_math:
+ dependency: transitive
+ description:
+ name: vector_math
+ sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.2.0"
+ vm_service:
+ dependency: transitive
+ description:
+ name: vm_service
+ sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "15.0.2"
+ web:
+ dependency: transitive
+ description:
+ name: web
+ sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.1.1"
+ xdg_directories:
+ dependency: transitive
+ description:
+ name: xdg_directories
+ sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.1.0"
+sdks:
+ dart: ">=3.9.0 <4.0.0"
+ flutter: ">=3.29.0"
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
new file mode 100644
index 0000000..ff8a43b
--- /dev/null
+++ b/example/pubspec.yaml
@@ -0,0 +1,93 @@
+name: example
+description: "AI Chat Assistant Example App"
+# The following line prevents the package from being accidentally published to
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+# The following defines the version and build number for your application.
+# A version number is three numbers separated by dots, like 1.2.43
+# followed by an optional build number separated by a +.
+# Both the version and the builder number may be overridden in flutter
+# build by specifying --build-name and --build-number, respectively.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
+# Read more about iOS versioning at
+# 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.0.0+1
+
+environment:
+ sdk: ^3.9.0
+
+# Dependencies specify other packages that your package needs in order to work.
+# To automatically upgrade your package dependencies to the latest versions
+# consider running `flutter pub upgrade --major-versions`. Alternatively,
+# dependencies can be manually updated by changing the version numbers below to
+# the latest version available on pub.dev. To see which dependencies have newer
+# versions available, run `flutter pub outdated`.
+dependencies:
+ flutter:
+ sdk: flutter
+
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+ cupertino_icons: ^1.0.8
+
+ # 添加本地 AI Chat Assistant plugin 依赖
+ ai_chat_assistant:
+ path: ../
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+ # The "flutter_lints" package below contains a set of recommended lints to
+ # encourage good coding practices. The lint set provided by the package is
+ # activated in the `analysis_options.yaml` file located at the root of your
+ # package. See that file for information about deactivating specific lint
+ # rules and activating additional ones.
+ flutter_lints: ^5.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
+
+ # To add assets to your application, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/to/resolution-aware-images
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/to/asset-from-package
+
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/to/font-from-package
diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart
new file mode 100644
index 0000000..092d222
--- /dev/null
+++ b/example/test/widget_test.dart
@@ -0,0 +1,30 @@
+// This is a basic Flutter widget test.
+//
+// To perform an interaction with a widget in your test, use the WidgetTester
+// utility in the flutter_test package. For example, you can send tap and scroll
+// gestures. You can also use WidgetTester to find child widgets in the widget
+// tree, read text, and verify that the values of widget properties are correct.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:example/main.dart';
+
+void main() {
+ testWidgets('Counter increments smoke test', (WidgetTester tester) async {
+ // Build our app and trigger a frame.
+ await tester.pumpWidget(const MyApp());
+
+ // Verify that our counter starts at 0.
+ expect(find.text('0'), findsOneWidget);
+ expect(find.text('1'), findsNothing);
+
+ // Tap the '+' icon and trigger a frame.
+ await tester.tap(find.byIcon(Icons.add));
+ await tester.pump();
+
+ // Verify that our counter has incremented.
+ expect(find.text('0'), findsNothing);
+ expect(find.text('1'), findsOneWidget);
+ });
+}
diff --git a/packages/basic_intl/lib/basic_intl.dart b/packages/basic_intl/lib/basic_intl.dart
new file mode 100644
index 0000000..f82e37f
--- /dev/null
+++ b/packages/basic_intl/lib/basic_intl.dart
@@ -0,0 +1,3 @@
+library basic_intl;
+
+export 'src/intl.dart';
diff --git a/packages/basic_intl/lib/intl.dart b/packages/basic_intl/lib/intl.dart
new file mode 100644
index 0000000..f82e37f
--- /dev/null
+++ b/packages/basic_intl/lib/intl.dart
@@ -0,0 +1,3 @@
+library basic_intl;
+
+export 'src/intl.dart';
diff --git a/packages/basic_intl/lib/src/intl.dart b/packages/basic_intl/lib/src/intl.dart
new file mode 100644
index 0000000..9f819ce
--- /dev/null
+++ b/packages/basic_intl/lib/src/intl.dart
@@ -0,0 +1,32 @@
+import 'dart:ui';
+
+class Intl {
+ static String _currentLocale = 'zh_CN';
+
+ /// 获取当前语言环境
+ static String getCurrentLocale() {
+ // 尝试从系统获取语言环境
+ try {
+ final systemLocale = PlatformDispatcher.instance.locale;
+ _currentLocale = '${systemLocale.languageCode}_${systemLocale.countryCode ?? 'CN'}';
+ } catch (e) {
+ _currentLocale = 'zh_CN';
+ }
+ return _currentLocale;
+ }
+
+ /// 设置当前语言环境
+ static void setCurrentLocale(String locale) {
+ _currentLocale = locale;
+ }
+
+ /// 判断是否为中文环境
+ static bool isChineseLocale() {
+ return getCurrentLocale().startsWith('zh');
+ }
+
+ /// 判断是否为英文环境
+ static bool isEnglishLocale() {
+ return getCurrentLocale().startsWith('en');
+ }
+}
diff --git a/packages/basic_intl/pubspec.lock b/packages/basic_intl/pubspec.lock
new file mode 100644
index 0000000..6b97eb2
--- /dev/null
+++ b/packages/basic_intl/pubspec.lock
@@ -0,0 +1,189 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+ async:
+ dependency: transitive
+ description:
+ name: async
+ sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.13.0"
+ boolean_selector:
+ dependency: transitive
+ description:
+ name: boolean_selector
+ sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.1.2"
+ characters:
+ dependency: transitive
+ description:
+ name: characters
+ sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.4.0"
+ clock:
+ dependency: transitive
+ description:
+ name: clock
+ sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.1.2"
+ collection:
+ dependency: transitive
+ description:
+ name: collection
+ sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.19.1"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.3.3"
+ flutter:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ leak_tracker:
+ dependency: transitive
+ description:
+ name: leak_tracker
+ sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "11.0.1"
+ leak_tracker_flutter_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_flutter_testing
+ sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "3.0.10"
+ leak_tracker_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_testing
+ sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "3.0.2"
+ matcher:
+ dependency: transitive
+ description:
+ name: matcher
+ sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.12.17"
+ material_color_utilities:
+ dependency: transitive
+ description:
+ name: material_color_utilities
+ sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.11.1"
+ meta:
+ dependency: transitive
+ description:
+ name: meta
+ sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.16.0"
+ path:
+ dependency: transitive
+ description:
+ name: path
+ sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.9.1"
+ sky_engine:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ source_span:
+ dependency: transitive
+ description:
+ name: source_span
+ sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.10.1"
+ stack_trace:
+ dependency: transitive
+ description:
+ name: stack_trace
+ sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.12.1"
+ stream_channel:
+ dependency: transitive
+ description:
+ name: stream_channel
+ sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.1.4"
+ string_scanner:
+ dependency: transitive
+ description:
+ name: string_scanner
+ sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.4.1"
+ term_glyph:
+ dependency: transitive
+ description:
+ name: term_glyph
+ sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.2.2"
+ test_api:
+ dependency: transitive
+ description:
+ name: test_api
+ sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.7.6"
+ vector_math:
+ dependency: transitive
+ description:
+ name: vector_math
+ sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.2.0"
+ vm_service:
+ dependency: transitive
+ description:
+ name: vm_service
+ sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "15.0.2"
+sdks:
+ dart: ">=3.8.0-0 <4.0.0"
+ flutter: ">=3.18.0-18.0.pre.54"
diff --git a/packages/basic_intl/pubspec.yaml b/packages/basic_intl/pubspec.yaml
new file mode 100644
index 0000000..520a608
--- /dev/null
+++ b/packages/basic_intl/pubspec.yaml
@@ -0,0 +1,16 @@
+name: basic_intl
+description: Basic internationalization utilities for ai_chat_assistant
+version: 0.2.0
+
+environment:
+ sdk: ^3.6.2
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+flutter:
diff --git a/pubspec.lock b/pubspec.lock
index 319d4ff..3de2e65 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -6,7 +6,7 @@ packages:
description:
name: args
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.7.0"
async:
@@ -14,7 +14,7 @@ packages:
description:
name: async
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.13.0"
audioplayers:
@@ -22,7 +22,7 @@ packages:
description:
name: audioplayers
sha256: c05c6147124cd63e725e861335a8b4d57300b80e6e92cea7c145c739223bbaef
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "5.2.1"
audioplayers_android:
@@ -30,7 +30,7 @@ packages:
description:
name: audioplayers_android
sha256: b00e1a0e11365d88576320ec2d8c192bc21f1afb6c0e5995d1c57ae63156acb5
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "4.0.3"
audioplayers_darwin:
@@ -38,7 +38,7 @@ packages:
description:
name: audioplayers_darwin
sha256: "3034e99a6df8d101da0f5082dcca0a2a99db62ab1d4ddb3277bed3f6f81afe08"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "5.0.2"
audioplayers_linux:
@@ -46,7 +46,7 @@ packages:
description:
name: audioplayers_linux
sha256: "60787e73fefc4d2e0b9c02c69885402177e818e4e27ef087074cf27c02246c9e"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.0"
audioplayers_platform_interface:
@@ -54,7 +54,7 @@ packages:
description:
name: audioplayers_platform_interface
sha256: "365c547f1bb9e77d94dd1687903a668d8f7ac3409e48e6e6a3668a1ac2982adb"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "6.1.0"
audioplayers_web:
@@ -62,7 +62,7 @@ packages:
description:
name: audioplayers_web
sha256: "22cd0173e54d92bd9b2c80b1204eb1eb159ece87475ab58c9788a70ec43c2a62"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "4.1.0"
audioplayers_windows:
@@ -70,63 +70,54 @@ packages:
description:
name: audioplayers_windows
sha256: "9536812c9103563644ada2ef45ae523806b0745f7a78e89d1b5fb1951de90e1a"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.0"
basic_intl:
dependency: "direct main"
description:
- name: basic_intl
- sha256: "15ba8447fb069bd80f0b0c74c71faf5dea45874e9566a68e4e30c897ab2b07c4"
- url: "http://175.24.250.68:4000"
- source: hosted
+ path: "packages/basic_intl"
+ relative: true
+ source: path
version: "0.2.0"
characters:
dependency: transitive
description:
name: characters
- sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
- url: "http://175.24.250.68:4000"
+ sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.3.0"
- clock:
- dependency: transitive
- description:
- name: clock
- sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
- url: "http://175.24.250.68:4000"
- source: hosted
- version: "1.1.2"
+ version: "1.4.0"
collection:
dependency: transitive
description:
name: collection
- sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
- url: "http://175.24.250.68:4000"
+ sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.19.0"
+ version: "1.19.1"
crypto:
dependency: transitive
description:
name: crypto
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.6"
ffi:
dependency: transitive
description:
name: ffi
- sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
- url: "http://175.24.250.68:4000"
+ sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.1.3"
+ version: "2.1.4"
file:
dependency: transitive
description:
name: file
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "7.0.1"
flutter:
@@ -139,7 +130,7 @@ packages:
description:
name: flutter_lints
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "5.0.0"
flutter_markdown:
@@ -147,7 +138,7 @@ packages:
description:
name: flutter_markdown
sha256: "08fb8315236099ff8e90cb87bb2b935e0a724a3af1623000a9cec930468e0f27"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "0.7.7+1"
flutter_tts:
@@ -155,7 +146,7 @@ packages:
description:
name: flutter_tts
sha256: bdf2fc4483e74450dc9fc6fe6a9b6a5663e108d4d0dad3324a22c8e26bf48af4
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "4.2.3"
flutter_web_plugins:
@@ -168,7 +159,7 @@ packages:
description:
name: fluttertoast
sha256: "25e51620424d92d3db3832464774a6143b5053f15e382d8ffbfd40b6e795dcf1"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "8.2.12"
http:
@@ -176,7 +167,7 @@ packages:
description:
name: http
sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.5.0"
http_parser:
@@ -184,7 +175,7 @@ packages:
description:
name: http_parser
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "4.1.2"
js:
@@ -192,7 +183,7 @@ packages:
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "0.6.7"
lints:
@@ -200,7 +191,7 @@ packages:
description:
name: lints
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "5.1.1"
markdown:
@@ -208,7 +199,7 @@ packages:
description:
name: markdown
sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "7.3.0"
material_color_utilities:
@@ -216,23 +207,23 @@ packages:
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
- sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
- url: "http://175.24.250.68:4000"
+ sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.15.0"
+ version: "1.16.0"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.0"
path:
@@ -240,7 +231,7 @@ packages:
description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.9.1"
path_provider:
@@ -248,31 +239,31 @@ packages:
description:
name: path_provider
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.5"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
- sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9
- url: "http://175.24.250.68:4000"
+ sha256: "993381400e94d18469750e5b9dcb8206f15bc09f9da86b9e44a9b0092a0066db"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.2.17"
+ version: "2.2.18"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
- sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
- url: "http://175.24.250.68:4000"
+ sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.4.1"
+ version: "2.4.2"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.1"
path_provider_platform_interface:
@@ -280,7 +271,7 @@ packages:
description:
name: path_provider_platform_interface
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.2"
path_provider_windows:
@@ -288,55 +279,63 @@ packages:
description:
name: path_provider_windows
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.3.0"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
- sha256: bc56bfe9d3f44c3c612d8d393bd9b174eb796d706759f9b495ac254e4294baa5
- url: "http://175.24.250.68:4000"
+ sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "10.4.5"
+ version: "12.0.1"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
- sha256: "59c6322171c29df93a22d150ad95f3aa19ed86542eaec409ab2691b8f35f9a47"
- url: "http://175.24.250.68:4000"
+ sha256: "1e3bc410ca1bf84662104b100eb126e066cb55791b7451307f9708d4007350e6"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "10.3.6"
+ version: "13.0.1"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
- sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5"
- url: "http://175.24.250.68:4000"
+ sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "9.1.4"
+ version: "9.4.7"
+ permission_handler_html:
+ dependency: transitive
+ description:
+ name: permission_handler_html
+ sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.1.3+5"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
- sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4"
- url: "http://175.24.250.68:4000"
+ sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "3.12.0"
+ version: "4.3.0"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
- sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098
- url: "http://175.24.250.68:4000"
+ sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "0.1.3"
+ version: "0.2.1"
platform:
dependency: transitive
description:
name: platform
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.6"
plugin_platform_interface:
@@ -344,81 +343,81 @@ packages:
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.8"
provider:
dependency: "direct main"
description:
name: provider
- sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84"
- url: "http://175.24.250.68:4000"
+ sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "6.1.5"
+ version: "6.1.5+1"
record:
dependency: "direct main"
description:
name: record
- sha256: daeb3f9b3fea9797094433fe6e49a879d8e4ca4207740bc6dc7e4a58764f0817
- url: "http://175.24.250.68:4000"
+ sha256: "9dbc6ff3e784612f90a9b001373c45ff76b7a08abd2bd9fdf72c242320c8911c"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "6.0.0"
+ version: "6.1.1"
record_android:
dependency: transitive
description:
name: record_android
- sha256: "97d7122455f30de89a01c6c244c839085be6b12abca251fc0e78f67fed73628b"
- url: "http://175.24.250.68:4000"
+ sha256: "8361a791c9a3fa5c065f0b8b5adb10f12531f8538c86b19474cf7b56ea80d426"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.3.3"
+ version: "1.4.1"
record_ios:
dependency: transitive
description:
name: record_ios
- sha256: "73706ebbece6150654c9d6f57897cf9b622c581148304132ba85dba15df0fdfb"
- url: "http://175.24.250.68:4000"
+ sha256: "13e241ed9cbc220534a40ae6b66222e21288db364d96dd66fb762ebd3cb77c71"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.0.0"
+ version: "1.1.2"
record_linux:
dependency: transitive
description:
name: record_linux
- sha256: "0626678a092c75ce6af1e32fe7fd1dea709b92d308bc8e3b6d6348e2430beb95"
- url: "http://175.24.250.68:4000"
+ sha256: "235b1f1fb84e810f8149cc0c2c731d7d697f8d1c333b32cb820c449bf7bb72d8"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.1.1"
+ version: "1.2.1"
record_macos:
dependency: transitive
description:
name: record_macos
- sha256: "02240833fde16c33fcf2c589f3e08d4394b704761b4a3bb609d872ff3043fbbd"
- url: "http://175.24.250.68:4000"
+ sha256: "2849068bb59072f300ad63ed146e543d66afaef8263edba4de4834fc7c8d4d35"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.0.0"
+ version: "1.1.1"
record_platform_interface:
dependency: transitive
description:
name: record_platform_interface
- sha256: c1ad38f51e4af88a085b3e792a22c685cb3e7c23fc37aa7ce44c4cf18f25fe89
- url: "http://175.24.250.68:4000"
+ sha256: b0065fdf1ec28f5a634d676724d388a77e43ce7646fb049949f58c69f3fcb4ed
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.3.0"
+ version: "1.4.0"
record_web:
dependency: transitive
description:
name: record_web
- sha256: a12856d0b3dd03d336b4b10d7520a8b3e21649a06a8f95815318feaa8f07adbb
- url: "http://175.24.250.68:4000"
+ sha256: "4f0adf20c9ccafcc02d71111fd91fba1ca7b17a7453902593e5a9b25b74a5c56"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.1.9"
+ version: "1.2.0"
record_windows:
dependency: transitive
description:
name: record_windows
- sha256: "85a22fc97f6d73ecd67c8ba5f2f472b74ef1d906f795b7970f771a0914167e99"
- url: "http://175.24.250.68:4000"
+ sha256: "223258060a1d25c62bae18282c16783f28581ec19401d17e56b5205b9f039d78"
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "1.0.6"
+ version: "1.0.7"
sky_engine:
dependency: transitive
description: flutter
@@ -429,7 +428,7 @@ packages:
description:
name: source_span
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.10.1"
string_scanner:
@@ -437,23 +436,23 @@ packages:
description:
name: string_scanner
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.4.1"
synchronized:
dependency: transitive
description:
name: synchronized
- sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225"
- url: "http://175.24.250.68:4000"
+ sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "3.3.0+3"
+ version: "3.4.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.2"
typed_data:
@@ -461,7 +460,7 @@ packages:
description:
name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.4.0"
uuid:
@@ -469,23 +468,23 @@ packages:
description:
name: uuid
sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.7"
vector_math:
dependency: transitive
description:
name: vector_math
- sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
- url: "http://175.24.250.68:4000"
+ sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
+ url: "https://pub.flutter-io.cn"
source: hosted
- version: "2.1.4"
+ version: "2.2.0"
web:
dependency: transitive
description:
name: web
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.1"
xdg_directories:
@@ -493,9 +492,9 @@ packages:
description:
name: xdg_directories
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
- url: "http://175.24.250.68:4000"
+ url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
sdks:
- dart: ">=3.6.2 <4.0.0"
- flutter: ">=3.27.0"
+ dart: ">=3.8.0 <4.0.0"
+ flutter: ">=3.29.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index b6aba21..ca1a9a4 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -14,10 +14,12 @@ dependencies:
flutter_markdown: ^0.7.7+1
audioplayers: ^5.2.1
uuid: ^3.0.5
- permission_handler: ^10.3.0
+ permission_handler: ^12.0.0
provider: ^6.1.5
flutter_tts: ^4.2.0
- basic_intl: ^0.2.0
+# basic_intl: 0.2.0
+ basic_intl:
+ path: packages/basic_intl
# flutter_ingeek_carkey: 1.4.7
# app_car:
# path: ../app_car
@@ -27,6 +29,11 @@ flutter:
uses-material-design: true
assets:
- assets/images/
+ plugin:
+ platforms:
+ android:
+ package: com.example.ai_assistant_plugin
+ pluginClass: AiAssistantPlugin
fonts:
- family: VWHead_Bold
fonts: