pass array between 2 activity with intent - java

i'm trying to pass one array
[the array is inizialized by me {1,2,3,4} and i associate the string "txx"]
between two activity but i recive this error
java.lang.runtimeexception: unable to start activity
componentinfo{com.example.android.bluetoothlegatt/com.example.android.bluetoothlegatt.graphcurrentactivity}:
java.lang.nullpointerexception: attempt to read from null array
from debug mode i see that this array doesn't pass between two activity. i think that there can be an error in delcaration private/public variable..
please help me
activity A
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA";
public final static String EXTRA_DATA2 =
"com.example.bluetooth.le.EXTRA_DATA2";
public final static String EXTRA_DATA3 =
"com.example.bluetooth.le.EXTRA_DATA3";
public final static String EXTRA_DATA4 =
"com.example.bluetooth.le.EXTRA_DATA4";
public final static String EXTRA_DATA5 =
"com.example.bluetooth.le.EXTRA_DATA5";
public final static String EXTRA_DATA6 =
"com.example.bluetooth.le.EXTRA_DATA6";
public final static String EXTRA_DATA7 =
"com.example.bluetooth.le.EXTRA_DATA7";
byte[] value;
int[] data_info = new int[6];
public int[] grap_curr = new int[] {0,0,0,0,0,0,0,0,0,0};
public int[] grap_volt = new int[] {0,0,0,0,0,0,0,0,0,0};
public int[] grap_temp = new int[] {0,0,0,0,0,0,0,0,0,0};
public int[] grap_soc = new int[] {0,0,0,0,0,0,0,0,0,0};
public int[] grap_soh = new int[] {0,0,0,0,0,0,0,0,0,0};
int i = 0;
int j = 0;
public final static UUID UUID_USER_DATA =
UUID.fromString(SampleGattAttributes.FIRST_NAME);
public ArrayList<String> receivedPackets = new ArrayList<String>();
// 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) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action,final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
/* Creo le Intent per passare i dati da visualizzare sui grafici alle altre classi */
Intent intentCurr = new Intent(getApplicationContext(), GraphCurrentActivity.class);
//final Intent intentVolt = new Intent(getApplicationContext(), GraphVoltageActivity.class);
//final Intent intentTemp = new Intent(getApplicationContext(), GraphTempActivity.class);
//final Intent intentSoC = new Intent(getApplicationContext(), GraphSoCActivity.class);
//final Intent intentSoH = new Intent(getApplicationContext(), GraphSoHActivity.class);
if (UUID_USER_DATA.equals(characteristic.getUuid())) {
int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0) {
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d(TAG, "Value format UINT16.");
} else {
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, "Value format UINT8.");
}
value = characteristic.getValue();
ByteBuffer bb = ByteBuffer.wrap(value);
bb.order(ByteOrder.LITTLE_ENDIAN);
i++;
if (value != null && value.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(value.length);
for(byte byteChar : value)
stringBuilder.append(String.format("%02X ", byteChar));
//su value ho la stringa ricevuta, quindi posso elaborare il dato per far si che leggo sulla app quello che voglio
Byte b5 = value[5];
Byte b6 = value[6];
Byte b7 = value[7];
data_info[0] = ((value[1] << 8) | (value [2] & 0xFF));//current
data_info[1] = ((value[3] << 8) | (value [4] & 0xFF));//voltage
data_info[2] = b5.intValue();//soc
data_info[3] = b6.intValue();//temp
data_info[4] = b7.intValue();//soh
data_info[5] = ((value[8] << 8) | (value [9] & 0xFF));
//preparo i dati da passare alle alre activity
grap_curr[j]=data_info[2];
grap_volt[j]=data_info[2];
grap_temp[j]=data_info[2];
grap_soc[j]=data_info[2];
grap_soh[j]=data_info[2];
j++;
//dopo 10 cicli invio ai grafici
if (j==3){
intent.putExtra(EXTRA_DATA7, "Riepilogo temporale disponibile");
Bundle curr =new Bundle (); //array da mandare alla activity GraphCurrentActivity
curr.putIntArray("txxx",new int[] {1,2,3,4});
intentCurr.putExtras(curr);
//intentCurr.putExtra("tx",grap_curr);
//intentCurr.putExtra("datavectorcurr",new int[] {1,2,3,4,5,6,7,8,9,10});
//intentVolt.putExtra("datavectorvolt",new int[] {1,2,3,4,5,6,7,8,9,10});
//intentTemp.putExtra("datavectortemp",new int[] {1,2,3,4,5,6,7,8,9,10});
//intentSoC.putExtra("datavectorsoc",new int[] {1,2,3,4,5,6,7,8,9,10});
//intentSoH.putExtra("datavectorsoh",new int[] {1,2,3,4,5,6,7,8,9,10});
j=0;
}
//inserisco i dati negli appositi campi
intent.putExtra(EXTRA_DATA, "Battery Current: " + Integer.toString(data_info[0]) + " [A]" );
intent.putExtra(EXTRA_DATA2, "Battery Voltage: " + Integer.toString(data_info[1]) + " [V]" );
intent.putExtra(EXTRA_DATA3, "SOC: " + Integer.toString(data_info[2]) + " [Ah]" );
intent.putExtra(EXTRA_DATA4, "SOH: " + Integer.toString(data_info[4]) + " [%]");
intent.putExtra(EXTRA_DATA5, "average temperature: " + Integer.toString(data_info[3]) + " [°C]");
intent.putExtra(EXTRA_DATA6, "remaining capacity: " + Integer.toString(data_info[5]) + " [°Ah]");
}
}
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
/**
* Initializes a reference to the local Bluetooth adapter.
*
* #return Return true if the initialization is successful.
*/
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(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* #param address The device address of the destination device.
*
* #return Return true if the connection is initiated successfully. The connection result
* is reported asynchronously through the
* {#code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.d(TAG, "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(TAG, "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(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {#code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
/**
* After using a given BLE device, the app must call this method to ensure resources are
* released properly.
*/
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) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(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(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
// This is specific to Heart Rate Measurement.
if (UUID_USER_DATA.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 void readCustomCharacteristic() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
/*check if the service is available on the device*/
BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString("0000181c-0000-1000-8000-00805f9b34fb"));
if(mCustomService == null){
Log.w(TAG, "Custom BLE Service not found");
return;
}
BluetoothGattCharacteristic mNotifyCharacteristic = mCustomService.getCharacteristic(UUID.fromString("00002a8a-0000-1000-8000-00805f9b34fb"));
UUID uuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
BluetoothGattDescriptor descriptor = mNotifyCharacteristic.getDescriptor(uuid);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
//To receive notification in Android is mandatory to set characteristic notification to true
mBluetoothGatt.setCharacteristicNotification(mNotifyCharacteristic, true);
/*get the read characteristic from the service*/
BluetoothGattCharacteristic mReadCharacteristic = mCustomService.getCharacteristic(UUID.fromString("00002A8A-0000-1000-8000-00805F9B34FB"));
if(mBluetoothGatt.readCharacteristic(mReadCharacteristic) == false){
Log.w(TAG, "Failed to read characteristic");
}
}
public void writeCustomCharacteristic(int value) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
/*check if the service is available on the device*/
BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString("0000181c-0000-1000-8000-00805f9b34fb"));
if(mCustomService == null){
Log.w(TAG, "Custom BLE Service not found");
return;
}
/*get the write characteristic from the service*/
BluetoothGattCharacteristic mWriteCharacteristic = mCustomService.getCharacteristic(UUID.fromString("00002a8a-0000-1000-8000-00805f9b34fb"));
mWriteCharacteristic.setValue(value,android.bluetooth.BluetoothGattCharacteristic.FORMAT_UINT8,0);
if(mBluetoothGatt.writeCharacteristic(mWriteCharacteristic) == false){
Log.w(TAG, "Failed to write characteristic");
}
}
}
activty B
public class GraphCurrentActivity extends Activity {
private XYPlot plot;
private GoogleApiClient client;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
Bundle b=this.getIntent().getExtras();
int[] arraydata;
arraydata = b.getIntArray("txxx");//array that i don't recive
// create a couple arrays of y-values to plot:
final Number[] domainLabels = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
//Number[] series1Numbers = {plottdata[0], plottdata[1], plottdata[2], plottdata[3], plottdata[4], plottdata[5], plottdata[6], plottdata[7], plottdata[8], plottdata[9]};
Number[] series1Numbers = {11, 12, 13, 14, 0, 5, 8, 7, 1, 11};
// turn the above arrays into XYSeries':
// (Y_VALS_ONLY means use the element index as the x value)
XYSeries series1 = new SimpleXYSeries(
Arrays.asList(series1Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Battery Current Plot");
LineAndPointFormatter series1Format = new LineAndPointFormatter(Color.RED, Color.GREEN, Color.BLUE, null);
series1Format.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
// add a new series' to the xyplot:
plot.addSeries(series1, series1Format);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new Format() {
#Override
public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
int i = Math.round(((Number) obj).floatValue());
return toAppendTo.append(domainLabels[i]);
}
#Override
public Object parseObject(String source, ParsePosition pos) {
return null;
}
});
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
public Action getIndexApiAction() {
Thing object = new Thing.Builder()
.setName("GraphCurrent Page") // TODO: Define a title for the content shown.
// TODO: Make sure this auto-generated URL is correct.
.setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]"))
.build();
return new Action.Builder(Action.TYPE_VIEW)
.setObject(object)
.setActionStatus(Action.STATUS_TYPE_COMPLETED)
.build();
}
#Override
public void onStart() {
super.onStart();
client.connect();
AppIndex.AppIndexApi.start(client, getIndexApiAction());
}
#Override
public void onStop() {
super.onStop();
AppIndex.AppIndexApi.end(client, getIndexApiAction());
client.disconnect();
}
}

Best solution I can suggest is define your array as
public static int[] xyz=new int[]{1,2,3,4};
And now that static int array can be called or used from any activity provided if they are in the same package.
Here for your example in GraphCurrentActivity,
Add this import statement:
import static yourpackagename.BluetoothLeService.xyz;
//And these lines to read that array:
int[] arraydata;
arraydata = xyz;
And let me know if this was wrong.

Related

Background service crash

So for some reason my background service crashes, and I don't know why.
So my service contains BLE, and I bind to the service from the MainActivity with:
public void startBluetoothService() {
// Start the BLE Service
Log.d(TAG, "Starting BLE Service");
Intent gattServiceIntent = new Intent(this, BLE_Service.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
Log.d(TAG, "Bluetooth is Enabled");
}
This runs, but then I get the following error
10-09 12:51:31.104 14007-14081/com.example.wrd I/ProviderInstaller: Installed default security provider GmsCore_OpenSSL
10-09 12:51:31.114 14007-14007/com.example.wrd D/AndroidRuntime: Shutting down VM
10-09 12:51:31.114 14007-14007/com.example.wrd E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.wrd, PID: 14007
java.lang.RuntimeException: Unable to instantiate service com.example.wrd.ble.BLE_Service: java.lang.InstantiationException: java.lang.Class<com.example.wrd.ble.BLE_Service> has no zero argument constructor
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3841)
at android.app.ActivityThread.access$2100(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1909)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.lang.InstantiationException: java.lang.Class<com.example.wrd.ble.BLE_Service> has no zero argument constructor
at java.lang.Class.newInstance(Native Method)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3838)
at android.app.ActivityThread.access$2100(ActivityThread.java:229) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1909) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:7325) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 
My service looks like this:
public class BLE_Service extends Service {
private Home ma;
private boolean mscanning;
public boolean Read = false;
private Handler mHandler;
private long scanPeriod;
private int signalStrength;
//Intent string
private static String DeviceAddress;
private static final String TAG = "BLE_Service";
// Bluetooth objects that we need to interact with
private static BluetoothManager mBluetoothManager;
private static BluetoothAdapter mBluetoothAdapter;
private static BluetoothGatt mBluetoothGatt;
private static BluetoothDevice device;
private static BluetoothGattCharacteristic BLECharacterisitc;
private final static String BaseUuid = "00000000-0000-1000-8000-00805f9b34f";
private final static String CSUuid = "00002902-0000-1000-8000-00805f9b34fb";
private final static String UuidWrite = BaseUuid + "0";
private final static String UuidRead = BaseUuid + "1";
private final static String UuidRead2 = BaseUuid + "2";
private final static String state_RW = BaseUuid + "0";
private final static String treatmentSettings_RW = BaseUuid + "1";
private final static String adjustment_RW = BaseUuid + "2";
private final static String validation_R = BaseUuid + "3";
//Broadcasts
public final static String BROADCAST_ADDED = "added";
public final static String BROADCAST_ADDEDFrag = "added";
// Bluetooth characteristics that we need to read/write
private static BluetoothGattCharacteristic mCharacterisitc, mCharacterisitc2, mCharacterisitcWrite, mCharacterisitc_state_RW,
mCharacterisitc_treatmentSettings_RW, mCharacterisitc_adjustment_RW, mCharacterisitc_validation_R;
private static StringBuilder sb = new StringBuilder();
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean connecting(String DeviceAddress) {
Log.d(TAG, "Connection State: connect");
device = mBluetoothAdapter.getRemoteDevice(DeviceAddress);
if (device == null) {
Log.d(TAG, "Connection State Device Not Available ");
return false;
} else {
Log.d(TAG, "Connection State Connecting...");
device.connectGatt(this, false, mGattCallback);
return true;
}
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean disconnect() {
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
return true;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void checkConnectedDevices() {
if (mBluetoothGatt != null){
String DeviceString = mBluetoothGatt.getDevice().getAddress();
String NameString = mBluetoothGatt.getDevice().getName();
Log.d(TAG, "checkConnectedDevices: " + NameString);
//broadCastHEX(BROADCAST_ADDEDFrag, NameString+";"+DeviceString, "get_conn_BLE_return");
}else{
//broadCastHEX(BROADCAST_ADDEDFrag, null, "Connected_BLE_Devices_return");
}
}
public class LocalBinder extends Binder {
public BLE_Service getService() {
return BLE_Service.this;
}
}
private final IBinder mBinder = new LocalBinder();
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
}
/**
* Initializes a reference to the local Bluetooth adapter.
*
* #return Return true if the initialization is successful.
*/
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean initialize() {
Log.d(TAG, "mBluetoothManager: service");
// 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(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
Log.d(TAG, "mBluetoothManager: initialize");
BluetoothManager bluetoothManager = (BluetoothManager) getBaseContext().getSystemService(Context.BLUETOOTH_SERVICE);
List<BluetoothDevice> devices = bluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
Log.d(TAG, "mBluetoothManager: initialize device" + devices.toString());
for(BluetoothDevice device : devices) {
if(device.getType() == BluetoothDevice.DEVICE_TYPE_LE) {
Log.d(TAG, "mBluetoothManager: running loop" + device.getName() + "\n");
}else{
Log.d(TAG, "mBluetoothManager: nothing" + device.getName() + "\n");
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public BLE_Service(Home home, long scanPeriod, int signalStrength) {
ma = home;
mHandler = new Handler();
this.scanPeriod = scanPeriod;
this.signalStrength = signalStrength;
final BluetoothManager bluetoothManager =
(BluetoothManager) ma.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
}
public boolean isScanning() {
return mscanning;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void start() {
if (!Utils.checkBluetooth(mBluetoothAdapter)) {
Utils.requestUserBluetooth(ma);
ma.stopScan();
} else {
scanLeDevice(true);
}
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void stop() {
scanLeDevice(false);
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private void scanLeDevice(final boolean enable) {
if (enable && !mscanning) {
Utils.toast(ma.getApplication(), "Starting BLE Scan...");
mHandler.postDelayed(new Runnable() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public void run() {
Utils.toast(ma.getApplicationContext(), "Stopping BLE scan...");
mscanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
ma.stopScan();
}
}, scanPeriod);
mscanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
}
}
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) {
Log.d(TAG, "Connection State Change: " + status + " -> " + connectionState(newState));
gatt.discoverServices();
if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
/*
* Once successfully connected, we must next discover all the services on the
* device before we can read and write their characteristics.
*/
mBluetoothGatt = gatt;
BluetoothDevice device = gatt.getDevice();
Log.d(TAG, "Connection State onConnectionStateChange: " + device);
} else if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_DISCONNECTED) {
/*
* If at any point we disconnect, send a message to clear the weather values
* out of the UI
*/
Log.d(TAG, "Connection State: 2");
} else if (status != BluetoothGatt.GATT_SUCCESS) {
/*
* If there is a failure at any stage, simply disconnect
*/
}
}
/**
* This is called when a service discovery has completed.
*
* It gets the characteristics we are interested in and then
* broadcasts an update to the main activity.
*
* #param gatt The GATT database object
* #param status Status of whether the write was successful.
*/
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public void onServicesDiscovered(final BluetoothGatt gatt, int status) {//prøv med ekstra status på denne
if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService mBluetoothGattService = gatt.getService(UUID.fromString(CSUuid));
if (mBluetoothGattService != null) {
Log.i(TAG, "Connection State: Service characteristic UUID found: " + mBluetoothGattService.getUuid().toString());
mCharacterisitc = mBluetoothGattService.getCharacteristic(UUID.fromString(UuidRead));
mCharacterisitc2 = mBluetoothGattService.getCharacteristic(UUID.fromString(UuidRead2));
mCharacterisitcWrite = mBluetoothGattService.getCharacteristic(UUID.fromString(UuidWrite));
//First activate buttons here....
Log.w(TAG, "Connection State 1: mCharacterisitc " + mCharacterisitc + " " + mCharacterisitc2);
Intent broadcastIntent = new Intent().putExtra("ConnState", true);
broadcastIntent.setAction(BLE_Service.BROADCAST_ADDED);
LocalBroadcastManager.getInstance(BLE_Service.this).sendBroadcast(broadcastIntent);
if(Read){
readCharacteristic(gatt, mCharacterisitc);
}
} else {
Log.i(TAG, "Connection State: Service characteristic not found for UUID: " + UuidRead);
}
}
}
private String connectionState(int status) {
switch (status) {
case BluetoothProfile.STATE_CONNECTED:
return "Connection State: Connected";
case BluetoothProfile.STATE_DISCONNECTED:
return "Connection State: Disconnected";
case BluetoothProfile.STATE_CONNECTING:
return "Connection State: Connecting";
case BluetoothProfile.STATE_DISCONNECTING:
return "Connection State: Disconnecting";
default:
return String.valueOf(status);
}
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "Connection State: onCharacteristicRead");
Log.w(TAG, "Connection State: Read 1");
// Verify that the read was the LED state
String uuid = characteristic.getUuid().toString();
// In this case, the only read the app does is the LED state.
// If the application had additional characteristics to read we could
// use a switch statement here to operate on each one separately.
if (uuid.equalsIgnoreCase(UuidRead)) {
Log.w(TAG, "Connection State: Read 2");
final int Val = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
broadCast(BROADCAST_ADDEDFrag, Val, "read_Service");
Log.i(TAG, "Connection State: onCharacteristicRead: " + Val);
Log.d(TAG, "Connection State Read state: "+Read);
readCharacteristic(gatt, mCharacterisitc2);
}
if (uuid.equalsIgnoreCase(UuidRead2)) {
Log.w(TAG, "Connection State: Read 3");
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));
String msg = "letter: " + new String(data) + "\nHEX: " + stringBuilder.toString();
Log.d(TAG, "Connection State: onCharacteristicRead2: 4 " + msg);
broadCastHEX(BROADCAST_ADDEDFrag, msg, "read_Service2");
}
Read = false; //Has to be set to false in the last read message..
Log.d(TAG, "Connection State Read state: "+Read);
}
}
}
};
/**
* Runs service discovery on the connected device.
*
* #return
*/
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void discoverServices() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.d(TAG, "Connection State BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.discoverServices();
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void Write(Integer integer) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.d(TAG, "Connection State BluetoothAdapter not initialized");
return;
}
Integer Val = integer;
byte[] byteVal;
byteVal = intToByteArray(Val);
mCharacterisitcWrite.setValue(byteVal);
Log.d(TAG, "Connection State write 1: " + byteVal);
mBluetoothGatt.writeCharacteristic(mCharacterisitcWrite);
}
public static byte[] intToByteArray(int a) {
byte[] ret = new byte[4];
ret[3] = (byte) (a & 0xFF);
ret[2] = (byte) ((a >> 8) & 0xFF);
ret[1] = (byte) ((a >> 16) & 0xFF);
ret[0] = (byte) ((a >> 24) & 0xFF);
return ret;
}
/**
* This method is used to read the state of the LED from the device
*/
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void readCharacteristic(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || gatt == null) {
Log.w(TAG, "Connection State: BluetoothAdapter not initialized 2");
return;
}
Log.w(TAG, "Connection State: BluetoothAdapter initialized");
gatt.readCharacteristic(characteristic);
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
final int new_rssi = rssi;
if (rssi > signalStrength && device.getName() != null) {
mHandler.post(new Runnable() {
#Override
public void run() {
try {
FragmentBLE.addDevice(device, new_rssi);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
};
public void broadCast(String broadcastTXT, Integer Val, String key) {
Log.d(TAG, "Connection State: -> broadCast: Service Broadcast");
Intent broadcastIntent = new Intent().putExtra(key, Val);
broadcastIntent.setAction(broadcastTXT);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
}
public void broadCastHEX(String broadcastTXT, String Val, String key) {
Log.d(TAG, "Connection State: -> broadCast: Service Broadcast");
Intent broadcastIntent = new Intent().putExtra(key, Val);
broadcastIntent.setAction(broadcastTXT);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
}
}
So what causes this error to occure?
looks like it's somthing to do with java.lang.RuntimeException: Unable to instantiate service com.example.wrd.ble.BLE_Service, and I've been serching on it, but can't seem to find anything that helps.
EDIT
So my filled contructer is done before my empty contructer is set. I bind in my onStart()
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
protected void onStart() {
super.onStart();
// Start the BLE Service
Log.d(TAG, "Starting BLE Service");
Intent gattServiceIntent = new Intent(this, BLE_Service.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
Log.d(TAG, "Bluetooth is Enabled");
registerReceiver(mBTStateUpdateReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}
And then in my oncreate I run the following
mBTLeScanner = new BLE_Service(this, 7500, -75);
but somehow BLE_Service(this, 7500, -75) is finished before onStart()
Create an empty constructor.
BLE_Service(){
}

BLE CallBack onCharacteristicChanged is not call back

I am a student working with BLE, and I am not good at English, so please understand it with the help of Google Translator.
Since the BLE notification does not work during the work, it is difficult to attach the source, so please help.
boolean success4 = mBluetoothGatt.writeDescriptor(descriptor); is false but I don't know why.
// Debugging
private static final String TAG = "BleManager";
// Constants that indicate the current connection state
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
// Message types sent from the BluetoothManager to Handler
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 = 10000; // Stops scanning after a pre-defined scan period.
public static final long SCAN_INTERVAL = 5 * 60 * 1000;
// System, Management
private static Context mContext = null;
Handler mHandler;
private boolean connect = false;
// Bluetooth
private BluetoothAdapter mBluetoothAdapter;
private BluetoothManager mBluetoothManager;
private BluetoothGattCharacteristic mcharacteristic;
private ArrayList<BluetoothDevice> mDeviceList = new ArrayList<BluetoothDevice>();
private BluetoothDevice mDefaultDevice = null;
private BluetoothGatt mBluetoothGatt = null;
private ArrayList<BluetoothGattService> mGattServices
= new ArrayList<BluetoothGattService>();
private BluetoothGattService mDefaultService = null;
private ArrayList<BluetoothGattCharacteristic> mGattCharacteristics
= new ArrayList<BluetoothGattCharacteristic>();
private ArrayList<BluetoothGattCharacteristic> mWritableCharacteristics
= new ArrayList<BluetoothGattCharacteristic>();
private BluetoothGattCharacteristic mDefaultChar = null;
// Parameters
private int mState = -1;
private void BleManager() {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = mBluetoothManager.getAdapter();
//mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mContext = this;
if (mContext == null) {return;}
else
{
scanLeDevice(true);
}
}
public synchronized void finalize() {
// Make sure we're not doing discovery anymore
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;
// Don't forget this!!
// Unregister broadcast listeners
// mContext.unregisterReceiver(mReceiver);
}
/*****************************************************
* Private methods
******************************************************/
/**
* This method extracts UUIDs from advertised data
* Because Android native code has bugs in parsing 128bit UUID
* use this method instead.
*/
private void stopScanning() {
if (mState < STATE_CONNECTING) {
mState = STATE_IDLE;
}
scanLeDevice(false);
//mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
/**
* Check services and looking for writable characteristics
*/
private int checkGattServices(List<BluetoothGattService> gattServices) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.e("# BluetoothAdapter", " not initialized");
return -1;
}
for (BluetoothGattService gattService : gattServices) {
// Default service info
Log.e("# GATT Service:", " " + gattService.getUuid().toString());
// Remember service
mGattServices.add(gattService);
// Extract characteristics
List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
// Remember characteristic
mGattCharacteristics.add(gattCharacteristic);
for (BluetoothGattDescriptor descriptor:gattCharacteristic.getDescriptors()){
Log.e("# GATT Char:", gattCharacteristic.getUuid().toString());
Log.e(TAG, "BluetoothGattDescriptor: " + descriptor.getUuid().toString());
}
boolean isWritable = isWritableCharacteristic(gattCharacteristic);
if (isWritable) {
mWritableCharacteristics.add(gattCharacteristic);
}
boolean isReadable = isReadableCharacteristic(gattCharacteristic);
if (isReadable) {
readCharacteristic(gattCharacteristic);
}
if (isNotificationCharacteristic(gattCharacteristic) && gattCharacteristic.getUuid().toString().equals("0000ffe1-0000-1000-8000-00805f9b34fb")) {
setCharacteristicNotification(gattCharacteristic, true);
if (gattCharacteristic.getUuid().toString().equals("0000ffe1-0000-1000-8000-00805f9b34fb")) {
Log.e("default", "##############################################");
mDefaultChar = gattCharacteristic;
Log.e("default", "////////////////////////////////////////////// " + mDefaultChar.getUuid().toString());
//break;
}
}
}
}
return mWritableCharacteristics.size();
}
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.e("# Found writable", " characteristic");
return true;
} else {
Log.e("# Not writable", " characteristic");
return false;
}
}
private boolean isReadableCharacteristic(BluetoothGattCharacteristic chr) {
if (chr == null) return false;
final int charaProp = chr.getProperties();
if ((charaProp & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
Log.e("# Found readable", " characteristic");
return true;
} else {
Log.e("# Not readable", " characteristic");
return false;
}
}
private boolean isNotificationCharacteristic(BluetoothGattCharacteristic chr) {
if (chr == null) return false;
final int charaProp = chr.getProperties();
if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
Log.e("# Found notification", " characteristic");
return true;
} else {
Log.e("# Not notification", " characteristic");
return false;
}
}
/**
* 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) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.e("# BluetoothAdapter", " not initialized");
return;
}
mBluetoothGatt.readCharacteristic(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.e("# BluetoothAdapter ", "not initialized");
return;
}
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
boolean success1 = mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
//00002902-0000-1000-8000-00805f9b34fb
//public static String CLIENT_CHARACTERISTIC_CONFIG = "0000ffe1-0000-1000-8000-00805f9b34fb";
Log.e("info1",characteristic.getUuid().toString() + " // " + characteristic.getValue() + " // " + enabled + " // " + success1);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
Log.e("info2",characteristic.getUuid().toString() + " // " + characteristic.getValue() + " // " + enabled);
boolean success3 = descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
boolean success2 = descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
Log.e("info3",characteristic.getUuid().toString() + " // " + characteristic.getValue() + " // " + enabled + " // " + success3 + " // " + success2);
//boolean success5 = mBluetoothGatt.writeCharacteristic(characteristic);
boolean success4 = mBluetoothGatt.writeDescriptor(descriptor);
Log.e("info4",descriptor.getCharacteristic() + " // " + descriptor.getValue() + " // " + descriptor.getPermissions() + " // " + descriptor.getUuid() + " // " + enabled + " // " + success4);
//mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
}
/*****************************************************
* Public methods
******************************************************/
public int getState() {
return mState;
}
private void scanLeDevice(final boolean enable) {
mHandler = new Handler();
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}, SCAN_PERIOD);
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if(device.getName() != null && device.getName().equals("AINTEL_MFD") && connect == false){
connect = true;
scanLeDevice(false);
Log.e("ScanDevice",device.getName() + " // " + device.getUuids() + " // " + device.getAddress() + " // " + rssi + " // " + scanRecord[0] + " // " + scanRecord[1]);
connectGatt(Vars.mContext,false, device);
}
}
});
}
};
public boolean scanLeDevice(final boolean enable, UUID[] uuid) {
boolean isScanStarted = false;
if (enable) {
if (mState == STATE_SCANNING)
return false;
if (mBluetoothAdapter.startLeScan(uuid, mLeScanCallback)) {
mState = STATE_SCANNING;
mDeviceList.clear();
// If you want to scan for only specific types of peripherals
// call below function instead
//startLeScan(UUID[], BluetoothAdapter.LeScanCallback);
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
stopScanning();
}
}, SCAN_PERIOD);
isScanStarted = true;
}
} else {
if (mState < STATE_CONNECTING) {
mState = STATE_IDLE;
}
stopScanning();
}
return isScanStarted;
}
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;
return true;
}
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.e("# 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;
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {#code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.e("# BluetoothAdapter", " not initialized");
return;
}
mBluetoothGatt.disconnect();
}
public boolean write(BluetoothGattCharacteristic chr, byte[] data) {
if (mBluetoothGatt == null) {
Log.e(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.e(TAG, "# Write failed - No available characteristic");
return false;
}
} else {
if (isWritableCharacteristic(mDefaultChar)) {
Log.e("# Default", "is PROPERY_WRITE | PROPERTY_WRITE_NO_RESPONSE");
writableChar = mDefaultChar;
} else {
Log.e("# De ", "is not writable");
mDefaultChar = null;
return false;
}
}
} else {
if (isWritableCharacteristic(chr)) {
Log.e("# user ", "GattCharacteristic is PROPERY_WRITE | PROPERTY_WRITE_NO_RESPONSE");
writableChar = chr;
} else {
Log.e("# user ", "GattCharacteristic is not writable");
return false;
}
}
writableChar.setValue(data);
writableChar.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
mBluetoothGatt.writeCharacteristic(writableChar);
mDefaultChar = writableChar;
return true;
}
public void setWritableCharacteristic(BluetoothGattCharacteristic chr) {
mDefaultChar = chr;
}
public ArrayList<BluetoothGattService> getServices() {
return mGattServices;
}
public ArrayList<BluetoothGattCharacteristic> getCharacteristics() {
return mGattCharacteristics;
}
public ArrayList<BluetoothGattCharacteristic> getWritableCharacteristics() {
return mWritableCharacteristics;
}
/*****************************************************
* Handler, Listener, Timer, Sub classes
******************************************************/
// Various callback methods defined by the BLE API.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mState = STATE_CONNECTED;
Log.e(TAG, "# Connected to GATT server.");
gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
mState = STATE_IDLE;
Log.e(TAG, "# Disconnected from GATT server.");
mBluetoothGatt = null;
mGattServices.clear();
mDefaultService = null;
mGattCharacteristics.clear();
mWritableCharacteristics.clear();
mDefaultChar = null;
mDefaultDevice = null;
}
}
#Override
// New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.e(TAG, "# New GATT service discovered.");
checkGattServices(gatt.getServices());
} else {
Log.e(TAG, "# onServicesDiscovered received: " + status);
}
}
#Override
// Result of a characteristic read operation
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
// We've received data from remote
Log.e(TAG, "# Read characteristic11111: " + String.format("%02X",characteristic.getValue()));
/*
* onCharacteristicChanged callback receives same message
*
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.e(TAG, stringBuilder.toString());
mHandler.obtainMessage(MESSAGE_READ, new String(data)).sendToTarget();
}
if(mDefaultChar == null && isWritableCharacteristic(characteristic)) {
mDefaultChar = characteristic;
}
*/
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
// We've received data from remote
byte[] newValue = characteristic.getValue();
Log.e(TAG, "# onCharacteristicChanged: " + String.format("%02X",newValue));
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.e(TAG, stringBuilder.toString());
}
if (mDefaultChar == null && isWritableCharacteristic(characteristic)) {
mDefaultChar = characteristic;
}
}
};
}
3 things:
First make sure you have permissions. Requires Manifest.permission.BLUETOOTH permission.
Make sure your service/characteristic is correct.
Override onDescriptorWrite and check what you have done with writeDescriptor from there. If there is a problem, the onDescriptorWrite will tell you.
Google docs about BLE are not that good. Therefore, this amazing article will help you solve any issue with BLE.

How to Automatically Connect BLE Device instead of Manual Click Scanner to get data to Android Application (Known Device name and UUID)

I want to be able to connect to a device automatically when I start up the app and get the data automatically.
I don't want to scan for Device name and manually click it to show services.
I know the device name and UUIDs for the service and characteristic data.
How do I go about doing so?
The name of the device is Electronic Scale
The service is on 0XFFF0.
The characteristic is on 0XFFF4. (Where the weight data is)
Here is my code for the scanner right now:
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA";
public final static UUID WEIGHT_MEASUREMENT =
UUID.fromString(SampleGattAttributes.WEIGHT_MEASUREMENT);
// 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) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
// This is special handling for the Heart Rate Measurement profile. Data parsing is
// carried out as per profile specifications:
//
if (WEIGHT_MEASUREMENT.equals(characteristic.getUuid())) {
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
double weightkg = (data[4]*256+data[5])/10.0;
double weightlb = weightkg * 2.2;
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X", byteChar));
intent.putExtra(EXTRA_DATA, new Double(weightkg) + "kg" + "\n" + weightlb + "lb" + "\n" +
stringBuilder.toString());
} else {
// For all other profiles, writes the data formatted in HEX.
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for (byte byteChar : data)
stringBuilder.append(String.format("%02X", byteChar));
intent.putExtra(EXTRA_DATA, new String(data) + stringBuilder.toString());
}
}
}
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
/**
* Initializes a reference to the local Bluetooth adapter.
*
* #return Return true if the initialization is successful.
*/
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(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* #param address The device address of the destination device.
*
* #return Return true if the connection is initiated successfully. The connection result
* is reported asynchronously through the
* {#code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.d(TAG, "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(TAG, "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(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {#code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
/**
* After using a given BLE device, the app must call this method to ensure resources are
* released properly.
*/
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) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(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(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
// 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();
}
}
Thanks!
Simply use your BluetoothLeService instance and call your connect(final String address) method passing the address of the device you want to connect to. This should work !

Android app crash on Bluetooth LE write

I am developing an Android app to control stepper motors via a Android Due and a Bluetooth HM-10 BLE module.
So far everything works, but there seems to be a problem on some devices, which cause the app to crash. On my Nexus 5 and 7 it is working fine, but for example on a Samsung Galaxy S5 it keeps crashing. All devices have Andoird 6.0.1, so they should be equal.
I am getting this error report from the user:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.bluetooth.BluetoothGattCharacteristic.setValue(byte[])' on a null object reference
at pm.puremoco.BluetoothLeService.WriteValue(BluetoothLeService.java:70)
at pm.puremoco.frag_moviesetlinear$3.onFinish(frag_moviesetlinear.java:266)
at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:127)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
So the error is occuring, when opening, at "onCreateView". There is the command to transmit a value:
mBluetoothLeService.WriteValue("1900_" + String.valueOf(variables.vidUpdateIntervall) + "#");
Here is almost the full fragment:
public class frag_moviesetlinear extends Fragment {
public static final String methodtocall = "ooo";
private final static String TAG = DeviceControlFragment.class.getSimpleName();
public AlertDialog alertTransmitData;
public BluetoothLeService mBluetoothLeService; //TODO evtl. private
public String methodcalled = "aaa";
public String dataLineReceived;
public long countDownTimerDelay = 200;
public AlertDialog alertTimeTooShort;
NumberPicker noPick1 = null;
NumberPicker noPick2 = null;
NumberPicker noPick3 = null;
long alertTransmitDataLength = 21000;
DeviceControlFragment devConFrag;
double minTimeFactor = 0;
TextView vid_maxSpeedU;
TextView vid_maxSpeedV;
TextView vid_maxSpeedW;
TextView vid_maxSpeedX;
TextView vid_maxSpeedY;
TextView vid_maxSpeedZ;
TextView vid_maxSpeedUspline;
TextView vid_maxSpeedVspline;
TextView vid_maxSpeedWspline;
TextView vid_maxSpeedXspline;
TextView vid_maxSpeedYspline;
TextView vid_maxSpeedZspline;
TextView txt_vidDuration;
TextView txt_vidUpdateIntervall;
TextView txt_minTime;
int timeForCalculation = 0;
int calculatedSpeedU = 0;
int calculatedSpeedV = 0;
int calculatedSpeedW = 0;
int calculatedSpeedX = 0;
int calculatedSpeedY = 0;
int calculatedSpeedZ = 0;
boolean movingHome = false;
private String mDeviceAddress;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
getActivity().finish();
}
Log.e(TAG, "mBluetoothLeService is okay");
// Log.e(TAG, mDeviceAddress);
// Automatically connects to the device upon successful start-up initialization.
if (mDeviceAddress == "---") {
Toast.makeText(getActivity(), "Bluetooth-Device not selected!", Toast.LENGTH_SHORT).show();
} else {
mBluetoothLeService.connect(mDeviceAddress);
}
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
private String mDeviceName;
private TextView mDataField;
private Button btn_vidSplineStart;
private Button btn_vidUpdateIntervalNeg;
private Button btn_vidUpdateIntervalPos;
private boolean mConnected = false;
// Handles various events fired by the Service.
// ACTION_GATT_CONNECTED: connected to a GATT server.
// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
// ACTION_DATA_AVAILABLE: received data from the device. This can be a result of read
// or notification operations.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { //���ӳɹ�
Log.e(TAG, "Only gatt, just wait");
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { //�Ͽ�����
mConnected = false;
getActivity().invalidateOptionsMenu();
// btnSend.setEnabled(false);
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) //���Կ�ʼ�ɻ���
{
mConnected = true;
// mDataField.setText("");
// ShowDialog();
//btnSend.setEnabled(true);
Log.e(TAG, "In what we need");
getActivity().invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { //�յ�����
Log.e(TAG, "RECV DATA");
final String data = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
Log.e(TAG, data);
if (data != null && data.substring(0, 1).equals("#") && data.substring(data.length() - 1).equals("$")) {
// if (mDataField.length() > 500)
// mDataField.setText("");
// mDataField.append(data);
dataLineReceived = data.substring(1, data.length() - 1);
ActionHandlerDataReceived();
}
}
}
};
private static IntentFilter makeGattUpdateIntentFilter() { //ע����յ��¼�
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
intentFilter.addAction(BluetoothDevice.ACTION_UUID);
return intentFilter;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
final Intent intent = getActivity().getIntent();
// mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
// mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
mDeviceAddress = variables.BluetoothAddress;
mDeviceName = variables.BluetoothName;
methodcalled = intent.getStringExtra(methodtocall);
Intent gattServiceIntent = new Intent(getActivity(), BluetoothLeService.class);
Log.d(TAG, "Try to bindService=" + getActivity().bindService(gattServiceIntent, mServiceConnection, getActivity().BIND_AUTO_CREATE));
getActivity().registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
#Override
public void onPause() {
super.onPause();
try {
getActivity().unregisterReceiver(mGattUpdateReceiver);
}
catch(Exception e){
}
try {
getActivity().unbindService(mServiceConnection);
}
catch(Exception e){
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "We are in destroy");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.setmovie, null);
vid_maxSpeedU = (TextView) layout.findViewById(R.id.vid_maxSpeedU);
vid_maxSpeedU.setText(String.valueOf(variables.speedU));
vid_maxSpeedV = (TextView) layout.findViewById(R.id.vid_maxSpeedV);
vid_maxSpeedV.setText(String.valueOf(variables.speedV));
vid_maxSpeedW = (TextView) layout.findViewById(R.id.vid_maxSpeedW);
vid_maxSpeedW.setText(String.valueOf(variables.speedW));
vid_maxSpeedX = (TextView) layout.findViewById(R.id.vid_maxSpeedX);
vid_maxSpeedX.setText(String.valueOf(variables.speedX));
vid_maxSpeedY = (TextView) layout.findViewById(R.id.vid_maxSpeedY);
vid_maxSpeedY.setText(String.valueOf(variables.speedY));
vid_maxSpeedZ = (TextView) layout.findViewById(R.id.vid_maxSpeedZ);
vid_maxSpeedZ.setText(String.valueOf(variables.speedZ));
double duration = 3700 * (double) variables.vidUpdateIntervall / 1000;
txt_vidUpdateIntervall = (TextView) layout.findViewById(R.id.txt_vidUpdateIntervall);
txt_vidUpdateIntervall.setText(String.valueOf(variables.vidUpdateIntervall));
txt_vidDuration = (TextView) layout.findViewById(R.id.txt_vidDuration);
txt_vidDuration.setText(String.format("%.2f", duration) + " s");
vid_maxSpeedUspline = (TextView) layout.findViewById(R.id.vid_maxSpeedUspline);
vid_maxSpeedVspline = (TextView) layout.findViewById(R.id.vid_maxSpeedVspline);
vid_maxSpeedWspline = (TextView) layout.findViewById(R.id.vid_maxSpeedWspline);
vid_maxSpeedXspline = (TextView) layout.findViewById(R.id.vid_maxSpeedXspline);
vid_maxSpeedYspline = (TextView) layout.findViewById(R.id.vid_maxSpeedYspline);
vid_maxSpeedZspline = (TextView) layout.findViewById(R.id.vid_maxSpeedZspline);
txt_minTime = (TextView) layout.findViewById(R.id.txt_minTime);
btn_vidSplineStart = (Button) layout.findViewById(R.id.btn_vidSplineStart);
btn_vidSplineStart.setOnClickListener(new event_btn_vidSplineStart());
btn_vidUpdateIntervalPos = (Button) layout.findViewById(R.id.btn_vidUpdateIntervalPos);
btn_vidUpdateIntervalPos.setOnClickListener(new event_btn_vidUpdateIntervalPos());
btn_vidUpdateIntervalNeg = (Button) layout.findViewById(R.id.btn_vidUpdateIntervalNeg);
btn_vidUpdateIntervalNeg.setOnClickListener(new event_btn_vidUpdateIntervalNeg());
//-----start-button------
minTimeFactor = 0;
timeForCalculation = variables.vidUpdateIntervall;
new CountDownTimer(countDownTimerDelay * 1, 1) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
mBluetoothLeService.WriteValue("1900_" + String.valueOf(variables.vidUpdateIntervall) + "#");
}
}.start();
new CountDownTimer(countDownTimerDelay * 2, 1) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
mBluetoothLeService.WriteValue("2000_" + String.valueOf(variables.linearWithFade) + "#");
}
}.start();
//-----start-button------
transmitDataAlert("calculation");
return layout;
}
private void ActionHandlerDataReceived() {
String variable;
String value;
String[] parts = dataLineReceived.split("_"); // escape .
variable = parts[0];
value = parts[1];
switch (variable) {
case "vidMaxSpeedU":
vid_maxSpeedUspline.setText(String.valueOf(value));
variables.vid_maxSpeedUspline = Integer.parseInt(value);
calculatedSpeedU = Integer.parseInt(value);
if (Integer.parseInt(value) > variables.speedU) {
vid_maxSpeedUspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedUspline.setTextColor(Color.parseColor("#FF14AA00"));
}
double FactorU = Double.valueOf(value) / variables.speedU;
if (minTimeFactor < FactorU) {
minTimeFactor = FactorU;
}
break;
case "vidMaxSpeedV":
vid_maxSpeedVspline.setText(String.valueOf(value));
variables.vid_maxSpeedVspline = Integer.parseInt(value);
calculatedSpeedV = Integer.parseInt(value);
if (Integer.parseInt(value) > variables.speedV) {
vid_maxSpeedVspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedVspline.setTextColor(Color.parseColor("#FF14AA00"));
}
double FactorV = Double.valueOf(value) / variables.speedV;
if (minTimeFactor < FactorV) {
minTimeFactor = FactorV;
}
break;
case "vidMaxSpeedW":
vid_maxSpeedWspline.setText(String.valueOf(value));
variables.vid_maxSpeedWspline = Integer.parseInt(value);
calculatedSpeedW = Integer.parseInt(value);
if (Integer.parseInt(value) > variables.speedW) {
vid_maxSpeedWspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedWspline.setTextColor(Color.parseColor("#FF14AA00"));
}
double FactorW = Double.valueOf(value) / variables.speedW;
if (minTimeFactor < FactorW) {
minTimeFactor = FactorW;
}
break;
case "vidMaxSpeedX":
vid_maxSpeedXspline.setText(String.valueOf(value));
variables.vid_maxSpeedXspline = Integer.parseInt(value);
calculatedSpeedX = Integer.parseInt(value);
if (Integer.parseInt(value) > variables.speedX) {
vid_maxSpeedXspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedXspline.setTextColor(Color.parseColor("#FF14AA00"));
}
double FactorX = Double.valueOf(value) / variables.speedX;
if (minTimeFactor < FactorX) {
minTimeFactor = FactorX;
}
break;
case "vidMaxSpeedY":
vid_maxSpeedYspline.setText(String.valueOf(value));
variables.vid_maxSpeedYspline = Integer.parseInt(value);
calculatedSpeedY = Integer.parseInt(value);
if (Integer.parseInt(value) > variables.speedY) {
vid_maxSpeedYspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedYspline.setTextColor(Color.parseColor("#FF14AA00"));
}
double FactorY = Double.valueOf(value) / variables.speedY;
if (minTimeFactor < FactorY) {
minTimeFactor = FactorY;
}
break;
case "vidMaxSpeedZ":
vid_maxSpeedZspline.setText(String.valueOf(value));
variables.vid_maxSpeedZspline = Integer.parseInt(value);
calculatedSpeedZ = Integer.parseInt(value);
if (Integer.parseInt(value) > variables.speedZ) {
vid_maxSpeedZspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedZspline.setTextColor(Color.parseColor("#FF14AA00"));
}
double FactorZ = Double.valueOf(value) / variables.speedZ;
if (minTimeFactor < FactorZ) {
minTimeFactor = FactorZ;
}
alertTransmitData.dismiss();
double vidMin = Math.ceil(minTimeFactor * timeForCalculation);
variables.vidMinIntervall = (int) vidMin;
//txt_minTime.setText(String.valueOf(variables.vidMinIntervall));
double duration = (3700 * (double) variables.vidMinIntervall) / 1000;
txt_minTime.setText(String.format("%.2f", duration) + " s");
if(variables.vidMinIntervall<=variables.vidUpdateIntervall) {
btn_vidSplineStart.setEnabled(true);
}
break;
case "movieFinished":
btn_vidSplineStart.setText("Move home");
btn_vidSplineStart.setEnabled(true);
movingHome = true;
alertTransmitData.dismiss();
break;
case "movieHome":
btn_vidSplineStart.setText("Start");
btn_vidSplineStart.setEnabled(true);
alertTransmitData.dismiss();
break;
}
}
void calculateNewSpeeds() {
//--------------U-Axis-----------------
if (variables.vid_maxSpeedUspline != 0) {
variables.vid_maxSpeedUspline = (timeForCalculation * calculatedSpeedU) / variables.vidUpdateIntervall;
vid_maxSpeedUspline.setText(String.valueOf(variables.vid_maxSpeedUspline));
if (variables.vid_maxSpeedUspline > variables.speedU) {
vid_maxSpeedUspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedUspline.setTextColor(Color.parseColor("#FF14AA00"));
}
}
//--------------V-Axis-----------------
if (variables.vid_maxSpeedVspline != 0) {
variables.vid_maxSpeedVspline = (timeForCalculation * calculatedSpeedV) / variables.vidUpdateIntervall;
vid_maxSpeedVspline.setText(String.valueOf(variables.vid_maxSpeedVspline));
if (variables.vid_maxSpeedVspline > variables.speedV) {
vid_maxSpeedVspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedVspline.setTextColor(Color.parseColor("#FF14AA00"));
}
}
//--------------W-Axis-----------------
if (variables.vid_maxSpeedWspline != 0) {
variables.vid_maxSpeedWspline = (timeForCalculation * calculatedSpeedW) / variables.vidUpdateIntervall;
vid_maxSpeedWspline.setText(String.valueOf(variables.vid_maxSpeedWspline));
if (variables.vid_maxSpeedWspline > variables.speedW) {
vid_maxSpeedWspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedWspline.setTextColor(Color.parseColor("#FF14AA00"));
}
}
//--------------X-Axis-----------------
if (variables.vid_maxSpeedXspline != 0) {
variables.vid_maxSpeedXspline = (timeForCalculation * calculatedSpeedX) / variables.vidUpdateIntervall;
vid_maxSpeedXspline.setText(String.valueOf(variables.vid_maxSpeedXspline));
if (variables.vid_maxSpeedXspline > variables.speedX) {
vid_maxSpeedXspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedXspline.setTextColor(Color.parseColor("#FF14AA00"));
}
}
//--------------Y-Axis-----------------
if (variables.vid_maxSpeedYspline != 0) {
variables.vid_maxSpeedYspline = (timeForCalculation * calculatedSpeedY) / variables.vidUpdateIntervall;
vid_maxSpeedYspline.setText(String.valueOf(variables.vid_maxSpeedYspline));
if (variables.vid_maxSpeedYspline > variables.speedY) {
vid_maxSpeedYspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedYspline.setTextColor(Color.parseColor("#FF14AA00"));
}
}
//--------------Z-Axis-----------------
if (variables.vid_maxSpeedZspline != 0) {
variables.vid_maxSpeedZspline = (timeForCalculation * calculatedSpeedZ) / variables.vidUpdateIntervall;
vid_maxSpeedZspline.setText(String.valueOf(variables.vid_maxSpeedZspline));
if (variables.vid_maxSpeedZspline > variables.speedZ) {
vid_maxSpeedZspline.setTextColor(Color.parseColor("#FFFF3434"));
} else {
vid_maxSpeedZspline.setTextColor(Color.parseColor("#FF14AA00"));
}
}
}
public void alert_TimeTooShort(int errorCase, int movieLengthSecondsNEW) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
getActivity());
// set title
alertDialogBuilder.setTitle("Error");
String errorMessage = "error";
// set dialog message
alertDialogBuilder
.setMessage(errorMessage)
.setCancelable(false);
alertDialogBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
}
});
// create alert dialog
alertTimeTooShort = alertDialogBuilder.create();
// show it
alertTimeTooShort.show();
}
public void transmitDataAlert(String type) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View promptView = layoutInflater.inflate(R.layout.alert_transmitdata, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
alertDialogBuilder.setView(promptView);
final ProgressBar progressbar = (ProgressBar) promptView.findViewById(R.id.progressBar_transmitData);
final TextView txt_PleaseWait = (TextView) promptView.findViewById(R.id.txt_PleaseWait);
final TextView txt_timeRemainVideo = (TextView) promptView.findViewById(R.id.txt_timeRemainVideo);
final TextView txt_timeRemainVideoTXT = (TextView) promptView.findViewById(R.id.txt_timeRemainVideoTXT);
new CountDownTimer(alertTransmitDataLength, 1) {
public void onTick(long millisUntilFinished) {
int longtointRemain = (int) millisUntilFinished;
int longtointFull = (int) alertTransmitDataLength;
int percentprogress = 100 - ((100 * longtointRemain) / longtointFull);
progressbar.setProgress(percentprogress);
float duration = (float) millisUntilFinished/1000;
txt_timeRemainVideo.setText(String.format("%.1f", duration) + " s");
}
public void onFinish() {
}
}.start();
}
alertDialogBuilder.setCancelable(false);
alertTransmitData = alertDialogBuilder.create();
alertTransmitData.show();
}
class event_btn_vidSplineStart implements View.OnClickListener {
#Override
public void onClick(View v) {
btn_vidSplineStart.setEnabled(false);
btn_vidSplineStart.setText("Moving...");
new CountDownTimer(countDownTimerDelay * 1, 1) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
//MotionMode
mBluetoothLeService.WriteValue("1900_" + String.valueOf(variables.vidUpdateIntervall) + "#");
}
}.start();
new CountDownTimer(countDownTimerDelay * 2, 1) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
//MotionMode
mBluetoothLeService.WriteValue("1110_0#");
}
}.start();
alertTransmitDataLength = (long) variables.vidUpdateIntervall*3700;
if(movingHome==true){
transmitDataAlert("moveHome");
movingHome=false;
}
else {
transmitDataAlert("videomove");
}
}
}
class event_btn_vidUpdateIntervalPos implements View.OnClickListener {
#Override
public void onClick(View v) {
variables.vidUpdateIntervall++;
double duration = (3700 * (double) variables.vidUpdateIntervall) / 1000;
txt_vidDuration.setText(String.format("%.2f", duration) + " s");
txt_vidUpdateIntervall.setText(String.valueOf(variables.vidUpdateIntervall));
calculateNewSpeeds();
if(variables.vidMinIntervall<=variables.vidUpdateIntervall) {
btn_vidSplineStart.setEnabled(true);
}
else{
btn_vidSplineStart.setEnabled(false);
}
}
}
class event_btn_vidUpdateIntervalNeg implements View.OnClickListener {
#Override
public void onClick(View v) {
if (variables.vidUpdateIntervall > 1) {
variables.vidUpdateIntervall--;
}
double duration = (3700 * (double) variables.vidUpdateIntervall) / 1000;
txt_vidDuration.setText(String.format("%.2f", duration) + " s");
txt_vidUpdateIntervall.setText(String.valueOf(variables.vidUpdateIntervall));
calculateNewSpeeds();
if(variables.vidMinIntervall<=variables.vidUpdateIntervall) {
btn_vidSplineStart.setEnabled(true);
}
else{
btn_vidSplineStart.setEnabled(false);
}
}
}
}
And here is the full BluetoothLeService, which I got from the website of the HM-10 Bluetooth manufacturer:
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import java.util.List;
import java.util.UUID;
/**
* Service for managing connection and data communication with a GATT server hosted on a
* given Bluetooth LE device.
*/
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mBluetoothGatt;
public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA";
public final static UUID UUID_NOTIFY =
UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb");
public final static UUID UUID_SERVICE =
UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb");
public BluetoothGattCharacteristic mNotifyCharacteristic;
public void WriteValue(String strValue)
{
mNotifyCharacteristic.setValue(strValue.getBytes());
mBluetoothGatt.writeCharacteristic(mNotifyCharacteristic);
}
public void findService(List<BluetoothGattService> gattServices)
{
Log.i(TAG, "Count is:" + gattServices.size());
for (BluetoothGattService gattService : gattServices)
{
Log.i(TAG, gattService.getUuid().toString());
Log.i(TAG, UUID_SERVICE.toString());
if(gattService.getUuid().toString().equalsIgnoreCase(UUID_SERVICE.toString()))
{
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
Log.i(TAG, "Count is:" + gattCharacteristics.size());
for (BluetoothGattCharacteristic gattCharacteristic :
gattCharacteristics)
{
if(gattCharacteristic.getUuid().toString().equalsIgnoreCase(UUID_NOTIFY.toString()))
{
Log.i(TAG, gattCharacteristic.getUuid().toString());
Log.i(TAG, UUID_NOTIFY.toString());
mNotifyCharacteristic = gattCharacteristic;
setCharacteristicNotification(gattCharacteristic, true);
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
return;
}
}
}
}
}
// 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) {
String intentAction;
Log.i(TAG, "oldStatus=" + status + " NewStates=" + newState);
if(status == BluetoothGatt.GATT_SUCCESS)
{
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mBluetoothGatt.close();
mBluetoothGatt = null;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.w(TAG, "onServicesDiscovered received: " + status);
findService(gatt.getServices());
} else {
if(mBluetoothGatt.getDevice().getUuids() == null)
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
Log.e(TAG, "OnCharacteristicWrite");
}
#Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
int status)
{
Log.e(TAG, "OnCharacteristicWrite");
}
#Override
public void onDescriptorRead(BluetoothGatt gatt,
BluetoothGattDescriptor bd,
int status) {
Log.e(TAG, "onDescriptorRead");
}
#Override
public void onDescriptorWrite(BluetoothGatt gatt,
BluetoothGattDescriptor bd,
int status) {
Log.e(TAG, "onDescriptorWrite");
}
#Override
public void onReadRemoteRssi(BluetoothGatt gatt, int a, int b)
{
Log.e(TAG, "onReadRemoteRssi");
}
#Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int a)
{
Log.e(TAG, "onReliableWriteCompleted");
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
// 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
// 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));
//intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
intent.putExtra(EXTRA_DATA, new String(data));
}
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
/**
* Initializes a reference to the local Bluetooth adapter.
*
* #return Return true if the initialization is successful.
*/
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(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* #param address The device address of the destination device.
*
* #return Return true if the connection is initiated successfully. The connection result
* is reported asynchronously through the
* {#code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
/*
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
*/
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "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.
if(mBluetoothGatt != null)
{
mBluetoothGatt.close();
mBluetoothGatt = null;
}
mBluetoothGatt = device.connectGatt(this.getApplication(), false, mGattCallback);
//mBluetoothGatt.connect();
Log.d(TAG, "Trying to create a new connection.");
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {#code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
/**
* After using a given BLE device, the app must call this method to ensure resources are
* released properly.
*/
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) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(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(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
/*
// 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();
}
}

Getting current value with Android Bluetooth LE Sample App

This is probably really straightforward, but I am new to Android and Bluetooth, and this has me lost.
I'm using the sample BluetoothLEGatt app as a starting point
http://developer.android.com/samples/BluetoothLeGatt/index.html
This allows you to select various characteristics from the connected Bluetooth LE device from an expandable list. Upon selecting the characteristic, the value is displayed in mDataField. I would like to just automatically display the heart rate measurement in the mDataField, without first having to select anything in the menu, but I can't figure out how the servicesListClickListner piece works.
Below is the DeviceControlActivity.java, which is the main screen
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.bluetooth.le;
import android.app.Activity;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* For a given BLE device, this Activity provides the user interface to connect, display data,
* and display GATT services and characteristics supported by the device. The Activity
* communicates with {#code BluetoothLeService}, which in turn interacts with the
* Bluetooth LE API.
*/
public class DeviceControlActivity extends Activity {
private final static String TAG = DeviceControlActivity.class.getSimpleName();
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 String mDeviceName;
private String mDeviceAddress;
private ExpandableListView mGattServicesList;
private BluetoothLeService mBluetoothLeService;
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics =
new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
private boolean mConnected = false;
private BluetoothGattCharacteristic mNotifyCharacteristic;
private final String LIST_NAME = "NAME";
private final String LIST_UUID = "UUID";
// 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(TAG, "Unable to initialize Bluetooth");
finish();
}
// Automatically connects to the device upon successful start-up initialization.
mBluetoothLeService.connect(mDeviceAddress);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
// Handles various events fired by the Service.
// ACTION_GATT_CONNECTED: connected to a GATT server.
// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
// ACTION_DATA_AVAILABLE: received data from the device. This can be a result of read
// or notification operations.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// Show all the supported services and characteristics on the user interface.
displayGattServices(mBluetoothLeService.getSupportedGattServices());
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};
// 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() {
#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.
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBluetoothLeService.readCharacteristic(characteristic);
}
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
mNotifyCharacteristic = characteristic;
mBluetoothLeService.setCharacteristicNotification(
characteristic, true);
}
return true;
}
return false;
}
};
private void clearUI() {
mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
mDataField.setText(R.string.no_data);
}
#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);
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(TAG, "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;
}
#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);
}
}
// 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.
private void displayGattServices(List<BluetoothGattService> gattServices) {
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);
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
}
And below is BluetoothLeService
package com.example.bluetooth.le;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import java.util.List;
import java.util.UUID;
/**
* Service for managing connection and data communication with a GATT server hosted on a
* given Bluetooth LE device.
*/
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;
public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA";
public final static UUID UUID_HEART_RATE_MEASUREMENT =
UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT);
// 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) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
// 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(TAG, "Heart rate format UINT16.");
} else {
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, "Heart rate format UINT8.");
}
final int heartRate = characteristic.getIntValue(format, 1);
Log.d(TAG, String.format("Received heart rate: %d", heartRate));
intent.putExtra(EXTRA_DATA, 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));
intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
}
}
sendBroadcast(intent);
}
public class LocalBinder extends Binder {
BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}
private final IBinder mBinder = new LocalBinder();
/**
* Initializes a reference to the local Bluetooth adapter.
*
* #return Return true if the initialization is successful.
*/
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(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* #param address The device address of the destination device.
*
* #return Return true if the connection is initiated successfully. The connection result
* is reported asynchronously through the
* {#code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.d(TAG, "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(TAG, "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(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {#code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}
/**
* After using a given BLE device, the app must call this method to ensure resources are
* released properly.
*/
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) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(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(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
// 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();
}
}
The displayGattServices method populates your ExpandableListView with possible services. So you could just select the service that you want in this for loop:
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
if (uuid.equals("THE NAME OF THE SERVICE THAT I WANT") {
// and then call
mBluetoothLeService.setCharacteristicNotification(characteristic, true);
}
}
And then modify the displayData method if you need to.
The line:
int flag = characteristic.getProperties();
in the sample code is expected to return the bit mask for the supported characteristic fields. It doesn't. It returns the characteristic properties, like PROPERTY_NOTIFY.
To get the bit mask for the supported characteristic fields, in the case of the example's Heart Rate Measurement characteristic, the first value of the characteristic needs to be read and used.
Thus replacing the line
int flag = characteristic.getProperties();
with something like
byte[] charValue = characteristic.getValue();
byte flag = charValue[0];
will work correctly.

Categories

Resources