嵌入式项目之Android导航语音识别——导航听写功能

文章目录


前言

最近在学习嵌入式系统的一个功能——导航语音识别,该功能是基于Android和科大讯飞语音识别语音合成,利用RFID射频识别技术实现的功能,整个导航语音识别功能包括语音识别、语音合成、导航听写、语音提示语音识别的语音合成三大模块。这里我整理了第二模块——导航识别。

一、导航语音识别

------------------------------------------------------说明------------------------------------------------------------

public class Dao {

    private final DatabaseHelper helper;
    public Dao(Context context){

        helper = new DatabaseHelper(context);

    }
Dao dao = new Dao(this);
protected static int my_i;//局部参数
Vector<Integer> path = new Vector<Integer>();//规划的路线

1. 代码示例

//导航语音识别
    protected void vitSpeech(){
        dictationResultStr = "[";
        // 语音配置对象初始化
        SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID
                + "=" + APPID);
        // 1.创建SpeechRecognizer对象,第2个参数:本地听写时传InitListener
        SpeechRecognizer mIat = SpeechRecognizer.createRecognizer(
                MainActivity.this, null);
        //设置语法ID和 SUBJECT 为空,以免因之前有语法调用而设置了此参数;或直接清空所有参数,具体可参考 DEMO 的示例。
        mIat.setParameter( SpeechConstant.CLOUD_GRAMMAR, null );
        mIat.setParameter( SpeechConstant.SUBJECT, null );
//设置返回结果格式,目前支持json,xml以及plain 三种格式,其中plain为纯听写文本内容
        mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");
//此处engineType为“cloud”
        mIat.setParameter( SpeechConstant.ENGINE_TYPE, "cloud" );
//设置语音输入语言,zh_cn为简体中文
        mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
//设置结果返回语言
        mIat.setParameter(SpeechConstant.ACCENT, "mandarin");
// 设置语音前端点:静音超时时间,单位ms,即用户多长时间不说话则当做超时处理
//取值范围{1000~10000}
        mIat.setParameter(SpeechConstant.VAD_BOS, "2000");
//设置语音后端点:后端点静音检测时间,单位ms,即用户停止说话多长时间内即认为不再输入,
//自动停止录音,范围{0~10000}
        mIat.setParameter(SpeechConstant.VAD_EOS, "1000");
//设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
        mIat.setParameter(SpeechConstant.ASR_PTT,"0");
        // 开始听写
        mIat.startListening(mRecognizerListener1);
    }
    private RecognizerListener mRecognizerListener1 = new RecognizerListener() {
        @Override
        public void onBeginOfSpeech() {
        }
        @Override
        public void onError(SpeechError error) {
        }
        @Override
        public void onEndOfSpeech() {
        }
        @Override
        public void onResult(RecognizerResult results, boolean isLast) {
            Log.d(TAG, results.getResultString());
            // TODO 自动生成的方法存根
            // Log.d("Result", results.getResultString());
            // contentTv.setText(results.getResultString());
            if (!isLast) {
                dictationResultStr += results.getResultString() + ",";
            } else {
                dictationResultStr += results.getResultString() + "]";
            }
            if (isLast) {
                // 解析Json列表字符串
                Gson gson = new Gson();
                List<DictationResult> dictationResultList = gson
                        .fromJson(dictationResultStr,
                                new TypeToken<List<DictationResult>>() {
                                }.getType());
                String finalResult2 = "";
                for (int i = 0; i < dictationResultList.size() - 1; i++) {
                    finalResult2 += dictationResultList.get(i)
                            .toString();
                }
                if(rfid.equals("") )speakText1("请先尝试识别到盲道上的电子标签点,以便我们确认您的位置。");
                    else if (!finalResult2.equals("") && dao.destinationQuery(finalResult2)) {
                        //dao模式

                        finallocation = finalResult2;
                        my_i = 0;
                        path = dao.pathQuery(rfid, finallocation, dijktra_date);
                        isfirst = true;
                        now_rfid = rfid;
                        speakText2("正在规划前往" + finalResult2 + "的路线,如需中途退出导航,请常按屏幕,请直行");

                    } else if (finalResult2.equals("退出导航")) {
                        speakText("正在退出导航。" + welcome);
                    } else if (finalResult2.equals("当前位置")) {
                        String now_position = dao.curPositionQuery(rfid);
                        speakText1("您当前的位置是," + now_position + "。请说出你想到达的目的地");
                    } else {
                        speakText1("未听清您想到达的目的地,请再说一遍");
                    }
                }
        }

        @Override
        public void onVolumeChanged(int volume, byte[] data) {
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
        }
    };

 其中:指位于业务逻辑和持久化数据之间实现对持久化数据的访问。通俗来讲,就是将数据库操作都封装起来。

对外提供相应的接口

在面向对象设计过程中,有一些"套路”用于解决特定问题称为模式。

DAO 模式提供了访问关系型数据库系统所需操作的接口,将数据访问和业务逻辑分离对上层提供面向对象的数据访问接口。

从以上 DAO 模式使用可以看出,DAO 模式的优势就在于它实现了两次隔离。

二、导向方向

1.代码示例

//导向方法
   private  void route() {
        //创建Thread实例s1
        //将Runnable实例s1run放入Thread实例中
        Thread s1 = new Thread(s1run);
        //通过线程对象操作线程(运行、停止)
        s1.start();
    }
    //创建Runnable实例
    private Runnable s1run = new Runnable() {
        Object obj = new Object();
        @Override
        //通过线程实例控制线程的行为(运行,停止),在运行时会调用Runnable接口中的run方法。
        public synchronized void run() {
            while(!daoda){
                try {
                    lock.lock();
                    String a = "";
                    //返回一个表示指定整数的 String 对象。
                    Log.d("qweasdzxc", Integer.toString(my_i));
                    for (int j = 0; j < path.size(); j++) {
                        //elementAt(j)方法用于获取组件的向量的指定索引/位置
                        //返回值:返回指定索引处的组件
                        a += path.elementAt(j);
                    }
                    if (!takephoto && distance <= 50) {
                        wancheng = true;
                        takephoto = true;
                        try {
                            speakText2("识别到前方有障碍物。正在识别中,请稍候!");
                            sleep(1000);
                        } catch (InterruptedException e) {
                            //InterruptedException 异常处理
                            //printStackTrace()方法的意思是:在命令行打印异常信息在程序中出错的位置及原因。
                            e.printStackTrace();
                        } finally {
                            //打开相机
                            turnOnCamera();
//                            rev_tv.post(new Runnable() {
//                                @Override
//                                public void run() {
//                                    photo_btn.performClick();
//                                }
//                            });
                        }
                        while(wancheng){

                        }
                    }
                    if (my_i <= path.size() - 1 && !now_rfid.equals(rfid)) {
                        //判断下一个点是否踩对
                        //detination_noQuery(finallocation)//通过建筑物名称查对应道路标识码
                        if (dao.rfidQuery(dao.detination_noQuery(finallocation)).equals(rfid)) {
                            daoda = true;
                            speakText1(finallocation + "到了,本次导航到此结束,你可以说退出导航或者说出下一个目的地的名称");
                        } else {
                            now_rfid = rfid;
                            //rfid_noQuery(rfid)通过rfid查对应道路标识码
                            if (path.indexOf(dao.rfid_noQuery(rfid)) != -1 && path.indexOf(dao.rfid_noQuery(rfid)) >= my_i) {
                                my_i = path.indexOf(dao.rfid_noQuery(rfid));
                                //constructionQuery(rfid)特殊建筑物播报
                                if (dao.constructionQuery(rfid)) {
                                    //curPositionQuery()//通过RFID标识码查询当前位置信息
                                    String now_position = dao.curPositionQuery(rfid);
                                    speakText2("正在经过" + now_position);
                                    try {
                                        sleep(2000);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                                //destinationQuery()//导向信息
                                speakText2(dao.directionQuery(path.elementAt(my_i - 1), path.elementAt(my_i), path.elementAt(my_i + 1)));
                                my_i++;
                            } else {
                                if (dao.constructionQuery(rfid)) {
                                    String now_position = dao.curPositionQuery(rfid);
                                    speakText2("正在经过" + now_position);
                                    try {
                                        sleep(2000);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                                //destinationQuery(dao.rfid_noQuery(rfid))//判断rfid查对应道路标识码是否存在表中
                                if (my_i < path.size() - 1 && !dao.directionQuery(dao.rfid_noQuery(rfid), path.elementAt(my_i), path.elementAt(my_i + 1)).equals("")) {

                                    path.add(my_i, dao.rfid_noQuery(rfid));
//                                        temp = dao.query6(path);
                                    speakText2("方向错误,请掉头");

                                } else if (my_i > 0 && !dao.directionQuery(dao.rfid_noQuery(rfid), path.elementAt(my_i - 1), path.elementAt(my_i)).equals("")) {
                                    path.add(my_i - 1, dao.rfid_noQuery(rfid));
                                    speakText2("方向错误,请掉头");
                                    my_i--;
                                } else {
                                    my_i = 0;
                                    path = dao.pathQuery(rfid, finallocation, dijktra_date);
                                    isfirst = true;
                                    now_rfid = rfid;
                                    speakText2("方向错误,正在重新规划前往" + finallocation + "的路线。请直行");
                                }
                            }
                        }
                    } else {
                        if (my_i > path.size()) {
                            speakText1("已退出当前路线导航,请稍后。您可以说出下一个目的地的名称。");
                        }
//                        else {
//                            route();
//                        }
                    }
                } finally {
                    lock.unlock();
                }
            }
        }
    };

    private  void route1() {
        Thread s1 = new Thread(s1run1);
        s1.start();
    }
    private Runnable s1run1 = new Runnable() {
        Object obj = new Object();
        @Override
        //修饰实例方法: 作用于当前对象实例加锁,进入同步代码前要获得 当前对象实例的锁
        public synchronized void run() {
            while(!daoda){
                try {
                    //主动获取锁
                    lock.lock();
                    String a = "";
                    Log.d("qweasdzxc", Integer.toString(my_i));
                    for (int j = 0; j < path.size(); j++) {
                        a += path.elementAt(j);
                    }
                    if (my_i <= path.size() - 1 && !now_rfid.equals(rfid)) {
                        //判断下一个点是否踩对
                        if (dao.rfidQuery(dao.detination_noQuery(finallocation)).equals(rfid)) {
                            daoda = true;
                            speakText1(finallocation + "到了,本次导航到此结束,你可以说退出导航或者说出下一个目的地的名称");
                        } else {
                            now_rfid = rfid;
                            if (path.indexOf(dao.rfid_noQuery(rfid)) != -1 && path.indexOf(dao.rfid_noQuery(rfid)) >= my_i) {
                                my_i = path.indexOf(dao.rfid_noQuery(rfid));
                                if (dao.constructionQuery(rfid)) {
                                    String now_position = dao.curPositionQuery(rfid);
                                    speakText2("正在经过" + now_position);
                                    try {
                                        sleep(2000);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                                speakText2(dao.directionQuery(path.elementAt(my_i - 1), path.elementAt(my_i), path.elementAt(my_i + 1)));
                                my_i++;
                            } else {
                                if (dao.constructionQuery(rfid)) {
                                    String now_position = dao.curPositionQuery(rfid);
                                    speakText2("正在经过" + now_position);
                                    try {
                                        sleep(2000);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                }
                                //path.size() :返回路径表中元素的个数
                                if (my_i < path.size() - 1 && !dao.directionQuery(dao.rfid_noQuery(rfid), path.elementAt(my_i), path.elementAt(my_i + 1)).equals("")) {
                                    //add() 方法将元素插入到指定位置的动态数组中。
                                    path.add(my_i, dao.rfid_noQuery(rfid));
//                                        temp = dao.query6(path);
                                    speakText2("方向错误,请掉头");

                                } else if (my_i > 0 && !dao.directionQuery(dao.rfid_noQuery(rfid), path.elementAt(my_i - 1), path.elementAt(my_i)).equals("")) {
                                    path.add(my_i - 1, dao.rfid_noQuery(rfid));
                                    speakText2("方向错误,请掉头");
                                    my_i--;
                                } else {
                                    my_i = 0;
                                    path = dao.pathQuery(rfid, finallocation, dijktra_date);
                                    isfirst = true;
                                    now_rfid = rfid;
                                    speakText2("方向错误,正在重新规划前往" + finallocation + "的路线。请直行");
                                }
                            }
                        }
                    } else {
                        if (my_i > path.size()) {
                            speakText1("已退出当前路线导航,请稍后。您可以说出下一个目的地的名称。");
                        }
                    }
                    if (!takephoto && distance <= 50) {
                        takephoto = true;
                        try {
                            speakText2("识别到前方有障碍物,请小心前行");
                            sleep(5000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                } finally {
                    lock.unlock();
                }
            }
        }
    };

解释1.

其中:

private  void route() {
    //创建Thread实例s1
    //将Runnable实例s1run放入Thread实例中
    Thread s1 = new Thread(s1run);
    //通过线程对象操作线程(运行、停止)
    s1.start();
}
//创建Runnable实例,并实现Runnable接口并重写run方法
private Runnable s1run = new Runnable() {
    Object obj = new Object();
    @Override
    //通过线程实例控制线程的行为(运行,停止),在运行时会调用Runnable接口中的run方法。
    public synchronized void run() {...}

 1. Runnable接口简介

(1)Runnable接口是线程辅助类,仅定义了一个方法run()方法

(2)作用:实现多线程

(3)优点:可继承其他类实现对Runnable实现类的增强,可避免Thread类由于继承Thread类而无法继承其他类的问题;同时Runnable接口的run()方法可以被多个线程共享,用于多个进程处理一种资源的问题

(4)使用方法:

(1) 实现Runnable接口 (2) 重写run()方法 (3) 创建runnable实例 (4) 创建Thread实例 (5) 将Runnable实例放入Thread实例中 (6) 通过线程实例控制线程的行为(运行,停止),在运行时会调用Runnable接口中的run方法。

注意:Java中真正能创建新线程的只有Thread类对象 通过实现Runnable的方式,最终还是通过Thread类对象来创建线程

 2. synchronized

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;

     2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;就是在方法的前面加synchronized,public synchronized void method(){}; synchronized修饰方法和修饰一个代码块类似,只是作用范围不一样,修饰代码块是大括号括起来的范围,而修饰方法范围是整个函数。如将的run方法改成如下的方式,实现的效果一样。

public synchronized void run() {
       {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println("线程名:"+Thread.currentThread().getName() + ":" + (count++));
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    } 

!!!在用synchronized修饰方法时要注意以下几点:

synchronized关键字不能继承。 虽然可以使用synchronized来定义方法,但synchronized并不属于方法定义的一部分,因此,synchronized关键字不能被继承。如果在父类中的某个方法使用了synchronized关键字,而在子类中覆盖了这个方法,在子类中的这个方法默认情况下并不是同步的,而必须显式地在子类的这个方法中加上synchronized关键字才可以。当然,还可以在子类方法中调用父类中相应的方法,这样虽然子类中的方法不是同步的,但子类调用了父类的同步方法,因此,子类的方法也就相当于同步了。

!!!

      3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;

      4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

 3.lock的lock()方法

平常使用得最多的一个方法,就是用来获取锁。如果锁已被其他线程获取,则进行等待。 由于在前面讲到如果采用Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁。因此一般来说,使用Lock必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生。

4.sleep()函数

Sleep函数可以使计算机程序(进程,任务或线程)进入休眠,使其在一段时间内处于非活动状态。当函数设定的计时器到期,或者接收到信号、程序发生中断都会导致程序继续执行。

解释2:

代码示例:

if (my_i <= path.size() - 1 && !now_rfid.equals(rfid)) {
                        //判断下一个点是否踩对
                        //detination_noQuery(finallocation)//通过建筑物名称查对应道路标识码
                        if (dao.rfidQuery(dao.detination_noQuery(finallocation)).equals(rfid)) {
                     ...
                        } else {
                           ...
                            if (path.indexOf(dao.rfid_noQuery(rfid)) != -1 && path.indexOf(dao.rfid_noQuery(rfid)) >= my_i) {
                              ...
                                if (dao.constructionQuery(rfid)) {
                                   ...
                                }
                                //directionQuery方向查询
                                speakText2(dao.directionQuery(path.elementAt(my_i - 1), path.elementAt(my_i), path.elementAt(my_i + 1)));
                             ...
                            } else {
                                if (dao.constructionQuery(rfid)) {
                                    String now_position = dao.curPositionQuery(rfid);
                                   ...
          
                              path = dao.pathQuery(rfid, finallocation, dijktra_date);
                         

其中

cursor.moveToNext()

Cursor是结果集游标,用于对结果集进行随机访问,如果大家熟悉jdbc, 其实Cursor与JDBC中的ResultSet作用很相似。使用moveToNext()方法可以将游标从当前行移动到下一行,如果已经移过了结果集的最后一行,返回结果为false,否则为true。

 用法:

首先通过query方法查找所需要的数据,query方法会返回一个Cursor对象;然后通过while循环遍历Cursor对象,其中需要获取到cursor的下标,再通过getInt(),getString()等方法通过下标获取数据,最后关闭cursor。

detination_noQuery()//通过建筑物名称查对应道路标识码

首先语音输入,通过科大讯飞云服务器语音识别获取到建筑物名称(destination)后,首先通过query方法查找所需要的数据,query方法会返回一个Cursor对象;然后初始化prompno用于存放查到的对应道路标识码,通过while循环:通过结果集游标,将游标从当前行移动到下一行,如果已经移过了结果集的最后一行;在这个过程中,如果表中有数据,cursor就会移动到第一个,也就是下标为0的位置,将获取到下标为0的标识码以int类型赋值给prompno后break;循环结束后返回对应道路标识码prompno。

public int detination_noQuery(String destination){//通过建筑物名称查对应道路标识码
    SQLiteDatabase db = helper.getWritableDatabase();
    Cursor cursor = db.query(Constants.TABLE_NAME,new String[]{"Prompno"},"Prompts = ?",new String[]{destination},null,null,null,null);
    int prompno = 0;
    while(cursor.moveToNext()){
        prompno = cursor.getInt(0);
        break;
    }
    cursor.close();
    return prompno;
}

rfid_noQuery()//通过rfid查对应道路标识码

通过rfid射频识别技术(导航识别)查找对应道路标识码,定义同上。

public int rfid_noQuery(String rfid){//通过rfid查对应道路标识码
    SQLiteDatabase db = helper.getWritableDatabase();
    Log.d("rfid",rfid);
    Cursor cursor = db.query(Constants.TABLE_NAME,new String[]{"Prompno"},"RFID = ?",new String[]{rfid},null,null,null,null);
    int prompno = 0;
    while(cursor.moveToNext()){
        prompno = cursor.getInt(0);
        break;
    }
    cursor.close();
    return prompno;
}

rfidQuery()//通过当前道路标识码查RFID标识码

通过 prompno对应道路标识码,首先通过query方法查找所需要的数据,query方法会返回一个Cursor对象;然后初始化RFID空字符串用于存放查到的RFID标识码;通过while循环:通过结果集游标,将游标从当前行移动到下一行,如果已经移过了结果集的最后一行;在这个过程中,如果表中有数据,cursor就会将获取到下标为0的标识码以字符串类型赋值给RFID后break;循环结束后返回RFID。

public String rfidQuery(int prompno){//通过当前道路标识码查RFID标识码
    SQLiteDatabase db = helper.getWritableDatabase();
    Cursor cursor = db.query(Constants.TABLE_NAME,new String[]{"RFID"},"Prompno = ?",new String[]{Integer.toString(prompno)},null,null,null,null);
    String RFID = "";
    while(cursor.moveToNext()){
        RFID = cursor.getString(0);
        break;
    }
    cursor.close();
    return RFID;
}

 curPositionQuery()//通过RFID标识码查询当前位置信息

通过当前道路标识码查RFID标识码后,首先通过query方法查找所需要的数据,query方法会返回一个Cursor对象;初始化prompts(当前位置)字符串为空用于存放查找的当前位置信息;通过while循环:...如果表中有数据,cursor就会将获取到下标为0的标识码以字符串类型赋值给prompts后break;循环结束后返回prompts。

 public String curPositionQuery(String Rfid){//通过RFID标识码查询当前位置信息
        SQLiteDatabase db = helper.getWritableDatabase();
        //columns:要查询出来的列名  selection:查询条件子句    selectionArgs:对应于selection语句中占位符的值  limit:指定偏移量和获取的记录数
        Cursor cursor = db.query(Constants.TABLE_NAME,new String[]{"Prompts"},"RFID = ?",new String[]{Rfid},null,null,null,null);
        String prompts = "";
        while(cursor.moveToNext()){
            prompts = cursor.getString(0);
            break;
        }

        cursor.close();
//        db.close();
        return prompts;
    }

 pathQuery()

Java.util.Vector提供了向量(Vector)类以实现类似动态数组的功能。Vector线程是安全的,同步的。创建了一个向量类的对象后,可以往其中随意地插入不同的类的对象,既不需顾及类型也不需预先选定向量的容量,并可方便地进行查找。对于预先不知或不愿预先定义数组大小,并需频繁进行查找、插入和删除工作的情况,可以考虑使用向量类Vector。

 通过上面的方法获取到RFID标识码、建筑物名称、路径规划属性值;获取通过rfid查对应道路RFID标识码;返回path里面获取到的通过建筑物名称查对应道路标识码。

public Vector<Integer> pathQuery(String Rfid, String destination, Dijktra_Date dijktra_date){//路径规划
    dijktra_date.dijktra.get_Dijktra(rfid_noQuery(Rfid));
    return dijktra_date.dijktra.print_path(detination_noQuery(destination));
}

destinationQuery()//判断目的地是否存在表中

public boolean destinationQuery(String destination){//判断目的地是否存在表中
    SQLiteDatabase db = helper.getWritableDatabase();
    Cursor cursor = db.query(Constants.TABLE_NAME,new String[]{"Prompts"},"Prompts = ?",new String[]{destination},null,null,null,null);
    String prompts = "";
    while(cursor.moveToNext()){
        prompts = cursor.getString(0);
        break;
    }
 //前面的同上
    //这里利用equals()方法,若prompts(目的地)跟表中的destination相同,则返回true;否则返回false
    if(prompts.equals(destination)){
        return true;
    } else{
        return false;
    }
}

directionQuery()//导向信息

定义三个int类型的标识码,首先通过query方法查找所需要的数据,query方法会返回一个Cursor对象并将其转化为String类型;初始化Tips空字符串用于存放三个位置的字符。

 public String directionQuery(int first_point, int second_point, int third_point) {//导向信息
     //自动生成数据库信息
        SQLiteDatabase db = helper.getWritableDatabase();
        Cursor cursor = db.query(Constants.TABLE_NAME,new String[]{"Tips"},"Prompbf = ? and Prompno = ? and Prompend = ?",new String[]{Integer.toString(first_point), Integer.toString(second_point), Integer.toString(third_point)},null,null,null,null);
        String Tips = "";
        while(cursor.moveToNext()) {
            Tips = cursor.getString(0);
            break;
        }
        cursor.close();
//        db.close();
        return Tips;
    }

constructionQuery()//特殊建筑物播报

通过RFID标识码,首先通过query方法查找所需要的数据,query方法会返回一个Cursor对象;Istrue存放判断结果,初始化Tips为0,通过日志工具类,打印rfid标签打印Rfid

 public boolean constructionQuery(String Rfid) {//特殊建筑物播报
        SQLiteDatabase db = helper.getWritableDatabase();
        Cursor cursor = db.query(Constants.TABLE_NAME,new String[]{"Istrue"},"RFID = ?",new String[]{Rfid},null,null,null,null);
        int Tips = 0;
        Log.d("rfid",Rfid);
        while(cursor.moveToNext()) {
            Tips = cursor.getInt(0);
            break;
        }
        cursor.close();
//        db.close();
        if(Tips == 1){
            return true;
        }else{
            return false;
        }
    }

 其中其中rfid通过接收数据函数获取

   /**
     * @Title: displayData
     * @Description: TODO(接收到的数据在scrollview上显示)
     * @param @param rev_string(接受的数据)
     * @return void
     * @throws
     */
    private void displayData(String rev_string, Intent intent)
    {
      ...
        bluedata = rev_string;
        //更新UI
        runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
//                rev_tv.setText(bluedata);
                if(bluedata.length() == RFID )
                {
                    rfid = bluedata;
                    rev_tv.setText(rfid);

                }
                else if(bluedata.length() == DISTANCE )
                {
                  ...
                }
            }
        });

 --------------------------------------------------补充说明-------------------------------------------------

Java String equals() 方法

用于将字符串与指定的对象比较

String类中重写了equals()方法用于比较两个字符串的内容是否相等。

示例:

**public** **class** Test {
  **public** **static** **void** main(String args[]) {
    String Str1 = **new** String("runoob");
    String Str2 = Str1;
    String Str3 = **new** String("runoob");
    **boolean** retVal;

​    retVal = Str1.equals( Str2 );
​    System.out.println("返回值 = " + retVal );

​    retVal = Str1.equals( Str3 );
​    System.out.println("返回值 = " + retVal );
  }
}

实例

if (my_i < path.size() - 1 && !dao.directionQuery(dao.rfid_noQuery(rfid), path.elementAt(my_i), path.elementAt(my_i + 1)).equals("")) {...}

 利用equals()比较,判断dao.directionQuery()函数是否为空字符串;这个语法的含义是,如果my_i < path.size() -1 和 !dao.directionQuery(dao.rfid_noQuery(rfid), path.elementAt(my_i), path.elementAt(my_i + 1)).equals("")同时为真条件才成立,然后要!dao.directionQuery(dao.rfid_noQuery(rfid), path.elementAt(my_i), path.elementAt(my_i + 1)).equals("")为真,则dao.directionQuery(dao.rfid_noQuery(rfid), path.elementAt(my_i), path.elementAt(my_i + 1)).equals("")要为假,即dao.directionQuery(dao.rfid_noQuery(rfid), path.elementAt(my_i), path.elementAt(my_i + 1))这个函数的返回结果要为非空,与空字符比较才为false,!false为true。整个条件满足才执行命令。

其中:

dao为定义的Dao类,directionQuery(dao.rfid_noQuery(rfid), path.elementAt(my_i), path.elementAt(my_i + 1))为定义的directionQuery(int first_point, int second_point, int third_point)类;

path.add(my_i, dao.rfid_noQuery(rfid));

 将rfid查对应道路标识码(元素)插入到my_i指定位置的动态数组path中

add() 方法将元素插入到指定位置的动态数组中。

add() 方法的语法为:

arraylist.add(int index,E element)

注:arraylist 是 ArrayList 类的一个对象。

参数说明:

  • index(可选参数)- 表示元素所插入处的索引值

  • element - 要插入的元素

如果 index 没有传入实际参数,元素将追加至数组的最末尾。

返回值

如果成功插入元素,返回 true。

注意:如果 index 超出范围,则该 add() 方法抛出 IndexOutOfBoundsException 异常。

总结

导航听写通过科大讯飞提供的语音识别和语音合成以及语音提示,结合RFID射频识别技术、采用Dijkstra(迪杰斯特拉)算法实现。其中整个导航功能还包含蓝牙连接路况识别等功能的结合这里只介绍导航的听写功能。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐