ANDROID经典蓝牙通讯

最近写了一个关于蓝牙的操作类,对蓝牙不熟悉的同学可以参考一下 功能包括 发现,搜索,连接,发送,接收等/ 直接上代码:

package com.***.****.BlueToothM;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.***.***.utils.LogUtil;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

/**
 * Created by bysd-2 on 2018/10/19.
 */

public class BlueToothHelper {
    public static final int REQUEST_BLUE_ENABLE = 110;
    private static Context mContext;
    private static BluetoothAdapter bluetoothAdapter;
    private static String UUID_STR = "00001101-0000-1000-8000-00805F9B34FB";
    public static CURR_STATUS curr_status;
    private static ConnectThread connectThread;
    private static ReadThread readThread;
    private static SendThread sendThread;
    private static Handler queueMsg;


    public enum CURR_STATUS {
        CONNECTED, DISCONNECTED
    }

// 初始化   这里需要注意是蓝牙如果没有开启则要开启后 在activity回调里再次获取发现搜索一下设备;
    public static BluetoothAdapter initBlueTooth(Context context, Activity currActivity) {
        mContext = context;
        BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        bluetoothAdapter = bluetoothManager.getAdapter();
        if (bluetoothAdapter != null) {
            if (!bluetoothAdapter.isEnabled()) {
                Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
//                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                currActivity.startActivityForResult(intent, REQUEST_BLUE_ENABLE);
            }
            return bluetoothAdapter;
        } else {
            return null;
        }
    }

// 初始化后可以调用此方法,还有在activity回调成功时调用;    此处还需要一个广播来接收相应的消息,这个广播我稍后发出来    ,广播其实也可以放到此工具类里,我只是分出来了,放到这个工具类里好处时各个状态比较好监听,放到外面则需要两个监听,有些多余;
    public static void startDiscover() {
        if (bluetoothAdapter != null) {
            if (bluetoothAdapter.isDiscovering()) {
                bluetoothAdapter.cancelDiscovery();
                bluetoothAdapter.startDiscovery();
            } else {
                bluetoothAdapter.startDiscovery();
            }
        }
    }

// 这个在连接之前,扫描设备超时的时候调用;节省资源;
    public static void cancelDiscover() {
        if (bluetoothAdapter != null) {
            bluetoothAdapter.cancelDiscovery();
        }
    }

// 退出的时候调用,释放及重置
    public static void close() {
        if (bluetoothSocket != null) {
            try {
                bluetoothSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (bluetoothAdapter != null) {
            bluetoothAdapter = null;
        }
        if (connectThread != null) {
            connectThread = null;
        }
        if (readThread != null) {
            readThread = null;
        }
        if (sendThread != null) {
            sendThread = null;
        }
        //
        curr_status = CURR_STATUS.DISCONNECTED;

    }

//  连接时的回调; 里面加了一个接收数据的回调;
    public static IConnectListener iConnectListener;

    public interface IConnectListener {
        void connectDevSuccess();//连接成功;

        void connectDevFail(String exception); // 连接出错;

        void dataRespon(byte[] bytes); // 接收
    }

// connect
    public static void connectDevice(IConnectListener l, BluetoothDevice device) {
        iConnectListener = l;
        //
        if (connectThread == null) {
            connectThread = new ConnectThread(device);
            connectThread.start();
        } else {
            LogUtil.e(TAG, "connectThread != null");
        }
    }

    private static final String TAG = BlueToothHelper.class.getSimpleName();
    //
    private static InputStream inS = null;
    private static OutputStream outs = null;
    private static BluetoothSocket bluetoothSocket;
    private static final int SEND_CONNECT_FAIL = 1;
    private static final int SEND_CONNECT_SUCCESS = 2;
    private static final int SEND_FLAG = 110;

    static class ConnectThread extends Thread {
        private BluetoothDevice device;

        public ConnectThread(BluetoothDevice device) {
            this.device = device;
        }

        @Override
        public void run() {
            super.run();
            //
            try {
                UUID uuid = UUID.fromString(UUID_STR);
                BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(device.getAddress());
                // // TODO: 2018/10/23  此处通过uuid连接蓝牙;但有时候连接不上,不能保证每次都可以连接上;
                bluetoothSocket = remoteDevice.createRfcommSocketToServiceRecord(uuid); // RFcomm 是一种简单的传输协议
                bluetoothSocket.connect();
                // 靠谱的方式;  这种是比较暴力的方式,直接连蓝牙,API没有开放,估计是为了安全的角度,通过信道连接,范围1-30; 通过递归直到练到正确的信道上;
//                bluetoothSocket = cretateBluetoothSocketbyChannel(remoteDevice, 1, true);
                if (bluetoothSocket == null) {
                    sendMSG(SEND_CONNECT_FAIL, "0: " + "change channel always error");
                    return;
                }
                LogUtil.e(TAG, "ok");
                //
                inS = bluetoothSocket.getInputStream();
                outs = bluetoothSocket.getOutputStream();

            } catch (IOException e) {
                e.printStackTrace();
                try {
                    if (bluetoothSocket != null) {
                        bluetoothSocket.close();
                    }
                    if (inS != null) {
                        inS.close();
                    }
                    if (outs != null) {
                        outs.close();
                    }
                    bluetoothSocket = null;
                    inS = null;
                    outs = null;
                } catch (IOException e1) {
                    e1.printStackTrace();
                    //
                    sendMSG(SEND_CONNECT_FAIL, "1: " + e.getMessage());
                    return;
                }
                //
                sendMSG(SEND_CONNECT_FAIL, "2: " + e.getMessage());
                return;
            }
            //
            sendMSG(SEND_CONNECT_SUCCESS, null);

        }
    }


    /**
     * 有时候用api提供的方法remoteDevice.createRfcommSocketToServiceRecord(uuid)不能成功连接,connect总出错误;
     *
     * @param Device
     * @param channel
     * @param autoForward
     * @return
     */
    private static BluetoothSocket cretateBluetoothSocketbyChannel(BluetoothDevice Device, int channel, boolean autoForward) {
        BluetoothSocket socket = null;
        try {
            // createRfcommSocket为内置方法,入参为int类型; invoke执行该方法并需传入当前类对象及所需的入参类型;得到该方法的返回;
            socket = (BluetoothSocket) Device.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(Device, Integer.valueOf(channel));
            socket.connect();
            LogUtil.e(TAG, "connect is ok .  " + channel);
        } catch (Exception e) {
            LogUtil.e(TAG, "get socket is failed . e: " + e.getMessage());
            if (channel < 30) {
                if (autoForward) {
                    socket = cretateBluetoothSocketbyChannel(Device, channel + 1, autoForward);
                }
            } else {
                return null;
            }
        }
        return socket;
    }

    private static void sendMSG(int what, Object object) {
        Message msg = mHandler.obtainMessage();
        msg.what = what;
        msg.obj = object;
        mHandler.sendMessage(msg);
    }

    private static Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SEND_CONNECT_FAIL:
                    if (iConnectListener != null) {
                        iConnectListener.connectDevFail((String) msg.obj);
                    }
                    //
                    curr_status = CURR_STATUS.DISCONNECTED;
                    break;
                case SEND_CONNECT_SUCCESS:
                    //
                    curr_status = CURR_STATUS.CONNECTED;
                    //
                    if (iConnectListener != null) {
                        iConnectListener.connectDevSuccess();
                    }
                    //
                    if (readThread == null) {
                        readThread = new ReadThread();
                        readThread.start();
                    } else {
                        LogUtil.e(TAG, "readThread != null");
                    }
                    //
                    if (sendThread == null) {
                        sendThread = new SendThread();
                        sendThread.start();
                    }
                    break;
            }
        }
    };

    static class SendThread extends Thread {

        @Override
        public void run() {
            super.run();
            //
            Looper.prepare();
            queueMsg = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    if (msg.what == SEND_FLAG) {
                        byte[] bytes = (byte[]) msg.obj;
                        sendToBlt(bytes);
                    }
                    super.handleMessage(msg);
                }
            };
            Looper.loop();
        }
    }

    static class ReadThread extends Thread {
        @Override
        public void run() {
            super.run();
            if (curr_status == CURR_STATUS.CONNECTED) {
                if (inS == null) {
                    return;
                }
                try {
                    int available = inS.available();
                    byte[] bRec = new byte[available];
                    int read = inS.read(bRec);
                    //
                    LogUtil.e(TAG, "rece ///  available: " + available + "   read: " + read);
                    if (read > 0) {
                        if (iConnectListener != null) {
                            iConnectListener.dataRespon(bRec);
                        }
                    }
                    Thread.sleep(200);
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

// 蓝牙发送  会放到队列里;
    public static void sendData(byte[] data) {
        if (queueMsg != null) {
            Message message = queueMsg.obtainMessage();
            message.what = SEND_FLAG;
            message.obj = data;
            queueMsg.sendMessage(message);
        }
    }

    private static void sendToBlt(byte[] data) {
        if (curr_status == CURR_STATUS.CONNECTED) {
            try {
                LogUtil.e(TAG, "send data");
                outs.write(data);
            } catch (IOException e) {
                LogUtil.e(TAG, "e: " + e.getMessage());
                e.printStackTrace();
            }
        } else {
            LogUtil.e(TAG, "sendToBlt is fail...");
        }
    }

}

还有一个广播的 这个广播监听蓝牙的状态,可以根据自己的需要来进行你想监听的消息; 之前已经说了 这个广播可以放到上面一起 // 注意 下面没有获取了RSSI DEVICE这两个,没有去重;

package com.***.***.BlueToothM;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import com.***.***.BlueToothM.bean.BlueToothBean;

/**
 * Created by bysd-2 on 2018/10/19.
 */

public class BlueToothReceiver extends BroadcastReceiver {
    private IStatusListener listener;

    public interface IStatusListener {
        void foundDevice(BlueToothBean btBean);

        void discoveryFinished();

        void disConnected();

        void connected();
    }

    public void setIStatusListener(IStatusListener l) {
        this.listener = l;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent != null) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                short rssi = intent.getExtras().getShort(BluetoothDevice.EXTRA_RSSI);
                BlueToothBean btBean = new BlueToothBean(device, rssi);
                if (listener != null) {
                    listener.foundDevice(btBean);
                }
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                if (listener != null) {
                    listener.discoveryFinished();
                }
            } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
                BlueToothHelper.curr_status = BlueToothHelper.CURR_STATUS.DISCONNECTED;
                if (listener != null) {
                    listener.disConnected();
                }
            } else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
                BlueToothHelper.curr_status = BlueToothHelper.CURR_STATUS.CONNECTED;
                if (listener != null) {
                    listener.connected();
                }
            }
        }
    }
}

// 使用

        registerListener();  // 注册那个广播,要记得解注册;
        blueToothReceiver.setIStatusListener(new MyListener()); // 实现这个监听;
        bluetoothAdapter = BlueToothHelper.initBlueTooth(getApplicationContext(), this); // 初始化
        //
        BlueToothHelper.startDiscover(); // 开始搜素


//
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == BlueToothHelper.REQUEST_BLUE_ENABLE && resultCode == RESULT_OK) {
            Toast.makeText(MainActivity.this, "open bluetooth success", Toast.LENGTH_LONG).show();
            BlueToothHelper.startDiscover();
        } else {
            LogUtil.e(TAG, "requestCode: " + requestCode);
        }
    }


// 连接蓝牙
BlueToothHelper.connectDevice(new BlueToothHelper.IConnectListener() {
                @Override
                public void connectDevSuccess() {                   
                }
                @Override
                public void connectDevFail(String exception) {
                }
                @Override
                public void dataRespon(byte[] bytes) {
                }
            }, device);

好了 关于普通蓝牙的大概这么多, 还有发送的 方法 sendData(byte[]);

写的比较简单,主要是为了对蓝牙使用不了解的人,大家使用之前一定要先看看大体的流程,不要直接使用,对自己并没有好处。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值