android蓝牙通信

       蓝牙能在移动电话、PDA、无线耳机、笔记本电脑、相关外设等众多设备之间进行无线信息交换。利用“蓝牙”技术,能够有效地简化移动通信终端设备之间的通信,也能够成功地简化设备与Internet之间的通信,从而数据传输变得更加迅速高效,为无线通信拓宽道路。

      在最近项目中,用到了android机器蓝牙同硬件通信,所以在此举个小例子总结一下。结构同上次介绍ch34串口差不多,大家有兴趣可以去看看https://blog.csdn.net/weixin_35959554/article/details/85262658

在下拙见通信细分为几个步骤:

      第一当然是开启权限了:

 <!-- 蓝牙操作权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>

第二获取到设备搜索到已配对的蓝牙列表:

// 得到蓝牙适配器对象
        _bluetooth  = BluetoothAdapter.getDefaultAdapter();
        // 得到所有设备
        devices = _bluetooth.getBondedDevices();
        if (devices != null && devices.size() > 0) {
            //默认获取第一个配对成功的蓝牙设备
            for (BluetoothDevice dev : devices) {
                _device = dev;
                break;
            }
        }

第三设置连接协议:

设置协议时,必须使用android的SSP(协议栈默认)的UUID:00001101-0000-1000-8000-00805F9B34FB才能正常和外部的,也是SSP串口的蓝牙设备去连接。

String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB";
 //选择连接的协议
_socket = _device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));

第四开启连接获取输入流:

  try {
            if (!_socket.isConnected()) {
                //发起连接请求
                _socket.connect();
            }
        } catch (IOException e) {
            sentConMsg("蓝牙连接异常");
            return;
        }
        try {
            //获取输入流
            if (_socket.getInputStream() != null) {
                inStream = _socket.getInputStream();
            } else {
                sentConMsg("蓝牙输入流为空");
                return;
            }
            //获取输出流
            if (_socket.getOutputStream() != null) {
                outStream = _socket.getOutputStream();
            } else {
                sentConMsg("蓝牙输出流为空");
                return;
            }
        } catch (IOException e) {
            sentConMsg("蓝牙输入输出数据异常");
            return;
        }

第五开启线程读取数据:

 //读取线程
    private class ReadThread extends Thread {
        public void run() {
            try {
                while (IsStart) {
                    int size = inStream.available();
                    if (size > 0) {
                        sentConMsg("蓝牙连接成功");
                        byte[] buf = new byte[size];
                        inStream.read(buf, 0, buf.length);
                        sentData(buf);
                        _Datatime = 0;
                    } else {
                        //数据为空时 开始断开计时
                        if (_Timer == null) {
                            _Timer = new Timer();
                            _Timer.schedule(new DataTimer(), 0, 1000);
                        }
                        continue;
                    }

                }
            } catch (Exception ex) {
            }
        }
    }

只要完成上面几个步骤,那么数据应该就是可以读到了。

发送数据时一个方法就行了:

 //发送数据
    public void send(byte[] data) {
        try {
            if (outStream != null) {
                outStream.write(data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

      当然要做就要做的运用起来方便一些,所以在读取类里面我写了两个接口,一个是发送现在蓝牙的连接状态,一个是读到的数据,在activity里面只需要实现这两个接口,那么就可以很方便的显示数据在界面上了。

 //发送数据
    private void sentData(byte[] bytes) {
        Message message = Message.obtain();
        message.obj = bytes;
        DataHandler.sendMessage(message);
    }
    /**
     * 数据传输事件
     */
    private List<GetDataListener> lsDatas;

    public void addGetData(GetDataListener dataListener) {
        if (lsDatas == null) {
            lsDatas = new ArrayList<>();
        }
        lsDatas.add(dataListener);
    }

    public void removeGetData(GetDataListener dataListener) {
        if (lsDatas == null) {
            lsDatas = new ArrayList<>();
        }
        lsDatas.remove(dataListener);
    }

    private Handler DataHandler = new Handler() {
        public void handleMessage(Message msg) {
            if (lsDatas == null)
                return;
            for (GetDataListener item : lsDatas) {
                item.getData((byte[]) msg.obj);
            }
        }
    };


    //发送状态
    private void sentConMsg(String msg) {
        Message message = Message.obtain();
        message.obj = msg;
        ConnetHandler.sendMessage(message);
    }
    /**
     * 连接状态事件
     */
    private List<ConnectStateListener> lstConnect;

    public void addConnectState(ConnectStateListener connectStateListener) {
        if (lstConnect == null) {
            lstConnect = new ArrayList<>();
        }
        lstConnect.add(connectStateListener);
    }

    public void removeConnectState(ConnectStateListener connectStateListener) {
        if (lstConnect == null) {
            lstConnect = new ArrayList<>();
        }
        lstConnect.remove(connectStateListener);
    }


    private Handler ConnetHandler = new Handler() {
        public void handleMessage(Message msg) {
            if (lstConnect == null)
                return;
            for (ConnectStateListener item : lstConnect) {
                item.ConnectState((String) msg.obj);
            }
        }
    };

当然在最后不使用蓝牙时也得关闭蓝牙回收资源:

  try {
            if (_socket != null) {
               // 关闭BluetoothSocket请求端。
                _socket.close();
                _socket = null;
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            if (inStream != null) {
                inStream.close();
            }
            if (outStream != null) {
                outStream.close();
            }
            if (_device != null) {
                _device = null;
            }

多的不说,大部分重要的就是上面那些,我就直接上我封装的一个操作类,注释也很详细的,大家可以看看


public class BluetoothHelper {
    //连接的协议
    private String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB";
    private static BluetoothHelper bluetoothHelper;
    private static Context context;
    private BluetoothAdapter _bluetooth ;
    private static BluetoothDevice _device = null;
    private static BluetoothSocket _socket = null;
    private InputStream inStream = null;
    private OutputStream outStream = null;
    private boolean IsStart = false;
    private ReadThread bluThread;
    private Timer _Timer = null;
    private int _Datatime = 0;
    Set<BluetoothDevice> devices;

    public static BluetoothHelper getInstance(Context con) {
        if (null == bluetoothHelper) {
            bluetoothHelper = new BluetoothHelper();
            context = con;
        }
        return bluetoothHelper;
    }

    //在3秒内持续没有数据 那么判定蓝牙断开
    private class DataTimer extends TimerTask {
        @Override
        public void run() {
            _Datatime++;
            if (_Datatime > 3) {
                sentConMsg("蓝牙已断开");
            }
        }
    }

    //得到当前连接蓝牙名称
    public String getDeviceName() {
        if (_device != null) {
            return _device.getName();
        }
        return "";
    }

    //得到已配对蓝牙列表
    public Set<BluetoothDevice> getDevices() {
        if (devices != null) {
            return devices;
        }
        return new HashSet<>();
    }

    //打开蓝牙连接
    public void open() {
        sentConMsg("正在搜索蓝牙设备");
       // 得到蓝牙适配器对象
        _bluetooth  = BluetoothAdapter.getDefaultAdapter();
        // 得到所有设备
        devices = _bluetooth.getBondedDevices();
        if (devices != null && devices.size() > 0) {
            //默认获取第一个配对成功的蓝牙设备
            for (BluetoothDevice dev : devices) {
                _device = dev;
                break;
            }
        }
        if (_device == null) {
            sentConMsg("没有搜索到已配对成功的蓝牙");
            return;
        }
        try {
            sentConMsg("正在连接蓝牙设备");
            //选择连接的协议
            _socket = _device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));
        } catch (IOException e) {
            sentConMsg("蓝牙初始化端口异常");
            return;
        }
        try {
            if (!_socket.isConnected()) {
                //发起连接请求
                _socket.connect();
            }
        } catch (IOException e) {
            sentConMsg("蓝牙连接异常");
            return;
        }
        try {
            //获取输入流
            if (_socket.getInputStream() != null) {
                inStream = _socket.getInputStream();
            } else {
                sentConMsg("蓝牙输入流为空");
                return;
            }
            //获取输出流
            if (_socket.getOutputStream() != null) {
                outStream = _socket.getOutputStream();
            } else {
                sentConMsg("蓝牙输出流为空");
                return;
            }
        } catch (IOException e) {
            sentConMsg("蓝牙输入输出数据异常");
            return;
        }
        IsStart = true;
        //开启线程读数据
        if (bluThread == null) {
            bluThread = new ReadThread();
            bluThread.start();
        }
    }

    //关闭蓝牙连接
    public void close() {
        if (_Timer != null) {
            _Timer.cancel();
            _Timer = null;
            _Datatime = 0;
        }
        try {
            if (_socket != null) {
               // 关闭BluetoothSocket请求端。
                _socket.close();
                _socket = null;
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        if (bluThread != null) {
            bluThread.interrupt();
            bluThread = null;
        }
        IsStart = false;
        try {
            if (inStream != null) {
                inStream.close();
            }
            if (outStream != null) {
                outStream.close();
            }
            if (_device != null) {
                _device = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //发送数据
    public void send(byte[] data) {
        try {
            if (outStream != null) {
                outStream.write(data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //读取线程
    private class ReadThread extends Thread {
        public void run() {
            try {
                while (IsStart) {
                    int size = inStream.available();
                    if (size > 0) {
                        sentConMsg("蓝牙连接成功");
                        byte[] buf = new byte[size];
                        inStream.read(buf, 0, buf.length);
                        sentData(buf);
                        _Datatime = 0;
                    } else {
                        //数据为空时 开始断开计时
                        if (_Timer == null) {
                            _Timer = new Timer();
                            _Timer.schedule(new DataTimer(), 0, 1000);
                        }
                        continue;
                    }

                }
            } catch (Exception ex) {
            }
        }
    }


    //发送数据
    private void sentData(byte[] bytes) {
        Message message = Message.obtain();
        message.obj = bytes;
        DataHandler.sendMessage(message);
    }
    /**
     * 数据传输事件
     */
    private List<GetDataListener> lsDatas;

    public void addGetData(GetDataListener dataListener) {
        if (lsDatas == null) {
            lsDatas = new ArrayList<>();
        }
        lsDatas.add(dataListener);
    }

    public void removeGetData(GetDataListener dataListener) {
        if (lsDatas == null) {
            lsDatas = new ArrayList<>();
        }
        lsDatas.remove(dataListener);
    }

    private Handler DataHandler = new Handler() {
        public void handleMessage(Message msg) {
            if (lsDatas == null)
                return;
            for (GetDataListener item : lsDatas) {
                item.getData((byte[]) msg.obj);
            }
        }
    };


    //发送状态
    private void sentConMsg(String msg) {
        Message message = Message.obtain();
        message.obj = msg;
        ConnetHandler.sendMessage(message);
    }
    /**
     * 连接状态事件
     */
    private List<ConnectStateListener> lstConnect;

    public void addConnectState(ConnectStateListener connectStateListener) {
        if (lstConnect == null) {
            lstConnect = new ArrayList<>();
        }
        lstConnect.add(connectStateListener);
    }

    public void removeConnectState(ConnectStateListener connectStateListener) {
        if (lstConnect == null) {
            lstConnect = new ArrayList<>();
        }
        lstConnect.remove(connectStateListener);
    }


    private Handler ConnetHandler = new Handler() {
        public void handleMessage(Message msg) {
            if (lstConnect == null)
                return;
            for (ConnectStateListener item : lstConnect) {
                item.ConnectState((String) msg.obj);
            }
        }
    };




}

activity代码如下,可以看看是怎么调用的:

ublic class MainActivity extends AppCompatActivity implements View.OnClickListener, ConnectStateListener, GetDataListener {

    private EditText readText, writeText;
    private TextView connectText;
    private Button writeButton, openButton, CloseButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
    }

    //初始化连接以及数据传输事件
    private void initData() {
        BluetoothHelper.getInstance(this).addConnectState(this);
        BluetoothHelper.getInstance(this).addGetData(this);
    }

    //设置连接状态显示
    @Override
    public void ConnectState(String s) {
        if (s != null && s.length() > 0)
            connectText.setText(s);
    }

    //设置接收数据显示
    @Override
    public void getData(byte[] bytes) {
        if (bytes != null && bytes.length > 0) {
            readText.setText(bytes2HexString(bytes));
        }
    }

    private void initView() {
        connectText = (TextView) findViewById(R.id.ConectValues);
        readText = (EditText) findViewById(R.id.ReadValues);
        writeText = (EditText) findViewById(R.id.WriteValues);
        writeButton = (Button) findViewById(R.id.WriteButton);
        openButton = (Button) findViewById(R.id.OpenButton);
        CloseButton = (Button) findViewById(R.id.CloseButton);
        CloseButton.setOnClickListener(this);
        writeButton.setOnClickListener(this);
        openButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.OpenButton:
                BluetoothHelper.getInstance(this).open();
                break;
            case R.id.WriteButton:
                byte[] to_send = toByteArray(writeText.getText().toString());
                BluetoothHelper.getInstance(this).send(to_send);
                break;
            case R.id.CloseButton:
                BluetoothHelper.getInstance(this).close();
                break;
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        BluetoothHelper.getInstance(this).removeConnectState(this);
        BluetoothHelper.getInstance(this).removeGetData(this);
        BluetoothHelper.getInstance(this).close();
    }

    /**
     * 将String转化为byte[]数组
     *
     * @param arg 需要转换的String对象
     * @return 转换后的byte[]数组
     */
    private byte[] toByteArray(String arg) {
        if (arg != null) {
            /* 1.先去除String中的' ',然后将String转换为char数组 */
            char[] NewArray = new char[1000];
            char[] array = arg.toCharArray();
            int length = 0;
            for (int i = 0; i < array.length; i++) {
                if (array[i] != ' ') {
                    NewArray[length] = array[i];
                    length++;
                }
            }
            /* 将char数组中的值转成一个实际的十进制数组 */
            int EvenLength = (length % 2 == 0) ? length : length + 1;
            if (EvenLength != 0) {
                int[] data = new int[EvenLength];
                data[EvenLength - 1] = 0;
                for (int i = 0; i < length; i++) {
                    if (NewArray[i] >= '0' && NewArray[i] <= '9') {
                        data[i] = NewArray[i] - '0';
                    } else if (NewArray[i] >= 'a' && NewArray[i] <= 'f') {
                        data[i] = NewArray[i] - 'a' + 10;
                    } else if (NewArray[i] >= 'A' && NewArray[i] <= 'F') {
                        data[i] = NewArray[i] - 'A' + 10;
                    }
                }
                /* 将 每个char的值每两个组成一个16进制数据 */
                byte[] byteArray = new byte[EvenLength / 2];
                for (int i = 0; i < EvenLength / 2; i++) {
                    byteArray[i] = (byte) (data[i * 2] * 16 + data[i * 2 + 1]);
                }
                return byteArray;
            }
        }
        return new byte[]{};
    }

    /* *
     * @param bytes 字节数组
     * @return 16进制大写字符串
     */
    public static String bytes2HexString(byte[] bytes) {
        if (bytes == null) return null;
        int len = bytes.length;
        if (len <= 0) return null;
        char[] ret = new char[len << 1];
        for (int i = 0, j = 0; i < len; i++) {
            ret[j++] = hexDigits[bytes[i] >>> 4 & 0x0f];
            ret[j++] = hexDigits[bytes[i] & 0x0f];
        }
        return new String(ret);
    }

    private static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};


}

布局文件就不贴了(感觉贴了太多代码了。。。。。),以上就是我分享的一些蓝牙通信技术,可能理解不太深刻有可能又讲错的,莫怪莫怪

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值