Dart | 使用 Flutter 制作一个像 SIRI 那样的语音机器人

1 概述

我们将为语音机器人创建一个应用程序,该程序将监听后台或前台的语音,并将回答提交的查询。

2 开始编码

2.1 首先创建一个新的 flutter 应用程序

在这里插入图片描述

2.2 在 pubspec.yaml 文件中添加以下包

dependencies:
  flutter:
    sdk: flutter
  flutter_tts: ^3.3.3

  flutter_background_service: ^2.1.0
  speech_to_text:

2.3 Android 配置

在 Android/app/build.gradle 文件中,将 Android SDK 的最小版本更改为21(或更高)。

注意: 针对 Android 11使用文本语音转换的应用程序应该在其清单的查询元素中声明 TextToSpeech.Engine.INTENT_ACTION_TTS_SERVICE

<queries>
	<intent>
		<action android:name="android.speech.RecognitionService"/>
	</intent>
</queries>

在 android/app/src/main/AndroidManifest.xml 中添加以下内容:

<uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>

2.4 在终端运行 flutter pub get 命令

在这里插入图片描述

2.5 创建 background_service.dart 文件

final service = FlutterBackgroundService();

Future initializeService()async{
  await service.configure(
    androidConfiguration: AndroidConfiguration(
      // this will executed when app is in foreground or background in separated isolate
      onStart: onStart,
      // auto start service
      autoStart: true,
      isForegroundMode: true,
    ),
    iosConfiguration: IosConfiguration(
      // auto start service
      autoStart: true,

      // this will executed when app is in foreground in separated isolate
      onForeground: onStart,

      // you have to enable background fetch capability on xcode project
      onBackground: onIosBackground,
    ),
  );
  await service.startService();
}
bool onIosBackground(ServiceInstance service) {
  WidgetsFlutterBinding.ensureInitialized();
  print('FLUTTER BACKGROUND FETCH');

  return true;
}
void onStart(ServiceInstance service) async {

  // Only available for flutter 3.0.0 and later
  DartPluginRegistrant.ensureInitialized();

  // For flutter prior to version 3.0.0
  // We have to register the plugin manually

  if (service is AndroidServiceInstance) {
    service.on('setAsForeground').listen((event) {
      //set as foreground
      service.setAsForegroundService();
    });

    service.on('setAsBackground').listen((event) async {
      //set as background
      service.setAsBackgroundService();
    });
  }

  service.on('stopService').listen((event) {
    service.stopSelf();
  });
  // bring to foreground
  Timer.periodic(const Duration(seconds:1), (timer) async {
    if (service is AndroidServiceInstance) {
      service.setForegroundNotificationInfo(
        title: "My App Service",
        content: "Updated at ${DateTime.now()}",
      );
    }

    /// you can see this log in logcat
    print('FLUTTER BACKGROUND SERVICE: ${DateTime.now()}');

    // test using external plugin
    service.invoke(
      'update',
      {
        "current_date": DateTime.now().toIso8601String(),
        "last_message": '_lastWords',
      },
    );
  });
}

现在应用程序将工作在后台模式。

2.6 设置语音监听

现在让我们设置语音监听器和机器人重播,让说当用户说“我想帮助”或包含“帮助”关键字,系统将回复 我们正在发送帮助 或用户在说”停止”后停止监听器。

final SpeechToText _speechToText = SpeechToText();
bool _speechEnabled = false;
String _lastWords="Say something";
void _initSpeech() async {
  _speechEnabled = await _speechToText.initialize();

}

void _startListening() async {
  await _speechToText.listen(onResult: _onSpeechResult);
}


void _stopListening() async {
  await _speechToText.stop();
}

Future<void> _onSpeechResult(SpeechRecognitionResult result) async {
  var flutterTts = FlutterTts();
  _lastWords=(result.recognizedWords.toString().toLowerCase());

  if(_lastWords.contains("hello") || _lastWords.contains('help'))
  {

    flutterTts.speak("We are sending help");

  }
  else if(_lastWords.contains('stop'))
    {
      _stopListening();
      flutterTts.speak("Stopped");
    }

}

2.7 启动监听

现在让我们在后台听语音,在函数 initializeService ()的开头添加以下行 _ initSpeech () ;并在 Timer.periodic 函数后面添加这些行。

if (_speechEnabled) {
	_startListening();
}

2.8 创建用户界面

让我们创建一个用户界面,在 main.dart 中添加以下代码:

import 'dart:async';

import 'package:flutter_background_service/flutter_background_service.dart' show AndroidConfiguration, FlutterBackgroundService, IosConfiguration, ServiceInstance;
import 'package:flutter/material.dart';
import 'background_service.dart';
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await initializeService();

  runApp( const MyApp());
}


class MyApp extends StatefulWidget {

  const MyApp({Key? key,}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String text = "Stop Service";


  @override
  Widget build(BuildContext context) {
    return  MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(

        appBar: AppBar(
          title: const Text("Voice Bot"),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              //for listen Continuous change in foreground we will be using Stream builder
              StreamBuilder<Map<String, dynamic>?>(
                stream: FlutterBackgroundService().on('update'),
                  builder: (context,snapshot){
                if (!snapshot.hasData) {
                  return const Center(
                    child: CircularProgressIndicator(),
                  );
                }
                final data = snapshot.data!;
                String? lastMessage = data["last_message"];
                DateTime? date = DateTime.tryParse(data["current_date"]);
                return Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(lastMessage ?? 'Unknown'),
                    Text(date.toString()),
                  ],
                );
              }),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: GestureDetector(
                  child: Container(
                    padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 20),
                      decoration: BoxDecoration(
                        color: Colors.blueAccent,
                        borderRadius: BorderRadius.circular(16)
                      ),
                      child: const Text("Foreground Mode",style: TextStyle(
                        color: Colors.white
                      ),)),
                  onTap: () {
                    FlutterBackgroundService().invoke("setAsForeground");

                  },
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: GestureDetector(
                  child: Container(
                      padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 20),
                      decoration: BoxDecoration(
                          color: Colors.blueAccent,
                          borderRadius: BorderRadius.circular(16)
                      ),
                      child: const Text("Background Mode",style: TextStyle(
                          color: Colors.white
                      ),)),
                  onTap: () {
                    print('start');
                    FlutterBackgroundService().invoke("setAsBackground");

                  },
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: GestureDetector(
                  child: Container(
                    padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 20),
                    decoration: BoxDecoration(
                        color: Colors.blueAccent,
                        borderRadius: BorderRadius.circular(16)
                    ),
                    child: Text(text,style: const TextStyle(
                        color: Colors.white
                    ),),
                  ),
                  onTap: () async {
                    final service=FlutterBackgroundService();

                    var isRunning = await service.isRunning();
                    if (isRunning) {
                      service.invoke("stopService");
                    } else {
                      service.startService();
                    }

                    if (!isRunning) {
                      text = 'Stop Service';
                    } else {
                      text = 'Start Service';
                    }
                    setState(() {});
                  },
                ),
              ),

            ],
          ),
        ),
      ),
    );
  }
}

3 可以测试这个程序啦

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
好的,下面是一个简单的登录界面示例,使用Flutter 的 Material Design 风格。 首先,在 `pubspec.yaml` 文件中添加 Material Design 库: ```yaml dependencies: flutter: sdk: flutter cupertino_icons: ^0.1.2 material_design_icons_flutter: ^3.6.95 ``` 然后,在 `lib/main.dart` 文件中编写代码: ```dart import 'package:flutter/material.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Login Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: LoginPage(), ); } } class LoginPage extends StatefulWidget { @override _LoginPageState createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { final _formKey = GlobalKey<FormState>(); String _email; String _password; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Login'), ), body: Center( child: Form( key: _formKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ TextFormField( decoration: InputDecoration( labelText: 'Email', prefixIcon: Icon(MdiIcons.email), ), keyboardType: TextInputType.emailAddress, validator: (value) { if (value.isEmpty) { return 'Please enter your email'; } return null; }, onSaved: (value) { _email = value; }, ), TextFormField( decoration: InputDecoration( labelText: 'Password', prefixIcon: Icon(MdiIcons.lock), ), obscureText: true, validator: (value) { if (value.isEmpty) { return 'Please enter your password'; } return null; }, onSaved: (value) { _password = value; }, ), SizedBox( height: 24, ), RaisedButton( onPressed: () { if (_formKey.currentState.validate()) { _formKey.currentState.save(); // TODO: Perform login action } }, child: Text('Login'), ), ], ), ), ), ); } } ``` 这个示例中,我们使用了 `Form` 和 `TextFormField` 来创建表单,使用了 Material Design 风格的图标来增强用户体验。 在表单的提交按钮中,我们可以执行具体的登录操作。你可以根据自己的需求来实现这个逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟华328

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值