2014-11-21 24 views
16

Zajmuję się tworzeniem aplikacji BLE, w oparciu o przykładowy projekt Gatt dostarczony przez google: https://developer.android.com/samples/BluetoothLeGatt/index.html. Dzięki temu mogę z powodzeniem przesyłać dane w charakterystyce. Teraz muszę wiedzieć, kiedy ta cecha zmieni jej wartość. Rozumiem, że muszę zaimplementować metodę setCharacteristicNotification() i metodę onDescriptorWrite(). Ale nie mogę tego zrobić. Wyszukiwanie, znalazłem kilka pomysłów na ten temat: Android BLE API: GATT Notification not received, What are the steps to get notified by Bluetooth Low Energy (BLE) device?, ale wciąż nie ma szczęścia Nie rozumiem, jak to działa, jaki parametr muszę zdefiniować lub co muszę zrobić !!!. Dobra dusza może mi udostępnić kompletny projekt, który to zrobi. Wszystko, czego potrzebuję, to wizualizacja wartości charakterystycznej, gdy urządzenie BLE zwraca niektóre dane.Subskrybuj powiadomienie BLE Gatt Android

Przeczytałem oficjalną dokumentację Androida, ale nie jest to tak szczegółowe. Dzięki z góry

To są moje kody:

urządzenia

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); 
} 
} 

usługi

@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

Czy sprawdzić czy GATT Server (BLE Device) ma włączone powiadomienia, w przeciwnym wypadku powiadomienia i wskazania nie będą działać na kliencie GATT (w tym przypadku aplikacja na system Android) – WedaPashi

Odpowiedz

42

Aby otrzymywać powiadomienia w Androidzie trzeba ustawić charakterystyczny zgłoszenie do prawdziwej

gatt.setCharacteristicNotification(characteristic, true); 

Należy również ustawić deskryptor klient konfiguracja charakterystyczny 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); 

Lepsze API byłoby setCharacteristicNotification aby ustawić deskryptor, ale niestety nie wydają się działać w ten sposób.

+0

Nie jestem dobrym programistą dla Androida, a następnie kopiuję i wklejałem część kodu w kilku częściach mojego projektu (dostosowując się do moich własnych zmienne). Teraz mogę osiągnąć metodę readCharacteristic(), ale teraz mam pytanie, w jaki sposób można złapać wartość charakterystycznego wysyłania przez moje urządzenie BLE? jeśli funkcja onCharacteristicRead() nie została wykonana, oznacza, że ​​kod nie działa? – Orlando

+0

Aby odczytać charakterystykę, należy wykonać BluetoothGatt.readCharacteristic następnie w BluetoothGattCallback.onCharacteristicChanged jesteś asynchronicznie powiadamiany, gdy wartość zostanie odczytana. – doncoleman

+1

+1. Równie konieczne jest, aby serwer GATT (urządzenie BLE) miał włączone powiadomienia, w przeciwnym razie powiadomienia i wskazania nie będą działać na kliencie GATT (w tym przypadku aplikacja na system Android). – WedaPashi

4

Oprócz przyjętej odpowiedzi, musiałem ustawić charakterystyczne dla WRITE_TYPE_DEFAULT podczas subskrybowania biegania obwodowej na OS X.

characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT); 
+0

OMG naprawiłam mój problem. Dzięki! – david72