# Android 蓝牙开发之数据通信

Android 蓝牙开发之数据通信

本文所述通信,是建立在已配对的基础上的。因为,个人认为,目前手机上的蓝牙配对功能已经很完善了,所以,我们完全可以先通过手机进行配对,然后直接在程序里面获取以配对的蓝牙设备进行开发即可,这样一来,我们把蓝牙开发里面的搜索和配对的工作就都给省略了。当然,这得根据个人想法以及功能需要来决断,因此不再多做赘述。下面简单描述下功能实现:

  • 从手机中已经配对的蓝牙设备中,得到指定的某一个蓝牙设备,进行连接,然后进行数据的发送和接收。

一、首先,需要获得一个BluetoothAdapter,可以通过getDefaultAdapter()获得系统默认的蓝牙适配器,当然我们也可以自己指定,但这个真心没有必要,至少我是不需要的。然后我们检查手机的蓝牙是否打开,如果没有,通过startActivity()方法打开。
代码如下:

/**
 *  获取已配对的蓝牙设备
 */
private void init(){
    /* 取得默认的蓝牙适配器 */
    BlueAdapter adapter = BluetoothAdapter.getDefaultAdapter();

        //adapter不等于null,说明本机有蓝牙设备
        if(adapter != null){

            //如果蓝牙设备未开启
            if(!adapter.isEnabled()){
                Intent intent = new     Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                //请求开启蓝牙设备
                context.startActivity(intent);
            }

            //获得已配对的远程蓝牙设备的集合
            Set<BluetoothDevice> devices = adapter.getBondedDevices();
            if(devices.size()>0){
                     //(这里用到了Iterator,有不懂的可以网上搜索一下,也比较好理解)
                for(Iterator<BluetoothDevice> it = devices.iterator();it.hasNext();){
                    BluetoothDevice device = it.next();
                    //获取远程蓝牙设备的名称
                    String bluetoothName = device.getName();
                    //如果蓝牙设备的名称跟我们的目标设备的名称一致,则记录下该设备(device)
                    if (bluetoothName.equals(lockName)) {
                        targetDevice = device;
                        Log.i("bluetooth", "连接设备的名称:" + device.getName());
                        break;
                    }
                }
            }else{
                toast.setText("还没有已配对的远程蓝牙设备!");
            }
        }else{
            toast.setText("本机没有蓝牙设备!");
        }
    }

二、搜索到该设备后,我们就要对该设备进行连接。下面是读取数据的代码:

/**
 * 连接应该放在一个线程中进行,要让该线程与我们程序的主线程进行通信,我们需要使用Handle,
 */
public void connect() {
        Thread thread = new Thread(new Runnable() {
            public void run() {
               //这里是调试遇到bug之后的解决方案,不明白的可以网上搜索下,
               //也可以去掉这一句以及最后面的那一句,观察log提示
                Looper.prepare();

                BluetoothSocket tmp = null;
                //这里需要重点说明下,本来连接设备之前是需要UUID的,所谓的UUID,就是用来进行配对的,
                //全称是Universally Unique Identifier,是一个128位的字符串ID,用于进行唯一标识。
                //因为我们是已经配对好的,所以这里直接通过下面的方法获得BluetoothSocket 即可。
                Method method;
                try {
                    method = targetDevice.getClass().getMethod("createRfcommSocket",
                            new Class[]{int.class});
                    tmp = (BluetoothSocket) method.invoke(targetDevice, 1);
                } catch (Exception e) {
                    Log.i("bluetooth", e.toString());
                }
                socket = tmp;
                try {

                    //连接设备之前还有一件事必须确保,取消扫描:
                    adapter.cancelDiscovery();
                    socket.connect();

                    toast.setText("连接成功,开始进行数据读取");
                    Log.i("bluetooth", "连接成功,开始进行数据读取");

                    // 连接成功之后进行读取
                    read();

                } catch (Exception e) {
                    Log.i("bluetooth", "连接失败");
                    //如果连接失败,则继续连接
                    connect();
                }

                Looper.loop();
            }
        });
        thread.start();
    }

三、连接完成之后,我们就可以进行数据的发送和读取了

/**
 * 读取目标蓝牙设备发送过来的数据
 */
    private void read() {
        Thread threadRead = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    InputStream inputStream = socket.getInputStream();
                    String result = "01100000";
                    /**
                     * 当然,这里只是将手机当做客户端,但是接收蓝牙模块发送过来的信息是没有必要特意
                     * 创建服务端的,我们只要一个不断监听并读取对方消息的循环就行。
                     */
                    while (true) {
                        try {

                            int count = 4;
                            int realCount = 0;  // 已经成功读取的字节的个数
                            创建一个长度为4的byte数组,每次读取4个字节
                            byte[] bytes = new byte[4];
                            //这里的这个循环,是为了保证每次都能够读取到4个字节。
                            //这里给大家一个连接,建议去体会
                            //(http://ouyangfei0426.iteye.com/blog/1024950)
                            while (realCount < count) {
                                realCount += inputStream.read(bytes, realCount, count - realCount);
                            }
                            //这里是将字节数组转换为十六进制字符串,后面会贴代码
                            String message = Utils.bytesToHexString(bytes);

//下面呢,则是我的一些数据处理的方式,这里大家就可以自由发挥了
                            result += message;

                            if (message.equals("3535376A")) {

                                int start = result.indexOf("A3200061");
                                int end = result.indexOf("3535376A");
                                result = result.substring(start + 6, end + 6);

                                Log.i("bluetooth", "最终接收数据结果:" + result);

                            }

                            Log.i("bluetooth", "读取的数据:" + message);

//这里是handler数据处理语句,具体代码不再贴了
                            Message msg = handler.obtainMessage();
                            msg.what = 0x00;
                            msg.obj = result;
                            handler.sendMessage(msg);

                        } catch (IOException e) {
                            Log.e("TAG", e.toString());
                            ***//循环结束语句在这里哦***
                            break;
                        }
                    }
                } catch (IOException e) {
                    Log.e("TAG", e.toString());
                }
            }
        });
        //千万别忘了开启线程(本人不才,犯过错误,,)
        threadRead.start();
    }

四、下面是发送数据的语句,也比较简单。代码如下:

/**
 *  写数据
 */
public void write(final byte[] bytes) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OutputStream out = socket.getOutputStream();
                    for (byte b : bytes) {
                        out.write(b);
                        Thread.sleep(10);
                    }
                    out.flush();
                } catch (Exception e) {
                    Log.e("Write", e.toString());
                }
            }
        });
        thread.start();
    }

五、OK!主体功能已经实现了,下面就是那个字节数据转十六进制字符串的方法了(比较惭愧,这个方法是借鉴的别人的)。

//二进制转十六进制字符串
    public static String bytesToHexString(byte[] bytes) {
        String result = "";
        for (int i = 0; i < bytes.length; i++) {
            String hexString = Integer.toHexString(bytes[i] & 0xFF);
            if (hexString.length() == 1) {
                hexString = '0' + hexString;
            }
            result += hexString.toUpperCase();
        }
        return result;
    }

六、以上就是个人的一点关于蓝牙开发数据通信方面的小小的总结。有不当的地方欢迎大家提出来,我们一起探讨学习。


重点参考博文链接地址(感谢一下O(∩_∩)O)

http://www.cnblogs.com/wenjiang/p/3200138.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值