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

看了半年的蓝牙,真的是快半年了,刚开始学安卓就是直接看蓝牙模块真的是难为自己了。今天终于实现了蓝牙的数据接收并显示在了手机上,所以需要稍微记录一下。

分为以下步骤:

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_NONE

2.       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.       获取本机uuid

UUID uuid= UUID.fromString(SPP_UUID);

l.        新建BluetoothSocket

btSocket=device.createRfcommSocketToServiceRecord(uuid);

m.     连接BluetoothSocket

btSocket.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发送出带有二进制信息的Message

Message message = new Message();
message.obj =functions.BytesToString(recvBuffer, 0, length);
//将输入二进制数转化为十六进制数
handler.sendMessage(message);

s.       回到handleMessage处理接收到的Message

Handlerhandler=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);
}

大工告成,当然还有环境配置之类的。目前虽然遇到过这些问题,但是也还没系统性搞明白怎么处理。以后再说了。

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值