Unity 接入 Android SDK-讯飞SDK实战
2017-12-15 13:12
375 查看
Unity 接入 Android SDK-讯飞SDK实战
系列篇 四所有篇幅
Unity Android 交互
Unity Android 交互 二
Unity Android 交互 三 多个 Module分别生成 aar 导入Unity自动合并 AndroidManifest.xml
Unity 接入 Android SDK - 讯飞SDK 实战
本篇以接入一个讯飞 SDK 为例实际操作一下
首先到讯飞官网注册并下载 SDK 讯飞官网
进入 SDK 下载中心,
随便申请一个应用,提交即可
然后下载 SDK
下载解压如下
libs 下为 SDK需要的 Msc .jar 包和 .so 库
SDK 准备完成,开始 打开 Android Studio
1. 首先新建一个 主 Module 作为程序主入口
2. new -> Module 创建一个 Phone 工程
然后就是参考 这里写链接内容
清除所有无用配置和资源,删除没用的依赖库
修改 build.gradle 设置为导出aar
apply plugin: 'com.android.library'
导入 Unity 自带 classes.jar 库,并添加依赖
修改 MainActivity 继承于 UnityPlayerActivity
package com.testSdk.demo; import android.os.Bundle; import com.unity3d.player.UnityPlayer; import com.unity3d.player.UnityPlayerActivity; public class MainActivity extends UnityPlayerActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } }
修改 AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.testSdk.demo"> <application android:allowBackup="true" android:label="@string/app_name" android:supportsRtl="true" > <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
3.主Module准备就绪,我将讯飞SDK 接入到一个新的 Module中,目的是解耦合,将讯飞SDK 所有配置和逻辑都放在 Module 中。
新建Module,作为一个 Android Library
项目名 xunfen 包名 com.xunfens.demo
老规矩清除所有无用资源配置,清除依赖
4.将 Msc.jar 放到 libs下,open Module Setting 打开设置依赖
5.将 讯飞 SDK 下 libs 中其他 .so 文件放入 src -> main -> jniLibs 下,如果没有 jniLibs 文件夹则创建一个
6.在讯分包名文件夹下新建一个
SynthesizerVoice.java类
按照 SDK 文档说明接入 语音合成SDK
代码如下
package com.xunfens.demo; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.widget.Toast; import android.os.Bundle; import com.iflytek.cloud.ErrorCode; import com.iflytek.cloud.InitListener; import com.iflytek.cloud.SpeechConstant; import com.iflytek.cloud.SpeechError; import com.iflytek.cloud.SpeechSynthesizer; import com.iflytek.cloud.SynthesizerListener; import com.iflytek.speech.*; import com.iflytek.*; import com.iflytek.cloud.SpeechUtility; public class SynthesizerVoice { // 单利 private static SynthesizerVoice instance; // 暂存 UnityPlayerActivity 的 Context private static Context unityContext; // 暂存 UnityPlayerActivity 的 Activity private static Activity unityActivity; // 语音合成对象 private SpeechSynthesizer speechSynthesizer; // 默认发言人 private String voicer = "xiaoyan"; // 引擎类型 private String mEngineType = SpeechConstant.TYPE_CLOUD; // 获取单利 public static SynthesizerVoice getInstance() { if (instance == null) { instance = new SynthesizerVoice(); } return instance; } // 构造函数 public SynthesizerVoice() { } // 在 MainActivity 中调用初始化,传入 MainActivity.this public void init(Context _context) { // 获取到 UnityPlayerActivity 的 Context 和 Activity unityContext = _context.getApplicationContext(); unityActivity = (Activity) _context; // 初始化讯飞 SDK // "appid=" + "5a30c837" 注意:"appid=" 中等号前后都不要加任何字符必须紧按着 5a30c837 为我当前应用的appid // 创建应用会生成一个唯一的 appid SpeechUtility.createUtility(unityContext, "appid=" + "5a30c837"); // 初始化语音合成对象,传入 Context 和 监听回调 speechSynthesizer = SpeechSynthesizer.createSynthesizer(_context, mTtsInitListener); } // 设置参数 private void setParam() { // 清空参数 speechSynthesizer.setParameter(SpeechConstant.PARAMS, null); // 根据合成引擎设置相应参数 if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) { speechSynthesizer.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); // 设置在线合成发音人 speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME, voicer); //设置合成语速 speechSynthesizer.setParameter(SpeechConstant.SPEED, "50"); //设置合成音调 speechSynthesizer.setParameter(SpeechConstant.PITCH, "50"); //设置合成音量 speechSynthesizer.setParameter(SpeechConstant.VOLUME, "50"); } else { speechSynthesizer.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL); // 设置本地合成发音人 voicer为空,默认通过语记界面指定发音人。 speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME, ""); /** * TODO 本地合成不设置语速、音调、音量,默认使用语记设置 * 开发者如需自定义参数,请参考在线合成参数设置 */ } //设置播放器音频流类型 speechSynthesizer.setParameter(SpeechConstant.STREAM_TYPE, "5"); // 设置播放合成音频打断音乐播放,默认为true speechSynthesizer.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true"); // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限 // 注:AUDIO_FORMAT参数语记需要更新版本才能生效 speechSynthesizer.setParameter(SpeechConstant.AUDIO_FORMAT, "wav"); //speechSynthesizer.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/tts.wav"); } // 外部调用开始播放 public void StartSpeaking() { // 需要合成声音的文字 String text = "哈哈哈哈哈哈哈哈哈哈快说出来"; // 设置参数 setParam(); // 开始播放 int code = speechSynthesizer.startSpeaking(text, mTtsListener); if (code != ErrorCode.SUCCESS) { showToast("语音合成失败,错误码: " + code); } else { showToast("语音合成成功啦"); } } // 播放回调 private SynthesizerListener mTtsListener = new SynthesizerListener() { @Override public void onSpeakBegin() { } @Override public void onSpeakPaused() { } @Override public void onSpeakResumed() { } @Override public void onBufferProgress(int percent, int beginPos, int endPos, String info) { // 合成进度 } @Override public void onSpeakProgress(int percent, int beginPos, int endPos) { // 播放进度 } @Override public void onCompleted(SpeechError error) { if (error == null) { showToast("播放完成"); } else if (error != null) { showToast(error.getPlainDescription(true)); } } @Override public void onEvent(int eventType, int arg1, int arg2, Bundle obj) { // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因 // 若使用本地能力,会话id为null // if (SpeechEvent.EVENT_SESSION_ID == eventType) { // String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID); // Log.d(TAG, "session id =" + sid); // } } }; /** * 初始化监听。 */ private InitListener mTtsInitListener = new InitListener() { @Override public void onInit(int code) { //Log.d(TAG, "InitListener init() code = " + code); if (code != ErrorCode.SUCCESS) { showToast("初始化失败,错误码:" + code); } else { // 初始化成功,之后可以调用startSpeaking方法 // 注:有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成, // 正确的做法是将onCreate中的startSpeaking调用移至这里 showToast("初始化成功"); } } }; // 传入 meg,弹出一个 Toast 操作 public static void showToast(final String meg) { unityActivity.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(unityContext, meg, Toast.LENGTH_LONG).show(); } }); } // 弹出一个提示窗口,窗口需要的文字信息从strings.xml 里面获取,点击确认关闭 public static void showAlertDialog(final String _title, final String _content) { unityActivity.runOnUiThread(new Runnable() { @Override public void run() { AlertDialog.Builder builder = new AlertDialog.Builder(unityActivity); builder.setTitle(_title).setMessage(_content).setPositiveButton("Down", null); builder.show(); } }); } }
代码注释很详细就不细说了
在 AndroidManifest.xml 中配置权限,需要的权限在 SDK 示例代码和文档中都可以找到,下面配置的是所有 讯飞 SDK 需要的一些权限,
有一些不是 语音合成 SDK 需要的,我就赖得删选,全部放进来了
添加前AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xunfens.demo" > </manifest>
添加后 AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xunfens.demo" > <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> </manifest>
xunfen Module 准备结束,在 主Module 加入对 xunfen Module 的依赖,然后在 主Module 的 MainActivity 中调用 xunfen 的初始化和调用
修改 MainActivity
package com.testSdk.demo; import android.os.Bundle; import com.unity3d.player.UnityPlayer; import com.unity3d.player.UnityPlayerActivity; // 引入xunfen 库 import com.xunfens.demo.SynthesizerVoice; public class MainActivity extends UnityPlayerActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 获取 xunfen 中SynthesizerVoice 单利 SynthesizerVoice synthesizerVoice = SynthesizerVoice.getInstance(); // 初始化 xunfen 将 MainActivity.this 传递进去 synthesizerVoice.init(MainActivity.this); } // 在Unity 中调用说话 public void StartSpeaking() { // 获取单利 SynthesizerVoice synthesizerVoice = SynthesizerVoice.getInstance(); // 调用说话 synthesizerVoice.StartSpeaking(); } }
准备就绪
执行 Buidl -> Rebuild Project,生成 aar
找到 主Module 和 xunfen Module 生成 aar
找到 主 Module 生成 aar, app-debug.aar,删除 libs 下 classes.jar
将 AndroidManifest.xml 复制出来
找到 xunfen Module 生成的 aar
将 app-debug.aar, AndroidManifest.xml, 和 xunfen-debug.aar 一起放入到 Unity工程 Plugins/Android 目录下
此处有坑,最好执行以下 Reimport重新导入以下
生成 APK 安装到模拟器上测试
在 MainActivity onCreate 方法中执行初始化,
运行游戏启动显示 Toast 初始化成功
点击 Speak 按钮
等待说完
测试成功
由于没有Android 真机测试,只能在 MUMU 模拟器上测
接入 SDK 时会出现各种各样的坑,需要认真仔细,细节决定成败
相关文章推荐
- Unity5.x+Android Studio 讯飞SDK的接入
- unity工程接入Android sdk后真机测试解锁屏后退出的解决
- unity接入讯飞语音识别iOS SDK的遇到的棘手问题!
- Unity 5.x&Android SDK接入 Unable to convert classes into dex format.错误的解决
- Unity接入友盟SDK后,添加打开安卓APP的功能 遇到的问题
- Unity接入Android各渠道SDK的坑
- unity接入ShareREC(iOS)SDK --获取录制的包含外部声音的视频路径
- Unity接入微信SDK——iOS(接入微信SDK)
- Unity接入安卓SDK方法
- 【Unity游戏开发】SDK接入与集成——小白入门篇
- unity接入android七鱼sdk记录一二
- Unity接入第三方SDK发布android闪退
- unity消息推送- 接入小米推送SDK-自定义消息通知声音
- 【SDK接入】使用UnityPlugin接入Bugly(iOS)
- 国内手游渠道SDK快速接入之Unity篇
- [Unity通信]快速接入sdk
- Unity 3D 接入 移动MM (3.1.3)计费SDK
- Unity 接入应用宝 SDK 即 YSDK 过程中遇到的问题记录 20180302