赞
踩
这边来记录一下这个盲人指示红绿灯 蓝牙app的制作过程。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EC6anZFL-1586166531716)(https://i.loli.net/2020/04/06/U9waJ2F3zHdXMGf.png)]
language选择java 最小api选择23 一般现在手机都比6.0高吧
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IWzjbjjk-1586166531718)(https://i.loli.net/2020/04/06/WjExD1Xd54LPCNc.png)]
在oncreate 函数中 添加.意思是代码获取到那两个text控件。方便后面动态的改变信息。
tip=findViewById(R.id.tip);
tip2=findViewById(R.id.tip2);
tip.setText("蓝牙已断开");
也需要在类中声明变量
TextView tip,tip2;
声明变量
BluetoothDevice device;
BluetoothSocket mSocket;
BluetoothAdapter mBluetoothAdapter;
构建线程函数,是一个跑在单独线程里的死循环。
安卓新版本都要动态申请权限。所以首先申请权限
下一步 循环检测设备有没有绑定。没绑定得先去绑定。
然后是 进行一个链接和通讯。每次循环前判断一次连接状态。如果正常就读取蓝牙数据。不正常就进行重连
public void bluetoothinit(){ Log.e("myTip123","开始线程"); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter == null) { // Device does not support Bluetooth } if (!mBluetoothAdapter.isEnabled()) {//申请权限 ask for permission Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, 1); } while (true){ Set<BluetoothDevice> tmp = mBluetoothAdapter.getBondedDevices(); for (BluetoothDevice d : tmp) { Log.e("add123",d.getAddress()); if(d.getAddress().equals("00:19:10:08:A5:3C")){ device=d; } } if(device==null){ Log.e("myTip123","设备未绑定。请绑定后再试。"); MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this.getApplicationContext(), "设备未绑定。请绑定后再试。", Toast.LENGTH_LONG).show(); Log.e("myTip123","设备未绑定。请绑定后再试。"); } }); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } }else{ break; } } // 所有已绑定设备,一个Set集合 try { mSocket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); } catch (IOException e) { e.printStackTrace(); } mBluetoothAdapter.cancelDiscovery(); while(true){ Log.e("myTip123","检查"); if(mSocket.isConnected()){ try { String hhh=""; while(mSocket.getInputStream().available()>0){ hhh+=(char)mSocket.getInputStream().read(); } Log.e("myTip123",hhh); int lastDirectionFlag=DirectionFlag; DirectionFlag=(hhh.contains("NSpass")?1:2); if(lastDirectionFlag!=DirectionFlag){//方向改变 Log.e("方向改变",""+DirectionFlag); tip.setText("蓝牙已链接 "+(DirectionFlag==1?"南北通":"东西通")); if(DirectionFlag==2){//东西 if(dir==3){//南 play(ns,gono); }else if(dir==2){ play(ew,goyes); } } else if(DirectionFlag==1){ if(dir==3){//南 play(ns,goyes); }else if(dir==2){ play(ew,gono); } } } } catch (IOException e) { Log.e("myTip123","检测available 出错"); e.printStackTrace(); } try { mSocket.getOutputStream().write(" ".getBytes()); } catch (IOException e) { e.printStackTrace(); try { mSocket.close(); } catch (IOException e1) { e1.printStackTrace(); } MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this.getApplicationContext(), "蓝牙已断开", Toast.LENGTH_LONG).show(); tip.setText("蓝牙已断开"); DirectionFlag=0; play(bno,null); } }); } } if(!mSocket.isConnected()){ try { mSocket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); mSocket.connect(); MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this.getApplicationContext(), "蓝牙已连接", Toast.LENGTH_LONG).show(); tip.setText("蓝牙已链接"); play(byes,null); } }); } catch (IOException e) { try { mSocket.close(); } catch (IOException e1) { e1.printStackTrace(); } MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this.getApplicationContext(), "链接失败。未找到设备。5秒后重新链接", Toast.LENGTH_LONG).show(); } }); e.printStackTrace(); } } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
new Thread (new Runnable(){
@Override
public void run(){
bluetoothinit();
}
}).start();
上面的蓝牙代码里已经有内容了。这边拿出来看一下
String hhh="";
while(mSocket.getInputStream().available()>0){
hhh+=(char)mSocket.getInputStream().read();
}
第八步。处理数据。
我们要做的就是判断红绿灯方向是否变化。并且做一个提醒。
变化这种就需要记录这一次和上一次的状态。
所以先创建flag变量
初始化
int DirectionFlag=0;int lastDirectionFlag=DirectionFlag;
然后在上面读取完数据后面对当前方向状态进行赋值,通过判断消息中有没有关键字
DirectionFlag=(hhh.contains("NSpass")?1:2);
如果发生了方向改变。我们进行提示。
显示设置文本 flag为1就是南北通。为2就是东西通
然后后面的是根据指南针数据进行对应的音频提示。这部分我们接下来讲
if(lastDirectionFlag!=DirectionFlag){//方向改变 Log.e("方向改变",""+DirectionFlag); tip.setText("蓝牙已链接 "+(DirectionFlag==1?"南北通":"东西通")); if(DirectionFlag==2){//东西 if(dir==3){//南 play(ns,gono); }else if(dir==2){ play(ew,goyes); } } else if(DirectionFlag==1){ if(dir==3){//南 play(ns,goyes); }else if(dir==2){ play(ew,gono); } } }
添加变量
private Sensor mAccelerometer;
private Sensor mMagneticField;
private float[] values = new float[3]; //orientation values
private float[] accelerometerValues = new float[3]; //data of acclerometer sensor
private float[] magneticFieldValues = new float[3] ; //data of magnetic field sensor
private float[] r = new float[9];
在oncreate中初始化
SensorManager mSensorManager;
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if(mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
//Success!存在磁力计
}else{
//Failure!不存在磁力计
}
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mSensorManager.registerListener((SensorEventListener) this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener((SensorEventListener) this, mMagneticField, SensorManager.SENSOR_DELAY_NORMAL);
给当前类添加接口SensorEventListener,即修改为
public class MainActivity extends AppCompatActivity implements SensorEventListener{
添加override函数
@Override public void onSensorChanged(SensorEvent sensorEvent) { if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { accelerometerValues = sensorEvent.values; } if (sensorEvent.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { magneticFieldValues = sensorEvent.values; } SensorManager.getRotationMatrix(r, null, accelerometerValues, magneticFieldValues); SensorManager.getOrientation(r, values); values[0] = (float) Math.toDegrees(values[0]); dirnum=(int)values[0]; lastdir=dir; if(dirnum>160||dirnum<-160||(dirnum<20&&dirnum>-20)){ dir=3; }else if((dirnum<-70&&dirnum>-110)||(dirnum>70&&dirnum<110)){ dir=2; }else{ dir=1; } if(dir!=lastdir){ MediaPlayer tar = null; if (dir== 1){ play(dirno,null); }else{ if(DirectionFlag==2){//东西 if(dir==3){//南 play(ns,gono); }else if(dir==2){ play(ew,goyes); } } else if(DirectionFlag==1){ if(dir==3){//南 play(ns,goyes); }else if(dir==2){ play(ew,gono); } } } } switch (dir){ case 1: tip2.setText("方向偏离过大"); break; case 2: tip2.setText("东西 "+dirnum); break; case 3: tip2.setText("南北 "+dirnum); break; } } @Override public void onAccuracyChanged(Sensor sensor, int i) { }
在以上函数中。对不同角度进行分类。即东西方向,南北方向,还有一个是偏离较大。就是介于东西和南北之间的。比较模糊的方向、
并且给全局的放前方向flag进行设置,同时更新text显示,并做语音提示。
用到的是MediaPlayer。
实现准备的音频文件有。
蓝牙已连接。蓝牙已断开。可以前行。不可前行。方向偏离大。当前方向为南北。当前方向为东西。
MediaPlayer goyes;//
MediaPlayer gono;
private MediaPlayer dirno;
private MediaPlayer byes;
private MediaPlayer bno;
private MediaPlayer ns;
private MediaPlayer ew;
然后我们进入到oncreate中添加对以上几个mediaplayer的加载
goyes = MediaPlayer.create(MainActivity.this.getApplicationContext(), R.raw.goyes);
gono = MediaPlayer.create(MainActivity.this.getApplicationContext(), R.raw.gono);
bno = MediaPlayer.create(MainActivity.this.getApplicationContext(), R.raw.bno);
byes = MediaPlayer.create(MainActivity.this.getApplicationContext(), R.raw.byes);
dirno = MediaPlayer.create(MainActivity.this.getApplicationContext(), R.raw.dirno);
ns = MediaPlayer.create(MainActivity.this.getApplicationContext(), R.raw.ns);
ew = MediaPlayer.create(MainActivity.this.getApplicationContext(), R.raw.ew);
采用的方案是安卓里的raw 资源,需要在项目下的app/src/main/res下新建一个raw 文件夹。然后把音频文件拖放进去。
由于我们的音频可能是两个要连续播放所以我构造了一下函数
MediaPlayer first,second; public void play(MediaPlayer tar1, final MediaPlayer tar2){ if (first!=null){ first.pause(); first.seekTo(0); } if(second!=null){ second.pause(); second.seekTo(0); } first=tar1; second=tar2; first.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { if(tar2!=null) tar2.start(); } }); first.start(); }
前两个判断是为了防止开始放当前音频的时候。之前的音频还没播放完。所以要先停止。
然后给第一个音频添加一个播放完毕的事件。如果有第二个音频不为null。那就第二个音频也进行播放。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。