精华内容
下载资源
问答
  • Android蓝牙通信

    千次下载 热门讨论 2011-12-09 17:22:11
    Android蓝牙通信,连个手机直接通信,收发数据,界面简洁友好,代码易懂。使用的是虚拟串口通信,波特率9600,也可以和其他非手机端蓝牙设备通信,只要使用协议相同就行了。我的博客有说明...
  • android蓝牙通信(分为客户端,服务端) 因为最近需要做物联网这一块,就简单的搞了个demo实现客户端向服务端发送指令
  • 该Demo满足日常的蓝牙通信开发,可以做到收发数据,做到与设备间的交互,可根据该链接以找到使用方法:https://blog.csdn.net/qq_35809640/article/details/66472626
  • android 蓝牙通信

    2018-03-14 23:56:14
    android 蓝牙通信app,实现server client 通信两种模式
  • 这是一个Android蓝牙开发的小程序,代码简单,实现了蓝牙打开、搜索、配对、连接、通信等功能。两个Android项目,一个服务器一个客户端
  • android蓝牙通信实例

    2018-08-27 16:38:41
    android蓝牙通信实例,修改相关参数可运行;相关疑问可联系解答;
  • 通过蓝牙功能与设备进行连接以及获取设备传输过来的数据
  • 这是一份蓝牙通信 Android APP源码,采用Android Studio开发,代码风格良好,使用蜂汇物联科技的BLE模块测试过。
  • Android蓝牙通信代码

    2021-06-05 10:57:50
    在做android蓝牙串口连接的时候一般会使用BluetoothSocket tmp = null;// Get a BluetoothSocket for a connection with the// given BluetoothDevicetry {tmp = device.createRfcommSocketToServiceRecord(MY_UUID)...

    在做android蓝牙串口连接的时候一般会使用

    BluetoothSocket tmp = null;

    // Get a BluetoothSocket for a connection with the

    // given BluetoothDevice

    try {

    tmp = device.createRfcommSocketToServiceRecord(MY_UUID);

    } catch (IOException e) {

    Log.e(TAG, "create() failed", e);

    }

    然后是tmp赋给BluetoothSocket,接着调用connect方法进行蓝牙设备的连接。

    可是 BluetoothSocket 的connect方法本身就会报很多异常错误。

    以下根据对蓝牙开发的一点研究可通过以下方法解决:

    方法1.先进行蓝牙自动配对,配对成功,通过UUID获得BluetoothSocket,然后执行connect()方法。

    方法2.通过UUID获得BluetoothSocket,然后先根据mDevice.getBondState()进行判断是否需要配对,最后执行connnect()方法。

    /**

    *

    * 蓝牙连接线程

    *

    *

    * @author lsw

    *

    */

    private class ConnectThread extends Thread {

    String macAddress = "";

    public ConnectThread(String mac) {

    macAddress = mac;

    }

    public void run() {

    connecting = true;

    connected = false;

    if(mBluetoothAdapter == null){

    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    }

    mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(macAddress);

    mBluetoothAdapter.cancelDiscovery();

    //initSocket();

    try {

    socket = mBluetoothDevice.createRfcommSocketToServiceRecord(uuid);

    } catch (IOException e) {

    // TODO Auto-generated catch block

    //e.printStackTrace();

    Log.e(TAG, "Socket", e);

    }

    //adapter.cancelDiscovery();

    while (!connected && connetTime <= 10) {

    connectDevice();

    }

    // 重置ConnectThread

    //synchronized (BluetoothService.this) {

    //ConnectThread = null;

    //}

    }

    public void cancel() {

    try {

    socket.close();

    socket = null;

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    connecting = false;

    }

    }

    }

    接下来是调用的连接设备方法connectDevice():

    protected void connectDevice() {

    try {

    // 连接建立之前的先配对

    if (mBluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE) {

    Method creMethod = BluetoothDevice.class

    .getMethod("createBond");

    Log.e("TAG", "开始配对");

    creMethod.invoke(mBluetoothDevice);

    } else {

    }

    } catch (Exception e) {

    // TODO: handle exception

    //DisplayMessage("无法配对!");

    e.printStackTrace();

    }

    mBluetoothAdapter.cancelDiscovery();

    try {

    socket.connect();

    //DisplayMessage("连接成功!");

    //connetTime++;

    connected = true;

    } catch (IOException e) {

    // TODO: handle exception

    //DisplayMessage("连接失败!");

    connetTime++;

    connected = false;

    try {

    socket.close();

    socket = null;

    } catch (IOException e2) {

    // TODO: handle exception

    Log.e(TAG, "Cannot close connection when connection failed");

    }

    } finally {

    connecting = false;

    }

    }

    方法3.利用反射通过端口获得BluetoothSocket,然后执行connect()方法。

    /**

    *

    * 蓝牙连接线程

    *

    *

    * @author lsw

    *

    */

    private class ConnectThread extends Thread {

    String macAddress = "";

    public ConnectThread(String mac) {

    macAddress = mac;

    }

    public void run() {

    connecting = true;

    connected = false;

    if(mBluetoothAdapter == null){

    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    }

    mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(macAddress);

    mBluetoothAdapter.cancelDiscovery();

    initSocket();

    //adapter.cancelDiscovery();

    while (!connected && connetTime <= 10) {

    try {

    socket.connect();

    connected = true;

    } catch (IOException e1) {

    connetTime++;

    connected = false;

    // 关闭 socket

    try {

    socket.close();

    socket = null;

    } catch (IOException e2) {

    //TODO: handle exception

    Log.e(TAG, "Socket", e2);

    }

    } finally {

    connecting = false;

    }

    //connectDevice();

    }

    // 重置ConnectThread

    //synchronized (BluetoothService.this) {

    //ConnectThread = null;

    //}

    }

    public void cancel() {

    try {

    socket.close();

    socket = null;

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    connecting = false;

    }

    }

    }

    接下来是初始化并得到BluetoothSocket的方法

    /**

    * 取得BluetoothSocket

    */

    private void initSocket() {

    BluetoothSocket temp = null;

    try {

    Method m = mBluetoothDevice.getClass().getMethod(

    "createRfcommSocket", new Class[] { int.class });

    temp = (BluetoothSocket) m.invoke(mBluetoothDevice, 1);//这里端口为1

    } catch (SecurityException e) {

    e.printStackTrace();

    } catch (NoSuchMethodException e) {

    e.printStackTrace();

    } catch (IllegalArgumentException e) {

    e.printStackTrace();

    } catch (IllegalAccessException e) {

    e.printStackTrace();

    } catch (InvocationTargetException e) {

    e.printStackTrace();

    }

    socket = temp;

    }

    要点:1.蓝牙配对和连接是两回事,不可混为一谈。

    2.蓝牙串口连接可通过端口 (1-30)和UUID两种方法进行操作。

    3.通过UUID进行蓝牙连接最好先进行配对操作。

    展开全文
  •  1:android6.0使用蓝牙时,需要开启gps定位权限,不然无法搜索其它蓝牙设备。 二:权限  1:权限配置 <!--允许程序连接到已配对的蓝牙设备--> <uses android:name=android.permission.BLUETOOTH> <!-- ...
  • 其实无论是socket方式还是Gatt,Android设备间蓝牙通信都是一种C/S(client-server)模式。 本文基于两种通信方式,进行详细展开,并推荐了开源项目,建议配合学习。 关键词 (1)Bluetooth 蓝牙(Blu

    1.摘要

    Android手机间通过蓝牙方式进行通信,有两种常见的方式,一种是socket方式,另一种是通过GATT Server(Android 5.0以后)通信。
    (1)socket方式最为简单,但是很多低功耗的蓝牙设备,如单片机上的蓝牙模块可能不支持
    (2)GATT方式相对比较复杂
    (3)socket、GATT均为C/S(client-server)模式
    本文基于两种通信方式,进行详细展开,并推荐了开源项目,建议配合学习。

    关键词

    (1)Bluetooth

    蓝牙(Bluetooth):蓝牙,是一种支持设备短距离通信(一般10m内)的无线电技术,能在包括移动电话、PDA、无线耳机、笔记本电脑、相关外设等众多设备之间进行无线信息交换。利用“蓝牙”技术,能够有效地简化移动通信终端设备之间的通信,也能够成功地简化设备与因特网Internet之间的通信,从而使数据传输变得更加迅速高效,为无线通信拓宽道路。

    (2) UUID

    UUID(Universally Unique Identifier):用于标识蓝牙服务以及通讯特征访问属性,不同的蓝牙服务和属性使用不同的访问方法。

    (3)服务UUID

    服务UUID(Service UUID):不同的服务(Service)应该有不同的编号(UUID),用以区分不同的服务(Service)。

    (4)特征值UUID

    特征值UUID(Characteristic UUID):特性(Characteristic) 是依附于某个服务(Service)的

    (5)属性(Property)

    (5.1)Read: 读属性

    Read: 读属性,具有这个属性的特性是可读的,也就是说这个属性允许手机来读取一些信息。手机可以发送指令来读取某个具有读属性UUID的信息。

    (5.2)Notify: 通知属性

    Notify: 通知属性, 具有这个属性的特性是可以发送通知的,也就是说具有这个属性的特性(Characteristic)可以主动发送信息给手机。

    (5.3)Write: 写属性

    Write: 写属性, 具有这个属性的特性是可以接收写入数据的。通常手机发送数据给蓝模块就是通过这个属性完成的。这个属性在Write 完成后,会发送写入完成结果的反馈给手机,然后手机再可以写入下一包或处理后续业务,这个属性在写入一包数据后,需要等待应用层返回写入结果,速度比较慢。

    (5.4)WriteWithout Response:写属性

    WriteWithout Response:写属性,从字面意思上看,只是写,不需要返回写的结果,这个属性的特点是不需要应用层返回,完全依靠协议层完成,速度快,但是写入速度超过协议处理速度的时候,会丢包。

    (6) GATT

    GATT(Generic Attribute Profile):中文名叫通用属性协议,它定义了services和characteristic两种东西来完成低功耗蓝牙设备之间的数据传输。它是建立在通用数据协议Attribute Protocol (ATT),之上的,ATT把services和characteristic以及相关的数据保存在一张简单的查找表中,该表使用16-bit的id作为索引。

    (7)profile

    profile可以理解为一种规范,一个标准的通信协议,它存在于从机中。蓝牙组织规定了一些标准的profile,例如 HID OVER GATT ,防丢器 ,心率计等。每个profile中会包含多个service,每个service代表从机的一种能力。

    2. Bluetooth Socket

    推荐开源项目:https://github.com/Zweo/Bluetoothhttps://github.com/zolty-lionheart/Bluetooth
    以该项目demo为例介绍

    蓝牙端口监听接口和TCP端口类似:Socket和ServerSocket类。在服务器端,使用BluetoothServerSocket类来创建一个 监听服务端口。当一个连接被BluetoothServerSocket所接受,它会返回一个新的BluetoothSocket来管理该连接。在客户 端,使用一个单独的BluetoothSocket类去初始化一个外接连接和管理该连接。

    最通常使用的蓝牙端口是RFCOMM,它是被Android API支持的类型。RFCOMM是一个面向连接,通过蓝牙模块进行的数据流传输方式,它也被称为串行端口规范(Serial Port Profile,SPP)。

    为了创建一个BluetoothSocket去连接到一个已知设备,使用方法 BluetoothDevice.createRfcommSocketToServiceRecord()。然后调用connect()方法去尝试一个 面向远程设备的连接。这个调用将被阻塞指导一个连接已经建立或者该链接失效。

    为了创建一个BluetoothSocket作为服务端(或者“主机”),查看BluetoothServerSocket文档。

    每当该端口连接成功,无论它初始化为客户端,或者被接受作为服务器端,通过getInputStream()和getOutputStream()来打开IO流,从而获得各自的InputStream和OutputStream对象

    BluetoothSocket类线程安全。特别的,close()方法总会马上放弃外界操作并关闭服务器端口。

    注意

    1.需要BLUETOOTH权限。
    2.此处BluetoothSocket使用uuid:00001101-0000-1000-8000-00805F9B34FB

    2.1 Server

    private static final String UUIDString = "00001101-0000-1000-8000-00805F9B34FB";
    //开启服务器
    private class ServerThread extends Thread {
        @Override
        public void run() {
            try {
                    /* 创建一个蓝牙服务器
                     * 参数分别:服务器名称、UUID   */
                mServerSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(PROTOCOL_SCHEME_RFCOMM, UUID.fromString(UUIDString));
                while (true){
                    Log.d("server", "wait cilent connect...");
                    Message msg = new Message();
                    msg.obj = "请稍候,正在等待客户端的连接...";
                    msg.what = WAITING_FOR_CLIENT;
                    linkDetectedHandler.sendMessage(msg);
                    /* 接受客户端的连接请求 */
                    BluetoothSocket socket = mServerSocket.accept();
                    socketMap.put(socket.getRemoteDevice().getAddress(), socket);
    //                  remoteDeviceMap.put(socket.getRemoteDevice().getAddress(),socket.getRemoteDevice());
                    Log.d("server", "accept success !");
                    Message msg2 = new Message();
                    String info = "客户端已经连接上!可以发送信息。";
                    msg2.obj = info;
                    msg.what = CONNECTED_CLIENT;
                    linkDetectedHandler.sendMessage(msg2);
                    //启动接受数据
                    ReadThread mreadThread = new ReadThread(socket.getRemoteDevice().getAddress());
                    readThreadMap.put(socket.getRemoteDevice().getAddress(),mreadThread);
                    mreadThread.start();
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    2.2 Client

    //开启客户端
    private class ClientThread extends Thread {
        private String remoteAddress;
        public ClientThread(String remoteAddress) {
            this.remoteAddress = remoteAddress;
        }
        @Override
        public void run() {
            try {
                //创建一个Socket连接:只需要服务器在注册时的UUID号
                BluetoothDevice device = bluetoothAdapter.getRemoteDevice(remoteAddress);
                BluetoothSocket socket = device.createRfcommSocketToServiceRecord(UUID.fromString(UUIDString));
                //连接
                Message msg2 = new Message();
                msg2.obj = "请稍候,正在连接服务器:" + remoteAddress;
                msg2.what = IS_CONNECTING_SERVER;
                linkDetectedHandler.sendMessage(msg2);
                socket.connect();
                socketMap.put(remoteAddress, socket);
                Message msg = new Message();
                msg.obj = remoteAddress;
                msg.what = CONNECTED_SERVER;
                linkDetectedHandler.sendMessage(msg);
                //启动接受数据
                ReadThread mreadThread = new ReadThread(remoteAddress);
                readThreadMap.put(remoteAddress,mreadThread);
                mreadThread.start();
            } catch (IOException e) {
                e.printStackTrace();
                socketMap.remove(remoteAddress);
                Log.e("connect", e.getMessage(), e);
                Message msg = new Message();
                msg.obj = "连接服务端异常!断开连接重新试一试。"+e.getMessage();
                msg.what = CONNECT_SERVER_ERROR;
                linkDetectedHandler.sendMessage(msg);
            }
        }
    }
    

    3. Bluetooth GATT

    推荐开源项目:https://github.com/dingpwen/bl_communicationhttps://github.com/zolty-lionheart/bl_communication
    以该项目demo为例介绍

    注意

    1.GATT提供了notifyCharacteristicChanged方法去响应客户端的请求值,响应值(characteristic.value)

    2.uuid经过本人测试仅支持以下情况,网文中提及手机端可能不支持自定义uuid。
     val BLE_SERVICE_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb")
     val BLE_WRITE_UUID = UUID.fromString("00002a02-0000-1000-8000-00805f9b34fb")
     val BLE_READ_UUID  = UUID.fromString("00002a03-0000-1000-8000-00805f9b34fb")
     val BLE_DESC_UUID  = UUID.fromString("00002a04-0000-1000-8000-00805f9b34fb")
    

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    3.1 Server

    private fun setupServer() {
        val gattService = BluetoothGattService(Constants.BLE_SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY)
        val characteristicRead = BluetoothGattCharacteristic(Constants.BLE_READ_UUID, BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ)
        val descriptor = BluetoothGattDescriptor(Constants.BLE_DESC_UUID, BluetoothGattCharacteristic.PERMISSION_WRITE)
        characteristicRead.addDescriptor(descriptor)
        gattService.addCharacteristic(characteristicRead)
        val characteristicWrite = BluetoothGattCharacteristic(Constants.BLE_WRITE_UUID, BluetoothGattCharacteristic.PROPERTY_WRITE or
                BluetoothGattCharacteristic.PROPERTY_READ or BluetoothGattCharacteristic.PROPERTY_NOTIFY,
                BluetoothGattCharacteristic.PERMISSION_WRITE)
        gattService.addCharacteristic(characteristicWrite)
        Log.d("wenpd", "startGattServer:stagattServicetus=$gattService")
        mGattServer.addService(gattService)
    }
    

    3.2 Client

    private class GattClientCallback extends BluetoothGattCallback {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            if (status == BluetoothGatt.GATT_FAILURE) {
                disconnectGattServer();
                return;
            } else if (status != BluetoothGatt.GATT_SUCCESS) {
                disconnectGattServer();
                return;
            }
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                mConnected = true;
                gatt.discoverServices();
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                disconnectGattServer();
            }
        }
    
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            Log.d(TAG, "onServicesDiscovered status:" + status);
            if (status != BluetoothGatt.GATT_SUCCESS) {
                return;
            }
            BluetoothGattService service = gatt.getService(Constants.SERVICE_UUID);
            BluetoothGattCharacteristic characteristic = service.getCharacteristic(Constants.CHARACTERISTIC_UUID);
            characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
            mInitialized = gatt.setCharacteristicNotification(characteristic, true);
        }
    
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            byte[] messageBytes = characteristic.getValue();
            /*for(int i = 0, j = messageBytes.length -1; i < j; ++i, --j) {
                byte temp = messageBytes[i];
                messageBytes[i] = messageBytes[j];
                messageBytes[j] = temp;
            }*/
            String messageString = new String(messageBytes, StandardCharsets.UTF_8);
            Log.d(TAG,"Received message: " + messageString);
            setReceivedData(messageString);
        }
    }
    

    参考文献

    1.Android Phone蓝牙通信方式总结(Socket与Gatt)
    2.Bluetooth之BluetoothSocket
    3.全面且简单明了的蓝牙服务及UUID介绍
    4.Android BLE蓝牙开发-读写数据 获取UUID
    5.简述蓝牙服务UUID自定义功能
    6.Android 蓝牙开发常用UUID表
    7.android bluetooth UUID蓝牙查询表

    附录

    常用uuid

    00001000-0000-1000-8000-00805F9B34FB Service Discovery Server Service
    00001001-0000-1000-8000-00805F9B34FB Browse Group Descriptor Service
    00001002-0000-1000-8000-00805F9B34FB Public Browse Group Service
    #蓝牙串口服务
    00001101-0000-1000-8000-00805F9B34FB Serial Port Service
    #使用PPP服务类的局域网访问
    00001102-0000-1000-8000-00805F9B34FB LAN Access Using PPP Service
    #拨号网络服务
    00001103-0000-1000-8000-00805F9B34FB Dialup Networking Service
    #信息同步服务
    00001104-0000-1000-8000-00805F9B34FB IrMC Sync Service
    00001105-0000-1000-8000-00805F9B34FB SDP_OBEX Object Push Service
    #文件传输服务
    00001106-0000-1000-8000-00805F9B34FB OBEX File Transfer Service
    00001107-0000-1000-8000-00805F9B34FB IrMC Sync Command Service
    00001108-0000-1000-8000-00805F9B34FB SDP_Headset Service
    00001109-0000-1000-8000-00805F9B34FB Cordless Telephony Service
    0000110A-0000-1000-8000-00805F9B34FB SDP_Audio Source Service
    0000110B-0000-1000-8000-00805F9B34FB SDP_Audio Sink Service
    0000110C-0000-1000-8000-00805F9B34FB SDP_AV Remote Control Target Service
    0000110D-0000-1000-8000-00805F9B34FB SDP_Advanced Audio Distribution Service
    0000110E-0000-1000-8000-00805F9B34FB SDP_AV Remote Control Service
    0000110F-0000-1000-8000-00805F9B34FB Video Conferencing Service
    00001110-0000-1000-8000-00805F9B34FB Intercom Service
    #蓝牙传真服务
    00001111-0000-1000-8000-00805F9B34FB Fax Service
    00001112-0000-1000-8000-00805F9B34FB Headset Audio Gateway Service
    00001113-0000-1000-8000-00805F9B34FB WAP Service
    00001114-0000-1000-8000-00805F9B34FB WAP Client Service
    #个人局域网服务
    00001115-0000-1000-8000-00805F9B34FB PANU Service
    #个人局域网服务
    00001116-0000-1000-8000-00805F9B34FB NAP Service
    #个人局域网服务
    00001117-0000-1000-8000-00805F9B34FB GN Service
    00001118-0000-1000-8000-00805F9B34FB Direct Printing Service
    00001119-0000-1000-8000-00805F9B34FB Reference Printing Service
    0000111A-0000-1000-8000-00805F9B34FB Imaging Service
    0000111B-0000-1000-8000-00805F9B34FB Imaging ResponderService
    0000111C-0000-1000-8000-00805F9B34FB Imaging Automatic Archive Service
    0000111D-0000-1000-8000-00805F9B34FB ImagingReferenceObjectsService
    0000111E-0000-1000-8000-00805F9B34FB SDP_Hands free Service
    0000111F-0000-1000-8000-00805F9B34FB Hands free Audio Gateway Service
    00001120-0000-1000-8000-00805F9B34FB Direct Printing Reference Objects Service
    00001121-0000-1000-8000-00805F9B34FB Reflected UI Service
    00001122-0000-1000-8000-00805F9B34FB Basic Pringing Service
    00001123-0000-1000-8000-00805F9B34FB Printing Status Service
    #人机输入服务
    00001124-0000-1000-8000-00805F9B34FB HumanInterface Device Service
    00001125-0000-1000-8000-00805F9B34FB Hardcopy Cable Replacement Service
    #蓝牙打印服务
    00001126-0000-1000-8000-00805F9B34FB HCR Print Service
    00001127-0000-1000-8000-00805F9B34FB HCR Scan Service
    00001128-0000-1000-8000-00805F9B34FB CommonI SDN Access Service
    00001129-0000-1000-8000-00805F9B34FB Video Conferencing GW Service
    0000112A-0000-1000-8000-00805F9B34FB UDIMT Service
    0000112B-0000-1000-8000-00805F9B34FB UDITA Service
    0000112C-0000-1000-8000-00805F9B34FB Audio Video Service
    0000112D-0000-1000-8000-00805F9B34FB SIM Access Service
    00001200-0000-1000-8000-00805F9B34FB PnP Information Service
    00001201-0000-1000-8000-00805F9B34FB Generic Networking Service
    00001202-0000-1000-8000-00805F9B34FB Generic File Transfer Service
    00001203-0000-1000-8000-00805F9B34FB Generic Audio Service
    00001204-0000-1000-8000-00805F9B34FB Generic Telephony Service
    
    ==============================================================================================
    Sample Services
    0000180d-0000-1000-8000-00805f9b34fb    Heart Rate Service    
    0000180a-0000-1000-8000-00805f9b34fb    Device Information Service    
    Sample Characteristics. 
    00002a37-0000-1000-8000-00805f9b34fb    Heart Rate Measurement    
    00002a29-0000-1000-8000-00805f9b34fb    Manufacturer Name String    
        
    GATT Services 
    00001800-0000-1000-8000-00805f9b34fb    GenericAccess    
    00001801-0000-1000-8000-00805f9b34fb    GenericAttribute    
     
    GATT Declarations 
    00002800-0000-1000-8000-00805f9b34fb    Primary Service    
    00002801-0000-1000-8000-00805f9b34fb    Secondary Service    
    00002802-0000-1000-8000-00805f9b34fb    Include    
    00002803-0000-1000-8000-00805f9b34fb    Characteristic    
             
    GATT Descriptors 
    00002900-0000-1000-8000-00805f9b34fb    Characteristic Extended Properties    
    00002901-0000-1000-8000-00805f9b34fb    Characteristic User Description    
    00002902-0000-1000-8000-00805f9b34fb    Client Characteristic Configuration    
    00002903-0000-1000-8000-00805f9b34fb    Server Characteristic Configuration    
    00002904-0000-1000-8000-00805f9b34fb    Characteristic Presentation Format    
    00002905-0000-1000-8000-00805f9b34fb    Characteristic Aggregate Format    
    00002906-0000-1000-8000-00805f9b34fb    Valid Range    
    00002907-0000-1000-8000-00805f9b34fb    External Report Reference Descriptor    
    00002908-0000-1000-8000-00805f9b34fb    Report Reference Descriptor    
     
    GATT Characteristics 
    00002a00-0000-1000-8000-00805f9b34fb    Device Name    
    00002a01-0000-1000-8000-00805f9b34fb    Appearance    
    00002a02-0000-1000-8000-00805f9b34fb    Peripheral Privacy Flag    
    00002a03-0000-1000-8000-00805f9b34fb    Reconnection Address    
    00002a04-0000-1000-8000-00805f9b34fb    PPCP    
    00002a05-0000-1000-8000-00805f9b34fb    Service Changed    
             
    GATT Service UUIDs 
    00001802-0000-1000-8000-00805f9b34fb    Immediate Alert    
    00001803-0000-1000-8000-00805f9b34fb    Link Loss    
    00001804-0000-1000-8000-00805f9b34fb    Tx Power    
    00001805-0000-1000-8000-00805f9b34fb    Current Time Service    
    00001806-0000-1000-8000-00805f9b34fb    Reference Time Update Service    
    00001807-0000-1000-8000-00805f9b34fb    Next DST Change Service    
    00001808-0000-1000-8000-00805f9b34fb    Glucose    
    00001809-0000-1000-8000-00805f9b34fb    Health Thermometer    
    0000180a-0000-1000-8000-00805f9b34fb    Device Information    
    0000180b-0000-1000-8000-00805f9b34fb    Network Availability    
    0000180d-0000-1000-8000-00805f9b34fb    Heart Rate    
    0000180e-0000-1000-8000-00805f9b34fb    Phone Alert Status Service    
    0000180f-0000-1000-8000-00805f9b34fb    Battery Service    
    00001810-0000-1000-8000-00805f9b34fb    Blood Pressure    
    00001811-0000-1000-8000-00805f9b34fb    Alert Notification Service    
    00001812-0000-1000-8000-00805f9b34fb    Human Interface Device    
    00001813-0000-1000-8000-00805f9b34fb    Scan Parameters    
    00001814-0000-1000-8000-00805f9b34fb    Running Speed and Cadence    
    00001816-0000-1000-8000-00805f9b34fb    Cycling Speed and Cadence    
    00001818-0000-1000-8000-00805f9b34fb    Cycling Power    
    00001819-0000-1000-8000-00805f9b34fb    Location and Navigation    
         
    GATT Characteristic UUIDs 
    00002a06-0000-1000-8000-00805f9b34fb    Alert Level    
    00002a07-0000-1000-8000-00805f9b34fb    Tx Power Level    
    00002a08-0000-1000-8000-00805f9b34fb    Date Time    
    00002a09-0000-1000-8000-00805f9b34fb    Day of Week    
    00002a0a-0000-1000-8000-00805f9b34fb    Day Date Time    
    00002a0c-0000-1000-8000-00805f9b34fb    Exact Time 256    
    00002a0d-0000-1000-8000-00805f9b34fb    DST Offset    
    00002a0e-0000-1000-8000-00805f9b34fb    Time Zone    
    00002a0f-0000-1000-8000-00805f9b34fb    Local Time Information    
    00002a11-0000-1000-8000-00805f9b34fb    Time with DST    
    00002a12-0000-1000-8000-00805f9b34fb    Time Accuracy    
    00002a13-0000-1000-8000-00805f9b34fb    Time Source    
    00002a14-0000-1000-8000-00805f9b34fb    Reference Time Information    
    00002a16-0000-1000-8000-00805f9b34fb    Time Update Control Point    
    00002a17-0000-1000-8000-00805f9b34fb    Time Update State    
    00002a18-0000-1000-8000-00805f9b34fb    Glucose Measurement    
    00002a19-0000-1000-8000-00805f9b34fb    Battery Level    
    00002a1c-0000-1000-8000-00805f9b34fb    Temperature Measurement    
    00002a1d-0000-1000-8000-00805f9b34fb    Temperature Type    
    00002a1e-0000-1000-8000-00805f9b34fb    Intermediate Temperature    
    00002a21-0000-1000-8000-00805f9b34fb    Measurement Interval    
    00002a22-0000-1000-8000-00805f9b34fb    Boot Keyboard Input Report    
    00002a23-0000-1000-8000-00805f9b34fb    System ID    
    00002a24-0000-1000-8000-00805f9b34fb    Model Number String    
    00002a25-0000-1000-8000-00805f9b34fb    Serial Number String    
    00002a26-0000-1000-8000-00805f9b34fb    Firmware Revision String    
    00002a27-0000-1000-8000-00805f9b34fb    Hardware Revision String    
    00002a28-0000-1000-8000-00805f9b34fb    Software Revision String    
    00002a29-0000-1000-8000-00805f9b34fb    Manufacturer Name String    
    00002a2a-0000-1000-8000-00805f9b34fb    IEEE 11073-20601 Regulatory Certification Data List    
    00002a2b-0000-1000-8000-00805f9b34fb    Current Time    
    00002a31-0000-1000-8000-00805f9b34fb    Scan Refresh    
    00002a32-0000-1000-8000-00805f9b34fb    Boot Keyboard Output Report    
    00002a33-0000-1000-8000-00805f9b34fb    Boot Mouse Input Report    
    00002a34-0000-1000-8000-00805f9b34fb    Glucose Measurement Context    
    00002a35-0000-1000-8000-00805f9b34fb    Blood Pressure Measurement    
    00002a36-0000-1000-8000-00805f9b34fb    Intermediate Cuff Pressure    
    00002a37-0000-1000-8000-00805f9b34fb    Heart Rate Measurement    
    00002a38-0000-1000-8000-00805f9b34fb    Body Sensor Location    
    00002a39-0000-1000-8000-00805f9b34fb    Heart Rate Control Point    
    00002a3e-0000-1000-8000-00805f9b34fb    Network Availability    
    00002a3f-0000-1000-8000-00805f9b34fb    Alert Status    
    00002a40-0000-1000-8000-00805f9b34fb    Ringer Control Point    
    00002a41-0000-1000-8000-00805f9b34fb    Ringer Setting    
    00002a42-0000-1000-8000-00805f9b34fb    Alert Category ID Bit Mask    
    00002a43-0000-1000-8000-00805f9b34fb    Alert Category ID    
    00002a44-0000-1000-8000-00805f9b34fb    Alert Notification Control Point    
    00002a45-0000-1000-8000-00805f9b34fb    Unread Alert Status    
    00002a46-0000-1000-8000-00805f9b34fb    New Alert    
    00002a47-0000-1000-8000-00805f9b34fb    Supported New Alert Category    
    00002a48-0000-1000-8000-00805f9b34fb    Supported Unread Alert Category    
    00002a49-0000-1000-8000-00805f9b34fb    Blood Pressure Feature    
    00002a4a-0000-1000-8000-00805f9b34fb    HID Information    
    00002a4b-0000-1000-8000-00805f9b34fb    Report Map    
    00002a4c-0000-1000-8000-00805f9b34fb    HID Control Point    
    00002a4d-0000-1000-8000-00805f9b34fb    Report    
    00002a4e-0000-1000-8000-00805f9b34fb    Protocol Mode    
    00002a4f-0000-1000-8000-00805f9b34fb    Scan Interval Window    
    00002a50-0000-1000-8000-00805f9b34fb    PnP ID    
    00002a51-0000-1000-8000-00805f9b34fb    Glucose Feature    
    00002a52-0000-1000-8000-00805f9b34fb    Record Access Control Point    
    00002a53-0000-1000-8000-00805f9b34fb    RSC Measurement    
    00002a54-0000-1000-8000-00805f9b34fb    RSC Feature    
    00002a55-0000-1000-8000-00805f9b34fb    SC Control Point    
    00002a5b-0000-1000-8000-00805f9b34fb    CSC Measurement    
    00002a5c-0000-1000-8000-00805f9b34fb    CSC Feature    
    00002a5d-0000-1000-8000-00805f9b34fb    Sensor Location    
    00002a63-0000-1000-8000-00805f9b34fb    Cycling Power Measurement    
    00002a64-0000-1000-8000-00805f9b34fb    Cycling Power Vector    
    00002a65-0000-1000-8000-00805f9b34fb    Cycling Power Feature    
    00002a66-0000-1000-8000-00805f9b34fb    Cycling Power Control Point    
    00002a67-0000-1000-8000-00805f9b34fb    Location and Speed    
    00002a68-0000-1000-8000-00805f9b34fb    Navigation    
    00002a69-0000-1000-8000-00805f9b34fb    Position Quality    
    00002a6a-0000-1000-8000-00805f9b34fb    LN Feature    
    00002a6b-0000-1000-8000-00805f9b34fb    LN Control Point"
    
    展开全文
  • Android 系统提供蓝牙 API 包 android.bluetooth,允许手机设备通过蓝牙与其他设备进行无线连接。Android蓝牙 API 可提供以下功能:需要说明的是,Android 模拟器不支持蓝牙功能,因此蓝牙相关的应用程序只能在...

    644f557f17dfcc1e23b45fb9fb2231dd.png

    Android 系统提供蓝牙 API 包 android.bluetooth,允许手机设备通过蓝牙与其他设备进行无线连接。

    Android 的蓝牙 API 可提供以下功能:

    需要说明的是,Android 模拟器不支持蓝牙功能,因此蓝牙相关的应用程序只能在真机上调试。

    要使用蓝牙功能,需要在 AndroidManifest.xml 中声明相应权限。蓝牙权限有两种,分别为:

    或者:

    如果想在应用程序中请求或者建立蓝牙连接并传递数据,必须声明 Bluetooth 权限。若想初始化设备发现功能或者对蓝牙设置进行更改,则必须声明 BLUETOOTH_ADMIN 权限。

    要在应用程序中使用蓝牙功能,必须保证当前设备具有蓝牙并且启用该功能蓝牙开发。若当前设备支持蓝牙,但是没有启用相关功能,则需要人工启用蓝牙功能。

    首先使用 BluetoothAdapter 类的对象来确认设备具有蓝牙功能,然后使用 Intent 开启蓝牙功能。相关代码如下:

    6bc5606371354db087a5c1449e840258.png

    BluetoothAdapter mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();

    if (mBluetoothAdapter==null) {

    //设备不支持蓝牙功能

    return;

    }

    //设备支持蓝牙功能

    if (!mBluetoothAdapter.isEnabled()) {

    //用于启动蓝牙功能的 Intent

    Intent enableBtIntent=new Intent (BluetoothAdapter.ACTION_REQUEST_ENABLE);

    startActivityForResult (enableBtIntent, REQUEST_ENABLE_BT);

    }startActivityForResult(enableBtIntent,REQUEST_ENABLE_BT) 调用后,会显示如图 1 所示的对话框,要求用户确认是否启用蓝牙功能。

    4594e5ad00ba686bbd745f7f4e7d6582.png

    图 1请求启用蓝牙功能对话框

    若用户单击 Yes 按钮,则 Android 系统会启用蓝牙功能。若蓝牙功能启用成功,onActivityResult() 方法会返回 RESULT_OK;若蓝牙功能启用失败或者用户单击 No 按钮,则返回 RESULT_CANCELED。

    通过 BluetoothAdapter 类对象可以发现其他的蓝牙设备。在启动设备发现服务前,应该首先对配对设备列表进行查询,以确定要连接的无线设备是否已知。

    配对设备列表中存储了以前配对过的蓝牙设备的基本信息,如设备名称、设备类型、设备的 MAC 地址等。通过设备列表查找设备可以节省大量查找时间。查询设备列表的代码如下:

    Set pairedDevices=mBluetoothAdapter.getBondedDevices();

    //已配对设备列表存在

    if(pairedDevices.size() > 0) {

    //列表内循环查找

    for(BluetoothDevice device : pairedDevices) {

    //将列表内的设备名字添加到 ArrayAdapter 中

    mArrayAdapter.add (device.getName()+"\n"+device.getAddress());

    }

    }当设备列表中未发现要连接的设备时,需要启动设备发现服务来发现远端蓝牙设备,扫描周围无线设备的时间为 12 秒钟左右。

    启动设备发现服务的方法很简单,只要调用 startDiscovery() 方法即可。但是为了接收设备发现服务返回的设备信息,应用程序需要注册用于接收含有 ACTION_FOUND 消息的 Intent 的 BroadcastReceiver。其代码如下:

    private final BroadcastReceiver mReceiver=new BroadcastReceiver(){

    public void onReceive(Context context,Intent intent){

    String action=intent.getAction();

    //发现服务发现远端设备时

    if (BluetoothDevice.ACTION_FOUND.equals(action)){

    //从 Intent 对象中获取 BluetoothDevice 对象信息

    BluetoothDevice device=intent.getParcelableExtra (BluetoothDevice.EXTRA_DEVICE);

    //当发现的新设备不存在于设备配对列表中时,将设备的名字和地址添加到ArrayAdapter中

    if(device.getBondState()!=BluetoothDevice.BOND_BONDED) {

    mArrayAdapter.add (device.getName()+"\n"+device.getAddress()) ;

    }

    }

    }

    };

    //注册 BroadcastReceiver

    IntentFilter filter=new IntentFilter (BluetoothDevice.ACTION_FOUND);

    registerReceiver(mReceiver,filter);使用 registerReceiver() 方式注册的 BroadcastReceiver,在应用程序结束时要记得注销。

    蓝牙设备间建立连接的过程和 TCP 连接的过程很相似。

    9230f6bbff7dd207cbed35268d2a4e9e.png

    展开全文
  • Android 开发进阶课程蓝牙通信 ??? 本教程介绍了Android 蓝牙通信的原理及具体实现,其中包括:客户端服务器结构和对等结构。然后介绍了基于Socket实现的蓝牙通信,以及基于蓝牙实现对等结构网络通讯。我们还介绍了...
  • Qt On Android蓝牙通信代码
  • android蓝牙通信

    2016-02-17 09:59:26
    android实现蓝牙通信,通过选择服务端和客户端匹配后可以进行数据传输
  • Android 蓝牙通信

    2017-07-17 21:42:24
    这是两个手机蓝牙通信的demo,不要用虚拟机会报错,找两个手机进行测试,并且可以打开另个手机存在的app
  • 基于Android平台的一个关于应用蓝牙设备进行聊天的程序,目前程序已实现2台设备之间的通信,服务器部分是按照的一对多的方式写的```没有测试3台设备是否能聊天,不过2台设备配对后``是百分百可以的,有UI界面,操作简单,...
  • android 蓝牙通信源码

    2016-08-14 18:47:15
    android蓝牙通信源码,亲测可用,需要2个手机,先配对,一个当服务端,一个当客户端口
  • 一、统一解决Android蓝牙通信过程中的兼容性问题 二、提供尽可能简单易用的接口,屏蔽蓝牙通信中的技术细节,只开放连接,读写,通知等语义。 三、实现串行化任务队列,统一处理蓝牙通信中的失败以及超时,支持可...
  • Android蓝牙通信编程

    2021-01-21 20:15:23
    项目涉及蓝牙通信,所以就简单的学了学,下面是自己参考了一些资料后的总结,希望对大家有帮助。  以下是开发中的几个关键步骤: 1、首先开启蓝牙  2、搜索可用设备  3、创建蓝牙socket,获取输入输出流  4、...
  • BluetoothKit是一款功能强大的Android蓝牙通信框架,支持经典蓝牙和低功耗蓝牙设备混合扫描,提供了一系列简单易用的接口用于低功耗蓝牙设备的连接,数据读写,通知等。 特点 一、支持经典蓝牙和BLE蓝牙...
  • 简单的蓝牙通讯代码,通过Java在PC端搭建服务端,实现与Android设备间通信。支持多个蓝牙手机同时连接PC进行数据传输
  • 最近在做的蓝牙项目,实现蓝牙互连并通信,适合初学者学习,代码内含详细注释,有不懂的欢迎大家一起探讨
  • 很不错的蓝牙通信demo实现发送和接受功能,就用了两个类就实现了,具体内容如下说下思路把 主要有两个类主界面类和 蓝牙聊天服务类。 首先创建线程 实际上就是创建BluetoothChatService()(蓝牙聊天服务类) 这个时候把...

    很不错的蓝牙通信demo实现发送和接受功能,就用了两个类就实现了,具体内容如下

    说下思路把 主要有两个类主界面类和 蓝牙聊天服务类。 首先创建线程 实际上就是创建BluetoothChatService()(蓝牙聊天服务类) 这个时候把handler 传过去 这样就可以操作UI 界面了,在线程中不断轮询读取蓝牙消息,当主界面点击发送按钮时 调用BluetoothChatService的发送方法write 方法,这里的write 方法 使用了handler 发送消息,在主界面显示,另一个 客户端 不断读取蓝牙消息 类似的有个read 方法 同样显示到界面上去,这样就完成了通信了。

    import java.util.ArrayList;

    import java.util.Set;

    import android.app.Activity;

    import android.app.AlertDialog;

    import android.bluetooth.BluetoothAdapter;

    import android.bluetooth.BluetoothDevice;

    import android.content.BroadcastReceiver;

    import android.content.Context;

    import android.content.DialogInterface;

    import android.content.Intent;

    import android.content.IntentFilter;

    import android.os.Bundle;

    import android.os.Handler;

    import android.os.Message;

    import android.util.Log;

    import android.view.Menu;

    import android.view.MenuItem;

    import android.view.View;

    import android.view.View.OnClickListener;

    import android.view.Window;

    import android.widget.Button;

    import android.widget.EditText;

    import android.widget.TextView;

    import android.widget.Toast;

    public class BluetoothChat extends Activity {

    // Message types sent from the BluetoothChatService Handler

    public static final int MESSAGE_STATE_CHANGE = 1;

    public static final int MESSAGE_READ = 2;

    public static final int MESSAGE_WRITE = 3;

    public static final int MESSAGE_DEVICE_NAME = 4;

    public static final int MESSAGE_TOAST = 5;

    // Key names received from the BluetoothChatService Handler

    public static final String DEVICE_NAME = "device_name";

    public static final String TOAST = "toast";

    // Intent request codes

    private static final int REQUEST_CONNECT_DEVICE = 1;

    private static final int REQUEST_ENABLE_BT = 2;

    private TextView mTitle;

    private EditText text_chat;

    private EditText text_input;

    private Button but_On_Off;

    private Button but_search; // ------> 在菜单中可以搜索

    private Button but_create; // ------> 在菜单中设置"可被发现"

    private Button mSendButton;

    // 连接到的蓝牙设备的名称

    private String mConnectedDeviceName;

    // String buffer for outgoing messages

    private StringBuffer mOutStringBuffer;

    // Local Bluetooth adapter

    private BluetoothAdapter mBluetoothAdapter = null;

    // Member object for the chat services

    private BluetoothChatService mChatService = null;

    private ArrayList mPairedDevicesList = new ArrayList();

    private ArrayList mNewDevicesList = new ArrayList();

    private String[] strName;

    private String address;

    @Override

    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);

    setContentView(R.layout.main);

    mTitle = (TextView) this.findViewById(R.id.text_title);

    text_chat = (EditText) this.findViewById(R.id.text_chat);

    text_input = (EditText) this.findViewById(R.id.text_input);

    but_On_Off = (Button) this.findViewById(R.id.but_off_on);

    but_search = (Button) this.findViewById(R.id.but_search_div);

    but_create = (Button) this.findViewById(R.id.but_cjlj);

    mSendButton = (Button) this.findViewById(R.id.but_fsxx);

    // 获得本地的蓝牙适配器

    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    // 如果为null,说明没有蓝牙设备

    if (mBluetoothAdapter == null) {

    Toast.makeText(this, "没有蓝牙设备", Toast.LENGTH_LONG).show();

    finish();

    return;

    }

    if (mBluetoothAdapter.isEnabled()) {

    but_On_Off.setText("关闭蓝牙");

    } else {

    but_On_Off.setText("开启蓝牙");

    }

    but_On_Off.setOnClickListener(new OnClickListener() {

    @Override

    public void onClick(View v) {

    if (!mBluetoothAdapter.isEnabled()) {

    mBluetoothAdapter.enable();

    Toast.makeText(BluetoothChat.this, "蓝牙已开启",

    Toast.LENGTH_SHORT).show();

    but_On_Off.setText("关闭蓝牙");

    } else {

    mBluetoothAdapter.disable();

    Toast.makeText(BluetoothChat.this, "蓝牙已关闭",

    Toast.LENGTH_SHORT).show();

    but_On_Off.setText("开启蓝牙");

    }

    }

    });

    but_search.setOnClickListener(new OnClickListener() {

    @Override

    public void onClick(View v) {

    searchDevice();

    }

    });

    but_create.setOnClickListener(new OnClickListener() {

    @Override

    public void onClick(View v) {

    final EditText et = new EditText(BluetoothChat.this);

    et.setSingleLine();

    et.setText(mBluetoothAdapter.getName());

    new AlertDialog.Builder(BluetoothChat.this)

    .setTitle("请输入房间名:")

    .setView(et)

    .setPositiveButton("确定",

    new DialogInterface.OnClickListener() {

    @Override

    public void onClick(DialogInterface dialog,

    int which) {

    String name = et.getText().toString()

    .trim();

    if (name.equals("")) {

    Toast.makeText(BluetoothChat.this,

    "请输入房间名",

    Toast.LENGTH_SHORT).show();

    return;

    }

    // 设置房间名

    mBluetoothAdapter.setName(name);

    }

    })

    .setNegativeButton("取消",

    new DialogInterface.OnClickListener() {

    @Override

    public void onClick(DialogInterface dialog,

    int which) {

    }

    }).create().show();

    // 创建连接,也就是设备本地蓝牙设备可被其他用户的蓝牙搜到

    ensureDiscoverable();

    }

    });

    // 获得一个已经配对的蓝牙设备的set集合

    Set pairedDevices = mBluetoothAdapter

    .getBondedDevices();

    if (pairedDevices.size() > 0) {

    for (BluetoothDevice device : pairedDevices) {

    mPairedDevicesList.add("已配对:" + device.getName() + "\n"

    + device.getAddress());

    }

    } else {

    Toast.makeText(this, "没有已配对的设备", Toast.LENGTH_SHORT).show();

    }

    // 当发现一个新的蓝牙设备时注册广播

    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);

    this.registerReceiver(mReceiver, filter);

    // 当搜索完毕后注册广播

    filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

    this.registerReceiver(mReceiver, filter);

    }

    @Override

    public void onStart() {

    super.onStart();

    // If BT is not on, request that it be enabled.

    // setupChat() will then be called during onActivityResult

    if (!mBluetoothAdapter.isEnabled()) {

    Intent enableIntent = new Intent(

    BluetoothAdapter.ACTION_REQUEST_ENABLE);

    startActivityForResult(enableIntent, REQUEST_ENABLE_BT);

    // Otherwise, setup the chat session

    } else {

    if (mChatService == null)

    setupChat();

    }

    }

    @Override

    public synchronized void onResume() {

    super.onResume();

    // Performing this check in onResume() covers the case in which BT was

    // not enabled during onStart(), so we were paused to enable it...

    // onResume() will be called when ACTION_REQUEST_ENABLE activity

    // returns.

    if (mChatService != null) {

    // Only if the state is STATE_NONE, do we know that we haven't

    // started already

    if (mChatService.getState() == BluetoothChatService.STATE_NONE) {

    // Start the Bluetooth chat services

    mChatService.start();

    }

    }

    }

    private void setupChat() {

    mSendButton.setOnClickListener(new OnClickListener() {

    public void onClick(View v) {

    // Send a message using content of the edit text widget

    String message = text_input.getText().toString();

    sendMessage(message);

    }

    });

    // Initialize the BluetoothChatService to perform bluetooth connections

    mChatService = new BluetoothChatService(this, mHandler);

    // Initialize the buffer for outgoing messages

    mOutStringBuffer = new StringBuffer("");

    }

    @Override

    public void onDestroy() {

    super.onDestroy();

    // Stop the Bluetooth chat services

    if (mChatService != null)

    mChatService.stop();

    // Make sure we're not doing discovery anymore

    if (mBluetoothAdapter != null) {

    mBluetoothAdapter.cancelDiscovery();

    }

    // Unregister broadcast listeners

    this.unregisterReceiver(mReceiver);

    }

    /** 使本地的蓝牙设备可被发现 */

    private void ensureDiscoverable() {

    if (mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {

    Intent discoverableIntent = new Intent(

    BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);

    discoverableIntent.putExtra(

    BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);

    startActivity(discoverableIntent);

    }

    }

    /**

    * Sends a message.

    *

    * @param message

    * A string of text to send.

    */

    private void sendMessage(String message) {

    // Check that we're actually connected before trying anything

    if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {

    Toast.makeText(this, "没有连接上", Toast.LENGTH_SHORT).show();

    return;

    }

    // Check that there's actually something to send

    if (message.length() > 0) {

    // Get the message bytes and tell the BluetoothChatService to write

    byte[] send = message.getBytes();

    mChatService.write(send);

    // Reset out string buffer to zero and clear the edit text field

    mOutStringBuffer.setLength(0);

    text_input.setText(mOutStringBuffer);

    }

    }

    // The Handler that gets information back from the BluetoothChatService

    private final Handler mHandler = new Handler() {

    @Override

    public void handleMessage(Message msg) {

    switch (msg.what) {

    case MESSAGE_STATE_CHANGE:

    switch (msg.arg1) {

    case BluetoothChatService.STATE_CONNECTED:

    mTitle.setText("已经连接");

    mTitle.append(mConnectedDeviceName);

    // mConversationArrayAdapter.clear();

    break;

    case BluetoothChatService.STATE_CONNECTING:

    mTitle.setText("正在连接中...");

    break;

    case BluetoothChatService.STATE_LISTEN:

    case BluetoothChatService.STATE_NONE:

    mTitle.setText("未连接上");

    break;

    }

    break;

    case MESSAGE_WRITE:

    byte[] writeBuf = (byte[]) msg.obj;

    // construct a string from the buffer

    String writeMessage = new String(writeBuf);

    // mConversationArrayAdapter.add("Me: " + writeMessage);

    text_chat.append("我:" + writeMessage + "\n");

    break;

    case MESSAGE_READ:

    byte[] readBuf = (byte[]) msg.obj;

    // construct a string from the valid bytes in the buffer

    String readMessage = new String(readBuf, 0, msg.arg1);

    // mConversationArrayAdapter.add(mConnectedDeviceName+": " +

    // readMessage);

    text_chat.append(mConnectedDeviceName + ":" + readMessage

    + "\n");

    break;

    case MESSAGE_DEVICE_NAME:

    // save the connected device's name

    mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);

    Toast.makeText(getApplicationContext(),

    "连接到 " + mConnectedDeviceName, Toast.LENGTH_SHORT)

    .show();

    break;

    case MESSAGE_TOAST:

    Toast.makeText(getApplicationContext(),

    msg.getData().getString(TOAST), Toast.LENGTH_SHORT)

    .show();

    break;

    }

    }

    };

    // 连接蓝牙设备

    private void linkDevice() {

    if (mBluetoothAdapter.isDiscovering()) {

    mBluetoothAdapter.cancelDiscovery();

    }

    int cou = mPairedDevicesList.size() + mNewDevicesList.size();

    if (cou == 0) {

    Toast.makeText(BluetoothChat.this, "没有搜索到可用的蓝牙设备",

    Toast.LENGTH_SHORT).show();

    return;

    }

    // 把已经配对的蓝牙设备和新发现的蓝牙设备的名称都放入数组中,以便在对话框列表中显示

    strName = new String[cou];

    for (int i = 0; i < mPairedDevicesList.size(); i++) {

    strName[i] = mPairedDevicesList.get(i);

    }

    for (int i = mPairedDevicesList.size(); i < strName.length; i++) {

    strName[i] = mNewDevicesList.get(i - mPairedDevicesList.size());

    }

    address = strName[0].substring(strName[0].length() - 17);

    new AlertDialog.Builder(BluetoothChat.this)

    .setTitle("搜索到的蓝牙设备:")

    .setSingleChoiceItems(strName, 0,

    new DialogInterface.OnClickListener() {

    @Override

    public void onClick(DialogInterface dialog,

    int which) {

    // 当用户点击选中的蓝牙设备时,取出选中的蓝牙设备的MAC地址

    address = strName[which].split("\\n")[1].trim();

    }

    })

    .setPositiveButton("连接", new DialogInterface.OnClickListener() {

    @Override

    public void onClick(DialogInterface dialog, int which) {

    if (address == null) {

    Toast.makeText(BluetoothChat.this, "请先连接外部蓝牙设备",

    Toast.LENGTH_SHORT).show();

    return;

    }

    Log.i("sxd", "address:" + address);

    // Get the BLuetoothDevice object

    BluetoothDevice device = mBluetoothAdapter

    .getRemoteDevice(address);

    // Attempt to connect to the device

    mChatService.connect(device);

    }

    })

    .setNegativeButton("取消", new DialogInterface.OnClickListener() {

    @Override

    public void onClick(DialogInterface dialog, int which) {

    }

    }).create().show();

    }

    // 搜索蓝牙设备蓝牙设备

    private void searchDevice() {

    mTitle.setText("正在努力搜索中...");

    setProgressBarIndeterminateVisibility(true);

    if (mBluetoothAdapter.isDiscovering()) {

    mBluetoothAdapter.cancelDiscovery();

    }

    mNewDevicesList.clear();

    mBluetoothAdapter.startDiscovery();

    }

    @Override

    public boolean onCreateOptionsMenu(Menu menu) {

    menu.add(0, 1, 0, "搜索设备");

    menu.add(0, 2, 0, "可被发现");

    return true;

    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {

    @Override

    public void onReceive(Context context, Intent intent) {

    String action = intent.getAction();

    // 当发现一个新的蓝牙设备时

    if (BluetoothDevice.ACTION_FOUND.equals(action)) {

    BluetoothDevice device = intent

    .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

    // If it's already paired, skip it, because it's been listed

    // already

    if (device.getBondState() != BluetoothDevice.BOND_BONDED) {

    String s = "未配对: " + device.getName() + "\n"

    + device.getAddress();

    if (!mNewDevicesList.contains(s))

    mNewDevicesList.add(s);

    }

    // When discovery is finished, change the Activity title

    } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED

    .equals(action)) {

    setProgressBarIndeterminateVisibility(false);

    if (mNewDevicesList.size() == 0) {

    Toast.makeText(BluetoothChat.this, "没有发现新设备",

    Toast.LENGTH_SHORT).show();

    }

    mTitle.setText("未连接");

    linkDevice();

    }

    }

    };

    @Override

    public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {

    case 1:

    searchDevice();

    return true;

    case 2:

    // Ensure this device is discoverable by others

    ensureDiscoverable();

    return true;

    }

    return false;

    }

    }

    package com.it2388.bluetooth;

    /*

    * Copyright (C) 2009 The Android Open Source Project

    *

    * Licensed under the Apache License, Version 2.0 (the "License");

    * you may not use this file except in compliance with the License.

    * You may obtain a copy of the License at

    *

    * http://www.apache.org/licenses/LICENSE-2.0

    *

    * Unless required by applicable law or agreed to in writing, software

    * distributed under the License is distributed on an "AS IS" BASIS,

    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

    * See the License for the specific language governing permissions and

    * limitations under the License.

    */

    import java.io.IOException;

    import java.io.InputStream;

    import java.io.OutputStream;

    import java.util.UUID;

    import android.bluetooth.BluetoothAdapter;

    import android.bluetooth.BluetoothDevice;

    import android.bluetooth.BluetoothServerSocket;

    import android.bluetooth.BluetoothSocket;

    import android.content.Context;

    import android.os.Bundle;

    import android.os.Handler;

    import android.os.Message;

    import android.util.Log;

    /**

    * This class does all the work for setting up and managing Bluetooth

    * connections with other devices. It has a thread that listens for incoming

    * connections, a thread for connecting with a device, and a thread for

    * performing data transmissions when connected.

    *

    * *这个类做所有的工作,建立和管理蓝牙 与其他设备的连接。它有一个线程监听 传入的连接,一个用于连接一个设备的线程,和一个 当连接时执行数据传输的线程。

    */

    public class BluetoothChatService {

    // Debugging

    private static final String TAG = "BluetoothChatService";

    private static final boolean D = true;

    // Name for the SDP record when creating server socket 对于SDP记录名称创建服务器套接字时

    private static final String NAME = "BluetoothChat";

    // Unique UUID for this application

    private static final UUID MY_UUID = UUID

    .fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");

    // Member fields

    private final BluetoothAdapter mAdapter;

    private final Handler mHandler;

    private AcceptThread mAcceptThread;

    private ConnectThread mConnectThread;

    private ConnectedThread mConnectedThread;

    private int mState;

    // Constants that indicate the current connection state

    public static final int STATE_NONE = 0; // we're doing nothing 我们什么都不做

    public static final int STATE_LISTEN = 1; // now listening for incoming 现在监听

    // connections

    public static final int STATE_CONNECTING = 2; // now initiating an outgoing

    // 启动一个外向

    // connection

    public static final int STATE_CONNECTED = 3; // now connected to a remote

    // 连接到一个远程

    // device

    /**

    * Constructor. Prepares a new BluetoothChat session.

    *

    * @param context

    * The UI Activity Context

    * @param handler

    * A Handler to send messages back to the UI Activity

    */

    public BluetoothChatService(Context context, Handler handler) {

    mAdapter = BluetoothAdapter.getDefaultAdapter();

    mState = STATE_NONE;

    mHandler = handler;

    }

    /**

    * Set the current state of the chat connection

    *

    * @param state

    * An integer defining the current connection state

    */

    private synchronized void setState(int state) {

    if (D)

    Log.d(TAG, "setState() " + mState + " -> " + state);

    mState = state;

    // Give the new state to the Handler so the UI Activity can update

    mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1)

    .sendToTarget();

    }

    /**

    * Return the current connection state.

    */

    public synchronized int getState() {

    return mState;

    }

    /**

    * Start the chat service. Specifically start AcceptThread to begin a

    * session in listening (server) mode. Called by the Activity onResume()

    */

    public synchronized void start() {

    if (D)

    Log.d(TAG, "start");

    // Cancel any thread attempting to make a connection

    if (mConnectThread != null) {

    mConnectThread.cancel();

    mConnectThread = null;

    }

    // Cancel any thread currently running a connection

    if (mConnectedThread != null) {

    mConnectedThread.cancel();

    mConnectedThread = null;

    }

    // Start the thread to listen on a BluetoothServerSocket

    if (mAcceptThread == null) {

    mAcceptThread = new AcceptThread();

    mAcceptThread.start();

    }

    setState(STATE_LISTEN);

    }

    /**

    * Start the ConnectThread to initiate a connection to a remote device.

    *

    * @param device

    * The BluetoothDevice to connect

    */

    public synchronized void connect(BluetoothDevice device) {

    if (D)

    Log.d(TAG, "connect to: " + device);

    // Cancel any thread attempting to make a connection

    if (mState == STATE_CONNECTING) {

    if (mConnectThread != null) {

    mConnectThread.cancel();

    mConnectThread = null;

    }

    }

    // Cancel any thread currently running a connection

    if (mConnectedThread != null) {

    mConnectedThread.cancel();

    mConnectedThread = null;

    }

    // Start the thread to connect with the given device

    mConnectThread = new ConnectThread(device);

    mConnectThread.start();

    setState(STATE_CONNECTING);

    }

    /**

    * Start the ConnectedThread to begin managing a Bluetooth connection

    *

    * @param socket

    * The BluetoothSocket on which the connection was made

    * @param device

    * The BluetoothDevice that has been connected

    */

    public synchronized void connected(BluetoothSocket socket,

    BluetoothDevice device) {

    if (D)

    Log.d(TAG, "connected");

    // Cancel the thread that completed the connection

    if (mConnectThread != null) {

    mConnectThread.cancel();

    mConnectThread = null;

    }

    // Cancel any thread currently running a connection

    if (mConnectedThread != null) {

    mConnectedThread.cancel();

    mConnectedThread = null;

    }

    // Cancel the accept thread because we only want to connect to one

    // device

    if (mAcceptThread != null) {

    mAcceptThread.cancel();

    mAcceptThread = null;

    }

    // Start the thread to manage the connection and perform transmissions

    mConnectedThread = new ConnectedThread(socket);

    mConnectedThread.start();

    // Send the name of the connected device back to the UI Activity

    Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);

    Bundle bundle = new Bundle();

    bundle.putString(BluetoothChat.DEVICE_NAME, device.getName());

    msg.setData(bundle);

    mHandler.sendMessage(msg);

    setState(STATE_CONNECTED);

    }

    /**

    * Stop all threads

    */

    public synchronized void stop() {

    if (D)

    Log.d(TAG, "stop");

    if (mConnectThread != null) {

    mConnectThread.cancel();

    mConnectThread = null;

    }

    if (mConnectedThread != null) {

    mConnectedThread.cancel();

    mConnectedThread = null;

    }

    if (mAcceptThread != null) {

    mAcceptThread.cancel();

    mAcceptThread = null;

    }

    setState(STATE_NONE);

    }

    /**

    * Write to the ConnectedThread in an unsynchronized manner

    *

    * @param out

    * The bytes to write

    * @see ConnectedThread#write(byte[])

    */

    public void write(byte[] out) {

    // Create temporary object

    ConnectedThread r;

    // Synchronize a copy of the ConnectedThread

    synchronized (this) {

    if (mState != STATE_CONNECTED)

    return;

    r = mConnectedThread;

    }

    // Perform the write unsynchronized

    r.write(out);

    }

    /**

    * Indicate that the connection attempt failed and notify the UI Activity.

    */

    private void connectionFailed() {

    setState(STATE_LISTEN);

    // Send a failure message back to the Activity

    Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);

    Bundle bundle = new Bundle();

    bundle.putString(BluetoothChat.TOAST, "不能连接到设备");

    msg.setData(bundle);

    mHandler.sendMessage(msg);

    }

    /**

    * Indicate that the connection was lost and notify the UI Activity.

    */

    private void connectionLost() {

    setState(STATE_LISTEN);

    // Send a failure message back to the Activity

    Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);

    Bundle bundle = new Bundle();

    bundle.putString(BluetoothChat.TOAST, "设备连接中断");

    msg.setData(bundle);

    mHandler.sendMessage(msg);

    }

    /**

    * This thread runs while listening for incoming connections. It behaves

    * like a server-side client. It runs until a connection is accepted (or

    * until cancelled).

    */

    private class AcceptThread extends Thread {

    // The local server socket

    private final BluetoothServerSocket mmServerSocket;

    public AcceptThread() {

    BluetoothServerSocket tmp = null;

    // Create a new listening server socket

    try {

    tmp = mAdapter

    .listenUsingRfcommWithServiceRecord(NAME, MY_UUID);

    } catch (IOException e) {

    Log.e("sxd", " ======== ufcomm exception =======", e);

    }

    mmServerSocket = tmp;

    }

    public void run() {

    if (D)

    Log.d(TAG, "BEGIN mAcceptThread" + this);

    setName("AcceptThread");

    BluetoothSocket socket = null;

    // Listen to the server socket if we're not connected

    while (mState != STATE_CONNECTED) {

    try {

    // This is a blocking call and will only return on a

    // successful connection or an exception

    socket = mmServerSocket.accept();

    } catch (IOException e) {

    Log.e("sxd", "---> accept socket failed

    break;

    }

    // If a connection was accepted

    if (socket != null) {

    synchronized (BluetoothChatService.this) {

    switch (mState) {

    case STATE_LISTEN:

    case STATE_CONNECTING:

    // Situation normal. Start the connected thread.

    connected(socket, socket.getRemoteDevice());

    break;

    case STATE_NONE:

    case STATE_CONNECTED:

    // Either not ready or already connected. Terminate

    // new socket.

    try {

    socket.close();

    } catch (IOException e) {

    Log.e(TAG, "Could not close unwanted socket", e);

    }

    break;

    }

    }

    }

    }

    if (D)

    Log.i(TAG, "END mAcceptThread");

    }

    public void cancel() {

    if (D)

    Log.d(TAG, "cancel " + this);

    try {

    mmServerSocket.close();

    } catch (IOException e) {

    Log.e(TAG, "close() of server failed", e);

    }

    }

    }

    /**

    * This thread runs while attempting to make an outgoing connection with a

    * device. It runs straight through; the connection either succeeds or

    * fails.

    */

    private class ConnectThread extends Thread {

    private final BluetoothSocket mmSocket;

    private final BluetoothDevice mmDevice;

    public ConnectThread(BluetoothDevice device) {

    mmDevice = device;

    BluetoothSocket tmp = null;

    // Get a BluetoothSocket for a connection with the

    // given BluetoothDevice

    try {

    tmp = device.createRfcommSocketToServiceRecord(MY_UUID);

    } catch (IOException e) {

    Log.e(TAG, "create() failed", e);

    }

    mmSocket = tmp;

    }

    public void run() {

    Log.i(TAG, "BEGIN mConnectThread");

    setName("ConnectThread");

    // Always cancel discovery because it will slow down a connection

    mAdapter.cancelDiscovery();

    // Make a connection to the BluetoothSocket

    try {

    // This is a blocking call and will only return on a

    // successful connection or an exception

    mmSocket.connect();

    } catch (IOException e) {

    Log.e("sxd", "链接发生了异常", e);

    connectionFailed();

    // Close the socket

    try {

    mmSocket.close();

    } catch (IOException e2) {

    Log.e(TAG,

    "unable to close() socket during connection failure",

    e2);

    }

    // Start the service over to restart listening mode

    BluetoothChatService.this.start();

    return;

    }

    // Reset the ConnectThread because we're done

    synchronized (BluetoothChatService.this) {

    mConnectThread = null;

    }

    // Start the connected thread

    connected(mmSocket, mmDevice);

    }

    public void cancel() {

    try {

    mmSocket.close();

    } catch (IOException e) {

    Log.e(TAG, "close() of connect socket failed", e);

    }

    }

    }

    /**

    * This thread runs during a connection with a remote device. It handles all

    * incoming and outgoing transmissions.

    *

    * 和已经建立连接的设置进行数据的传输

    */

    private class ConnectedThread extends Thread {

    private final BluetoothSocket mmSocket;

    private final InputStream mmInStream;

    private final OutputStream mmOutStream;

    public ConnectedThread(BluetoothSocket socket) {

    Log.d(TAG, "create ConnectedThread");

    mmSocket = socket;

    InputStream tmpIn = null;

    OutputStream tmpOut = null;

    // Get the BluetoothSocket input and output streams

    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.i(TAG, "BEGIN mConnectedThread");

    byte[] buffer = new byte[1024];

    int bytes;

    // Keep listening to the InputStream while connected

    while (true) {

    try {

    // Read from the InputStream

    bytes = mmInStream.read(buffer);

    // Send the obtained bytes to the UI Activity

    mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes,

    -1, buffer).sendToTarget();

    } catch (IOException e) {

    Log.e(TAG, "disconnected", e);

    connectionLost();

    break;

    }

    }

    }

    /**

    * Write to the connected OutStream.

    *

    * @param buffer

    * The bytes to write

    */

    public void write(byte[] buffer) {

    try {

    mmOutStream.write(buffer);

    // Share the sent message back to the UI Activity

    mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1,

    buffer).sendToTarget();

    } catch (IOException e) {

    Log.e(TAG, "Exception during write", e);

    }

    }

    public void cancel() {

    try {

    mmSocket.close();

    } catch (IOException e) {

    Log.e(TAG, "close() of connect socket failed", e);

    }

    }

    }

    }

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,637
精华内容 7,454
关键字:

安卓蓝牙通信