如何申请appid 未知的错误ttscontroller的appid

2893人阅读
高德地图(11)
使用安卓sdk 24 编译官方导航Demo,运行时APP崩溃,异常信息如下:
UnsatisfiedLinkError: dlopen failed ... text relocations
和高德技术人员交流后,发现是语音模块的问题,高德地图使用了科大讯飞语音模块,下面就讲述一下,使用sdk 24编译&&执行官方Demo的办法。
下载科大讯飞SDK
将so文件&&Msc.jar放入高德官方Demo
这里需要注意一下:
下载的sdk中对应很多abi的so文件,在实际开发中应该将这些abi文件夹都复制到jniLibs文件夹下;
将原来官方Demo中jniLibs下armeabi文件夹下面的so文件,除libmsc.so文件外,向其他的abi文件夹中都复制一份(注意,对于兼容性没有做测试)。
TTSController.java文件
其内容如下:
package com.pansoft.oilgas.
import android.content.C
import android.os.B
import android.util.L
import com.amap.api.navi.AMapNaviL
import com.amap.api.navi.model.AMapLaneI
import com.amap.api.navi.model.AMapNaviC
import com.amap.api.navi.model.AMapNaviI
import com.amap.api.navi.model.AMapNaviL
import com.amap.api.navi.model.AMapNaviTrafficFacilityI
import com.amap.api.navi.model.AimLessModeCongestionI
import com.amap.api.navi.model.AimLessModeS
import com.amap.api.navi.model.NaviI
import com.autonavi.tbt.TrafficFacilityI
import com.iflytek.cloud.SpeechC
import com.iflytek.cloud.SpeechE
import com.iflytek.cloud.SpeechS
import com.iflytek.cloud.SynthesizerL
* 语音播报组件
public class TTSController implements SynthesizerListener, AMapNaviListener {
public static final String TAG = TTSController.class.getSimpleName();
public static TTSController ttsM
boolean isfinish = true;
private Context mC
private SpeechSynthesizer mSpeechS
public void onEvent(int i, int i1, int i2, Bundle bundle) {
TTSController(Context context) {
mContext =
public static TTSController getInstance(Context context) {
if (ttsManager == null) {
ttsManager = new TTSController(context);
return ttsM
public void init() {
mSpeechSynthesizer = SpeechSynthesizer.createSynthesizer(mContext, null);
initSpeechSynthesizer();
* 使用SpeechSynthesizer合成语音,不弹出合成Dialog.
public void playText(String playText) {
if (null == mSpeechSynthesizer) {
APPUtil.appendLog(mContext, "mSpeechSynthesizer is null");
mSpeechSynthesizer = SpeechSynthesizer.createSynthesizer(mContext, null);
initSpeechSynthesizer();
mSpeechSynthesizer.startSpeaking(playText, this);
public void stopSpeaking() {
if (mSpeechSynthesizer != null)
mSpeechSynthesizer.stopSpeaking();
public void startSpeaking() {
isfinish = true;
private void initSpeechSynthesizer() {
mSpeechSynthesizer.setParameter(SpeechConstant.VOICE_NAME,
mContext.getString(R.string.preference_default_tts_role));
mSpeechSynthesizer.setParameter(SpeechConstant.SPEED,
"" + mContext.getString(R.string.preference_key_tts_speed));
mSpeechSynthesizer.setParameter(SpeechConstant.VOLUME,
"" + mContext.getString(R.string.preference_key_tts_volume));
mSpeechSynthesizer.setParameter(SpeechConstant.PITCH,
"" + mContext.getString(R.string.preference_key_tts_pitch));
public void onBufferProgress(int arg0, int arg1, int arg2, String arg3) {
Log.d(TAG, "onBufferProgress");
public void onCompleted(SpeechError arg0) {
APPUtil.appendLog(mContext, "error info :" + arg0.getErrorDescription());
Log.e(TAG, arg0.getErrorDescription());
Log.d(TAG, "onCompleted");
isfinish = true;
public void onSpeakBegin() {
APPUtil.appendLog(mContext, "onSpeakBegin");
Log.d(TAG, "onSpeakBegin");
isfinish = false;
public void onSpeakPaused() {
APPUtil.appendLog(mContext, "onSpeakPaused");
Log.d(TAG, "onSpeakPaused");
public void onSpeakProgress(int arg0, int arg1, int arg2) {
APPUtil.appendLog(mContext, "onSpeakProgress
:" + arg0);
public void onSpeakResumed() {
APPUtil.appendLog(mContext, "onSpeakResumed ");
public void destroy() {
if (mSpeechSynthesizer != null) {
mSpeechSynthesizer.stopSpeaking();
public void onArriveDestination() {
this.playText("到达目的地");
public void onArrivedWayPoint(int arg0) {
public void onCalculateRouteFailure(int arg0) {
this.playText("路径计算失败,请检查网络或输入参数");
public void onCalculateRouteSuccess() {
String calculateResult = "路径计算就绪";
this.playText(calculateResult);
public void onEndEmulatorNavi() {
this.playText("导航结束");
public void onGetNavigationText(int arg0, String arg1) {
this.playText(arg1);
public void onInitNaviFailure() {
public void onInitNaviSuccess() {
public void onLocationChange(AMapNaviLocation arg0) {
public void onReCalculateRouteForTrafficJam() {
this.playText("前方路线拥堵,路线重新规划");
public void onReCalculateRouteForYaw() {
this.playText("您已偏航");
public void onStartNavi(int arg0) {
public void onTrafficStatusUpdate() {
public void onGpsOpenStatus(boolean arg0) {
public void onNaviInfoUpdated(AMapNaviInfo arg0) {
public void onNaviInfoUpdate(NaviInfo arg0) {
public void OnUpdateTrafficFacility(TrafficFacilityInfo trafficFacilityInfo) {
public void OnUpdateTrafficFacility(AMapNaviTrafficFacilityInfo aMapNaviTrafficFacilityInfo) {
public void showCross(AMapNaviCross aMapNaviCross) {
public void hideCross() {
public void showLaneInfo(AMapLaneInfo[] aMapLaneInfos, byte[] bytes, byte[] bytes1) {
public void hideLaneInfo() {
public void onCalculateMultipleRoutesSuccess(int[] ints) {
public void notifyParallelRoad(int i) {
public void OnUpdateTrafficFacility(AMapNaviTrafficFacilityInfo[] aMapNaviTrafficFacilityInfos) {
public void updateAimlessModeStatistics(AimLessModeStat aimLessModeStat) {
public void updateAimlessModeCongestionInfo(AimLessModeCongestionInfo aimLessModeCongestionInfo) {
在APPlication中添加
public void onCreate() {
super.onCreate();
SpeechUtility.createUtility(this, SpeechConstant.APPID + "=577a0332");
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:153959次
积分:2869
积分:2869
排名:第12434名
原创:110篇
转载:11篇
译文:18篇
评论:32条
(3)(1)(3)(2)(9)(5)(2)(3)(6)(13)(29)(11)(14)(10)(2)(2)(2)(1)(4)(5)(3)(1)(1)(5)(1)(1)第三方SDK(2)
百度语音SDK提供:
语音识别:将声音转成文字
语音合成:将文字转成语音文件,然后播放语音文件,即文字变声音。
语音唤醒:语音唤醒,激活运用程序
在这里,本篇介绍百度语音合成的使用。
百度语音介绍:
多语言(中文,中英混读)多音色(男音,女音)可选
离线与在线,节省流量
详情参考,
百度语音使用流程指南:
成为开发者,创建运用,选择服务
下载对应的SDK,集成开发。
详情参考,、.
项目集成百度语音SDK:
在androidStudio中按照其AS特有的使用方式添加添加so库,相关的jar。
添加完so库,jar库后,需Gradle中配置如下:
sourceSets {
jniLibs.srcDirs = ['libs']
dependencies {
compile files('libs/com.baidu.tts_2.3.0.jar')
在androidStudio中assert文件夹下添加文本模型文件.dat,和声音模型文件.dat(无网络,离线下使用的)。这里因项目需求,只添加下载到女生模型文件。
添加以下权限:
android:name="android.permission.INTERNET" /&
android:name="android.permission.ACCESS_NETWORK_STATE" /&
android:name="android.permission.READ_EXTERNAL_STORAGE" /&
android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&
android:name="android.permission.WRITE_SETTINGS" /&
android:name="android.permission.READ_PHONE_STATE" /&
android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&
android:name="android.permission.ACCESS_WIFI_STATE" /&
android:name="android.permission.CHANGE_WIFI_STATE" /&
Proguard配置(不需要混淆sdk中jar包)
编写相关使用代码如下:
5.1 加载离线资源,先创建存储的文件夹,然后将assert中模型文件一个个通过Stream读写(异步操作,可考虑工作线程或者RxJava完成)指定的文件夹下:
* 百度tts文件夹
public static final String BAIDU_TTS_DIR_NAME = "baiduTts";
public static final String SPEECH_FEMALE_MODE_NAME = "bd_etts_ch_speech_female.dat";
public static final String TEXT_MODEL_NAME = "bd_etts_ch_text.dat";
* 初始化语音文件的配置
private void initFileConfig(Context context) {
File dirFile = getDirFile(context);
if (dirFile != null && !dirFile.exists()) {
dirFile.mkdir();
copyFromAssertsToSDCard(context, SPEECH_FEMALE_MODE_NAME, getFilePath(dirFile, SPEECH_FEMALE_MODE_NAME));
copyFromAssertsToSDCard(context, TEXT_MODEL_NAME, getFilePath(dirFile, TEXT_MODEL_NAME));
* 获取目录
public File getDirFile(Context context) {
return MyUtils.getCacheFile(context, BAIDU_TTS_DIR_NAME);
* 获取文件路径
* fileName
public String getFilePath(File dirFile, String fileName) {
return dirFile.getAbsolutePath() + File.separator + fileN
* 将文件写入sdcard中
* assertFileName
* filePath
private void copyFromAssertsToSDCard(Context context, String assertFileName, String filePath) {
FileOutputStream outputStream = null;
InputStream inputStream = null;
inputStream = context.getResources().getAssets().open(assertFileName);
outputStream = new FileOutputStream(filePath);
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) & 0) {
outputStream.write(buffer, 0, length);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
outputStream.close();
if (inputStream != null) {
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
MyUtil工具类中创建文件夹的代码如下:
* 获得存储文件
public static File getCacheFile(Context context,String name) {
String cacheP
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
cachePath = context.getExternalCacheDir().getPath();
cachePath = context.getCacheDir().getPath();
return new File(cachePath + File.separator + name);
5.2 配置语音合成客户端:
* 运用的配置信息,由百度语音官网给定
public static final String API_KEY = "hBuMkBgzGR0YQQHflkufAWcvFRaqTxxx";
public static final String SECRET_KEY = "FemUYlEKxzr0moQ0jydZcmQ3fo11xxx";
public static final String APP_ID = "9369xxx";
* 语音合成的客户端
private SpeechSynthesizer speechS
* 合成状态的监听器
private SpeechSynthesizerListener speechSynthesizerL
* 初始化语音的client
private void initBaiduTts(Context context) {
speechSynthesizer = SpeechSynthesizer.getInstance();
speechSynthesizer.setContext(context);
if (getSpeechSynthesizerListener() != null) {
speechSynthesizer.setSpeechSynthesizerListener(getSpeechSynthesizerListener());
speechSynthesizer.setApiKey(API_KEY, SECRET_KEY);
speechSynthesizer.setAppId(APP_ID);
File dirFile = getDirFile(context);
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, getFilePath(dirFile, TEXT_MODEL_NAME));
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, getFilePath(dirFile, SPEECH_FEMALE_MODE_NAME));
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "0");
speechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_DEFAULT);
if (isAuthSuccess()) {
LogController.i(BaiduTtsController.class.getSimpleName(), "首次验证成功");
speechSynthesizer.initTts(TtsMode.MIX);
* 用于首次使用的使用,测试检查运用是成功申请到授权。注意点:若是测试无误后,可省略该步骤。
public boolean isAuthSuccess() {
AuthInfo info = speechSynthesizer.auth(TtsMode.MIX);
if (!info.isSuccess()) {
LogController.i(BaiduTtsController.class.getSimpleName(), "错误信息: " + info.getTtsError().getMessage());
return info.isSuccess();
public SpeechSynthesizerListener getSpeechSynthesizerListener() {
return speechSynthesizerL
* 设置语音合成的监听器
* speechSynthesizerListener
public void setSpeechSynthesizerListener(SpeechSynthesizerListener speechSynthesizerListener) {
this.speechSynthesizerListener = speechSynthesizerL
if(speechSynthesizerListener!=null){
this.speechSynthesizer.setSpeechSynthesizerListener(this.speechSynthesizerListener);
5.3 语音合成客户端的生命周期管理:
在Activity或者Service的生命周期中使用,onCreate()调用客户端的初始化操作(即以上两个配置步骤), onResume()调用客户端的resume(),Onstop()中调用客户端的stop().最后在onDestory()中调用客户端的release()
* 释放资源
public void release() {
this.speechSynthesizer.release();
* 停止正在执行的任务
public void stop() {
this.speechSynthesizer.stop();
* 恢复暂停的任务
public void resume() {
this.speechSynthesizer.resume();
5.4 通过语音合成的客户端,将多段文本按一定顺序或者单独一段文本进行播放:
* 将text转成一个语音文件,然后自动播放。
public void speeckText(String text) {
if (!TextUtils.isEmpty(text)) {
this.speechSynthesizer.speak(text);
* 有顺序的合成多段语音,然后按一定顺序播放。
public void speeckTextValues(String[] values) {
if (values == null && values.length == 0) {
List&SpeechSynthesizeBag& bags = new ArrayList&&();
for (int i = 0; i & values. ++i) {
bags.add(getSpeechSynthesizeBag(values[i], String.valueOf(i)));
this.speechSynthesizer.batchSpeak(bags);
* text 播放的文本内容
* utterancedId
播放顺序,即第几个播放
private SpeechSynthesizeBag getSpeechSynthesizeBag(String text, String utterancedId) {
SpeechSynthesizeBag speechSynthesizeBag = new SpeechSynthesizeBag();
speechSynthesizeBag.setText(text);
speechSynthesizeBag.setUtteranceId(utterancedId);
return speechSynthesizeB
5.5 监控语音合成客户端的监听器(即SpeechSynthesizerListener)
public class MessageDialogActivity extends BaseActivity implements View.OnClickListener,SpeechSynthesizerListener {
private static final String TAG=MessageDialogActivity.class.getSimpleName();
public void onSynthesizeStart(String s) {
LogController.i(TAG," onSynthesizeStart "+s);
public void onSynthesizeDataArrived(String s, byte[] bytes, int i) {
LogController.i(TAG," onSynthesizeDataArrived "+s);
public void onSynthesizeFinish(String s) {
LogController.i(TAG," onSynthesizeFinish "+s);
public void onSpeechStart(String s) {
LogController.i(TAG," onSpeechStart "+s);
public void onSpeechProgressChanged(String s, int i) {
LogController.i(TAG," onSpeechProgressChanged "+s);
public void onSpeechFinish(String s) {
LogController.i(TAG," onSpeechFinish "+s);
public void onError(String s, SpeechError speechError) {
LogController.i(TAG," onError "+speechError.description);
(个人)在实际项目中做法:
将百度语音客户端的初始化操作,生命周期管理操作,播放语音操作,封装成一个操作类。
public class BaiduTtsController {
public static BaiduTtsC
private BaiduTtsController(Context context) {
initConfig(context);
public synchronized static BaiduTtsController getInstance(Context context) {
return instance = instance == null ? new BaiduTtsController(context) :
public void initConfig(Context context) {
initFileConfig(context);
initBaiduTts(context);
将这个操作类保存到自定义的Application子类中,作为一个全局共享的对象。
public class BaseApplication extends Application {
private BaiduTtsC
BaiduTtsController
initBaiduTts(){
return controller= controller==null?BaiduTtsController.getInstance(this):
public BaiduTtsController getBaiduTtsController(){
public void setBaiduTtsController(BaiduTtsController controller){
this.controller=
在service中通过Application子类对象,获取到操作类对象,拿到需要播放的文本,调用播放语音的操作。
private BaiduTtsC
controller=BaseApplication.getAppContext().getBaiduTtsController();
controller.setSpeechSynthesizerListener(this);
controller.speeckText(msg1);
开发遇到问题:
so库没有加载成功,控制台日志如下:
No implementation found for int com.baidu.tts.jni.EmbeddedSynthesizerEngine.bdTTSGetLicense
No implementation found for int com.baidu.speechsynthesizer.utility.SpeechDecoder.decodeWithCallback
解决方式:正确导入so库,可以在手机中安装的运用查看so库是否随运用一起安装在手机上。
运用的签名错误,控制台日志如下:
Authentication Error
=============================================
sha1;package:B3:88:6A:66:18:70:4E:FE:48:60:4C:4C:37:A9:2D:84:5D:16:56:com.xxx.mjqzclient
key:RWpAlKWQE8SBoE354xUYeRcy906Asxxx
errorcode: -11 uid: -1 appid -1 msg: httpsPost failed,IOException:Unable to resolve host "api.": No address associated with hostname
请仔细核查 SHA1、package与key申请信息是否对应,key是否删除,平台是否匹配
errorcode为230时,请参考论坛链接:
http://bbs./forum.php?mod=viewthread&tid=106461
解决方式:正确配置App的签名,然后在开发平台上,填写对应的包名,和sha1值。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:66162次
积分:1431
积分:1431
排名:千里之外
原创:73篇
评论:50条
(7)(7)(7)(30)(1)(4)(1)(1)(5)(4)(2)(8)

我要回帖

更多关于 如何申请google appid 的文章

 

随机推荐