您的位置:首页 > 移动开发 > Android开发

安卓经典蓝牙:从设备扫描到数据接收

2018-03-07 15:48 639 查看
看了半年的蓝牙,真的是快半年了,刚开始学安卓就是直接看蓝牙模块真的是难为自己了。今天终于实现了蓝牙的数据接收并显示在了手机上,所以需要稍微记录一下。
分为以下步骤:
a.       获取本机蓝牙BA =BluetoothAdapter.getDefaultAdapter();
b.       打开蓝牙Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
turnOn.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 10);
mContext.startActivity(turnOn);c.       获取已经匹配蓝牙pairedDevices = BA.getBondedDevices();
//得到的pairedDevices应该是一个数组类型
for(BluetoothDevice device : pairedDevices) {
    list1.add("已配对:" + device.getName() + "/" + device.getAddress());
    mainList1.add(device);
    adapter1.notifyDataSetChanged();     其中mainList1为ArrayList类型,泛型为BluetoothDevice为了在点击ListView时获取
d.       扫描未匹配蓝牙
1.       添加广播过滤器,打开广播IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);   //搜索到蓝牙设备
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
mContext.registerReceiver(mReceiver, filter);同时需要在广播响应中设置:class Receiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if(!mainList1.contains(device)){
                list1.add("未配对:" + device.getName() + "/" + device.getAddress());
                mainList1.add(device);
                adapter1.notifyDataSetChanged();
            }
        }
    }

2.       开始扫描BA.startDiscovery();其中:
a.       广播中获取动作String action = intent.getAction();b.       获取扫描到的蓝牙设备BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);e.       点击设备lv1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        Log.d("检测:","mainList1:"+mainList1.get(i));
        BA.cancelDiscovery();
        connectDevice(mainList1.get(i));
        String deviceName=mainList1.get(i).getAddress().toString();
        StoreData.put(MainActivity.this,"address",deviceName);
        new Thread(){
            @Override
            public void run(){
                String deviceName=StoreData.
                        get(MainActivity.this,"address","").toString();
                BluetoothDevice device=BA.getRemoteDevice(deviceName);
                communicate(device);
                DataTransport();
            }
        }.start();
        String address=mainList1.get(i).toString();
        Log.d("检测:","getRemoteAddress:"+BA.getRemoteDevice(address).getBondState());
    }
}); 
f.       配对设备
1.       判断状态mBluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE2.       Method creMethod(连接蓝牙)Method creMethod = BluetoothDevice.class
        .getMethod("createBond");
Log.e("TAG", "开始配对");
creMethod.invoke(mBluetoothDevice);g.       存储蓝牙设备Mac地址String deviceName=mainList1.get(i).getAddress().toString();
StoreData.put(MainActivity.this,"address",deviceName);其中StoreData.put()为自定义函数,继承的
SharedPreferences类
h.       通过Mac地址找回设备对象(getRemoteDevice(String str))String deviceName=StoreData.
   get(MainActivity.this,"address","").toString(); BluetoothDevice device=BA.getRemoteDevice(deviceName); 
i.        判断状态(同f.1)
j.        新建线程并完成以下步骤new Thread(){
    @Override
    public void run(){
        String deviceName=StoreData.
                get(MainActivity.this,"address","").toString();
        BluetoothDevice device=BA.getRemoteDevice(deviceName);
        communicate(device);
        DataTransport();
    }
}.start(); 
k.       获取本机uuidUUID uuid= UUID.fromString(SPP_UUID);l.        新建BluetoothSocketbtSocket=device.createRfcommSocketToServiceRecord(uuid);m.     连接BluetoothSocketbtSocket.connect();n.       获取BluetooSocket的输入输出流inputStream=btSocket.getInputStream();
outputStream=btSocket.getOutputStream();
 
其中:
对于imn三步骤,涉及到输入输出数据传输,因此需要在try/catch结构中实现
o.       将输入输出流读取成可处理格式length = inputStream.read(recvBuffer);p.       其中length为int型,recvBuffer是byte[]型
q.       将输入输出流转化为二进制,即对recvBuffer进行处理public class functions {
    /**
     * 用于建立十六进制字符的输出的大写字符数组
     */
    private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
    /**
     * 用于建立十六进制字符的输出的小写字符数组
     */
    private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    public static String BytesToString(byte[] inHex, int nOff, int nLen) {
        int i;
        StringBuilder strResult = new StringBuilder();
        strResult.append("");
        for (i = 0; i < nLen; i++) {
            strResult.append(String
                    .valueOf(DIGITS_UPPER[(0xF0 & inHex[nOff + i]) >>> 4]));
            strResult.append(String
                    .valueOf(DIGITS_UPPER[inHex[nOff + i] & 0x0F]));
        }
        return strResult.toString();
    }
}r.       通过handler发送出带有二进制信息的MessageMessage message = new Message();
message.obj =functions.BytesToString(recvBuffer, 0, length);
//将输入二进制数转化为十六进制数
handler.sendMessage(message);s.       回到handleMessage处理接收到的MessageHandlerhandler=new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        String str3 = (String) msg.obj;
        StoreData sdata = new StoreData();
        sdata.setContent(str3);
        EventBus.getDefault().post(sdata);
        return false;
    }
});1.       通过EventBus将数据发送至显示层String str3 = (String) msg.obj;
StoreData sdata = new StoreData();
sdata.setContent(str3);
EventBus.getDefault().post(sdata); 
2.       在显示层通过onEventMainThread()函数接收、读取并显示public void onEventMainThread(StoreData sdata) {
    tv1.setText(sdata.mMsg);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    EventBus.getDefault().unregister(this);
}大工告成,当然还有环境配置之类的。目前虽然遇到过这些问题,但是也还没系统性搞明白怎么处理。以后再说了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息