繁体   English   中英

编写 BLE 特性而不发现服务 Android

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM