蓝牙实现数据传递

实现数据传递需要做些什么?需要用到什么?怎么才能让数据传递到另一端?
以下几个类有什么作用,作用域在哪?
1、BluetoothAdapter
2、BluetoothDevice
3、BluetoothSocket
4、BluetoothServerScoket

  • 客户端实现了的功能
    1. 控制蓝牙的开关
    2. 扫描发现附近蓝牙设备
    3. 配对蓝牙
    4. 取消正在配对
    5. 解绑已经配对
    6. 发送数据到服务端(demo传递100随机数)
    蓝牙实现数据传递
  • 服务端主要实现功能
  • 接收客户端传递过来的信息(接收传递来的100内随机数)
    蓝牙实现数据传递
  • BluetoothAdapter介绍以及作用
    BluetoothAdapter代表了移动设备的本地的蓝牙适配器, 通过该蓝牙适配器可以对蓝牙进行基本操作, 例如 : 启动设备发现(startDiscovery), 获取已配对设备(getBoundedDevices), 通过mac蓝牙地址获取蓝牙设备(getRemoteDevice), 从其它设备创建一个监听连接(listenUsingRfcommWithServiceRecord);
    (1)开关状态值
    蓝牙关闭 : int STATE_OFF , 值为10, 蓝牙模块处于关闭状态;
    蓝牙打开中 : int STATE_TURNING_ON , 值为11, 蓝牙模块正在打开;
    蓝牙开启 : int STATE_ON , 值为12, 蓝牙模块处于开启状态;
    蓝牙开启中 : int STATE_TURNING_OFF , 值为13, 蓝牙模块正在关闭;
    蓝牙开关状态顺序 : STATE_OFF --> STATE_TURNING_ON --> STATE_ON --> STATE_TURNING_OFF --> STATE_OFF;
    (2)扫描状态值
    无功能状态 : int SCAN_MODE_NONE , 值为20, 查询扫描和页面扫描都失效, 该状态下蓝牙模块既不能扫描其它设备, 也不可见;
    扫描状态 : int SCAN_MODE_CONNECTABLE , 值为21, 查询扫描失效, 页面扫描有效, 该状态下蓝牙模块可以扫描其它设备, 从可见性来说只对已配对的蓝牙设备可见, 只有配对的设备才能主动连接本设备;
    可见状态 : int SCAN_MODE_CONNECTABLE_DISCOVERABLE, 值为23, 查询扫描和页面扫描都有效;
//静态方法可以获取该适配器对象
BluetoothAdapter BluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
  • BluetoothDevice
    BluetoothDevice对象代表了一个远程的蓝牙设备, 通过这个类可以查询远程设备的物理地址, 名称, 连接状态等信息;
    对这个类的操作, 会执行在远程蓝牙设备的硬件上.
    对象获取途径 :
a. 调用BluetoothAdapter的getRemoteDevice(address)方法获取物理地址对应的该类对象;
b. 调用BluetoothAdapter的getBoundedDevices()方法, 可以获取已经配对的蓝牙设备集合;
  • BluetoothSocket
    已连接或正在连接的蓝牙插座。
    蓝牙套接字的接口类似于TCP套接字:Socket和ServerSocket。在服务器端,使用BluetoothServerSocket来创建侦听服务器套接字。当一个连接被BluetoothServerSocket接受时,它将返回一个新的BluetoothSocket来管理这个连接。在客户端,使用一个单一的BluetoothSocket来发起一个传出连接和管理连接。
    最常见的蓝牙套接字类型是RFCOMM,这是Android api所支持的类型。RFCOMM是一个基于蓝牙的面向连接的流传输。它也被称为串口配置文件(SPP)。
    要创建一个用于连接到已知设备的BluetoothDevice.createRfcommSocketToServiceRecord()。然后调用connect()来尝试连接到远程设备。此调用将阻塞,直到连接建立或连接失败。
    要创建一个作为服务器(或“主机”)的BluetoothServerSocket,请参阅BluetoothServerSocket文档。
    一旦套接字连接上,无论是作为客户端初始化还是作为服务器接受,都可以通过调用getInputStream()和getOutputStream()来打开IO流,以便分别检索自动连接到套接字的InputStream和OutputStream对象。
    BluetoothSocket线程安全。特别地,close()将总是立即中止正在进行的操作并关闭套接字。
  • BluetoothServerScoket
    收听蓝牙插座。
    蓝牙套接字的接口类似于TCP套接字:Socket和ServerSocket。在服务器端,使用BluetoothServerSocket来创建侦听服务器套接字。当一个连接被BluetoothServerSocket接受时,它将返回一个新的BluetoothSocket来管理这个连接。在客户端,使用一个单一的BluetoothSocket来发起一个传出连接和管理连接。
    对于蓝牙BR/EDR,最常见的套接字类型是RFCOMM,这是Android api所支持的类型。RFCOMM是一个基于蓝牙BR/EDR的面向连接的流传输。它也被称为串口配置文件(SPP)。使用BluetoothAdapter.listenUsingRfcommWithServiceRecord()来创建一个准备好接收蓝牙BR/EDR连接的侦听BluetoothServerSocket。
    对于蓝牙LE,套接字使用LE面向连接通道(CoC)。LE CoC是基于蓝牙LE的面向连接的流传输,并具有基于信用的流控制。相应地,使用BluetoothAdapter.listenUsingL2capChannel()来创建一个正在监听的BluetoothServerSocket,它已经准备好接收蓝牙LE CoC连接。对于LE CoC,您可以使用getPsm()来获取对等端需要使用的协议/服务多路复用器(PSM)值来连接到您的套接字。
    在创建侦听的BluetoothServerSocket之后,调用accept()来监听传入的连接请求。这个调用将阻塞,直到连接建立,此时,它将返回一个BluetoothSocket来管理连接。一旦获得了BluetoothServerSocket,当它不再需要接受连接时,在BluetoothServerSocket上调用close()是个好主意。关闭BluetoothServerSocket不会关闭返回的BluetoothSocket。
    BluetoothServerSocket是线程安全。特别地,close()将总是立即中止正在进行的操作并关闭服务器套接字。
  • 蓝牙的开和关
 /**
     * 打开蓝牙
     */
    public boolean openBluetooth(){
        if (!isBlueEnable()){
            boolean b = false;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ECLAIR) {
                b = adapter.enable();
            }
            LogUtil.v("openBluetooth="+b);
            return b ;
        }
        return false ;
    }



 /**
     * 关闭蓝牙
     */
    public boolean closeBluetooth(){
        if (isBlueEnable()){
            boolean b = false;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ECLAIR) {

                if (isDiscovering()){
                    cancelDiscovery() ;
                }

                b = adapter.disable();
            }
            LogUtil.v("closeBluetooth="+b);
            return b ;
        }
        return false;
    }
  • 扫描发现附近蓝牙设备
 /**
     * 启动发现扫描
     */
    public boolean startDiscovery(){
        if (!isBlueEnable()){
            LogUtil.v("startDiscovery this is not open");
            return false ;
        }

        if (isDiscovering()){
            LogUtil.v("startDiscovery this is isDiscovering");
            adapter.cancelDiscovery();
        }

        /*启动蓝牙发现*/
        return adapter.startDiscovery();
    }

  • 注册广播接收扫描的结果

    /**
     * 注册广播
     *
     * @param context
     */
    public void register(Context context){
        scanBluetoothReceiver = new ScanBluetoothReceiver();
        scanBluetoothReceiver.setScanBluetoothListener(scanBluetoothListener);

        IntentFilter intentFilter = new IntentFilter();
        /*开始扫描可用蓝牙设备
         * android.bluetooth.adapter.action.DISCOVERY_STARTED*/
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        /*完成扫描可用蓝牙设备
         * android.bluetooth.adapter.action.DISCOVERY_FINISHED*/
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        /*扫描得到可用蓝牙设备
         * android.bluetooth.device.action.FOUND*/
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        /*蓝牙配对状态变化
         * android.bluetooth.device.action.BOND_STATE_CHANGED*/
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        /*请求配对
         * android.bluetooth.device.action.PAIRING_REQUEST*/
        intentFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
        /*蓝牙配对状态进行监听
         * android.bluetooth.adapter.action.SCAN_MODE_CHANGED*/
        intentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
        /*android.bluetooth.adapter.action.STATE_CHANGED*/
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);

        context.registerReceiver(scanBluetoothReceiver,intentFilter);
    }

  • 配对蓝牙
    /**
     * 创建配对
     *
     * @param device
     */
    public boolean createBond(BluetoothDevice device){
        if (device.getBondState()==BluetoothDevice.BOND_NONE){
            Class<? extends BluetoothDevice> cls = device.getClass();
            try {
                Method method = cls.getMethod("createBond");
                Boolean returnValue = (Boolean) method.invoke(device);
                return returnValue.booleanValue();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        return false ;
    }

  • 取消正在配对
// 取消配对
    @SuppressWarnings("unchecked")
    public boolean cancelBondProcess(Class btClass, BluetoothDevice device)  {
        Method createBondMethod = null;
        try {
            createBondMethod = btClass.getMethod("cancelBondProcess");
            Boolean returnValue = (Boolean) createBondMethod.invoke(device);
            return returnValue.booleanValue();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return false ;
    }


  • 解绑已经配对
 /**
     * 解除配对
     *
     * @param device
     */
    public boolean removeBond(BluetoothDevice device){
        Class<? extends BluetoothDevice> cls = device.getClass();
        try {
            Method method = cls.getMethod("removeBond");
            Boolean returnValue = (boolean) method.invoke(device);
            return returnValue.booleanValue();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return false ;
    }
  • 客户端发送数据到服务端(BluetoothSocket)
 /**
     * 开始连接
     *
     * @param callBack
     */
    public void startConnect(CallBack callBack){
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (serverDevice == null){
                    if (callBack!=null)
                        callBack.onError(-1,"蓝牙还未配对");
                    return;
                }

                if (socket!=null){
                    try {
                        // Connect the device through the socket. This will block
                        // until it succeeds or throws an exception
                        socket.connect();
                    } catch (IOException connectException) {
                        // Unable to connect; close the socket and get out
                        try {
                            Method m = serverDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
                            socket = (BluetoothSocket) m.invoke(serverDevice, 1);
                            socket.connect();
                        } catch (Exception e) {
                            if (callBack!=null) callBack.onError(-1,"连接失败!");
                            try{
                                socket.close();
                            }catch (IOException ie){
                                ie.printStackTrace();
                            }
                        }
                        return;
                    }
                }else {
                    if (callBack!=null)
                        callBack.onError(-1,"获取socket失败!");
                    return;
                }

                OutputStream os = null;
                InputStream in = null;
                try {
                    os = socket.getOutputStream();
                    in = socket.getInputStream();
                    //发送100以内的随机数
                    sendMsgToServer(os,callBack);
                    //读取接收服务端返回的信息
                    new readSocketTask().execute(in) ;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

  • 服务端主要实现(BluetoothServerSocket)
  private void start(){
        new Thread(new Runnable() {
            @SuppressLint("MissingPermission")
            @Override
            public void run() {
                try {
                    /**
                     * 2、
                     * 如果阻塞就会一直停留在这儿
                     */
                    socket = serverSocket.accept();
                    /**
                     * 3、
                     * 读取客户端传递来的数据
                     */
                    InputStream in = socket.getInputStream();
                    OutputStream out = socket.getOutputStream();

                    /**
                     * 4、
                     * 阻塞获取消息长度
                     */
                    while (in.available() == 0);

                    /**
                     * 5、
                     * 将信息打印出来
                     */
                    String msg=manageConnectedSocket(in);

                    /**6、将信息反馈给客户端*/
                    responseClient(msg,out);

                } catch (IOException e) {
                    e.printStackTrace();
                    sendMsg(e.getMessage());
                }
                finally {
                    try {
                        socket.close();
                        socket = null ;
                    } catch (IOException e) {
                        e.printStackTrace();
                    }finally {
                        start();
                    }
                }
            }
        }).start();
    }
上一篇:一文详解前端错误捕获和上报


下一篇:Java零基础(11)异常处理