Flutter: Google 어시스턴트 또는 SIRI와 같은 백그라운드의 사용자 지정 음성 봇입니다.

이 튜토리얼에서는 백그라운드 또는 포그라운드에서 음성을 듣고 제출된 쿼리에 응답하는 음성 봇용 애플리케이션을 만들 것입니다.
나는 iOS에서 응용 프로그램을 테스트하지 않기 때문에 Android에만 집중할 것입니다(돈이 충분하지 않음).

코딩을 시작하자-



1) 먼저 다음과 같이 새로운 플러터 애플리케이션을 만듭니다.

2) pubspec.yaml 파일에 다음 패키지를 추가합니다.

- flutter_tts: ^3.3.3 (use for text to speech)

- flutter_background_service: ^2.1.0 (use for handling app in background)

- speech_to_text: (use for speech to text)


삼). 안드로이드 구성:

`Change the minimum Android SDK version to 21 (or higher) in your android/app/build.gradle file.



minSdk버전 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"/>


4) 이제 터미널에서 명령을 실행하십시오.flutter pub get
5) 이제 같은 디렉토리에 'background_service.dart'라는 새 파일을 만듭니다.

6) 먼저 배경 처리를 설정하므로 새 파일에 다음 코드를 작성하고 가장 중요한 것은 필요한 모든 파일을 가져오는 것을 잊었습니다.

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',
      },
    );
  });
}


Now app will be working in background mode.



7) 이제 재생을 위해 음성 수신기와 봇을 설정하겠습니다.
사용자가 "도움을 원합니다"라고 말하거나 "도움말"키워드가 포함된 항목을 말하면 시스템이 응답합니다.
** "도움을 보내고 있습니다"** 또는 "중지"라고 말한 후 사용자가 리스너를 중지합니다.

이제 동일한 파일에 다음 코드를 추가합니다.

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");
    }

}


8) 이제 백그라운드에서 음성을 들을 수 있습니다.
함수 initializeService() 시작 부분에 다음 줄을 추가합니다._initSpeech();또한 onStart() 함수에서 Timer.periodic 함수 뒤에 이 줄을 추가합니다.
if (_speechEnabled) {
_startListening();
}

9) UI를 만들고 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(() {});
                  },
                ),
              ),

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



10) 만세 앱 완료...


컴파일하고 즐기자.



GitHub 레포: Click here

좋은 웹페이지 즐겨찾기