安卓蓝牙操作+蓝牙工具类

由于前段时间,需要蓝牙操作一些东西。但是没有写过蓝牙连接与蓝牙操作等一系列的东西。

然后就去网上找找大家写的。到现在。已经结束了这个蓝牙的开发。

安卓端蓝牙操作。主要需要如下类

BluetoothAdapter  通过名字,可以了解到这是一个蓝牙适配器的类。可以获取到蓝牙的状态。开关,。扫描等一系列的常规操作
BluetoothSocket    这个呢,是一个蓝牙的socket。不做过多的介绍。和普通socket一样
BluetoothDevice   这个类是获取远程设备的类。


有了上面3个类。蓝牙的基本操作就可以实现了。
当然。,蓝牙的操作需要广播来支持、。下面是具体的代码。

蓝牙相关广播

 

             Action值                                                说明

 

      ACTION_STATE_CHANGED                    蓝牙状态值发生改变

      ACTION_SCAN_MODE_CHANGED         蓝牙扫描状态(SCAN_MODE)发生改变

      ACTION_DISCOVERY_STARTED             蓝牙扫描过程开始

      ACTION_DISCOVERY_FINISHED             蓝牙扫描过程结束

      ACTION_LOCAL_NAME_CHANGED        蓝牙设备Name发生改变

      ACTION_REQUEST_DISCOVERABLE       请求用户选择是否使该蓝牙能被扫描

                PS:如果蓝牙没有开启,用户点击确定后,会首先开启蓝牙,继而设置蓝牙能被扫描。

      ACTION_REQUEST_ENABLE                  请求用户选择是否打开蓝牙

 

      ACTION_FOUND  (该常量字段位于BluetoothDevice类中)

                说明:蓝牙扫描时,扫描到任一远程蓝牙设备时,会发送此广播。

 

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {//开始扫描蓝牙时候的广播
              mDeviceList.clear();
               mAdapter.notifyDataSetChanged();
            }
            if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {   //这个广播是扫描结束,蓝牙发送的广播
                if (progressDialog!=null){
                    progressDialog.cancel();
                    progressDialog=null;
                }
               showToast("搜素完成");
            }
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {   //当扫描到蓝牙设备时,会发送这个广播
               mDeviceList.add((BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
                mAdapter.notifyDataSetChanged();

               
            }
            if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(action)) {  //蓝牙扫描状态(SCAN_MODE)发生改变
                if (intent.getIntExtra("android.bluetooth.adapter.extra.SCAN_MODE", 0) == 23) {

                }
            }
            if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {  //绑定时候的广播
                BluetoothDevice remoteDevice = (BluetoothDevice) intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE");
                if (remoteDevice == null) {
                   showToast("no device");
                    return;
                }
                int status = intent.getIntExtra("android.bluetooth.device.extra.BOND_STATE", 0);
                if (status == 12) {
                   showToast("配对完成 " + remoteDevice.getName());
                    blueToothUtils.searchDevices();
                    showToast("刷新列表中 ");
                } else if (status == 11) {
                  showToast("正在配对 " + remoteDevice.getName());
                } else if (status == 10) {
                   showToast("配对失败 " + remoteDevice.getName());
                }
            }
        }
    };

//设置要监听的广播。
void initView(){
 
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
mContext.registerReceiver(mReceiver, filter);
}
 

上面的设置完成以后

编写一个蓝牙工具类进行使用。方便以后的开发。

在一开始。网上找了一些蓝牙的操作工具类。但是多多少少都有写瑕疵。

大多数都是2个手机通信。无法和蓝牙单片机模块通信。

具体的蓝牙操作类如下,这个工具类都是我在网上的大多数工具类中攒在一起的。里面有些方法也没用。我也就不删了。在接收数据的时候。如果是单片机发过来的话,数据会接收不完全。这里,将原来类方法更改了一下。、大家在接收数据时,尽量选择一个用不到的数字或者字母等,来当做结束位。进行判断、工具类里面的注释基本都有。

在网上找资料时,发现2个工具类,一个如下,看着比较简单,大家容易懂,还有一个。都是英文,后面翻译了一下,也放在文章最后吧。其实思路都一样。喜欢那个,用那个

工具类如下:

public class BlueToothUtils {
    private static final String TAG = "BlueToothUtils";
    private Context mContext;
    public static BlueToothUtils sInstance;
    private BluetoothAdapter mBA;
    private SharedPreferences sp;
    // UUID.randomUUID()随机获取UUID
    private final UUID MY_UUID = UUID
            .fromString("00001101-0000-1000-8000-00805F9B34FB");
    // 连接对象的名称
    private final String NAME = "Chaoba";

    // 这里本身即是服务端也是客户端,需要如下类
    private BluetoothSocket mSocket;
    private BluetoothDevice mOldDevice;
    private BluetoothDevice mCurDevice;
    // 输出流_客户端需要往服务端输出
    private OutputStream os;
    private InputStream inputStream;
    //线程类的实例
    private AcceptThread ac;
    private Handler mhandler;
    private Handler handler2;

    private BlueToothUtils.Readtask readtask;

    public static synchronized BlueToothUtils getInstance() {
        if (sInstance == null) {
            sInstance = new BlueToothUtils();
        }
        return sInstance;
    }

    public BlueToothUtils() {
        mBA = BluetoothAdapter.getDefaultAdapter();
        ac = new AcceptThread();
    }

    public void setContext(Context context) {
        this.mContext = context;
    }

    public void setHandler(Handler handler){
        this.mhandler=handler;
    }
    public void setHandler2(Handler handler2){
        this.handler2=handler2;
    }
    public BluetoothAdapter getBA() {
        return mBA;
    }

    public AcceptThread getAc() {
        return ac;
    }

    public BluetoothDevice getCurDevice() {
        return mCurDevice;
    }

    /**
     * 判断是否打开蓝牙
     *
     * @return
     */
    public boolean isEnabled() {
        if (mBA.isEnabled()) {
            return true;
        }
        return false;
    }

    /**
     * 搜索设备
     */
    public void searchDevices() {
        // 判断是否在搜索,如果在搜索,就取消搜索
        if (mBA.isDiscovering()) {
            mBA.cancelDiscovery();
        }
        // 开始搜索
        mBA.startDiscovery();
        Log.e(TAG, "正在搜索...");
    }

    /**
     * 获取已经配对的设备
     *
     * @return
     */
    public List<BluetoothDevice> getBondedDevices() {
        List<BluetoothDevice> devices = new ArrayList<>();
        Set<BluetoothDevice> pairedDevices = mBA.getBondedDevices();
        // 判断是否有配对过的设备
        if (pairedDevices.size() > 0) {
            for (BluetoothDevice device : pairedDevices) {
                devices.add(device);
                Log.e(TAG, "BondedDevice:" + device.getName());
            }
        }
        return devices;
    }

    /**
     * 与设备配对
     *
     * @param device
     */
    public void createBond(BluetoothDevice device) {
        try {
            Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
            createBondMethod.invoke(device);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 与设备解除配对
     *
     * @param device
     */
    public void removeBond(BluetoothDevice device) {
        try {
            Method removeBondMethod = device.getClass().getMethod("removeBond");
            removeBondMethod.invoke(device);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * @param device
     * @param str  设置PIN码
     * @return
     */
    public boolean setPin(BluetoothDevice device, String str) {
        try {
            Method removeBondMethod = device.getClass().getDeclaredMethod("setPin",
                    new Class[]{byte[].class});
            Boolean returnValue = (Boolean) removeBondMethod.invoke(device,
                    new Object[]{str.getBytes()});
            Log.e("returnValue", "" + returnValue);
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 取消用户输入
     */
    public boolean cancelPairingUserInput(BluetoothDevice device) {
        Boolean returnValue = false;
        try {
            Method createBondMethod = device.getClass().getMethod("cancelPairingUserInput");
            returnValue = (Boolean) createBondMethod.invoke(device);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        // cancelBondProcess()
        return returnValue.booleanValue();
    }

    /**
     * 取消配对
     */
    public boolean cancelBondProcess(BluetoothDevice device) {
        Boolean returnValue = null;
        try {
            Method createBondMethod = device.getClass().getMethod("cancelBondProcess");
            returnValue = (Boolean) createBondMethod.invoke(device);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return returnValue.booleanValue();
    }

    /**
     * @param strAddr
     * @param strPsw
     * @return
     */
    public boolean pair(String strAddr, String strPsw) {
        boolean result = false;
        mBA.cancelDiscovery();

        if (!mBA.isEnabled()) {
            mBA.enable();
        }

        if (!BluetoothAdapter.checkBluetoothAddress(strAddr)) { // 检查蓝牙地址是否有效
            Log.d("mylog", "devAdd un effient!");
        }

        BluetoothDevice device = mBA.getRemoteDevice(strAddr);
        if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
            Log.d("mylog", "NOT BOND_BONDED");
            try {
                setPin(device, strPsw); // 手机和蓝牙采集器配对
                createBond(device);
                result = true;
            } catch (Exception e) {
                Log.d("mylog", "setPiN failed!");
                e.printStackTrace();
            } //

        } else {
            Log.d("mylog", "HAS BOND_BONDED");
            try {
                createBond(device);
                setPin(device, strPsw); // 手机和蓝牙采集器配对
                createBond(device);
                result = true;
            } catch (Exception e) {
                Log.d("mylog", "setPiN failed!");
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 获取device.getClass()这个类中的所有Method
     *
     * @param clsShow
     */
    public void printAllInform(Class clsShow) {
        try {
            // 取得所有方法
            Method[] hideMethod = clsShow.getMethods();
            int i = 0;
            for (; i < hideMethod.length; i++) {
                Log.e("method name", hideMethod[i].getName() + ";and the i is:" + i);
            }
            // 取得所有常量
            Field[] allFields = clsShow.getFields();
            for (i = 0; i < allFields.length; i++) {
                Log.e("Field name", allFields[i].getName());
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 打开蓝牙
     */
    public void openBlueTooth() {
        if (!mBA.isEnabled()) {
            // 弹出对话框提示用户是后打开
            /*Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, 1);*/
            // 不做提示,强行打开
            mBA.enable();
            showToast("打开蓝牙");
        } else {
            showToast("蓝牙已打开");
        }
    }

    /**
     * 关闭蓝牙
     */
    public void closeBlueTooth() {
        mBA.disable();
        showToast("关闭蓝牙");
    }

    /**
     * 弹出Toast窗口
     *
     * @param message
     */
    private void showToast(String message) {
        if (mContext != null) {
            Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
        } else {
            Log.e(TAG, "message:" + message);
        }
    }

    /**
     * 主动连接蓝牙
     *
     * @param device
     */
    public void connectDevice(BluetoothDevice device) {
        // 判断是否在搜索,如果在搜索,就取消搜索
        if (mBA.isDiscovering()) {
            mBA.cancelDiscovery();
        }
        try {
            // 获得远程设备
            if (mCurDevice == null || mCurDevice != mOldDevice) {
                mCurDevice = mBA.getRemoteDevice(device.getAddress());
                mOldDevice = mCurDevice;
                Log.e(TAG, "device:" + mCurDevice);
//                sp.edit().putString("device","device:"+mCurDevice).commit();
                mSocket = mCurDevice.createRfcommSocketToServiceRecord(MY_UUID);
                // 连接
//                mSocket.connect();
//                boolean connected = mSocket.isConnected();
//                if (connected){
//
//                    // 获得输出流
//                    os = mSocket.getOutputStream();
//                    inputStream=mSocket.getInputStream();
//                    while (true){
//                        readDataFromServer();
//                    }
//                }


                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            mSocket.connect();
                            os = mSocket.getOutputStream();
                            mhandler.sendEmptyMessage(10);
                            readtask = new BlueToothUtils.Readtask();  //连接成功后开启读取数据的线程
                            readtask.start();
                            mContext.getSharedPreferences("demo",Context.MODE_PRIVATE).edit().putString("device","已连接").commit();
                        } catch (IOException e) {
                            mhandler.sendEmptyMessage(11);
                            e.printStackTrace();
                        }
                    }
                }).start();

            }
            // 如果成功获得输出流

        } catch (IOException e) {
            e.printStackTrace();
            mhandler.sendEmptyMessage(11);

        }





    }


    public static final int CONNECT_FAILED=1;
    public static final int CONNECT_SUCCESS=5;
    public  static final int READ_FAILED=2;
    public static final int WRITE_FAILED=3;
    public  static final int DATA=4;
    private boolean isConnect=false;

    /**
     *开辟连接线程任务
     */
    public void connectTow(final BluetoothDevice device){
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                BluetoothSocket tmp = null;
                Method method;
                try {
                    method = device.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
                    tmp = (BluetoothSocket) method.invoke(device, 1);
                } catch (Exception e) {
//                    setState(CONNECT_FAILED);
                    Log.e("TAG", e.toString());
                }
                mSocket = tmp;
                try {
                    mSocket.connect();
                    isConnect = true;
//                    setState(CONNECT_SUCCESS);
                   readtask = new BlueToothUtils.Readtask();  //连接成功后开启读取数据的线程
                    readtask.start();
                } catch (Exception e) {

                    Log.e("TAG", e.toString());
                }
            }
        });
        new Thread(thread).start();
    }
    /**
     *开辟线程读任务
     */
    public class Readtask extends Thread{
        @Override
        public void run(){
//            byte[] buffer = new byte[9999];
//            int bytes;
//            InputStream inputStream ;   //建立输入流读取数据
//            while (true) {
//                try {
//                    inputStream = mSocket.getInputStream();
//                    if ((bytes = inputStream.read(buffer)) > 0) {
//                        byte[] buf_data= new byte[bytes];
//                        for (int i = 0; i < bytes; i++) {
//                            buf_data[i] = buffer[i];
//                        }
//                        String s = new String(buf_data);
//
//                        setState(1,s);
//
//                    }
//                } catch (IOException e) {
//
//                    Log.e("TAG", e.toString());
//                    break;
//                }
//            }



            byte[] tt = new byte[100];
            try {
                int ch;
                inputStream = mSocket.getInputStream();

                int i;
                while (true) {
                    synchronized (this) {
                     i=0;
                        while ((ch=inputStream.read())!='#'){
                            if (ch!=-1){
                                tt[i]=(byte)ch;
                                i++;
                            }


                        }

                        if (tt.length > 0) {
                            String s = new String(tt, "GBK");
                        System.out.println(s);
                            setState(1,s);
                        }else {
                            System.out.println(111);
                        }
                    }
                }


            } catch (IOException e) {
                e.printStackTrace();
                Message message=new Message();
                message.obj="连接已断开,请重新连接";
                handler.sendMessage(message);
            }



            if (mSocket != null) {
                try {
                    mSocket.close();
                } catch (IOException e) {
                    Log.e("TAG", e.toString());
                }
            }
        }
        public void cancel() {
            try {
                mSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }
    /**
     *开辟线程写任务
     */
    public  class WriteTask extends Thread{
        private String srt;
        public  WriteTask(String str){
            this.srt=str;
        }
        @Override
        public void run(){
            OutputStream outputStream=null;
            byte[] st=srt.getBytes();
            try{
                outputStream=mSocket.getOutputStream();
                outputStream.write(st);
            }catch (Exception e){

                e.printStackTrace();
            }
        }

    }


    private void setState(int mes,String str){
        Message message=new Message();
        message.what=mes;
        message.obj=str;
        handler2.sendMessage(message);

    }







    /**
     * 传输数据
     *
     * @param message
     */
    public void write(String message) {
        try {
            if (os != null) {
                os.write(message.getBytes("GBK"));
            }
            Log.e(TAG, "write:" + message);
            handler2.sendEmptyMessage(3);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    /**
     * Stop all threads
     */
    public synchronized void stops() {

        if (readtask != null) {readtask.cancel(); readtask = null;}
            Message message=new Message();
        message.obj="关闭所有线程";
        handler.sendMessage(message);
    }


    public void initSP(){
        sp=mContext.getSharedPreferences("demo",Context.MODE_PRIVATE);
    }

    // 服务端,需要监听客户端的线程类
    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            showToast(String.valueOf(msg.obj));
            Log.e(TAG, "服务端:" + msg.obj);
            super.handleMessage(msg);
        }
    };


    // 线程服务类
    public class AcceptThread extends Thread {
        private BluetoothServerSocket serverSocket;
        private BluetoothSocket socket;
        // 输入 输出流
        private OutputStream os;
        private InputStream is;

        public AcceptThread() {
            try {
                serverSocket = mBA.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {
            // 截获客户端的蓝牙消息
            try {
                socket = serverSocket.accept(); // 如果阻塞了,就会一直停留在这里
                is = socket.getInputStream();
                os = socket.getOutputStream();
                while (true) {
                    synchronized (this) {
                        byte[] tt = new byte[is.available()];
                        if (tt.length > 0) {
                            is.read(tt, 0, tt.length);
                            Message msg = new Message();
                            msg.obj = new String(tt, "GBK");
                            Log.e(TAG, "客户端:" + msg.obj);
                            handler.sendMessage(msg);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}

 

第二个工具类

/**
 *建立和管理与其他设备的BT连接。

 *它有一个线程来侦听传入的连接,一个线程

 *用于与设备连接,以及用于执行数据的线程

 *连接时的传输。
 */
public class BTService {

    // 表示当前连接状态的常量
    public static final int STATE_NONE = 0;         // 我们什么也不做
    public static final int STATE_LISTEN = 1;       // 现在监听传入的连接
    public static final int STATE_CONNECTING = 2;   // 现在启动输出连接
    public static final int STATE_CONNECTED = 3;    // 现在连接到远程设备
    private static final String TAG = "BTConnection";
    // 创建服务器套接字时SDP记录的名称
    private static final String MY_NAME = "BTConnection";

//引用:[来自Android SDK文档]

//如果您正在连接蓝牙串行板,则尝试使用众所周知的

//SPP UUID 000 000 110~00 0 0 0 0 0 0 0 0 0 0 0 5 5 F9B34 FB。

//    但是,如果您正在连接Android对等体,那么请生成您自己的
//
///独特的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 mConnThread;
    private ConnectedThread mConnectedThread;
    private int mState;
    private final Context mContext;
    public static BTService sInstance;
    /**
     * Constructor. Prepares a new BT session.
     *
     * @param handler A Handler to send message back to the UI Activity.
     *                构造函数。准备新的BT会话。 * * @param handler一个Handler,用于将消息发送回UI Activity。
     */
    public BTService(Context context, Handler handler) {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mState = STATE_NONE;
        mHandler = handler;
        mContext = context;
    }



    /**
     * 判断是否打开蓝牙
     *
     * @return
     */
    public boolean isEnabled() {
        if (mAdapter.isEnabled()) {
            return true;
        }
        return false;
    }

    /**
     * 搜索设备
     */
    public void searchDevices() {
        // 判断是否在搜索,如果在搜索,就取消搜索
        if (mAdapter.isDiscovering()) {
            mAdapter.cancelDiscovery();
        }
        // 开始搜索
        mAdapter.startDiscovery();
        Log.e(TAG, "正在搜索...");
    }

    /**
     * 获取已经配对的设备
     *
     * @return
     */
    public List<BluetoothDevice> getBondedDevices() {
        List<BluetoothDevice> devices = new ArrayList<>();
        Set<BluetoothDevice> pairedDevices = mAdapter.getBondedDevices();
        // 判断是否有配对过的设备
        if (pairedDevices.size() > 0) {
            for (BluetoothDevice device : pairedDevices) {
                devices.add(device);
                Log.e(TAG, "BondedDevice:" + device.getName());
            }
        }
        return devices;
    }

    /**
     * 与设备配对
     *
     * @param device
     */
    public void createBond(BluetoothDevice device) {
        try {
            Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
            createBondMethod.invoke(device);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 与设备解除配对
     *
     * @param device
     */
    public void removeBond(BluetoothDevice device) {
        try {
            Method removeBondMethod = device.getClass().getMethod("removeBond");
            removeBondMethod.invoke(device);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * @param device
     * @param str  设置PIN码
     * @return
     */
    public boolean setPin(BluetoothDevice device, String str) {
        try {
            Method removeBondMethod = device.getClass().getDeclaredMethod("setPin",
                    new Class[]{byte[].class});
            Boolean returnValue = (Boolean) removeBondMethod.invoke(device,
                    new Object[]{str.getBytes()});
            Log.e("returnValue", "" + returnValue);
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 取消用户输入
     */
    public boolean cancelPairingUserInput(BluetoothDevice device) {
        Boolean returnValue = false;
        try {
            Method createBondMethod = device.getClass().getMethod("cancelPairingUserInput");
            returnValue = (Boolean) createBondMethod.invoke(device);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        // cancelBondProcess()
        return returnValue.booleanValue();
    }

    /**
     * 取消配对
     */
    public boolean cancelBondProcess(BluetoothDevice device) {
        Boolean returnValue = null;
        try {
            Method createBondMethod = device.getClass().getMethod("cancelBondProcess");
            returnValue = (Boolean) createBondMethod.invoke(device);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return returnValue.booleanValue();
    }

    /**
     * @param strAddr
     * @param strPsw
     * @return
     */
    public boolean pair(String strAddr, String strPsw) {
        boolean result = false;
        mAdapter.cancelDiscovery();

        if (!mAdapter.isEnabled()) {
            mAdapter.enable();
        }

        if (!BluetoothAdapter.checkBluetoothAddress(strAddr)) { // 检查蓝牙地址是否有效
            Log.d("mylog", "devAdd un effient!");
        }

        BluetoothDevice device = mAdapter.getRemoteDevice(strAddr);
        if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
            Log.d("mylog", "NOT BOND_BONDED");
            try {
                setPin(device, strPsw); // 手机和蓝牙采集器配对
                createBond(device);
                result = true;
            } catch (Exception e) {
                Log.d("mylog", "setPiN failed!");
                e.printStackTrace();
            } //

        } else {
            Log.d("mylog", "HAS BOND_BONDED");
            try {
                createBond(device);
                setPin(device, strPsw); // 手机和蓝牙采集器配对
                createBond(device);
                result = true;
            } catch (Exception e) {
                Log.d("mylog", "setPiN failed!");
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 获取device.getClass()这个类中的所有Method
     *
     * @param clsShow
     */
    public void printAllInform(Class clsShow) {
        try {
            // 取得所有方法
            Method[] hideMethod = clsShow.getMethods();
            int i = 0;
            for (; i < hideMethod.length; i++) {
                Log.e("method name", hideMethod[i].getName() + ";and the i is:" + i);
            }
            // 取得所有常量
            Field[] allFields = clsShow.getFields();
            for (i = 0; i < allFields.length; i++) {
                Log.e("Field name", allFields[i].getName());
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 打开蓝牙
     */
    public void openBlueTooth() {
        if (!mAdapter.isEnabled()) {
            // 弹出对话框提示用户是后打开
            /*Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, 1);*/
            // 不做提示,强行打开
            mAdapter.enable();
            showToast("打开蓝牙");
        } else {
            showToast("蓝牙已打开");
        }
    }

    /**
     * 关闭蓝牙
     */
    public void closeBlueTooth() {
        mAdapter.disable();
        showToast("关闭蓝牙");
    }

    /**
     * 弹出Toast窗口
     *
     * @param message
     */
    private void showToast(String message) {
        if (mContext != null) {
            Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
        } else {
            Log.e(TAG, "message:" + message);
        }
    }





    public static synchronized BTService getInstance(Context context, Handler handler) {
        if (sInstance == null) {
            sInstance = new BTService(context,handler);
        }
        return sInstance;
    }


    public BluetoothAdapter getBA() {
        return mAdapter;
    }
    /**
     * Return the current connection state.
     *
     * @return mState current connection state
     * 返回当前连接状态。 * * @return mState当前连接状态
     */
    public synchronized int getState() {
        return mState;
    }

    /**
     * Set the current state of BT connection.
     *
     * @param state An integer defining the current connection state
     *
     *    *设置BT连接的当前状态。 * * @param state定义当前连接状态的整数
     */
    private synchronized void setState(int state) {
        Log.d(TAG, "setState() " + mState + "-> " + state);
        mState = state;

        // Give the new state to the Handler so the UI Activity can update
        //将新状态提供给处理程序,以便UI活动可以更新
        mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
    }

    /**
     * Start the BT service. Specifically start AcceptThread to begin a
     * session in listening (server) mode. Called by the Activity onResume()
     * *启动BT服务。具体来说,启动AcceptThread以在侦听(服务器)模式下开始*会话。由Activity onResume()调用
     */
    public synchronized void start() {
        Log.d(TAG, "start");

        // Cancel any thread attempting to make a connection
        //取消任何尝试建立连接的线程
        if (mConnThread != null) {
            mConnThread.cancel();
            mConnThread = null;
        }

        // Cancel any thread currently running a connection
        //取消当前正在运行连接的任何线程
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }

        setState(STATE_LISTEN);

        // Start the thread to listen on a BluetoothServerSocket
        //启动线程以侦听BluetoothServerSocket
        if (mAcceptThread == null) {
            mAcceptThread = new AcceptThread();
            mAcceptThread.start();
        }
    }

    /**
     * Start the ConnThread to initiate a connection to a remote device.
     *启动ConnThread以启动与远程设备的连接。
     * @param device The BluetoothDevice to connect
     */
    public synchronized void connect(BluetoothDevice device) {
        Log.d(TAG, "Connect to: " + device);

        // Cancel any thread attempting to make a connection
        //取消任何尝试建立连接的线程
        if (mState == STATE_CONNECTING) {
            if (mConnThread != null) {
                mConnThread.cancel();
                mConnThread = null;
            }
        }
        // Cancel any thread currently running a connection
        //取消当前正在运行连接的任何线程
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        // Start the thread to connect with the given device
        //启动线程以连接给定设备
        mConnThread = new ConnectThread(device);
        mConnThread.start();
        setState(STATE_CONNECTING);
    }

    /**
     * 启动ConnectedThread以开始管理蓝牙连接。
     *
     * @param socket 连接所在的BluetoothSocket
     * @param device 已连接的BluetoothDevice
     */
    public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
        Log.d(TAG, "Connected");

        // 取消完成连接的线程
        if (mConnThread != null) {
            mConnThread.cancel();
            mConnThread = null;
        }
       //取消当前正在运行连接的任何线程
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
       //取消接受线程,因为我们只想连接到一个设备
        if (mAcceptThread != null) {
            mAcceptThread.cancel();
            mAcceptThread = null;
        }

      //启动线程来管理连接并执行传输
        mConnectedThread = new ConnectedThread(socket);
        mConnectedThread.start();

        // 将已连接设备的名称发送回UI活动
        Message msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();
        bundle.putString(Constants.DEVICE_NAME, device.getName());
        msg.setData(bundle);
        mHandler.sendMessage(msg);

        setState(STATE_CONNECTED);
    }


    /**
     * 停止所有线程。
     */
    public synchronized void stop() {
        Log.d(TAG, "stop");

        if (mConnThread != null) {
            mConnThread.cancel();
            mConnThread = null;
        }
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        if (mAcceptThread != null) {
            mAcceptThread.cancel();
            mAcceptThread = null;
        }
        setState(STATE_NONE);
    }

    /**
     * 以不同步的方式写入ConnectedThread。
     *
     * @param content 要写入的字节
     * @see
     */
    public void write(String content) {
     //创建临时对象
        ConnectedThread r;
      //同步ConnectedThread的副本
        synchronized (this) {
            if (mState != STATE_CONNECTED) {
                Log.d(TAG, "State: " + getState());
                return;
            }
            r = mConnectedThread;
        }
       //执行写入不同步
        r.write(content);
    }

    /**
     * 指示连接尝试失败并通知UI活动。
     */
    private void connectionError(String errMsg) {
        Log.e(TAG, "Connection Error:" + errMsg);
        // 将失败消息发送回活动
        Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(Constants.TOAST, errMsg);
        msg.setData(bundle);
        mHandler.sendMessage(msg);

        // 启动服务以重新启动侦听模式
        BTService.this.start();
    }


    /**
   *此线程在侦听传入连接时运行。它表现得很好
     *像服务器端客户端。它会一直运行,直到接受连接
     *(或直到取消)。
     */
    private class AcceptThread extends Thread {
        private final BluetoothServerSocket mmServerSocket;

        public AcceptThread() {
           //使用稍后分配给mmServerSocket的临时对象
            //因为mmServerSocket是最终的
            BluetoothServerSocket tmp = null;

            try {
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(MY_NAME, MY_UUID);
            } catch (IOException e) {
                Log.e(TAG, "套接字听不通", e);
            }
            mmServerSocket = tmp;
        }

        public void run() {
            Log.d(TAG, "套接字开始");

            BluetoothSocket socket = null;

            // Listen to the server socket if we're not connected
            while (mState != STATE_CONNECTED) {
                try {
                   //这是一个阻止调用,只会返回
                    //成功连接或异常
                    socket = mmServerSocket.accept();
                } catch (IOException e) {
                    Log.e(TAG, "套接字accept()失败", e);
                    break;
                }

            //如果接受了连接
                if (socket != null) {
                    synchronized (BTService.this) {
                        switch (mState) {
                            case STATE_LISTEN:
                            case STATE_CONNECTING:
                               //情况正常启动连接的线程。
                                connected(socket, socket.getRemoteDevice());
                                break;
                            case STATE_NONE:
                            case STATE_CONNECTED:
                             //未准备好或已连接。终止新套接字。
                                try {
                                    socket.close();
                                } catch (IOException e) {
                                    Log.e(TAG, "无法关闭不需要的套接字", e);
                                }
                                break;
                        }
                    }
                }
            }
        }

        public void cancel() {
            Log.d(TAG, "套接字取消");
            try {
                mmServerSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "服务器的套接字close()失败", e);
            }
        }
    }

    /***此线程在尝试进行传出连接时运行
     *带有设备。它直接通过;连接
     *成功或失败。
     */
    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        private ConnectThread(BluetoothDevice device) {
            mmDevice = device;
            BluetoothSocket tmp = null;

         //获取与之连接的BluetoothSocket
            //给出了BluetoothDevice
            try {
//                device.fetchUuidsWithSdp();
//                ParcelUuid[] uuids = device.getUuids();
//                for (ParcelUuid u : uuids) {
//                    Log.d(TAG, u.getUuid().toString());
//                }
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) {
                Log.e(TAG, "Socket create() failed", e);
            }
            mmSocket = tmp;
        }

        public void run() {
            try {
                mmSocket.connect();
            } catch (IOException e) {
                e.printStackTrace();
                try {
                    mmSocket.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                connectionError("连接失败");
                return;
            }

           //重置ConnectThread,因为我们已经完成了
            synchronized (BTService.this) {
                mConnThread = null;
            }

           //启动连接的线程
            connected(mmSocket, mmDevice);
        }

        public void cancel() {
            Log.d(TAG, "Socket cancel");
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "Socket close() of server failed", e);
            }
        }
    }

    /**
    *此线程在与远程设备连接期间运行。
     *它处理所有传入和传出传输。
     */
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        private ConnectedThread(BluetoothSocket socket) {
            Log.d(TAG, "create ConnectedThread");
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            //获取BluetoothSocket输入和输出流
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "temp sockets not created", e);
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
            Log.d(TAG, "BEGIN mConnectedThread");
            byte[] buffer = new byte[512];
            byte[] ret = null;

           //连接时继续收听inputStream
            while (true) {
                try {
                    //从InputStream中读取
                    int bytes = mmInStream.read(buffer);
                    Log.e(TAG, "length: " + bytes);

                    for (int i = 0; i < bytes; i++) {
                        if ((buffer[i] & 0xFF) == 255) {
                            ret = Arrays.copyOfRange(buffer, 0, i + 1);
                            break;
                        }
                    }
                    Log.e(TAG, "data: " + ret);
                   //将获取的字节发送到UI活动
                    mHandler.obtainMessage(Constants.MESSAGE_READ, -1, -1, ret).sendToTarget();
                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);
                    connectionError("连接失败");
                   //启动服务以重新启动侦听模式
                    BTService.this.start();
                    break;
                }
            }
        }

        /**
         * 写入已连接的OutStream。
         *
         * @param content The bytes to write
         */
        public void write(String content) {
            try {
                mmOutStream.write(content.getBytes());
                // 将发送的消息共享回UI活动
                mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, content).sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "E写入期间的xception", e);
            }
        }

        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "connect()的连接套接字失败", e);
            }
        }
    }

 

posted @ 2018-11-18 21:30  暮雪超霸  阅读(1925)  评论(0编辑  收藏  举报