Android Native 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工程,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)題
-
app/build.gradle中defaultConfig下添加ndk選擇代碼
ndk{ abiFilters "arm64-v7a","arm64-v8a","x86_64","x86" } -
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(); }



