Android 蓝牙配对、连接和通信

效果
在这里插入图片描述

权限

	<uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

动态申请权限

public class ApplyPermission {

    public static void ApplyPermission(Context context) {
        ActivityCompat.requestPermissions((Activity) context, new String[]{
                Manifest.permission.BLUETOOTH,
                Manifest.permission.BLUETOOTH_ADMIN,
        }, 1);
    }
}

连接工具类

/**
 * @anthor GrainRain
 * @funcation 蓝牙连接工具类
 * @date 2019/11/7
 */
public class Util {

    //存放蓝牙设备名列表
    private static ArrayList<String> deviceNameList = new ArrayList<>();
    //存放蓝牙设备mac地址列表
    private static ArrayList<String> deviceMacList = new ArrayList<>();
    //存放蓝牙设备名和地址 用于显示
    private static ArrayList<String> deviceMsgList = new ArrayList<>();
    //存放已配对蓝牙列表
    private static ArrayList<String> pairedDeviceNameList = new ArrayList<>();

    private static Context context;
    private static BluetoothDevice btDevice;
    private static ArrayList<BluetoothDevice> btDeviceList = new ArrayList<>();
    private static OnConnectListener onConnectListener;

    private static final String[] items = new String[100];
    private static ArrayAdapter<String> adapter = null;
    private static BluetoothAdapter blueadapter;

    //这条是蓝牙串口通用的UUID,不要更改
    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    private static BluetoothSocket btSocket = null;
    private static OutputStream outStream = null;
    private static InputStream inStream = null;
    private static int deviceMatchingNum = 0;
    private static boolean deviceMatching = false;

    private static ReceiveThread rThread = null;  //数据接收线程

    public Util() {
        for(int i = 0; i < items.length; i++) {
            items[i] = "";
        }
    }

    public void get(Context context, OnConnectListener listener) {
        setContext(context);
        showListDialog();
        blueadapter = BluetoothAdapter.getDefaultAdapter();

        //判断蓝牙是否打开
        if(!blueadapter.isEnabled()) {
//            blueadapter.enable();
        } else {
            getContext().registerReceiver(bluetoothReceiver, intentFilter);//用BroadcastReceiver 来取得结果
            doDiscovry();
        }

        setOnConnectListener(listener);
        listener.onConnectSuccess(null);
        listener.onConnectFailed(null);
    }

    static IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);//注册广播接收信号
    private static final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            String action = intent.getAction(); //得到action

            //创建一个蓝牙device对象 从Intent中获取设备对象
            btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            btDeviceList.add(btDevice);

            //获取已配对蓝牙列表
//            Set<BluetoothDevice> devices = blueadapter.getBondedDevices();
//            for (BluetoothDevice bluetoothDevice : devices) {
//                pairedDeviceNameList.add(bluetoothDevice.getName());
//            }

            //发现设备
            if(BluetoothDevice.ACTION_FOUND.equals(action)){

                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                deviceMsgList.add(device.getName() + " " + device.getAddress());//将搜索到的蓝牙名称和地址添加到列表
                deviceNameList.add(device.getName());       //将搜索到的蓝牙名称添加到列表
                deviceMacList.add(device.getAddress());     //将搜索到的蓝牙地址添加到列表

                Log.w("-----------------", deviceMsgList.get(deviceMsgList.size()-1));
                items[deviceMsgList.size()-1] = deviceMsgList.get(deviceMsgList.size()-1);
                adapter.notifyDataSetChanged();
            }
        }
    };

    private static void doDiscovry() {
        if (blueadapter.isDiscovering()) {
            //判断蓝牙是否正在扫描,如果是调用取消扫描方法;如果不是,则开始扫描
            blueadapter.cancelDiscovery();
        } else
            blueadapter.startDiscovery();
    }

    //搜索到的蓝牙列表
    private void showListDialog() {
        final AlertDialog.Builder listDialog = new AlertDialog.Builder(context);
        adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1, items);

        listDialog.setAdapter(adapter, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {

                for(int j = 0; j < btDeviceList.size(); j++) {
                    if(btDeviceList.get(j).getAddress().equals(btDeviceList.get(i).getAddress())) {
                        deviceMatching = true;
                        deviceMatchingNum = j;
                    }
                }

                //连接配对
                if(deviceMatching) {
                    //HC-05设备如果有多个,第一个搜到的那个会被尝试。
                    if (btDeviceList.get(deviceMatchingNum).getBondState() == BluetoothDevice.BOND_NONE) {
                        //未配对 进行配对
                        try {
                            //通过工具类ClsUtils,调用createBond方法
                            PairUtils.createBond(btDeviceList.get(deviceMatchingNum).getClass(), btDeviceList.get(deviceMatchingNum));
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    } else {
                        //已配对 进行连接
                        //mac 要连接的目标蓝牙设备MAC地址
                        new ConnectTask().execute(deviceMacList.get(deviceMatchingNum));
                    }
                }
            }
        });

        listDialog.setPositiveButton("返回", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt) {
                listDialog.create();
            }
        });
        listDialog.show();
    }

    //连接蓝牙设备的异步任务
    static class ConnectTask extends AsyncTask<String,String,String> {
        @Override
        protected String doInBackground(String... params) {
            // TODO Auto-generated method stub
            BluetoothDevice device = blueadapter.getRemoteDevice(params[0]);
            try {
                btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
                btSocket.connect();
                Log.e("error", "ON RESUME: BT connection established, data transfer link open.");
            } catch (IOException e) {
                try {

                    //将异常信息传递给回调接口
                    if(getOnConnectListener() != null) {
                        getOnConnectListener().onConnectFailed(e);
                    }
                    btSocket.close();
                    return "Socket 创建失败";
                } catch (IOException e2) {

                    //将异常信息传递给回调接口
                    if(getOnConnectListener() != null) {
                        getOnConnectListener().onConnectFailed(e2);
                    }
                    Log .e("error","ON RESUME: Unable to close socket during connection failure", e2);
                    return "Socket 关闭失败";
                }
            }
            //取消搜索
            blueadapter.cancelDiscovery();
            try {
                outStream = btSocket.getOutputStream();
            } catch (IOException e) {

                //将异常信息传递给回调接口
                if(getOnConnectListener() != null) {
                    getOnConnectListener().onConnectFailed(e);
                }
                Log.e("error", "ON RESUME: Output stream creation failed.", e);
                return "Socket 流创建失败";
            }
            return "蓝牙连接正常,Socket 创建成功";
        }

        @Override    //这个方法是在主线程中运行的,所以可以更新界面
        protected void onPostExecute(String result) {
            // TODO Auto-generated method stub
            //连接成功则启动监听
            rThread = new ReceiveThread();
            rThread.start();
            Log.e("Bluetooth", "连接状态:" + result);

            super.onPostExecute(result);
        }
    }

    //从蓝牙接收信息的线程
    static class ReceiveThread extends Thread {
        @Override
        public void run() {
            while(btSocket != null ) {

                //定义一个存储空间buff
                byte[] buff = new byte[1024];
                try {
                    inStream = btSocket.getInputStream();
                    System.out.println("waitting for instream");

                    if(inStream != null) {
                        inStream.read(buff); //读取数据存储在buff数组中
                    }
                    processBuffer(buff,1024);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        public void processBuffer(byte[] buff,int size) {
            int length = 0;
            for(int i = 0; i < size; i++) {
                if(buff[i] > '\0') {
                    length++;
                } else {
                    break;
                }
            }

            //newbuff字节数组,用于存放真正接收到的数据
            byte[] newbuff = new byte[length];
            int[] receiveData = new int[length];

            for(int j = 0; j < length; j++) {
                newbuff[j] = buff[j];
                receiveData[j] = buff[j] & 0xff;
            }

            Log.w("收到数据: ", Arrays.toString(receiveData));
            //回调
            if(getOnConnectListener() != null) {
                getOnConnectListener().onConnectSuccess(receiveData);
            }
        }
    }

    //发送String数据到蓝牙设备的异步任务
    static class SendInfoTask extends AsyncTask<String,String,String> {

        @Override
        protected void onPostExecute(String result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
            Log.e("Bluetooth", "连接状态:" + result);
        }

        @Override
        protected String doInBackground(String... arg0) {

            // TODO Auto-generated method stub
            if(btSocket == null) {

                new ConnectTask().execute(deviceMacList.get(deviceMatchingNum));

                return "还没有创建连接";
            }

            if(arg0[0].length()>0) {
                //不是空白串
                //String target=arg0[0];
                byte[] msgBuffer = arg0[0].getBytes();
                try {
                    if(outStream != null) {
                        //  将msgBuffer中的数据写到outStream对象中
                        outStream.write(msgBuffer);
                    }
                } catch (IOException e) {
                    Log.e("error", "ON RESUME: Exception during write.", e);
                    return "发送失败";
                }
            }
            return "发送成功";
        }
    }

    //发送byte数据到蓝牙设备的异步任务
       /*
     static class SendInfoTask extends AsyncTask<byte[], String, String> {
        @Override
        protected String doInBackground(byte[]... bytes) {

            try {
                outStream.write(bytes[0]);
            } catch (IOException e) {
                e.printStackTrace();
            }
        return null;
    }

    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
    }
}
*/


    //回调接口
    public interface OnConnectListener{
        //连接成功
        void onConnectSuccess(int[] msg);
        //连接异常信息
        void onConnectFailed(Exception e);
    }

    public static OnConnectListener getOnConnectListener() {
        return onConnectListener;
    }

    public void setOnConnectListener(OnConnectListener onConnectListener) {
        this.onConnectListener = onConnectListener;
    }

    public static Context getContext() {
        return context;
    }

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

配对工具类

/**
 * @anthor GrainRain
 * @funcation 配对工具类
 * @date 2019/10/25
 */
public class PairUtils {

    /**
     * 与设备配对 参考源码:platform/packages/apps/Settings.git
     * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
     */

    static public boolean createBond(Class btClass, BluetoothDevice btDevice) throws Exception {

        Method createBondMethod = btClass.getMethod("createBond");
        Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
        return returnValue.booleanValue();
    }

    /**
     * 与设备解除配对 参考源码:platform/packages/apps/Settings.git
     * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
     */
    static public boolean removeBond(Class<?> btClass, BluetoothDevice btDevice) throws Exception {

        Method removeBondMethod = btClass.getMethod("removeBond");
        Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);
        return returnValue.booleanValue();
    }

    static public boolean setPin(Class<? extends BluetoothDevice> btClass, BluetoothDevice btDevice,
                                 String str) throws Exception {
        try {
            Method removeBondMethod = btClass.getDeclaredMethod("setPin", byte[].class);
            Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice,
                    new Object[]{ str.getBytes() });

            Log.e("returnValue", "" + returnValue);
        } catch (SecurityException e) {

            // throw new RuntimeException(e.getMessage());
            e.printStackTrace();
        } catch (IllegalArgumentException e) {

            // throw new RuntimeException(e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return true;
    }

    // 取消用户输入
    static public boolean cancelPairingUserInput(Class<?> btClass, BluetoothDevice device)
            throws Exception {

        Method createBondMethod = btClass.getMethod("cancelPairingUserInput");
//        cancelBondProcess(btClass, device);
        Boolean returnValue = (Boolean) createBondMethod.invoke(device);
        return returnValue.booleanValue();
    }

    // 取消配对
    static public boolean cancelBondProcess(Class<?> btClass, BluetoothDevice device) throws Exception {

        Method createBondMethod = btClass.getMethod("cancelBondProcess");
        Boolean returnValue = (Boolean) createBondMethod.invoke(device);
        return returnValue.booleanValue();
    }

    //确认配对
    static public void setPairingConfirmation(Class<?> btClass,BluetoothDevice device,boolean isConfirm)throws Exception {

        Method setPairingConfirmation = btClass.getDeclaredMethod("setPairingConfirmation",boolean.class);
        setPairingConfirmation.invoke(device,isConfirm);
    }

    /**
     *
     * @param clsShow
     */
    static 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) {

            // throw new RuntimeException(e.getMessage());
            e.printStackTrace();
        } catch (IllegalArgumentException e) {

            // throw new RuntimeException(e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

使用 activity

	//打开蓝牙
	if(!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
       BluetoothAdapter.getDefaultAdapter().enable();
    }

通过回调接收信息

    new Util().get(BlueAct.this, new Util.OnConnectListener() {
        @Override
        public void onConnectSuccess(int[] msg) {

        }

        @Override
        public void onConnectFailed(Exception e) {

        }
    });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值