1

まず、私のアプリはBLEを使用してヌガーのデータを読み取れません BlueNRG-MSモジュールを使用してデバイスに接続しています。 MarshmallowまでOnCharacteristicChangedメソッドが呼び出され、データを受け取ることができます。しかし、7.0.0以上のonCharacteristicChangedメソッドは呼び出されませんでした。android nougat(7.0.0以上)のBLE(Bluetooth Low Energy)はデータを読み取ることができません

私はこれを検索し、誰かがこのコードを追加するように指示します。

BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_UUID); 
     if (descriptor != null) { 
      descriptor.setValue(enabled ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 
      mBluetoothGatt.writeDescriptor(descriptor); 
     } 

しかし、私はCLIENT_UUIDに何を入れるべきか正確には分かりません。

これはすべて私のコードです。

public class BleManager { 

private static final String TAG = "BleManager"; 

static final private UUID CCCD_ID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); 

public static final int STATE_ERROR = -1; 
public static final int STATE_NONE = 0;  // Initialized 
public static final int STATE_IDLE = 1;  // Not connected 
public static final int STATE_SCANNING = 2; // Scanning 
public static final int STATE_CONNECTING = 13; // Connecting 
public static final int STATE_CONNECTED = 16; // Connected 

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; 

public static final long SCAN_PERIOD = 5*1000; 

private static Context mContext = null; 
private static BleManager mBleManager = null; 
private final Handler mHandler; 

private final BluetoothAdapter mBluetoothAdapter; 
private BluetoothAdapter.LeScanCallback mLeScanCallback = null; 

private ArrayList<BluetoothDevice> mDeviceList = new ArrayList<BluetoothDevice>(); 
private BluetoothDevice mDefaultDevice = null; 

private BluetoothGatt mBluetoothGatt = null; 

private ArrayList<BluetoothGattService> mGattServices 
     = new ArrayList<BluetoothGattService>(); 
private ArrayList<BluetoothGattCharacteristic> mGattCharacteristics 
     = new ArrayList<BluetoothGattCharacteristic>(); 
private ArrayList<BluetoothGattCharacteristic> mWritableCharacteristics 
     = new ArrayList<BluetoothGattCharacteristic>(); 
private BluetoothGattCharacteristic mDefaultChar = null; 

private int mState = -1; 

/** 
* Constructor. Prepares a new Bluetooth session. 
* @param context The UI Activity Context 
* @param h A Listener to receive messages back to the UI Activity 
*/ 
private BleManager(Context context, Handler h) { 
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
    mState = STATE_NONE; 
    mHandler = h; 
    mContext = context; 

    if(mContext == null) 
     return; 
} 

public synchronized static BleManager getInstance(Context c, Handler h) { 
    if(mBleManager == null) 
     mBleManager = new BleManager(c, h); 

    return mBleManager; 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
public synchronized void finalize() { 
    if (mBluetoothAdapter != null) { 
     mState = STATE_IDLE; 
     mBluetoothAdapter.stopLeScan(mLeScanCallback); 
     disconnect(); 
    } 

    mDefaultDevice = null; 
    mBluetoothGatt = null; 
    mDefaultService = null; 
    mGattServices.clear(); 
    mGattCharacteristics.clear(); 
    mWritableCharacteristics.clear(); 

    if(mContext == null) 
     return; 

} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
private void stopScanning() { 
    if(mState < STATE_CONNECTING) { 
     mState = STATE_IDLE; 
     mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_IDLE, 0).sendToTarget(); 
    } 
    mBluetoothAdapter.stopLeScan(mLeScanCallback); 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
private int checkGattServices(List<BluetoothGattService> gattServices) { 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) { 
     Log.d(TAG, "# BluetoothAdapter not initialized"); 
     return -1; 
    } 

    for (BluetoothGattService gattService : gattServices) { 
     Log.d(TAG, "# GATT Service: "+gattService.toString()); 
     Toast.makeText(mContext, "" + gattService.toString(), Toast.LENGTH_SHORT).show(); 

     mGattServices.add(gattService); 

     List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics(); 
     for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) { 
      Toast.makeText(mContext, "" + gattCharacteristic.toString(), Toast.LENGTH_SHORT).show(); 
      mGattCharacteristics.add(gattCharacteristic); 
      Log.d(TAG, "# GATT Char: "+gattCharacteristic.toString()); 

      boolean isWritable = isWritableCharacteristic(gattCharacteristic); 
      if(isWritable) { 
       mWritableCharacteristics.add(gattCharacteristic); 
      } 

      boolean isReadable = isReadableCharacteristic(gattCharacteristic); 
      if(isReadable) { 
       readCharacteristic(gattCharacteristic); 
      } 

      if(isNotificationCharacteristic(gattCharacteristic)) { 
       setCharacteristicNotification(gattCharacteristic, true); 
       if(isWritable && isReadable) { 
        mDefaultChar = gattCharacteristic; 
       } 
      } 
     } 
    } 

    return mWritableCharacteristics.size(); 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
private boolean isWritableCharacteristic(BluetoothGattCharacteristic chr) { 
    if(chr == null) return false; 

    final int charaProp = chr.getProperties(); 
    if (((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) | 
      (charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) > 0) { 
     Log.d(TAG, "# Found writable characteristic"); 
     return true; 
    } else { 
     Log.d(TAG, "# Not writable characteristic"); 
     return false; 
    } 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
private boolean isReadableCharacteristic(BluetoothGattCharacteristic chr) { 
    if(chr == null) return false; 

    final int charaProp = chr.getProperties(); 
    if((charaProp & BluetoothGattCharacteristic.PROPERTY_READ) > 0) { 
     Log.d(TAG, "# Found readable characteristic"); 
     return true; 
    } else { 
     Log.d(TAG, "# Not readable characteristic"); 
     return false; 
    } 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
private boolean isNotificationCharacteristic(BluetoothGattCharacteristic chr) { 
    if(chr == null) return false; 

    final int charaProp = chr.getProperties(); 
    if((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) { 
     Log.d(TAG, "# Found notification characteristic"); 
     return true; 
    } else { 
     Log.d(TAG, "# Not notification characteristic"); 
     return false; 
    } 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
public void readCharacteristic(BluetoothGattCharacteristic characteristic) { 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) { 
     Log.d(TAG, "# BluetoothAdapter not initialized"); 
     return; 
    } 
    mBluetoothGatt.readCharacteristic(characteristic); 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, 
              boolean enabled) { 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) { 
     Log.d(TAG, "# BluetoothAdapter not initialized"); 
     return; 
    } 

    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); 

    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CCCD_ID); 
    if (descriptor != null) { 
     descriptor.setValue(enabled ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); 
     mBluetoothGatt.writeDescriptor(descriptor); 
    } 
} 


public void setScanCallback(BluetoothAdapter.LeScanCallback cb) { 
    mLeScanCallback = cb; 
} 

public int getState() { 
    return mState; 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
public boolean scanLeDevice(final boolean enable) { 
    boolean isScanStarted = false; 
    if (enable) { 
     if(mState == STATE_SCANNING) 
      return false; 

     if(mBluetoothAdapter.startLeScan(mLeScanCallback)) { 
      mState = STATE_SCANNING; 
      mDeviceList.clear(); 

      mHandler.postDelayed(new Runnable() { 
        @Override 
        public void run() { 
         stopScanning(); 
        } 
       }, SCAN_PERIOD); 

      mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_SCANNING, 0).sendToTarget(); 
      isScanStarted = true; 
     } 
    } else { 
     if(mState < STATE_CONNECTING) { 
      mState = STATE_IDLE; 
      mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_IDLE, 0).sendToTarget(); 
     } 
     stopScanning(); 
    } 

    return isScanStarted; 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
public boolean connectGatt(Context c, boolean bAutoReconnect, BluetoothDevice device) { 
    if(c == null || device == null) 
     return false; 

    mGattServices.clear(); 
    mGattCharacteristics.clear(); 
    mWritableCharacteristics.clear(); 

    mBluetoothGatt = device.connectGatt(c, bAutoReconnect, mGattCallback); 
    mDefaultDevice = device; 

    mState = STATE_CONNECTING; 
    mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_CONNECTING, 0).sendToTarget(); 
    return true; 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
public boolean connectGatt(Context c, boolean bAutoReconnect, String address) { 
    if(c == null || address == null) 
     return false; 

    if(mBluetoothGatt != null && mDefaultDevice != null 
      && address.equals(mDefaultDevice.getAddress())) { 
     if (mBluetoothGatt.connect()) { 
      mState = STATE_CONNECTING; 
      return true; 
     } 
    } 

    BluetoothDevice device = 
      BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 
    if (device == null) { 
     Log.d(TAG, "# Device not found. Unable to connect."); 
     return false; 
    } 

    mGattServices.clear(); 
    mGattCharacteristics.clear(); 
    mWritableCharacteristics.clear(); 

    mBluetoothGatt = device.connectGatt(c, bAutoReconnect, mGattCallback); 
    mDefaultDevice = device; 

    mState = STATE_CONNECTING; 
    mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_CONNECTING, 0).sendToTarget(); 
    return true; 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
public void disconnect() { 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) { 
     Log.d(TAG, "# BluetoothAdapter not initialized"); 
     return; 
    } 
    mBluetoothGatt.disconnect(); 
} 

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
public boolean write(BluetoothGattCharacteristic chr, byte[] data) { 
    if (mBluetoothGatt == null) { 
     Log.d(TAG, "# BluetoothGatt not initialized"); 
     return false; 
    } 

    BluetoothGattCharacteristic writableChar = null; 

    if(chr == null) { 
     if(mDefaultChar == null) { 
      for(BluetoothGattCharacteristic bgc : mWritableCharacteristics) { 
       if(isWritableCharacteristic(bgc)) { 
        writableChar = bgc; 
       } 
      } 
      if(writableChar == null) { 
       Log.d(TAG, "# Write failed - No available characteristic"); 
       return false; 
      } 
     } else { 
      if(isWritableCharacteristic(mDefaultChar)) { 
       Log.d(TAG, "# Default GattCharacteristic is PROPERY_WRITE | PROPERTY_WRITE_NO_RESPONSE"); 
       writableChar = mDefaultChar; 
      } else { 
       Log.d(TAG, "# Default GattCharacteristic is not writable"); 
       mDefaultChar = null; 
       return false; 
      } 
     } 
    } else { 
     if (isWritableCharacteristic(chr)) { 
      Log.d(TAG, "# user GattCharacteristic is PROPERY_WRITE | PROPERTY_WRITE_NO_RESPONSE"); 
      writableChar = chr; 
     } else { 
      Log.d(TAG, "# user GattCharacteristic is not writable"); 
      return false; 
     } 
    } 

    writableChar.setValue(data); 
    writableChar.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT); 
    mBluetoothGatt.writeCharacteristic(writableChar); 
    mDefaultChar = writableChar; 
    return true; 
} 

private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { 
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
    @Override 
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { 
     if (newState == BluetoothProfile.STATE_CONNECTED) { 
      mState = STATE_CONNECTED; 
      Log.d(TAG, "# Connected to GATT server."); 

      mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_CONNECTED, 0).sendToTarget(); 

      gatt.discoverServices(); 

     } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { 
      mState = STATE_IDLE; 
      Log.d(TAG, "# Disconnected from GATT server."); 
      mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_IDLE, 0).sendToTarget(); 
      mBluetoothGatt = null; 
      mGattServices.clear(); 
      mDefaultService = null; 
      mGattCharacteristics.clear(); 
      mWritableCharacteristics.clear(); 
      mDefaultChar = null; 
      mDefaultDevice = null; 
     } 
    } 

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
    @Override 
    public void onServicesDiscovered(BluetoothGatt gatt, int status) { 
     if (status == BluetoothGatt.GATT_SUCCESS) { 
      Log.d(TAG, "# New GATT service discovered."); 
      checkGattServices(gatt.getServices()); 
     } else { 
      Log.d(TAG, "# onServicesDiscovered received: " + status); 
     } 
    } 

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
    @Override 
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { 
     if (status == BluetoothGatt.GATT_SUCCESS) { 
      // We've received data from remote 
      Log.d(TAG, "# Read characteristic: "+characteristic.toString()); 

      final byte[] data = characteristic.getValue(); 
      if (data != null && data.length > 0) { 
       final StringBuilder stringBuilder = new StringBuilder(data.length); 
       stringBuilder.append(data); 
       Log.d(TAG, stringBuilder.toString()); 

       mHandler.obtainMessage(MESSAGE_READ, byteArrayToHex(data)).sendToTarget(); 
      } 

      if(mDefaultChar == null && isWritableCharacteristic(characteristic)) { 
       mDefaultChar = characteristic; 
      } 
     } 
    } 

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) 
    @Override 
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { 
     // We've received data from remote 
     Log.d(TAG, "# onCharacteristicChanged: "+characteristic.toString()); 

     final byte[] data = characteristic.getValue(); 
     if (data != null && data.length > 0) { 
      final StringBuilder stringBuilder = new StringBuilder(data.length); 
      //for(byte byteChar : data) 
      // stringBuilder.append(String.format("%02X ", byteChar)); 
      stringBuilder.append(data); 
      Log.d(TAG, stringBuilder.toString()); 

      mHandler.obtainMessage(MESSAGE_READ, byteArrayToHex(data)).sendToTarget(); 
     } 

     if(mDefaultChar == null && isWritableCharacteristic(characteristic)) { 
      mDefaultChar = characteristic; 
     } 
    } 
}; 

String byteArrayToHex(byte[] a) { 
    StringBuilder sb = new StringBuilder(); 
    for(final byte b: a) 
     sb.append(String.format("%02x", b&0xff)); 
    return sb.toString(); 
}} 

答えて

0

Bluetooth低エネルギー特性の通知を有効にするには、以下の機能を試してください。私は7.0.0以上のAndroidには何の問題も気づかなかった。

特性更新を購読しているときは、のCharacteristicChangedCallback()に値を更新する必要があります。値が周辺機器で実際に更新されていることを確認してください)

private void enableNotifications(BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic characteristic){ 

    UUID CLIENT_CHARACTERISTIC_CONFIG = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); 

    byte[] payload = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE; 

    bluetoothGatt.setCharacteristicNotification(characteristic, true); 

    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
      CLIENT_CHARACTERISTIC_CONFIG); 

    if (descriptor == null){ 
     Log.w(TAG, "Notification not supported for characteristic"); 
     return; 
    } 

    descriptor.setValue(payload); 

    bluetoothGatt.writeDescriptor(descriptor); 
} 
関連する問題