2014-11-21 3 views
16

Я разрабатываю приложение BLE, основанное на примере проекта Gatt, предоставленном google: https://developer.android.com/samples/BluetoothLeGatt/index.html. Итак, я могу отправить запись данных в характеристику успешно. Теперь мне нужно знать, когда эта характеристика меняет свою ценность. Я понимаю, что мне нужно реализовать метод setCharacteristicNotification() и метод onDescriptorWrite(). Но я не могу этого сделать. Поиск, я нашел некоторые идеи по этому поводу: Android BLE API: GATT Notification not received, What are the steps to get notified by Bluetooth Low Energy (BLE) device?, но все равно не повезло Я не понимаю, как это работает, какой параметр мне нужно определить или что мне нужно делать !!!. Некоторая хорошая душа может поделиться со мной полным проектом, который делает это. Все, что мне нужно, - это визуализировать значение признака, когда устройство BLE возвращает некоторые данные.Подпишитесь на уведомление BLE Gatt Android

Я читал официальную документацию на Android, но это не так уж и специфично. Заранее спасибо

Это мои коды:

устройств

public class DeviceControlActivity extends Activity { 

public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME"; 
public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS"; 

private TextView mConnectionState; 
private TextView mDataField; 
private TextView mRssiField; 
private String mDeviceName; 
private String mDeviceAddress; 
private ExpandableListView mGattServicesList; 
private BluetoothLeService mBluetoothLeService; 
static ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = new  ArrayList<ArrayList<BluetoothGattCharacteristic>>(); 
private boolean mConnected = false; 
private BluetoothGattCharacteristic mNotifyCharacteristic; 
private BluetoothGattCharacteristic mWriteCharacteristic, mReadCharacteristic; 
Button Escritor; 
byte hello[] = { 0 }; 

private final String LIST_NAME = "NAME"; 
private final String LIST_UUID = "UUID"; 

// BluetoothGattCharacteristic characteristic; 

// public BluetoothGatt mBluetoothGatt; 
// Code to manage Service lifecycle. 
private final ServiceConnection mServiceConnection = new ServiceConnection() { 

    @Override 
    public void onServiceConnected(ComponentName componentName, IBinder service) { 
     mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService(); 
     if (!mBluetoothLeService.initialize()) { 
      Log.e("Unable to initialize Bluetooth"); 
      finish(); 
     } 
     // Automatically connects to the device upon successful start-up 
     // initialization. 
     mBluetoothLeService.connect(mDeviceAddress); 
     mBluetoothLeService.setBLEServiceCb(mDCServiceCb); 
    } 

    @Override 
    public void onServiceDisconnected(ComponentName componentName) { 
     mBluetoothLeService = null; 
    } 
}; 

// If a given GATT characteristic is selected, check for supported features. 
// This sample 
// demonstrates 'Read' and 'Notify' features. See 
// http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for 
// the complete 
// list of supported characteristic features. 
private final ExpandableListView.OnChildClickListener servicesListClickListner = new ExpandableListView.OnChildClickListener() { 
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 
    @Override 
    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { 
     if (mGattCharacteristics != null) { 
      final BluetoothGattCharacteristic characteristic = mGattCharacteristics.get(groupPosition).get(childPosition); 
      final int charaProp = characteristic.getProperties(); 
      if ((charaProp & BluetoothGattCharacteristic.PROPERTY_READ) > 0) { 
       // If there is an active notification on a characteristic, 
       // clear 
       // it first so it doesn't update the data field on the user 
       // interface. 
       Log.d("BluetoothGattCharacteristic has PROPERTY_READ, so send read request"); 

       if (mNotifyCharacteristic != null) { 
        mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, true); 
        mNotifyCharacteristic = null; 
       } 
       mBluetoothLeService.readCharacteristic(characteristic); 
       /*Toast.makeText(getApplicationContext(), "Leyó Algo", 
         Toast.LENGTH_SHORT).show();*/ 
      } 

      if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) { 
       Log.d("BluetoothGattCharacteristic has PROPERTY_NOTIFY, so send notify request"); 

       mNotifyCharacteristic = characteristic; 
       mBluetoothLeService.setCharacteristicNotification(characteristic, true); 
      } 

      if (((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) | (charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) > 0) { 
       Log.d("BluetoothGattCharacteristic has PROPERY_WRITE | PROPERTY_WRITE_NO_RESPONSE"); 

       mWriteCharacteristic = characteristic; 
       // popup an dialog to write something. 
       showCharactWriteDialog(); 
      } 
      return true; 
     } 
     return false; 
    } 
}; 

private void showCharactWriteDialog() { 
    DialogFragment newFrame = new BleCharacterDialogFragment(); 
    newFrame.show(getFragmentManager(), "blewrite"); 
} 

private void clearUI() { 
    mGattServicesList.setAdapter((SimpleExpandableListAdapter) null); 
    mDataField.setText(R.string.no_data); 
} 

@TargetApi(Build.VERSION_CODES.HONEYCOMB) 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.gatt_services_characteristics); 

    final Intent intent = getIntent(); 
    mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME); 
    mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS); 

    // Sets up UI references. 
    ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress); 
    mGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list); 
    mGattServicesList.setOnChildClickListener(servicesListClickListner); 
    mConnectionState = (TextView) findViewById(R.id.connection_state); 
    mDataField = (TextView) findViewById(R.id.data_value); 
    mRssiField = (TextView) findViewById(R.id.signal_rssi); 

    getActionBar().setTitle(mDeviceName); 
    getActionBar().setDisplayHomeAsUpEnabled(true); 
    Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); 
    bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); 
} 

@Override 
protected void onResume() { 
    super.onResume(); 
    // registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter()); 
    if (mBluetoothLeService != null) { 
     final boolean result = mBluetoothLeService.connect(mDeviceAddress); 
     Log.d("Connect request result=" + result); 
    } 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    // unregisterReceiver(mGattUpdateReceiver); 
} 

@Override 
protected void onDestroy() { 
    super.onDestroy(); 
    unbindService(mServiceConnection); 
    mBluetoothLeService = null; 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.gatt_services, menu); 
    if (mConnected) { 
     menu.findItem(R.id.menu_connect).setVisible(false); 
     menu.findItem(R.id.menu_disconnect).setVisible(true); 
    } else { 
     menu.findItem(R.id.menu_connect).setVisible(true); 
     menu.findItem(R.id.menu_disconnect).setVisible(false); 
    } 
    return true; 
} 

@TargetApi(Build.VERSION_CODES.ECLAIR) 
@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()) { 
    case R.id.menu_connect: 
     mBluetoothLeService.connect(mDeviceAddress); 
     return true; 
    case R.id.menu_disconnect: 
     mBluetoothLeService.disconnect(); 
     return true; 
    case android.R.id.home: 
     onBackPressed(); 
     return true; 
    } 
    return super.onOptionsItemSelected(item); 
} 

private void updateConnectionState(final int resourceId) { 
    runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      mConnectionState.setText(resourceId); 
     } 
    }); 
} 

private void displayData(String data) { 
    if (data != null) { 
     mDataField.setText(data); 

    } 
} 

private void displayRssi(String rssi) { 
    if (rssi != null) { 
     // Log.d("-- dispaly Rssi: " + rssi); 
     mRssiField.setText(rssi); 
    } 
} 

private void displayRetorno(String rssi) { 

    if (rssi != null) { 
     // Log.d("-- dispaly Rssi: " + rssi); 
     mRssiField.setText(rssi+"Ñ"); 
     Toast.makeText(getApplicationContext(), "SsSsSs"+"viendo", Toast.LENGTH_SHORT).show(); 
    } 
} 

// Demonstrates how to iterate through the supported GATT 
// Services/Characteristics. 
// In this sample, we populate the data structure that is bound to the 
// ExpandableListView 
// on the UI. 
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 
private void displayGattServices(List<BluetoothGattService> gattServices) { 
    Log.d("displayGATTServices"); 

    if (gattServices == null) 
     return; 
    String uuid = null; 
    String unknownServiceString = getResources().getString(R.string.unknown_service); 
    String unknownCharaString = getResources().getString(R.string.unknown_characteristic); 
    ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>(); 
    ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList<ArrayList<HashMap<String, String>>>(); 
    mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>(); 

    // Loops through available GATT Services. 
    for (BluetoothGattService gattService : gattServices) { 
     HashMap<String, String> currentServiceData = new HashMap<String, String>(); 
     uuid = gattService.getUuid().toString(); 
     currentServiceData.put(LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString)); 
     currentServiceData.put(LIST_UUID, uuid); 
     gattServiceData.add(currentServiceData); 

     ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList<HashMap<String, String>>(); 
     List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics(); 
     ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<BluetoothGattCharacteristic>(); 

     // Loops through available Characteristics. 
     for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) { 
      charas.add(gattCharacteristic); 
      HashMap<String, String> currentCharaData = new HashMap<String, String>(); 
      uuid = gattCharacteristic.getUuid().toString(); 
      currentCharaData.put(LIST_NAME, SampleGattAttributes.lookup(uuid, unknownCharaString)); 
      currentCharaData.put(LIST_UUID, uuid); 
      gattCharacteristicGroupData.add(currentCharaData); 
     } 
     mGattCharacteristics.add(charas); 
     gattCharacteristicData.add(gattCharacteristicGroupData); 
    } 

    SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(this, gattServiceData, android.R.layout.simple_expandable_list_item_2, new String[] { LIST_NAME, LIST_UUID }, 
      new int[] { android.R.id.text1, android.R.id.text2 }, gattCharacteristicData, android.R.layout.simple_expandable_list_item_2, new String[] { LIST_NAME, LIST_UUID }, new int[] { 
        android.R.id.text1, android.R.id.text2 }); 
    mGattServicesList.setAdapter(gattServiceAdapter); 


    final BluetoothGattCharacteristic characteristic = mGattCharacteristics.get(2).get(0); 
    final int charaProp = characteristic.getProperties(); 
    mWriteCharacteristic = characteristic; 
    mBluetoothLeService.setCharacteristicNotification(mWriteCharacteristic, true); 

    if (mWriteCharacteristic != null) { 
     byte[] value = { (byte) 0x0D }; 
     mWriteCharacteristic.setValue("ATZ"); 
     Toast.makeText(getApplicationContext(), String.valueOf(mWriteCharacteristic.getStringValue(0)), Toast.LENGTH_SHORT).show(); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue(value); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     boolean jo=mBluetoothLeService.mBluetoothGatt.readCharacteristic(mWriteCharacteristic); 
     Toast.makeText(getApplicationContext(), String.valueOf(mWriteCharacteristic.getStringValue(0)), Toast.LENGTH_SHORT).show(); 

     /*mWriteCharacteristic.setValue("ATE0"); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue(value); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue("ATE0"); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue(value); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue("ATL0"); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue(value); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue("ATM0"); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue(value); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue("ATS0"); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue(value); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue("ATH0"); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue(value); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue("ATAT2"); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue(value); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic);*/ 
     /*mWriteCharacteristic.setValue("ATZ"); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
     mWriteCharacteristic.setValue(value); 
     mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic);*/ 

    } 

    final BluetoothGattCharacteristic characteristic2 = mGattCharacteristics.get(0).get(0); 
    final int charaProp2 = characteristic2.getProperties(); 

    mReadCharacteristic = characteristic2; 
    mBluetoothLeService.readCharacteristic(mReadCharacteristic); 
} 



private DCServiceCb mDCServiceCb = new DCServiceCb(); 

public class DCServiceCb implements BluetoothLeService.BLEServiceCallback { 

    @Override 
    public void displayRssi(final int rssi) { 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 

       DeviceControlActivity.this.displayRssi(String.valueOf(rssi)); 
      } 
     }); 
    } 

    @Override 
    public void displayRetorno (final int rssi) { 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 

       DeviceControlActivity.this.displayRetorno("algo!!!!"); 
      } 
     }); 
    } 

    @Override 
    public void displayData(final String data) { 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       DeviceControlActivity.this.displayData(data); 
       Toast.makeText(getApplicationContext(), data+"SsSsSs", Toast.LENGTH_SHORT).show(); 
      } 
     }); 
    } 

    @Override 
    public void notifyConnectedGATT() { 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       mConnected = true; 
       updateConnectionState(R.string.connected); 
       invalidateOptionsMenu(); 
      } 
     }); 
    } 

    @Override 
    public void notifyDisconnectedGATT() { 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       mConnected = false; 
       updateConnectionState(R.string.disconnected); 
       invalidateOptionsMenu(); 
       clearUI(); 
      } 
     }); 
    } 

    @Override 
    public void displayGATTServices() { 
     Log.d("displayGATTServices."); 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       if (mBluetoothLeService != null) { 
        DeviceControlActivity.this.displayGattServices(mBluetoothLeService.getSupportedGattServices()); 
       } 
      } 
     }); 
    } 
} 

@SuppressLint("ValidFragment") 
public class BleCharacterDialogFragment extends DialogFragment { 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View v = inflater.inflate(R.layout.write_charact_dialog, container, false); 
     final EditText ed = (EditText) v.findViewById(R.id.charact_value); 
     Button ok = (Button) v.findViewById(R.id.dialog_confirm); 
     Button cancel = (Button) v.findViewById(R.id.dialog_cancel); 

     ok.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 


       if (mWriteCharacteristic != null) { 
        mWriteCharacteristic.setValue("AA"); 
        mBluetoothLeService.mBluetoothGatt.writeCharacteristic(mWriteCharacteristic); 
       } 

       // characteristic.setValue("FF"); 
       // characteristic.setValue(new byte[] {(byte) 0xFF}); 
       // writeCharacteristicValue(characteristic); 
       // 
       Toast.makeText(getApplicationContext(), "Se envío el dato", Toast.LENGTH_SHORT).show(); 
       dismiss(); 
       return; 
      } 
     }); 

     cancel.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       dismiss(); 
      } 
     }); 

     return v; 
    } 
} 

public void writeCharacteristicValue(BluetoothGattCharacteristic characteristica) { 
    byte[] value = { (byte) 0xFF }; 
    characteristica.setValue(bytesToHex(value)); 
    boolean status = mBluetoothLeService.mBluetoothGatt.writeCharacteristic(characteristica); 
} 

final protected static char[] hexArray = "ABCDEF".toCharArray(); 

public String bytesToHex(byte[] bytes) { 
    char[] hexChars = new char[bytes.length * 2]; 
    int v; 
    for (int j = 0; j < bytes.length; j++) { 
     v = bytes[j] & 0xFF; 
     hexChars[j * 2] = hexArray[v >>> 4]; 
     hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 
    } 
    return new String(hexChars); 
} 
} 

Сервиса

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 
public class BluetoothLeService extends Service { 
// private final static String TAG = 
// BluetoothLeService.class.getSimpleName(); 

private BluetoothManager mBluetoothManager; 
private BluetoothAdapter mBluetoothAdapter; 
private String mBluetoothDeviceAddress; 
BluetoothGatt mBluetoothGatt; 
private int mConnectionState = STATE_DISCONNECTED; 
private BLEServiceCallback mBLEServiceCb = null; 

private static final int STATE_DISCONNECTED = 0; 
private static final int STATE_CONNECTING = 1; 
private static final int STATE_CONNECTED = 2; 
private static final int GATT_SUCCESS=0; 

public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT); 

private final long READING_RSSI_TASK_FREQENCY = 500; 

private static final int READ_RSSI_REPEAT = 1; 

private final Handler mHandler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
     case READ_RSSI_REPEAT: 
      if (mBluetoothGatt != null) { 
       mBluetoothGatt.readRemoteRssi(); 
       if(DeviceControlActivity.mGattCharacteristics.size()==3) 
       { 
        boolean pp=mBluetoothGatt.readCharacteristic(DeviceControlActivity.mGattCharacteristics.get(2).get(0));// 
        //BluetoothGattCallback.onCharacteristicRead(mBluetoothGatt, DeviceControlActivity.mGattCharacteristics.get(2).get(0), GATT_SUCCESS); 
       } 
      } 
      sendMessageDelayed(obtainMessage(READ_RSSI_REPEAT), READING_RSSI_TASK_FREQENCY); 
      break; 
     } 
    } 
}; 

private void startReadRssi() { 
    if (mHandler.hasMessages(READ_RSSI_REPEAT)) { 
     Log.w("+++++++++ Handler already has Message: READ_RSSI_REPEAT"); 
    } 
    mHandler.sendEmptyMessage(READ_RSSI_REPEAT); 
} 

private void stopReadRssi() { 
    mHandler.removeMessages(READ_RSSI_REPEAT); 
} 

// Implements callback methods for GATT events that the app cares about. For 
// example, 
// connection change and services discovered. 
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { 
    @Override 
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { 
     Log.d("onConnectionStateChange status = " + status + ", newState = " + newState); 

     if (newState == BluetoothProfile.STATE_CONNECTED) { 
      if (mBLEServiceCb != null) { 
       mBLEServiceCb.notifyConnectedGATT(); 
      } 

      Log.d("Connected to GATT server."); 
      // Attempts to discover services after successful connection. 
      Log.d("Attempting to start service discovery:" + mBluetoothGatt.discoverServices()); 
      startReadRssi(); 
      //si se conecta empiece a leer mi caracteritica 

     } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { 
      if (mBLEServiceCb != null) { 
       mBLEServiceCb.notifyDisconnectedGATT(); 
      } 
      stopReadRssi(); 
      Log.d("Disconnected from GATT server."); 
     } 
    } 

    @Override 
    public void onServicesDiscovered(BluetoothGatt gatt, int status) { 
     Log.d("onServicesDiscovered status = " + status); 

     if (status == BluetoothGatt.GATT_SUCCESS) { 
      if (mBLEServiceCb != null) { 
       mBLEServiceCb.displayGATTServices(); 
      } 

     } else { 
      Log.d("onServicesDiscovered received: " + status); 
     } 
     setCharacteristicNotification(DeviceControlActivity.mGattCharacteristics.get(2).get(0), true);//puede que sea mejor no ponerlo, pero no se 
    } 

    @Override 
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { 
     Log.d("onCharacteristicRead status: " + status); 
     Toast.makeText(getApplicationContext(), "MMMM"+"BBB"+"SsSsSs", Toast.LENGTH_SHORT).show(); 
     if (status == BluetoothGatt.GATT_SUCCESS) { 
      displayCharacteristic(characteristic); 
     } 
    } 

    @Override 
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { 
     Log.d("------------- onCharacteristicWrite status: " + status); 

     // handler callback of write characteristic. 
     // do somethings here. 
    } 

    @Override 
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { 
     Log.d("onCharacteristicChanged"); 
     Toast.makeText(getApplicationContext(), "se ejecutó el metodo de cambio en caracteristica", Toast.LENGTH_SHORT).show(); 
     displayCharacteristic(characteristic); 
    } 

    @Override 
    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { 
     // Log.d("onReadRemoteRssi rssi = " + rssi + "; status = " + 
     // status); 
     if (mBLEServiceCb != null) { 
      mBLEServiceCb.displayRssi(rssi); 
     } 
    } 
}; 

public void setBLEServiceCb(BLEServiceCallback cb) { 
    if (cb != null) { 
     mBLEServiceCb = cb; 
    } 
} 

private void displayCharacteristic(final BluetoothGattCharacteristic characteristic) { 
    String msg = null; 
    // This is special handling for the Heart Rate Measurement profile. Data 
    // parsing is 
    // carried out as per profile specifications: 
    // http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml 
    if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) { 
     int flag = characteristic.getProperties(); 
     int format = -1; 
     if ((flag & 0x01) != 0) { 
      format = BluetoothGattCharacteristic.FORMAT_UINT16; 
      Log.d("Heart rate format UINT16."); 
     } else { 
      format = BluetoothGattCharacteristic.FORMAT_UINT8; 
      Log.d("Heart rate format UINT8."); 
     } 
     final int heartRate = characteristic.getIntValue(format, 1); 
     Log.d(String.format("Received heart rate: %d", heartRate)); 

     msg = String.valueOf(heartRate); 
    } else { 
     // For all other profiles, writes the data formatted in HEX. 
     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)); 

      msg = new String(data) + "\n" + stringBuilder.toString(); 
     } 
    } 

    if (mBLEServiceCb != null) { 
     mBLEServiceCb.displayData(msg); 
    } 

} 

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

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

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

private final IBinder mBinder = new LocalBinder(); 

public boolean initialize() { 
    // For API level 18 and above, get a reference to BluetoothAdapter 
    // through 
    // BluetoothManager. 
    if (mBluetoothManager == null) { 
     mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 
     if (mBluetoothManager == null) { 
      Log.e("Unable to initialize BluetoothManager."); 
      return false; 
     } 
    } 

    mBluetoothAdapter = mBluetoothManager.getAdapter(); 
    if (mBluetoothAdapter == null) { 
     Log.e("Unable to obtain a BluetoothAdapter."); 
     return false; 
    } 

    return true; 
} 

public boolean connect(final String address) { 
    if (mBluetoothAdapter == null || address == null) { 
     Log.w("BluetoothAdapter not initialized or unspecified address."); 
     return false; 
    } 

    // Previously connected device. Try to reconnect. 
    if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) { 
     Log.d("Trying to use an existing mBluetoothGatt for connection."); 
     if (mBluetoothGatt.connect()) { 
      mConnectionState = STATE_CONNECTING; 
      return true; 
     } else { 
      return false; 
     } 
    } 

    final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); 
    if (device == null) { 
     Log.w("Device not found. Unable to connect."); 
     return false; 
    } 
    // We want to directly connect to the device, so we are setting the 
    // autoConnect 
    // parameter to false. 
    mBluetoothGatt = device.connectGatt(this, false, mGattCallback); 
    Log.d("Trying to create a new connection."); 
    mBluetoothDeviceAddress = address; 
    mConnectionState = STATE_CONNECTING; 
    return true; 
} 

public void disconnect() { 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) { 
     Log.w("BluetoothAdapter not initialized"); 
     return; 
    } 
    mBluetoothGatt.disconnect(); 
} 

public void close() { 
    if (mBluetoothGatt == null) { 
     return; 
    } 
    mBluetoothGatt.close(); 
    mBluetoothGatt = null; 
} 

/** 
* Request a read on a given {@code BluetoothGattCharacteristic}. The read 
* result is reported asynchronously through the 
* {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)} 
* callback. 
* 
* @param characteristic 
*   The characteristic to read from. 
*/ 
public void readCharacteristic(BluetoothGattCharacteristic characteristic) { 
    Toast.makeText(getApplicationContext(), "readCharacteristic en Servicio", Toast.LENGTH_SHORT).show(); 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) { 
     Log.w("BluetoothAdapter not initialized"); 

     return; 
    } 
    mBluetoothGatt.readCharacteristic(characteristic); 
} 

/** 
* Requst a write on a give {@code BluetoothGattCharacteristic}. The write 
* result is reported asynchronously through the 
* {@code BluetoothGattCallback#onCharacteristicWrite(andorid.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)} 
* callback. 
*/ 
public void writeCharacteristic(BluetoothGattCharacteristic characteristic) { 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) { 
     Log.w("BluetoothAdapter not initialized"); 
     return; 
    } 
    mBluetoothGatt.writeCharacteristic(characteristic); 
} 

/** 
* Enables or disables notification on a give characteristic. 
* 
* @param characteristic 
*   Characteristic to act on. 
* @param enabled 
*   If true, enable notification. False otherwise. 
*/ 
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) { 
    if (mBluetoothAdapter == null || mBluetoothGatt == null) { 
     Log.w("BluetoothAdapter not initialized"); 
     return; 
    } 
    mBluetoothGatt.setCharacteristicNotification(characteristic, true); 

    // This is specific to Heart Rate Measurement. 
    if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) { 
     BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG)); 
     descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); 
     mBluetoothGatt.writeDescriptor(descriptor); 
    } 
} 

/** 
* Retrieves a list of supported GATT services on the connected device. This 
* should be invoked only after {@code BluetoothGatt#discoverServices()} 
* completes successfully. 
* 
* @return A {@code List} of supported services. 
*/ 
public List<BluetoothGattService> getSupportedGattServices() { 
    if (mBluetoothGatt == null) 
     return null; 

    return mBluetoothGatt.getServices(); 
} 

public interface BLEServiceCallback { 
    public void displayRssi(int rssi); 

    public void displayData(String data); 

    public void notifyConnectedGATT(); 

    public void notifyDisconnectedGATT(); 

    public void displayGATTServices(); 

    public void displayRetorno(int rssi); 
} 
} 
+0

ли вы проверить, если сервер ГАТТ (BLE устройств) позволило уведомления, еще уведомления и показания не будут работать на клиента GATT (приложение Android в этом случае) – WedaPashi

ответ

42

Для получения уведомления в Android необходимо установить характеристическое уведомление истинной

gatt.setCharacteristicNotification(characteristic, true); 

Кроме того, необходимо установить Дескриптор клиента характерной конфигурации 0x2902

// 0x2902 org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml 
UUID uuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); 
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(uuid); 
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); 
gatt.writeDescriptor(descriptor); 

А лучше API будет для setCharacteristicNotification установить дескриптор, но, к сожалению, это, кажется, не работает.

+0

Я не очень хороший разработчик Android, затем копирую и вставляю часть кода в несколько частей моего проекта (при этом соответствующие настройки меняются переменные). Теперь я могу получить метод readCharacteristic(), но теперь у меня есть вопрос, как можно поймать значение отправки признаков моим устройством BLE? если функция onCharacteristicRead() не выполнена, значит, код не работает? – Orlando

+0

Чтобы прочитать характеристику, вам необходимо выполнить BluetoothGatt.readCharacteristic, а затем в BluetoothGattCallback.onCharacteristicChanged вы будете асинхронно уведомлены при чтении значения. – doncoleman

+1

+1. Также необходимо, чтобы сервер GATT (устройство BLE) активировал уведомления, другие уведомления и указания не будут работать на клиенте GATT (приложение Android в этом случае) – WedaPashi

4

В дополнение к принятым ответ, я должен был установить характерные для WRITE_TYPE_DEFAULT при подключении к периферийным, работающих на OS X.

characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT); 
+0

OMG это исправил мою проблему. Благодаря! – david72