Flutter-Native SDK集成實(shí)現(xiàn)百度語(yǔ)音識(shí)別功能

Android Native SDK集成流程

  • 下載 百度語(yǔ)音識(shí)別Android SDK

  • 使用Android Studio打開(kāi)Android項(xiàng)目,OpenFile - Android項(xiàng)目

  • 創(chuàng)建語(yǔ)音Library(File-new Module-Library(asr_plugin)

  • 添加sdk(解壓下載的SDK/core/libs/***.jar)拷貝到asr_plugin/libs下

  • 配置so庫(kù)文件(解壓下載的SDK/core/src/main/jniLibs)將jniLibs整個(gè)文件夾拷貝到項(xiàng)目同等位置,刪除下面的armeabi,armeabi-v7a(因?yàn)镕lutter沒(méi)有armeabi,armeabi-v7a架構(gòu)的so),刪除使用不到的庫(kù)文件,保留圖中文件

    image
  • 在AndroidManifest中聲明權(quán)限

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.yangdxg.asr_plugin">
    
        <uses-permission android:name="android.permission.RECORD_AUDIO" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    </manifest>
    
  • 在控制臺(tái)創(chuàng)建應(yīng)用獲取AppId并配置到AndroidManifest

     <application>
        <meta-data android:name="com.baidu.speech.APP_ID"
            android:value="9788136" />
        <meta-data
            android:name="com.baidu.speech.API_KEY"
            android:value="0GjQNO5H4pGPf9HyA3AmZEbz" />
        <meta-data
            android:name="com.baidu.speech.SECRET_KEY"
            android:value="db981ef3ec647ba8a09b599ad7447a24" />
      </application>
    
  • 設(shè)置service,同樣在AndroidManifest中配置

    <service android:name="com.baidu.speech.VoiceRecognitionService" android:exported="false" />
    
  • 在app build.gradle中dependencies中添加依賴

    implementation project(':asr_plugin')
    

    注:報(bào)錯(cuò)Error:Program type already present: android.support.v4.os.ResultReceiver

    解決:在gradle.properties中添加

    android.useAndroidX=true
    android.enableJetifier=true
    

iOS Native SDK集成流程

  • 下載iOS SDK

  • 打包iOS工程,Mac下雙擊工程目錄下Runner.xcworkspace文件即可

  • Runner上右鍵new Group命名為plugin

  • 將下載的SDK中BDSClientLib文件夾拖到plugin下,勾選Copy items if needed和Create groups,刪除BDSClientLib下的.gitignore

  • 拖動(dòng)BDSClientResource/ASR/BDSClientResources到plugin下,勾選Copy items if needed和Create folder references

  • 拖動(dòng)BDSClientResource/ASR/BDSClientEASRResources到plugin下,勾選Copy items if needed和Create folder references

  • 添加framework,點(diǎn)擊如圖'+'號(hào),添加以下需要的framework

    image

    ? CoreTelephony.framework

    ? libsqlite3.0.tbd

    ? libiconv.2.4.0.tbd

    ? libc++.tbd

    ? libs.1.2.5.tbd

  • 添加語(yǔ)音權(quán)限Privacy - Microphone Usage Description

    image

Flutter Plugin開(kāi)發(fā)指南 - Dart端實(shí)現(xiàn)

在lib下創(chuàng)建plugin/asr_manager.dart編寫Dart端代碼,用于傳遞信息到Native端實(shí)現(xiàn)相應(yīng)功能

import 'package:flutter/services.dart';

class AsrManager {
  static const MethodChannel _channel = const MethodChannel('asr_plugin');

  /**
   * 開(kāi)始錄音
   */
  static Future<String> start({Map params}) async {
    return await _channel.invokeMethod('start', params ?? {});
  }

  /**
   * 停止錄音
   */
  static Future<String> stop() async {
    return await _channel.invokeMethod('stop');
  }

  /**
   * 取消錄音
   */
  static Future<String> cancel() async {
    return await _channel.invokeMethod('cancel');
  }
}

Flutter Plugin開(kāi)發(fā)指南 - Android端實(shí)現(xiàn)

  • 為Android Model添加Flutter依賴,在model中build.gradle添加如下代碼

    apply plugin: 'com.android.library'
    
    def localProperties = new Properties()
    def localPropertiesFile = rootProject.file('local.properties')
    if (localPropertiesFile.exists()) {
        localPropertiesFile.withReader('UTF-8') { reader ->
            localProperties.load(reader)
        }
    }
    
    def flutterRoot = localProperties.getProperty('flutter.sdk')
    apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
    
    flutter {
        source '../..'
    }
    
  • 解決model和app都依賴Flutter沖突問(wèn)題

    1. app/build.gradle中defaultConfig下添加ndk選擇代碼

              ndk{
                  abiFilters "arm64-v7a","arm64-v8a","x86_64","x86"
              }
      
    2. app/build.gradle中android下添加下面代碼

          packagingOptions {
              // 確保app與asr_plugin都依賴的libflutter.so merge時(shí)不沖突@https://github.com/card-io/card.io-Android-SDK/issues/186#issuecomment-427552552
              pickFirst 'lib/x86_64/libflutter.so'
              pickFirst 'lib/x86/libflutter.so'
              pickFirst 'lib/arm64-v8a/libflutter.so'
          }
      
  • 實(shí)現(xiàn)Android端語(yǔ)音識(shí)別功能(略)

  • Android端創(chuàng)建AsrPlugin實(shí)現(xiàn)接收Dart的消息

        @Override
        public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
            initPermission();
            switch (methodCall.method) {
                case "start":
                    resultStateful = ResultStateful.of(result);
                    start(methodCall, resultStateful);
                    break;
                case "stop":
                    stop(methodCall,result);
                    break;
                case "cancel":
                    cancel(methodCall,result);
                    break;
                default:
                    result.notImplemented();
            }
        }
    
  • 注冊(cè)插件到MainActivity

    AsrPlugin.registerWith(registrarFor("com.yangdxg.asr_plugin.asr.AsrPlugin"));
    

Flutter Plugin開(kāi)發(fā)指南 - iOS端實(shí)現(xiàn)

  • 在plugin下創(chuàng)建文件夾ASRPlugin,拖到工程plugin下,將導(dǎo)入的SDK等資源文件拖到ASRPlugin下,刪除SDK等三個(gè)資源文件(選擇Remove References)只刪除路徑再?gòu)男聦?dǎo)入

    image
  • 在plugin下右鍵創(chuàng)建Object-C文件取名AsrManager,FileType選擇Category,class選擇NSObject,創(chuàng)建成功后更改.h和.m文件名為AsrManager

  • iOS端實(shí)現(xiàn)語(yǔ)音識(shí)別略(參考百度API文檔)

  • iOS接收Dart消息

    + (void)registerWithRegistrar:(NSObject <FlutterPluginRegistrar> *)registrar {
        FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"asr_plugin" binaryMessenger:[registrar messenger] ];
        AsrPlugin* instance =[AsrPlugin new];
        [registrar addMethodCallDelegate:instance channel:channel];
    }
    - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
        if ([@"start" isEqualToString:call.method]) {
            self.result = result;
            [[self _asrManager] start];
        }else if ([@"stop" isEqualToString:call.method]) {
             [[self _asrManager] stop];
        }else if ([@"cancel" isEqualToString:call.method]) {
            [[self _asrManager] cancel];
        } else{
            result(FlutterMethodNotImplemented);
        }
    }
    - (AsrManager*)_asrManager{
        if (!self.asrManager) {
            self.asrManager = [AsrManager initWith:^(NSString *message) {
                if (self.result) {
                    self.result(message);
                    self.result = nil;
                }
            } failure:^(NSString *message) {
                if (self.result) {
                    self.result([FlutterError errorWithCode:@"ASR fail" message:message details:nil]);
                    self.result = nil;
                }
            }];
        }
        return self.asrManager;
    }
    
  • 注冊(cè)Dart消息接收

    - (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      [GeneratedPluginRegistrant registerWithRegistry:self];
        //注冊(cè)自有的插件
        [AsrPlugin registerWithRegistrar:[self registrarForPlugin:@"AsrPlugain"]];
      // Override point for customization after application launch.
      return [super application:application didFinishLaunchingWithOptions:launchOptions];
    }
    

Flutter AI智能語(yǔ)音功能實(shí)現(xiàn)

  • 界面開(kāi)發(fā)略

  • 實(shí)現(xiàn)點(diǎn)擊方法調(diào)用AsrManager對(duì)應(yīng)的調(diào)用Native的方法

      _speakStart() {
        controller.forward();
        setState(() {
          speakTips = '-- 識(shí)別中 --';
        });
    
        AsrManager.start().then((text) {
          print(text);
          if (text != null && text.length > 0) {
            setState(() {
              speakResult = text;
            });
            //選關(guān)閉再跳轉(zhuǎn)
            Navigator.pop(context);
            Navigator.push(context, MaterialPageRoute(
                builder: (context) => SearchPage(keyword: speakResult,)));
          }
        }).catchError((e) {
          print('識(shí)別出錯(cuò)---' + e);
        });
      }
    
      _speakStop() {
        setState(() {
          speakTips = '長(zhǎng)按說(shuō)話';
        });
        controller.reset();
        controller.stop();
        AsrManager.stop();
      }
    
      _speakCancle() {
        AsrManager.cancel();
      }
    
    

Demo下載

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容