android设备与蓝牙模块之间交互(蓝牙命令,收发)的两种方式,附DEMO下载地址

该文章主要用于android设备与蓝牙模块间的操作和通讯。

直接拿到Demo的工具类,并放到自己的项目中去引用。

这是Demo下载地址

1.主要包括界面

          

2.AndroidManifest.xml需要用到的权限

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- SD卡操作权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

3.主要的蓝牙工具类:

package com.example.bluetooth;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import com.example.main.MainActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
/**
 * 蓝牙服务类,包括蓝牙连接监听线程、连接线程、已连接线程
 * @author Administrator
 *
 */
public class BluetoothService {
    
    private static final String TAG = "Service";
    private static final boolean DEBUG = true;

    // 蓝牙端口名
    private static final String BT_NAME = "XULANG";

    // 获取设备UUID				 				
    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    private final BluetoothAdapter mAdapter;
    private final Handler mHandler;
    private AcceptThread mAcceptThread;
    private ConnectThread mConnectThread;
    private ConnectedThread mConnectedThread;
    private int BtState;
    //蓝牙状态常量
    public static final int IDLE = 0;       // 闲置
    public static final int LISTENING = 1;  // 监听
    public static final int CONNECTING = 2; // 正在连接
    public static final int CONNECTED = 3;  // 已连接

    public static boolean allowRec=true;
    /**
     * @param handler  在线程与UI间通讯
     */
    public BluetoothService(Handler handler) {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        BtState = IDLE;
        mHandler = handler;
    }

    /**
     * 设置当前蓝牙状态
     * @param state  当前蓝牙状态
     */
    private synchronized void setState(int state) {
        BtState = state;
    }

    /**
     * 获取当前蓝牙状态
     * @return 当前蓝牙状态
     */
    public synchronized int getState() {
        return BtState;
    }

    /**
     * 启动本地蓝牙接收监听
     */
    public synchronized void acceptWait() {
        if (DEBUG) Log.e(TAG, "进入acceptWait");
        // 开启外主蓝牙接收监听线程
        if (mAcceptThread == null&&mConnectedThread==null) {
            mAcceptThread = new AcceptThread();
            mAcceptThread.start();
        }
        setState(LISTENING);
    }

    /**
     * 开启连接线程方法
     * @param device  欲连接的设备
     */
    public synchronized void connect(BluetoothDevice device) {
        if (DEBUG) Log.e(TAG, "正在连接" + device);

        //关闭所有可能的蓝牙服务线程以便开启连接线程
        cancelAllBtThread();
        // 开启连接线程
        mConnectThread = new ConnectThread(device);
        mConnectThread.start();
        setState(CONNECTING);
    }

    /**
     * 开启已连接线程的方法
     * @param socket  已建立连接的蓝牙端口
     * @param device  已连接的蓝牙设备
     */
    public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
        if (DEBUG) Log.e(TAG, "connected");

        //关闭所有可能的蓝牙服务线程以便开启已连接线程
        cancelAllBtThread();

        // 开启已连接线程
        mConnectedThread = new ConnectedThread(socket);
        mConnectedThread.start();

        //发送已连接设备名回UI
        sendString2UI(MainActivity.CONNECTED_DEVICE_NAME,
        				MainActivity.DEVICE_NAME,device.getName());
        setState(CONNECTED);
    }

    /**
     * 关闭所有蓝牙服务线程
     */
    public synchronized void cancelAllBtThread() {
        if (DEBUG) Log.e(TAG, "cancelAllBtThread方法");
        if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
        if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
        if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;}
        setState(IDLE);
    }

    /**
     * 写输出数据
     * @param out 输出字节流
     * @see ConnectedThread#write(byte[])
     */
    public void write(byte[] out) {
        //                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              object
        ConnectedThread r;
        // 同步
        synchronized (this) {
            if (BtState != CONNECTED) return;
            r = mConnectedThread;
        }
        r.write(out);
    }

    /**
     * 连接失败处理方法
     */
    private void connectionFailed() {
        setState(LISTENING);
        mConnectedThread=null;
        BluetoothService.this.acceptWait();
        //向UI发送连接失败通知
        sendString2UI(MainActivity.BT_TOAST,MainActivity.TOAST,"连接失败");
    }
    /**
     * 发送字符串会UI
     * @param what 什么类型
     * @param key  关键字
     * @param str  字符串
     */
    private void sendString2UI(int what,String key,String str){
    	Message msg = mHandler.obtainMessage(what);
        Bundle bundle = new Bundle();
        bundle.putString(key, str);
        msg.setData(bundle);
        mHandler.sendMessage(msg);
    }
    /**
     * 连接断开处理方法
     */
    private void connectionBreak() {
        setState(LISTENING);
        mConnectedThread=null;
        BluetoothService.this.acceptWait();
        // 向UI发送连接断开通知
        sendString2UI(MainActivity.BT_TOAST,MainActivity.TOAST,"连接断开");
    }

    /**
     * 监听外部主蓝牙设备线程
     */
    private class AcceptThread extends Thread {
       
        private final BluetoothServerSocket mBtServSocket;

        public AcceptThread() {
            BluetoothServerSocket bss = null;
            // 获取蓝牙监听端口
            try {
                bss = mAdapter.listenUsingRfcommWithServiceRecord(BT_NAME, MY_UUID);
            } catch (IOException e) {
                Log.e(TAG, "listen() failed", e);
            }
            mBtServSocket = bss;
        }

        public void run() {
            if (DEBUG) Log.e(TAG, "Begin mAcceptThread");
            setName("AcceptThread");
            BluetoothSocket socket = null;
            // 监听端口直到连接上
            while (BtState != CONNECTED) {
                try {
                    //成功连接时退出循环
                    socket = mBtServSocket.accept();
                } catch (IOException e) {
                    Log.e(TAG, "accept() failed", e);
                    break;
                }
                // 成功接收主设备
                if (socket != null) {
                    synchronized (BluetoothService.this) {
                        switch (BtState) {
                        case LISTENING:
                        case CONNECTING:
                            // 启动已连接线程
                            connected(socket, socket.getRemoteDevice());
                            break;
                        case IDLE:
                        case CONNECTED:
                            try {
                                socket.close();
                            } catch (IOException e) {
                                Log.e(TAG, "Could not close unwanted socket", e);
                            }
                            break;
                        }
                    }
                }
            }
            if (DEBUG) Log.e(TAG, "End mAcceptThread");
        }

        public void cancel() {
            if (DEBUG) Log.e(TAG, "cancel " + this);
            try {
            	mBtServSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of server failed", e);
            }
        }
    }
    /**
     * 连接蓝牙设备的线程
     */
    private class ConnectThread extends Thread {
        private final BluetoothSocket mBtSocket;
        private final BluetoothDevice mBtDevice;

        public ConnectThread(BluetoothDevice device) {
        	mBtDevice = device;
            BluetoothSocket bs = null;

            // 根据UUID获取欲连接设备
            try {
                bs = device.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) {
                Log.e(TAG, "create() failed", e);
            }
            mBtSocket = bs;
        }

        public void run() {
        	if (DEBUG) Log.e(TAG, "Begin mConnectThread");
            setName("ConnectThread");
            // 尝试连接蓝牙端口
            try {
            	mBtSocket.connect();
            } catch (IOException e) {
                // 当连接失败或异常
                connectionFailed();
                try {
                	mBtSocket.close();
                } catch (IOException e2) {
                    Log.e(TAG, "close() fail", e2);
                }
                // 重新开启连接监听线程并退出连接线程
                BluetoothService.this.acceptWait();
                if (DEBUG) Log.d(TAG, "End mConnectThread");
                return;
            }

            synchronized (BluetoothService.this) {
                mConnectThread = null;
            }
            // 启动已连接线程
            connected(mBtSocket, mBtDevice);
            if (DEBUG) Log.d(TAG, "End mConnectThread");
        }

        public void cancel() {
            if (DEBUG) Log.e(TAG, "cancel " + this);
            try {
            	mBtSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() fail", e);
            }
        }
    }

    /**
     * 已连接的相关处理线程
     */
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mBtSocket;
        private final InputStream mInputStream;
        private final OutputStream mOutputStream;

        public ConnectedThread(BluetoothSocket socket) {
        	if (DEBUG) Log.d(TAG, "construct ConnectedThread");
            mBtSocket = socket;
            InputStream is = null;
            OutputStream os = null;

            // 获取输入输出流
            try {
            	is = socket.getInputStream();
            	os = socket.getOutputStream();
            } catch (IOException e) {
                Log.i(TAG, "get Stream fail", e);
            }

            mInputStream = is;
            mOutputStream = os;
        }

        public void run() {
        	if (DEBUG) Log.i(TAG, "Begin mConnectedThread");
            byte[] buffer=new byte[1024];
            int bytes;

            // 监听输入流以备获取数据
            while (true) {
                try {
                    bytes = mInputStream.read(buffer);
                    // 将接受数据发回UI处理
                    if(bytes!=-1&&allowRec){
                    mHandler.obtainMessage(MainActivity.REC_DATA,bytes,-1,buffer).sendToTarget();
                    }
                } catch (IOException e) {
                    Log.e(TAG, "connection break", e);
                    connectionBreak();
                    break;
                }
                try {
                	//线程睡眠20ms以避免过于频繁工作  50ms->20ms 2017.12.2
                	//导致UI处理发回的数据不及时而阻塞
					Thread.sleep(20);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
            }
            if (DEBUG) Log.i(TAG, "End mConnectedThread");
        }

        /**
         * 写输出流以发送数据
         * @param buffer 欲输出字节流
         */
        public void write(byte[] buffer) {
            try {
            	mOutputStream.write(buffer);

            } catch (IOException e) {
                Log.e(TAG, "Exception during write", e);
            }
        }

        public void cancel() {
            if (DEBUG) Log.e(TAG, "cancel " + this);
            try {
            	mBtSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() fail", e);
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_35809640/article/details/66472626
今日推荐