zoukankan      html  css  js  c++  java
  • 安卓蓝牙操作+蓝牙工具类

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

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

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

    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);
                }
            }
        }
    一万年太久,只争朝夕!
  • 相关阅读:
    P3507 [POI2010]GRA-The Minima Game
    P2038 无线网络发射器选址
    2017.9.23清北第二场
    P3183 [HAOI2016]食物链
    2017.9.17校内noip模拟赛解题报告
    Day2代码
    P1328 生活大爆炸版石头剪刀布
    Fibinary Numbers
    Mac os 进行Android开发笔记(1)
    python中文注释及输出出错
  • 原文地址:https://www.cnblogs.com/chaoba/p/9979616.html
Copyright © 2011-2022 走看看