星期三, 05. 九月 2018 02:03上午 – beautifulzzzz

首先须求在清单配置内部增多七个权力:

未来成千上万做蓝牙( Bluetooth® 卡塔尔应用软件的都亟需同一时间连接五个设施,那该怎么手艺同期管住三个设备呢?以下是本人的艺术,首要是经过ArrayMap来管理不相同器材的BluetoothGatt,然后使用各自的BluetoothGatt来和从机实行多少人机联作,大家能够绑定该service进行方式的调用。

android
bluetooth——蓝牙( Bluetooth® 卡塔 尔(阿拉伯语:قطر‎的拉开、搜索、配成对与连接

最关键四个类:

图片 1

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
public class BluetoothLeService2 extends Service {

private ArrayMap<String, BluetoothGatt> gattArrayMap = new ArrayMap<>();
private BluetoothAdapter mBluetoothAdapter;

@Override
public void onCreate() {
    super.onCreate();
    initBluetooth();
}

/**
 * 蓝牙是否开启
 */
public boolean isBluetoothEnabled() {
    return mBluetoothAdapter.isEnabled();
}


private void initBluetooth() {
    BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = bluetoothManager.getAdapter();
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return super.onStartCommand(intent, Service.START_FLAG_RETRY, startId);
}


@Override
public IBinder onBind(Intent intent) {
    return mBinder;
}


public class LocalBinder extends Binder {
    public BluetoothLeService2 getService() {
        return BluetoothLeService2.this;
    }
}

private final IBinder mBinder = new LocalBinder();

@Override
public boolean onUnbind(Intent intent) {
    return super.onUnbind(intent);
}


/**
 * 连接设备
 *
 * @param address 设备地址
 */
public synchronized void connect(final String address) {
    BluetoothGatt gatt = gattArrayMap.get(address);
    if (gatt != null) {
        gatt.disconnect();
        gatt.close();
        gattArrayMap.remove(address);
    }
    BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
    if (device == null) return;
    device.connectGatt(this, false, mGattCallback);
}

//蓝牙连接,数据通信的回掉
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) {
        String address = gatt.getDevice().getAddress();
        if (status == BluetoothGatt.GATT_SUCCESS) {
            if (newState == BluetoothGatt.STATE_CONNECTED) {// 连接成功
                gatt.discoverServices();// 寻找服务
                gattArrayMap.put(address, gatt);
                Log.i("yushu", "connect succeed: ");
            } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {// 断开连接
                onDisConnected(gatt, address);
                Log.i("yushu", "connect fail ");
            }
        } else {
            onDisConnected(gatt, address);
            Log.i("yushu", "connect fail ");
        }
    }


    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            enableNotification(gatt);//notification
        }
    }


    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        byte[] value = characteristic.getValue();
/**
 * 这里可以拿到设备notification回来的数据
*/

    }


    @Override
    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
        super.onReadRemoteRssi(gatt, rssi, status);
        if (status == BluetoothGatt.GATT_SUCCESS) {

        }
    }
};


private void onDisConnected(BluetoothGatt gatt, String address) {
    gatt.disconnect();
    gatt.close();
}


/**
 * 使能通知
 */
private void enableNotification(BluetoothGatt mBluetoothGatt) {
    if (mBluetoothGatt == null) return;
    BluetoothGattService ableService = mBluetoothGatt.getService(UUIDUtils.UUID_LOST_SERVICE);
    if (ableService == null) return;
    BluetoothGattCharacteristic TxPowerLevel = ableService.getCharacteristic(UUIDUtils.UUID_LOST_ENABLE);
    if (TxPowerLevel == null) return;
    setCharacteristicNotification(mBluetoothGatt, TxPowerLevel, true);
}

/**
 * 使能通知
 */
private void setCharacteristicNotification(BluetoothGatt mBluetoothGatt, BluetoothGattCharacteristic characteristic, boolean enabled) {
    if (mBluetoothGatt == null) return;
    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
    if (UUIDUtils.UUID_LOST_ENABLE.equals(characteristic.getUuid())) {
        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUIDUtils.CLIENT_CHARACTERISTIC_CONFIG);
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        mBluetoothGatt.writeDescriptor(descriptor);
    }
}


/**
 * 写数据到硬件,这里的服务UUID和特这的UUID参考硬件那边,两边要对应
 */
public synchronized void writeDataToDevice(byte[] bs, String address) {
    BluetoothGatt mBluetoothGatt = gattArrayMap.get(address);
    if (mBluetoothGatt == null) return;
    BluetoothGattService alertService = mBluetoothGatt.getService(UUIDUtils.UUID_LOST_SERVICE);
    if (alertService == null) return;
    BluetoothGattCharacteristic alertLevel = alertService.getCharacteristic(UUIDUtils.UUID_LOST_WRITE);
    if (alertLevel == null) return;
    alertLevel.setValue(bs);
    alertLevel.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
    mBluetoothGatt.writeCharacteristic(alertLevel);
}


public boolean readRssi(String address) {
    BluetoothGatt bluetoothGatt = gattArrayMap.get(address);
    return bluetoothGatt != null && bluetoothGatt.readRemoteRssi();
}


public void remove(String address) {
    BluetoothGatt bluetoothGatt = gattArrayMap.get(address);
    if (bluetoothGatt != null) {
        bluetoothGatt.disconnect();
        bluetoothGatt.close();
        gattArrayMap.remove(address);
    }
}

public void disConnect(String address) {
    BluetoothGatt bluetoothGatt = gattArrayMap.get(address);
    if (bluetoothGatt != null) {
        bluetoothGatt.disconnect();
        gattArrayMap.remove(address);
    }
}


@Override
public void onDestroy() {
    gattArrayMap.clear();
    super.onDestroy();
}
}

在一而再再而三一遍后退出再连接蓝牙5.0设备时会报以下错误:
06-14 10:37:49.916 6304-6347/com.bluetooth.demo W/System.err:
java.io.IOException: read failed, socket might closed or timeout, read
ret: -1

BluetoothAdapter bluetoothAdapter

1、前言

上生龙活虎篇讲了什么编写翻译安装BlueZ-5,本篇主要在于玩BlueZ,用命令行去操作BLE设备:

  • [BlueZ] 1、Download install and use the BlueZ and hcitool on PI
    3B+

图片 2

android里面蓝牙( Bluetooth® 卡塔 尔(英语:State of Qatar)是透过Bluetooth( Bluetooth® 卡塔尔国Adapter来展开操作的,所以率先大家要求获得到蓝牙5.0( Bluetooth® 卡塔尔Adapter的实例

查阅google说明文书档案

BluetoothSocket btSocket;

2、gatttool —— 老工具趟坑

刚初始跟着 Get Started with Bluetooth Low Energy on
Linux
操作gatttool,开采坑太多(主因是工具老了卡塔尔:

采用sudo gatttool -b 4D:69:98:0E:91:5E -I去连接
察觉会报错:Error: connect error: Connection refused (111)
最后参谋LINK-11发掘必要加random选项([\#1](https://stackoverflow.com/questions/32947807/cannot-connect-to-ble-device-on-raspberry-pi))

➜  ~  sudo gatttool -b 4D:69:98:0E:91:5E -I
[4D:69:98:0E:91:5E][LE]> connect
Attempting to connect to 4D:69:98:0E:91:5E
Error: connect error: Connection refused (111)
[4D:69:98:0E:91:5E][LE]> exit
➜  ~  sudo gatttool  -t random  -b 4D:69:98:0E:91:5E -I
[4D:69:98:0E:91:5E][LE]> connect
Attempting to connect to 4D:69:98:0E:91:5E
Connection successful
[4D:69:98:0E:91:5E][LE]> 
(gatttool:3104): GLib-WARNING **: Invalid file descriptor.

过二次会10S电动断开,英特网说这么些工具岁数大了,不建议用了([\#2](https://www.spinics.net/lists/linux-bluetooth/msg67617.html)):

There are new tools to use with GATT, bluetoothctl/bluetoothd is the preferred since with that you have GAP, etc, 
but if want to use a stand alone tool then I suggest you use btgatt-client.

图片 3

//先获取BlueToothAdapter的实例
BluetoothAdapter blueToothAdapter = BluetoothAdapter.getDefaultAdapter();

图片 4

BluetoothDevice device

3、bluetoothctl——NB的新工具

指令行踏向bluetoothctl操作碰着([\#6](https://mcuoneclipse.com/2016/12/19/tutorial-ble-pairing-the-raspberry-pi-3-model-b-with-hexiwear/))

bluetoothctl

自个儿在四哥伦比亚大学上用lightblue模拟三个BLE设备ty_prod,之后对其service举行改换,调用scan
on进行查找依旧老的,
谈到底开采要先用remove移除早先的装置,之后再scan就能不能自已[NEW] Device 72:3B:E1:81:4E:4F ty_prod设备
注: 用lightblue模拟的装置的MAC不是长久的
注:
小编发今后lightblue中不管怎么模拟BLE设备,风度翩翩旦被连上找出到的service都以IPone的

[bluetooth]# devices
Device 28:ED:6A:A0:26:B7 ty_prod
Device 58:71:33:00:00:24 Bluetooth Keyboard
Device 00:1A:7D:DA:71:0A SHEN-PC
Device 94:87:E0:B3:AC:6F Mi Phone
[bluetooth]# remove 28:ED:6A:A0:26:B7 
...
[bluetooth]# scan on
Discovery started
[NEW] Device 72:3B:E1:81:4E:4F ty_prod
[bluetooth]# scan off
...
Discovery stopped
[bluetooth]# connect 72:3B:E1:81:4E:4F
Attempting to connect to 72:3B:E1:81:4E:4F
[CHG] Device 72:3B:E1:81:4E:4F Connected: yes
Connection successful
[ty_prod]

差相当的少就用三星手提式有线电话机自带的劳动做测量试验了~

[ty_prod]# info
Device 28:ED:6A:A0:26:B7 (public)
    Name: tuya_mdev_test
    Alias: tuya_mdev_test
    Appearance: 0x0040
    Icon: phone
    Paired: yes
    Trusted: no
    Blocked: no
    Connected: yes
    LegacyPairing: no
    UUID: Fax                       (00001111-0000-1000-8000-00805f9b34fb)
    UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)
    UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
    UUID: Current Time Service      (00001805-0000-1000-8000-00805f9b34fb)
    UUID: Device Information        (0000180a-0000-1000-8000-00805f9b34fb)
    UUID: Battery Service           (0000180f-0000-1000-8000-00805f9b34fb)
    UUID: Vendor specific           (7905f431-b5ce-4e99-a40f-4b1e122d00d0)
    UUID: Vendor specific           (89d3502b-0f36-433a-8ef4-c502ad55f8dc)
    UUID: Vendor specific           (9fa480e0-4967-4542-9390-d343dc5d04ae)
    UUID: Vendor specific           (d0611e78-bbb4-4591-a5f8-487910ae4366)
[CHG] Device 28:ED:6A:A0:26:B7 ServicesResolved: no
[CHG] Device 28:ED:6A:A0:26:B7 Connected: no

我们用Current Time Service,列出装有attributes操作如下:

[tuya_mdev_test]# menu gatt
[tuya_mdev_test]# list-attributes 28:ED:6A:A0:26:B7
...
Primary Service
    /org/bluez/hci0/dev_47_B1_26_C1_81_18/service0041
    00001805-0000-1000-8000-00805f9b34fb
    Current Time Service
Characteristic
    /org/bluez/hci0/dev_47_B1_26_C1_81_18/service0041/char0045
    00002a0f-0000-1000-8000-00805f9b34fb
    Local Time Information
Characteristic
    /org/bluez/hci0/dev_47_B1_26_C1_81_18/service0041/char0042
    00002a2b-0000-1000-8000-00805f9b34fb
    Current Time
Descriptor
    /org/bluez/hci0/dev_47_B1_26_C1_81_18/service0041/char0042/desc0044
    00002902-0000-1000-8000-00805f9b34fb
    Client Characteristic Configuration
...

上面Current Time Service对应的劳动如下图:

图片 5

咱俩选用Current Time举行操作UUID:0x2A2B

[ty_prod]# select-attribute /org/bluez/hci0/dev_47_B1_26_C1_81_18/service0041/char0042
[tuya_mdev_test:/service0041/char0042]# read
Attempting to read /org/bluez/hci0/dev_47_B1_26_C1_81_18/service0041/char0042
[CHG] Attribute /org/bluez/hci0/dev_47_B1_26_C1_81_18/service0041/char0042 Value:
  e2 07 09 05 01 24 11 03 f1 02                    .....$....      
  e2 07 09 05 01 24 11 03 f1 02                    .....$.... 
[tuya_mdev_test:/service0041/char0042]# attribute-info
Characteristic - Current Time
    UUID: 00002a2b-0000-1000-8000-00805f9b34fb
    Service: /org/bluez/hci0/dev_47_B1_26_C1_81_18/service0041
    Value:
  e2 07 09 05 01 2e 01 03 f5 02                    ..........      
    Notifying: yes
    Flags: read
    Flags: notify

读出结果大约意思应该是:2018-9/5-1:36:17 周三

读取一下0x180A的Device Information:

[tuya_mdev_test:/service0006/char0007]# select-attribute /org/bluez/hci0/dev_47_B1_26_C1_81_18/service0047/char004a
[tuya_mdev_test:/service0047/char004a]# attribute-info
Characteristic - Model Number String
    UUID: 00002a24-0000-1000-8000-00805f9b34fb
    Service: /org/bluez/hci0/dev_47_B1_26_C1_81_18/service0047
    Flags: read
[tuya_mdev_test:/service0047/char004a]# read
Attempting to read /org/bluez/hci0/dev_47_B1_26_C1_81_18/service0047/char004a
[CHG] Attribute /org/bluez/hci0/dev_47_B1_26_C1_81_18/service0047/char004a Value:
  69 50 68 6f 6e 65 36 2c 32                       iPhone6,2       
  69 50 68 6f 6e 65 36 2c 32                       iPhone6,2    

当然写、使能notify也十分轻松,看help就能够。最终断开连接、并脱离!!!

[tuya_mdev_test:/service0047/char004a]# disconnect 28:ED:6A:A0:26:B7
Attempting to disconnect from 28:ED:6A:A0:26:B7
[CHG] Device 28:ED:6A:A0:26:B7 ServicesResolved: no
Successful disconnected
[CHG] Device 28:ED:6A:A0:26:B7 Connected: no
[bluetooth]# quit

图片 6

在查找从前,我们能够先获得与大家配对过的设施

Paste_Image.png

bluetoothAdapter =
BluetoothAdapter.getDefaultAdapter();

LINKS

[1].Cannot connect to BLE device on Raspberry
Pi
[2].Invalid file descriptor gatttool of bluez
5.32
[3].Get Started with Bluetooth Low Energy on
Linux
[4].Reverse Engineering a Bluetooth Low Energy Light
Bulb
[5].Doing Bluetooth Low Energy on
Linux
[6].Tutorial: BLE Pairing the Raspberry Pi 3 Model B with
Hexiwear

图片 7

@beautifulzzzz
智能硬件、物联网,热爱技术,关注产品
博客:http://blog.beautifulzzzz.com
园友交流群:414948975
//获取已经配对过的设备的集合
Set<BluetoothDevice> bondedDevices = blueToothAdapter.getBondedDevices()

为了幸免上述荒谬应该在服务端连接一回就重新初始化

bluetoothAdapter.startDiscovery();//起首搜寻左近的蓝牙5.0设备,搜索的时候会发生两个广播如下

而是想要获取到配成对过的配备,我们必需是在

图片 8

startDiscovery()方法是多个异步方法,它会对此外蓝牙( Bluetooth® 卡塔 尔(英语:State of Qatar)设备开展搜寻,持续时间为12秒。寻觅进程实际上是在System
Service中张开,大家得以通过cancelDiscovery()方法来终止那个寻找。在系统查找蓝牙( Bluetooth® 卡塔 尔(阿拉伯语:قطر‎设备的经过中,系统也许会发送以下四个广播:ACTION_DISCOVERY_START(起头寻找),ACTION_DISCOVERY_FINISHED(寻觅停止)和ACTION_FOUND(找到设备)。ACTION_FOUND那么些才是我们想要的。所以在startDiscovery早先大家应有登记二个播放如下:

//手机有蓝牙设备并且蓝牙是打开的
blueToothAdapter != null && blueToothAdapter.isEnabled()

Paste_Image.png

IntentFilter intentfilter = new IntentFilter(
                BluetoothDevice.ACTION_FOUND);
        bluetoothReceiver = new BluetoothReceiver();
        // 注册bluetoothReceiver
        registerReceiver(bluetoothReceiver, intentfilter);

上面大家谈一下蓝牙5.0的<b>张开情势</b>,这段时间作者知道的艺术有3种
第一种:

广播接收类BluetoothReceiver的落实如下:

//强制打开蓝牙
blueToothAdapter.enable();
   public class BluetoothReceiver extends BroadcastReceiver {

        @SuppressLint("ShowToast")
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Toast.makeText(MainActivity.this, "扫描中...", 100).show();
            // device对象代表被扫描到的远程设备的对象
            // 将搜索到的蓝牙设备在ListView中显示出来

            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent
                        .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                String str = device.getName() + "|" + device.getAddress();

                if (lstDevices.indexOf(str) == -1)// 防止重复添加
                    lstDevices.add(str); // 获取设备名称和mac地址
                adtDevices.notifyDataSetChanged();

            }

        }

    }

第二种:

private List<String> lstDevices = new ArrayList<String>();

//会以dialog的形式打开一个activity,并且如果我们通过startActivityForResult的形式的话
//还能查看蓝牙是否被打开,或者处理蓝牙被打开之后的操作
//如果是result_ok的话那么是打开,反之打开失败
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE));

搜寻到了之后就能够把每叁个蓝牙5.0设备的name展现在多少个listview中,点击listview中的有个别设备之后,就能与之开端接连:

第三种:

String str = lstDevices.get(arg2);
            String[] values = str.split("\\|");
            String address = values[1];
            Log.e("address", values[1]);

            uuid = UUID.fromString(SPP_UUID);
            Log.e("uuid", uuid.toString());
            // btDev是远端的蓝牙设备,get到之后,用btsocket得到其中的socket,建立连接的套接字
            BluetoothDevice btDev = bluetoothAdapter.getRemoteDevice(address);
            try {
                btSocket = (BluetoothSocket) btDev
                        .getClass()
                        .getMethod("createRfcommSocket",
                                new Class[] { int.class })
                        .invoke(btDev, Integer.valueOf(1));
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            // 取消查找
            bluetoothAdapter.cancelDiscovery();

            try {
                Toast.makeText(MainActivity.this, "正在连接...", Toast.LENGTH_SHORT)
                        .show();
                btSocket.connect();
                Log.e(TAG,
                        " BT connection established, data transfer link open.");

                Toast.makeText(MainActivity.this, "连接成功,进入控制界面",
                        Toast.LENGTH_SHORT).show();

                // 打开控制界面
                Intent intent = new Intent(MainActivity.this,
                        CtrlActivity.class);
                startActivity(intent);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                Log.e(TAG, " Connection failed.", e);
                Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT)
                        .show();
            }
//设置本地设备可以被其它设备搜索,可被搜索的时间是有限的,最多为300s
//效果和第二种类似
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);

btSocket = btDev.createRfcommSocketToServiceRecord(SPP_UUID);

<b>关闭蓝牙5.0</b>大家能够调用

前边用这种方式给btSocket赋值时,btSocket.connect()便是抛出分外,后来改用如下格局就能够符合规律连接了

blueToothAdapter.disable();

btSocket = (BluetoothSocket) btDev
                        .getClass()
                        .getMethod(“createRfcommSocket”,
                                new Class[] { int.class })
                        .invoke(btDev, Integer.valueOf(1));

接下去是<b>Bluetooth寻觅</b>
率先纵然想要开启Bluetooth找寻,那么只供给调用

静心在实践connect()操作在此以前必供给先

blueToothAdapter.startDiscovery();
bluetoothAdapter.cancelDiscovery();

可是大家该怎么吸取大家搜求到的配备呢,很刚烈当然是通过吸收播放的款型来接过。所以大家应该自定义三个播放接受器,

class BluetoothReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)) {
                Log.e(getPackageName(), "找到新设备了");
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            }
        }
    }

如上代码,我们能够取获得搜索到的蓝牙( Bluetooth® 卡塔尔设备。我们只需在代码里面注册这么些广播接纳器,在调用蓝牙( Bluetooth® 卡塔 尔(英语:State of Qatar)的物色方法,就可以实行蓝牙( Bluetooth® 卡塔 尔(阿拉伯语:قطر‎的探究了。

//注册广播
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
registerReceiver(new BluetoothReceiver(), intentFilter);

此间要求留意的是,倘若您的代码将运转在(Build.VECRUISERSION.SDK_INT >=
23卡塔尔国的装置上,那么必需加上以下放权力限,并在代码中动态的报名权限

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

private void requestPermission() {
        if (Build.VERSION.SDK_INT >= 23) {
            int checkAccessFinePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
            if (checkAccessFinePermission != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        REQUEST_PERMISSION_ACCESS_LOCATION);
                Log.e(getPackageName(), "没有权限,请求权限");
                return;
            }
            Log.e(getPackageName(), "已有定位权限");
            //这里可以开始搜索操作
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case REQUEST_PERMISSION_ACCESS_LOCATION: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.e(getPackageName(), "开启权限permission granted!");
                    //这里可以开始搜索操作
                } else {
                    Log.e(getPackageName(), "没有定位权限,请先开启!");
                }
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

再来正是<b>Bluetooth的配成对</b>,近期楼主采纳的是通过反射的款型来调用BluetoothDevice的createBondde()方法,假设大家想监听配没错这一个历程,那么我们可以为广播选取器再登记三个action。

try {
      //如果想要取消已经配对的设备,只需要将creatBond改为removeBond
       Method method = BluetoothDevice.class.getMethod("createBond");
       Log.e(getPackageName(), "开始配对");
       method.invoke(device);
    } catch (Exception e) {
      e.printStackTrace();
    }

//绑定状态发生变化
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);

播音选择器里面大家得以如此写

if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                switch (device.getBondState()) {
                    case BluetoothDevice.BOND_NONE:
                        Log.e(getPackageName(), "取消配对");
                        break;
                    case BluetoothDevice.BOND_BONDING:
                        Log.e(getPackageName(), "配对中");
                        break;
                    case BluetoothDevice.BOND_BONDED:
                        Log.e(getPackageName(), "配对成功");
                        break;
                }
}

再来正是<b>向业已配对的装置发送数据</b>
发送数据分为服务端和顾客端,通过socket来进展消息的相互作用。

服务端

new Thread(new Runnable() {
            @Override
            public void run() {
                InputStream is = null;
                try {
                    BluetoothServerSocket serverSocket = blueToothAdapter.listenUsingRfcommWithServiceRecord("serverSocket", uuid);
                    mHandler.sendEmptyMessage(startService);
                    BluetoothSocket accept = serverSocket.accept();
                    is = accept.getInputStream();

                    byte[] bytes = new byte[1024];
                    int length = is.read(bytes);

                    Message msg = new Message();
                    msg.what = getMessageOk;
                    msg.obj = new String(bytes, 0, length);
                    mHandler.sendMessage(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

客户端

new Thread(new Runnable() {
            @Override
            public void run() {
                OutputStream os = null;
                try {
                    BluetoothSocket socket = strArr.get(i).createRfcommSocketToServiceRecord(uuid);
                    socket.connect();
                    os = socket.getOutputStream();
                    os.write("testMessage".getBytes());
                    os.flush();
                    mHandler.sendEmptyMessage(sendOver);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

能够看看不论是服务端还是顾客端,都亟需新起多少个子线程来操作。那么服务端和客商端是怎么辨识对方的啊,那么就要求用到<b>UUID</b>了,独有当服务端和客商端的<b>UUID</b>同一时间才可以建构连接。

<b>蓝牙( Bluetooth® 卡塔 尔(英语:State of Qatar)连接发送数据的时候的坑</b>
当博主第2回写好客商端服务端测量试验的时候,服务端一直报错

java.io.IOException: bt socket closed, read return: -1

约等于那句话报错

is.read(bytes)

旋即直接感到是读取重返值是-1就能够报错,但是不对啊,早先这么写也没错过,在网络百度了半天,看了别人的博客论坛也不曾解决办法,最终才注意到报错的前一句,

bt socket closed

事先一贯感觉是什么服务端这边,报错连接才会断开,后来风流洒脱想顾客端也会断开连接啊,那才找到难题所在。原本是本身立刻write完数据之后将接连关闭了,那才产生服务端这边连接断开的。所以最主要的事体要说3遍,千万别急着断开连接,千万别急着断开连接,千万别急着断开连接。

<a
href=”;

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图