[英]Write BLE characteristic without discover services Android
是否可以在不事先发现 ble 服务的情况下编写 ble 特性? 我想实现连接到外围设备的应用程序,写入特性并断开连接,然后连接到另一个设备等等......断开连接后我调用gatt.close()
命令来释放所有资源。 在第一次连接时,我创建了绑定。 如果我等待回调onServicesDiscovered
并写入特征:
BluetoothGattService mCustomService = mBluetoothGatt.getService(myUUID));
byte[] values = new byte[]{0x00, 0x01};
mWriteCharacteristic.setValue(values);
if(mBluetoothGatt.writeCharacteristic(mWriteCharacteristic) == false) {
Log.w(TAG, "Failed to write characteristic");
}
一切正常。 但我想改进和加快整个过程。 与bond ble设备连接后,有没有办法跳过发现服务并写入ble char?
BluetoothGattCharacteristic mCharacteristic = new BluetoothGattCharacteristic(UUID.fromString(GattAttributes.P1_MINI_POWER_CHARACTERISTIC), (BluetoothGattCharacteristic.PROPERTY_WRITE |BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE | BluetoothGattCharacteristic.PROPERTY_NOTIFY | BluetoothGattCharacteristic.PROPERTY_EXTENDED_PROPS), 0);
mCustomService.addCharacteristic(mCharacteristic);
byte[] values = new byte[]{0x00, 0x01};
mWriteCharacteristic.setValue(values);
if(mBluetoothGatt.writeCharacteristic(mWriteCharacteristic) == false) {
Log.w(TAG, "Failed to write characteristic");
}
但没有任何成功。
不,您必须使用discoverServices。 你不能自己写定义。 很多原因之一是 BLE 栈需要知道特征值的 ATT 句柄,该句柄没有通过 BluetoothGattCharacteristic 暴露出来。
尽管该技术要求您使用 NDK 访问 BluetoothGattService 中的灰色列表字段,并在连接到您的 BluetoothDevice 的 BluetoothGatt 上使用一些反射,但在某些版本的 Android 上是可能的。 请注意,除非您有很多相同的蓝牙设备要连接,否则它是不值得的,因为它不会节省那么多时间 - 您仍然需要连接并在第一个上执行discoverServices()。
就我而言,我有数百个要与之交谈,因此缓存 GATT 是值得的。 如果你只有两个,不要浪费你的时间。 这是为特定的 Android 设备开发的,不适用于(比如)三星 Galaxy S8,尽管也可能有解决方法。
步骤是: 1. 在第一台设备上,连接,执行discoverServices(),保留您想要缓存的GattService 和GattCharacteristics 的副本。 我有一个类(GattWrapper),它有一些静态字段来缓存服务和特征。
当连接到第二个及后续设备时,检查您是否已经完成了discoverServices()。 如果有,您可以复制 GattService 和 GattCharacteristics 并将您的新设备注入新创建的副本:
ble_inject.c - 用于在 BluetoothGattService 上设置设备
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <strings.h>
#include "android/log.h"
// inject a bluetooth device into a BluetoothGattService
JNIEXPORT jint JNICALL Java_com_foo_Utilities_BLEFix_injectdevice
(JNIEnv *, jobject,jobject, jobject);
// inject a bluetooth device into a BluetoothGattService
JNIEXPORT jint JNICALL Java_au_com_smartshepherd_ss2_Utilities_BLEFix_injectservices
(JNIEnv *, jobject,jobject, jobject);
JNIEXPORT jint JNICALL
Java_com_foo_Utilities_Utilities_BLEFix_injectdevice(JNIEnv *env, jobject bleFix,
jobject bluetoothGattService, jobject bluetoothDevice)
{
jclass bGattServiceClass = (*env)->GetObjectClass(env,bluetoothGattService);
//jclass bGattServiceClass = (*env)->FindClass(env,"android/bluetooth/BluetoothGattService");
jfieldID f_setDevice = (*env)->GetFieldID(env,bGattServiceClass,"mDevice","Landroid/bluetooth/BluetoothDevice;");
(*env)->SetObjectField(env,bluetoothGattService,f_setDevice,bluetoothDevice);
//env->SetObjectField(instance_CS, f_codeHeight, cs.codeHeight);
return 0;
}
安卓.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
TARGET_PLATFORM := android-3
LOCAL_MODULE := libblefix
LOCAL_SRC_FILES := ble_inject.c
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
BLEFix.java
import android.bluetooth.BluetoothGattService;
import android.util.Log;
import java.util.List;
public class BLEFix {
private static final String TAG = "ble_fix";
private static boolean mLoaded = false;
public void InjectDevice(BluetoothGattService service, BluetoothDevice dev)
{
injectdevice(service,dev);
}
private native int injectdevice(Object bluetoothGattService, Object bluetoothDevice);
static {
try {
System.loadLibrary("blefix");
mLoaded = true;
}
catch(java.lang.UnsatisfiedLinkError e)
{
mLoaded = false;
Log.e( TAG, "Failed to load blefix library" );
}
}
}
复制 BluetoothGattService 和 BluetoothGattCharacteristic 的代码:
private BluetoothGattCharacteristic cloneGattCharacteristic(BluetoothGattCharacteristic bgc)
{
return new BluetoothGattCharacteristic(bgc.getUuid(),bgc.getProperties(),bgc.getPermissions());
}
static Field mServicesField = null;
// static initialiser for this field
static
{
Field[] fields = BluetoothGatt.class.getDeclaredFields();
for (Field fld : fields)
{
if (fld.getName() == "mServices")
{
mServicesField = fld;
if (Modifier.isPrivate(mServicesField.getModifiers())) {
mServicesField.setAccessible(true);
}
}
}
}
private static BluetoothGattService mGattService;
private static BluetoothGatt mBluetoothGatt; // set this after onConnected()
private boolean copyCharacteristics()
{
mGattService = new BluetoothGattService(sGattService.getUuid(),BluetoothGattService.SERVICE_TYPE_PRIMARY);
// FIXME extremely unsafe juse of JNI to inject this device into already discovered characteristics
bleFix.InjectDevice(mGattService,mBluetoothGatt.getDevice());
List<BluetoothGattService> services = mBluetoothGatt.getServices();
if (services.isEmpty()) {
// use reflection, the mServices value isn't hidden it's private though
try {
services.add(mGattService);
if (mServicesField != null) // if this doesn't exist you are SOL on this device, it is implementation dependent I think
{
mServicesField.set(mBluetoothGatt, services);
}
} catch (Exception ex) {
mBluetoothGatt.discoverServices();
return false;
}
// sMyGattCharacteristic - store it away in a static after the first discoverServices() is successful
mMyGattCharacteristic = cloneGattCharacteristic(sMyGattCharacteristic);
mGattService.addCharacteristic(mMyGattCharacteristic);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.