Android API 29 百度步行导航语音tts集成

Android API 29 百度步行导航语音tts集成

这个参考官方demo修改。 关键来了,步行导航跟驾车导航不一样的是,驾车导航有专门的语音包支持,而步行和骑行导航只支持路线文字播报, 不支持语音播报。
经过一天研究完成步行导航语音:
过程:需要去百度AI语音官方下载tts语音合成集成包(申请appid,key等账号,另外目前官方的包版本较低的,使用API 29版本需要修改代码。下面把关键步骤列举:

1, 下载官方demo工程在这里插入图片描述
2, 官方指导 app\libs\com.baidu.tts_2.3.2.20180713_6101c2a.jar 这个jar包不要复制到自己的工程,有jar包冲突。
3, 复制官网demo下面5个.dat文件
在这里插入图片描述
4, 复制下面文件到自己工程的armeabi目录下:
在这里插入图片描述
5, 以上包文件准备好后就开始编写代码了:
官方指导有合成播放,还有其他好多功能。(运行demo工程可以看到)。我们只需要其中的 合成播报功能:
主要使用一下代码:
将下面的文件夹直接拷贝到工程
在这里插入图片描述
新建walkGuideActivty 导航类:
修改你的MainActivity,增加调用

Intent intent = new Intent(MainActivity.this,
WalkGuideActivity.class);
startActivity(intent);

修改:在这里插入图片描述
在这里插入图片描述
walkGuideActivty 类关键解析:

去百度AI 语音平台 申请账号,注意 不是 百度地图平台账号,
在这里插入图片描述
下面初始化导航,注意
在这里插入图片描述
这2个语音初始化要在
在这里插入图片描述
之前。

在这里插入图片描述

/*
 * Copyright (C) 2018 Baidu, Inc. All Rights Reserved.
 */
package com.yf.aiya;

import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;

import com.baidu.mapapi.walknavi.WalkNavigateHelper;
import com.baidu.mapapi.walknavi.adapter.IWRouteGuidanceListener;
import com.baidu.mapapi.walknavi.adapter.IWTTSPlayer;
import com.baidu.mapapi.walknavi.model.RouteGuideKind;
import com.baidu.navisdk.adapter.BNRoutePlanNode;
import com.baidu.navisdk.adapter.IBNRouteGuideManager;
import com.baidu.navisdk.adapter.IBNaviListener;
import com.baidu.tts.chainofresponsibility.logger.LoggerProxy;
import com.baidu.tts.client.SpeechSynthesizer;
import com.baidu.tts.client.SpeechSynthesizerListener;
import com.baidu.tts.client.TtsMode;
import com.yf.aiya.control.InitConfig;
import com.yf.aiya.control.MySyntherizer;
import com.yf.aiya.listener.UiMessageListener;
import com.yf.aiya.util.OfflineResource;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static com.yf.aiya.MainHandlerConstant.INIT_SUCCESS;
import static com.yf.aiya.MainHandlerConstant.PRINT;

/**
 * 导航类
 *
 * @author geyuan on 2019/7/18.
 */
public class WalkGuideActivity extends Activity {
    private static final String TAG = WalkGuideActivity.class.getName();
    private BNRoutePlanNode mBNRoutePlanNode = null;
    private IBNRouteGuideManager mRouteGuideManager;
    private IBNaviListener.DayNightMode mMode = IBNaviListener.DayNightMode.DAY;
    WalkNavigateHelper  mNaviHelper = null;

    // ================== 初始化参数设置开始 ==========================
    /**
     * 发布时请替换成自己申请的appId appKey 和 secretKey。注意如果需要离线合成功能,请在您申请的应用中填写包名。
     * 本demo的包名是com.baidu.tts.sample,定义在build.gradle中。
     */
    protected String appId = "16822358";
    protected String appKey = "1P0GKFo2MbWbFH8Rp7zv58SW";
    protected String secretKey = "6YOCLTSFOr09pufu4EBWGj07OkVufTUx";
    // TtsMode.MIX; 离在线融合,在线优先; TtsMode.ONLINE 纯在线; 没有纯离线
    protected TtsMode ttsMode = TtsMode.MIX;
    // 离线发音选择,VOICE_FEMALE即为离线女声发音。
    // assets目录下bd_etts_common_speech_m15_mand_eng_high_am-mix_v3.0.0_20170505.dat为离线男声模型;
    // assets目录下bd_etts_common_speech_f7_mand_eng_high_am-mix_v3.0.0_20170512.dat为离线女声模型
    protected String offlineVoice = OfflineResource.VOICE_MALE;
    protected Handler mainHandler;
    protected Button[] buttons;
    // ===============初始化参数设置完毕,更多合成参数请至getParams()方法中设置 =================

    // 主控制类,所有合成控制方法从这个类开始
    protected MySyntherizer synthesizer;

    protected static String DESC = "请先看完说明。之后点击“合成并播放”按钮即可正常测试。\n"
            + "测试离线合成功能需要首次联网。\n"
            + "纯在线请修改代码里ttsMode为TtsMode.ONLINE, 没有纯离线。\n"
            + "本Demo的默认参数设置为wifi情况下在线合成, 其它网络(包括4G)使用离线合成。 在线普通女声发音,离线男声发音.\n"
            + "合成可以多次调用,SDK内部有缓存队列,会依次完成。\n\n";

    //
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        boolean fullScreen = supportFullScreen();
        //createHandler();
        mainHandler = new Handler() {
            /*
             * @param msg
             */
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                //handle(msg);
            }

        };

        //获取WalkNavigateHelper实例
        mNaviHelper = WalkNavigateHelper.getInstance();
//获取诱导页面地图展示View
        View view = mNaviHelper.onCreate(WalkGuideActivity.this);
        if (view != null) {
            setContentView(view);
        }

        initialTts(); // 初始化TTS引擎
        initTTSListener();
        mNaviHelper.startWalkNavi(WalkGuideActivity.this);
        mNaviHelper.setRouteGuidanceListener(this, new IWRouteGuidanceListener() {
            //诱导图标更新
            @Override
            public void onRouteGuideIconUpdate (Drawable drawable){
            }

            //诱导类型枚举
            @Override
            public void onRouteGuideKind (RouteGuideKind routeGuideKind){
            }

            /**
             * 诱导信息
             * @param charSequence 第一行显示的信息,如“沿当前道路”
             * @param charSequence1  第二行显示的信息,比如“向东出发”,第二行信息也可能为空
             */
            @Override
            public void onRoadGuideTextUpdate (CharSequence charSequence, CharSequence charSequence1){
            }
            //总的剩余距离
            @Override
            public void onRemainDistanceUpdate (CharSequence charSequence){
            }
            //总的剩余时间
            @Override
            public void onRemainTimeUpdate (CharSequence charSequence){
            }

            //GPS状态发生变化,来自诱导引擎的消息
            @Override
            public void onGpsStatusChange (CharSequence charSequence, Drawable drawable){
            }

            //已经开始偏航
            @Override
            public void onRouteFarAway (CharSequence charSequence, Drawable drawable){
            }

            //偏航规划中
            @Override
            public void onRoutePlanYawing (CharSequence charSequence, Drawable drawable){
            }

            //重新算路成功
            @Override
            public void onReRouteComplete () {
            }

            //抵达目的地
            @Override
            public void onArriveDest () {

            }

            @Override
            public void onIndoorEnd(Message message) {
            }

            @Override
            public void onFinalEnd(Message message) {

            }

            //震动
            @Override
            public void onVibrate () {
            }
        });
    }

    protected void handle(Message msg) {
        switch (msg.what) {
            case INIT_SUCCESS:
                for (Button b : buttons) {
                    b.setEnabled(true);
                }
                msg.what = PRINT;
                break;
            default:
                break;
        }
    }

    /**
     * 初始化引擎,需要的参数均在InitConfig类里
     * <p>
     * DEMO中提供了3个SpeechSynthesizerListener的实现
     * MessageListener 仅仅用log.i记录日志,在logcat中可以看见
     * UiMessageListener 在MessageListener的基础上,对handler发送消息,实现UI的文字更新
     * FileSaveListener 在UiMessageListener的基础上,使用 onSynthesizeDataArrived回调,获取音频流
     */
    protected void initialTts() {
        LoggerProxy.printable(true); // 日志打印在logcat中
        // 设置初始化参数
        // 此处可以改为 含有您业务逻辑的SpeechSynthesizerListener的实现类
        SpeechSynthesizerListener listener = new UiMessageListener(mainHandler);
        Map<String, String> params = getParams();

        // appId appKey secretKey 网站上您申请的应用获取。注意使用离线合成功能的话,需要应用中填写您app的包名。包名在build.gradle中获取。
        InitConfig initConfig = new InitConfig(appId, appKey, secretKey, ttsMode, params, listener);
        synthesizer = new MySyntherizer(this, initConfig, mainHandler); // 此处可以改为MySyntherizer 了解调用过程
    }

    /**
     * 合成的参数,可以初始化时填写,也可以在合成前设置。
     *
     * @return
     */
    protected Map<String, String> getParams() {
        Map<String, String> params = new HashMap<String, String>();
        // 以下参数均为选填
        // 设置在线发声音人: 0 普通女声(默认) 1 普通男声 2 特别男声 3 情感男声<度逍遥> 4 情感儿童声<度丫丫>
        params.put(SpeechSynthesizer.PARAM_SPEAKER, "0");
        // 设置合成的音量,0-9 ,默认 5
        params.put(SpeechSynthesizer.PARAM_VOLUME, "9");
        // 设置合成的语速,0-9 ,默认 5
        params.put(SpeechSynthesizer.PARAM_SPEED, "5");
        // 设置合成的语调,0-9 ,默认 5
        params.put(SpeechSynthesizer.PARAM_PITCH, "5");
        params.put(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_DEFAULT);
        // 该参数设置为TtsMode.MIX生效。即纯在线模式不生效。
        // MIX_MODE_DEFAULT 默认 ,wifi状态下使用在线,非wifi离线。在线状态下,请求超时6s自动转离线
        // MIX_MODE_HIGH_SPEED_SYNTHESIZE_WIFI wifi状态下使用在线,非wifi离线。在线状态下, 请求超时1.2s自动转离线
        // MIX_MODE_HIGH_SPEED_NETWORK , 3G 4G wifi状态下使用在线,其它状态离线。在线状态下,请求超时1.2s自动转离线
        // MIX_MODE_HIGH_SPEED_SYNTHESIZE, 2G 3G 4G wifi状态下使用在线,其它状态离线。在线状态下,请求超时1.2s自动转离线

        // 离线资源文件, 从assets目录中复制到临时目录,需要在initTTs方法前完成
        OfflineResource offlineResource = createOfflineResource(offlineVoice);
        // 声学模型文件路径 (离线引擎使用), 请确认下面两个文件存在
        params.put(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, offlineResource.getTextFilename());
        params.put(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE,
                offlineResource.getModelFilename());
        return params;
    }

    protected OfflineResource createOfflineResource(String voiceType) {
        OfflineResource offlineResource = null;
        try {
            offlineResource = new OfflineResource(this, voiceType);
        } catch (IOException e) {
            // IO 错误自行处理
            e.printStackTrace();
            toPrint("【error】:copy files from assets failed." + e.getMessage());
        }
        return offlineResource;
    }
    protected void toPrint(String str) {
        Message msg = Message.obtain();
        msg.obj = str;
        mainHandler.sendMessage(msg);
    }


    //语音播报监听器
    private void initTTSListener() {

        mNaviHelper.setTTsPlayer(new IWTTSPlayer() {
            /**
             * 诱导文本回调
             * @param s 诱导文本
             * @param b 是否抢先播报
             * @return
             */
            @Override
            public int playTTSText(String s, boolean b) {
                Log.d("步行导航---:" ,s);
                //调用合成器识别文字信息播报
                speak(s);
                return 0;
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        mNaviHelper.resume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mNaviHelper.pause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mNaviHelper.unInitNaviEngine();
        //mNaviHelper.quit();
    }

    /**
     * speak 实际上是调用 synthesize后,获取音频流,然后播放。
     * 获取音频流的方式见SaveFileActivity及FileSaveListener
     * 需要合成的文本text的长度不能超过1024个GBK字节。
     */
    public void speak(String s) {

        int result = synthesizer.speak(s);
        checkResult(result, "speak");
    }

    private void checkResult(int result, String method) {
        if (result != 0) {
            toPrint("error code :" + result + " method:" + method + ", 错误码文档:http://yuyin.baidu.com/docs/tts/122 ");
        }
    }

    private boolean supportFullScreen() {
        if (Build.VERSION.SDK_INT >= 21) {
            Window window = getWindow();
            int color;
            if (Build.VERSION.SDK_INT >= 23) {
                color = Color.TRANSPARENT;
            } else {
                color = 0x2d000000;
            }
            window.setStatusBarColor(color);

            if (Build.VERSION.SDK_INT >= 23) {
                window.getDecorView().setSystemUiVisibility(
                        View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
                int uiVisibility = window.getDecorView().getSystemUiVisibility();
                if (mMode == IBNaviListener.DayNightMode.DAY) {
                    uiVisibility |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
                }
                window.getDecorView().setSystemUiVisibility(uiVisibility);
            } else {
                window.getDecorView().setSystemUiVisibility(
                        View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
            }

            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            return true;
        }

        return false;
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值