diff --git a/.idea/misc.xml b/.idea/misc.xml
index 3d21ecd..54207cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -37,7 +37,7 @@
-
+
diff --git a/Application/src/main/AndroidManifest.xml b/Application/src/main/AndroidManifest.xml
index f99e75c..e56cc40 100644
--- a/Application/src/main/AndroidManifest.xml
+++ b/Application/src/main/AndroidManifest.xml
@@ -1,5 +1,4 @@
-
-
-
-
-
-
+ PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE)
+ -->
+
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/Application/src/main/java/fr/centralesupelec/students/clientble/BluetoothLeService.java b/Application/src/main/java/fr/centralesupelec/students/clientble/BluetoothLeService.java
index 9ac9c31..1cddf6a 100644
--- a/Application/src/main/java/fr/centralesupelec/students/clientble/BluetoothLeService.java
+++ b/Application/src/main/java/fr/centralesupelec/students/clientble/BluetoothLeService.java
@@ -34,6 +34,7 @@ import android.os.IBinder;
import android.util.Log;
import java.util.List;
+import java.util.StringTokenizer;
import java.util.UUID;
/**
@@ -64,10 +65,6 @@ public class BluetoothLeService extends Service {
public final static String EXTRA_DATA =
"fr.centralesupelec.students.clientble.EXTRA_DATA";
- /* TODO
- 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.
@@ -113,11 +110,13 @@ public class BluetoothLeService extends Service {
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
+ Log.d(TAG, "onCharacteristicChanged() appelé.");
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
private void broadcastUpdate(final String action) {
+ Log.d(TAG, "broadcastUpdate(String) appelé.");
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
@@ -125,7 +124,7 @@ public class BluetoothLeService extends Service {
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
-
+ Log.d(TAG, "broadcastUpdate(String, BluetoothGattChar.) appelé.");
/* TODO
// This is special handling for the Heart Rate Measurement profile. Data parsing is
// carried out as per profile specifications:
@@ -148,10 +147,18 @@ public class BluetoothLeService extends Service {
// 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());
+ if (SampleGattAttributes.SENSOR_CHARACTERISTIC_UUID.equals(characteristic.getUuid())) {
+ int value = (data[0]<<8)&0x0000ff00 | (data[1]<<0)&0x000000ff;
+ intent.putExtra(EXTRA_DATA, String.format("%d", value));
+ } else {
+ final StringBuilder stringBuilder = new StringBuilder(data.length);
+ //stringBuilder.append(String.format("%d", data));/
+ //stringBuilder.append(" --- ");
+ for (byte byteChar : data)
+ stringBuilder.append(String.format("%02X ", byteChar));
+ Log.d(TAG, String.format(stringBuilder.toString()));
+ intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
+ }
}
/* TODO
}
@@ -301,6 +308,7 @@ public class BluetoothLeService extends Service {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
+ Log.d(TAG, "setChar.Notification() appelé");
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
/* TODO
@@ -322,7 +330,11 @@ public class BluetoothLeService extends Service {
*/
public List getSupportedGattServices() {
if (mBluetoothGatt == null) return null;
-
return mBluetoothGatt.getServices();
}
+
+ public BluetoothGattService getPrivateService() {
+ if (mBluetoothGatt == null) return null;
+ return mBluetoothGatt.getService(SampleGattAttributes.PRIVATE_SERVICE_UUID);
+ }
}
diff --git a/Application/src/main/java/fr/centralesupelec/students/clientble/DeviceScanActivity.java b/Application/src/main/java/fr/centralesupelec/students/clientble/DeviceScanActivity.java
index b983c5e..e72fcb3 100644
--- a/Application/src/main/java/fr/centralesupelec/students/clientble/DeviceScanActivity.java
+++ b/Application/src/main/java/fr/centralesupelec/students/clientble/DeviceScanActivity.java
@@ -180,14 +180,25 @@ public class DeviceScanActivity extends ListActivity {
protected void onListItemClick(ListView l, View v, int position, long id) {
final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
if (device == null) return;
- final Intent intent = new Intent(this, DeviceControlActivity.class);
- intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
- intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
- if (mScanning) {
- mBluetoothAdapter.stopLeScan(mLeScanCallback);
- mScanning = false;
+ if (true) {
+ final Intent intent = new Intent(this, DeviceControlActivity.class);
+ intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
+ intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
+ if (mScanning) {
+ mBluetoothAdapter.stopLeScan(mLeScanCallback);
+ mScanning = false;
+ }
+ startActivity(intent);
+ } else {
+ final Intent intent = new Intent(this, SimpleDetailActivity.class);
+ intent.putExtra(SimpleDetailActivity.EXTRAS_DEVICE_NAME, device.getName());
+ intent.putExtra(SimpleDetailActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
+ if (mScanning) {
+ mBluetoothAdapter.stopLeScan(mLeScanCallback);
+ mScanning = false;
+ }
+ startActivity(intent);
}
- startActivity(intent);
}
private void scanLeDevice(final boolean enable) {
diff --git a/Application/src/main/java/fr/centralesupelec/students/clientble/SampleGattAttributes.java b/Application/src/main/java/fr/centralesupelec/students/clientble/SampleGattAttributes.java
index 7cea0c3..c7c0e1d 100644
--- a/Application/src/main/java/fr/centralesupelec/students/clientble/SampleGattAttributes.java
+++ b/Application/src/main/java/fr/centralesupelec/students/clientble/SampleGattAttributes.java
@@ -18,12 +18,21 @@
package fr.centralesupelec.students.clientble;
import java.util.HashMap;
+import java.util.UUID;
/**
* This class includes a small subset of standard GATT attributes for demonstration purposes.
*/
public class SampleGattAttributes {
private static HashMap attributes = new HashMap();
+ public static final String PRIVATE_SERVICE_UUID_STRING =
+ "11223344-5566-7788-9900-aabbccddeeff";
+ public static final UUID PRIVATE_SERVICE_UUID =
+ UUID.fromString(PRIVATE_SERVICE_UUID_STRING);
+ public static final String SENSOR_CHARACTERISTIC_UUID_STRING =
+ "01020304-0506-0708-0900-0a0b0c0d0e0f";
+ public static final UUID SENSOR_CHARACTERISTIC_UUID =
+ UUID.fromString(SENSOR_CHARACTERISTIC_UUID_STRING);
static {
// Sample Services.
@@ -32,8 +41,7 @@ public class SampleGattAttributes {
attributes.put("00001800-0000-1000-8000-00805f9b34fb", "Generic Access");
attributes.put("0000180f-0000-1000-8000-00805f9b34fb", "Battery Service");
- attributes.put("11223344-5566-7788-9900-aabbccddeeff", "Private Service");
-
+ attributes.put(PRIVATE_SERVICE_UUID_STRING, "Private Service");
// Sample Characteristics.
attributes.put("00002a19-0000-1000-8000-00805f9b34fb", "Battery Level");
@@ -42,7 +50,7 @@ public class SampleGattAttributes {
attributes.put("00002a04-0000-1000-8000-00805f9b34fb", "Peripheral Preferred Connection Parameters");
attributes.put("00002a29-0000-1000-8000-00805f9b34fb", "Manufacturer Name");
- attributes.put("01020304-0506-0708-0900-0a0b0c0d0e0f", "5-byte r char.");
+ attributes.put(SENSOR_CHARACTERISTIC_UUID_STRING, "5-byte r notif. sensor value");
attributes.put("ff020304-0506-0708-0900-0a0b0c0d0e0f", "3-byte rw notif. char.");
}
diff --git a/Application/src/main/java/fr/centralesupelec/students/clientble/SimpleDetailActivity.java b/Application/src/main/java/fr/centralesupelec/students/clientble/SimpleDetailActivity.java
new file mode 100644
index 0000000..28303ae
--- /dev/null
+++ b/Application/src/main/java/fr/centralesupelec/students/clientble/SimpleDetailActivity.java
@@ -0,0 +1,209 @@
+package fr.centralesupelec.students.clientble;
+
+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.IBinder;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.TextView;
+
+public class SimpleDetailActivity extends Activity {
+ private final static String TAG = SimpleDetailActivity.class.getSimpleName();
+
+ public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
+ public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
+
+ private TextView mDeviceAddressView;
+ private TextView mConnectionStateView;
+ private TextView mSensorValueView;
+
+ private String mDeviceName;
+ private String mDeviceAddress;
+
+
+ private BluetoothLeService mBluetoothLeService;
+ private boolean mConnected = false;
+ private BluetoothGattCharacteristic mSensorValueCharac;
+
+
+ // 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.
+ Log.d(TAG, "ACTION_GATT_SERVICES_DISCOVERED reçu.");
+ displayValues();
+ } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
+ Log.d(TAG, "ACTION_DATA_AVAILABLE reçu.");
+ final String data = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
+ Log.d(TAG, data);
+ displayData(data);
+ }
+ }
+ };
+
+ private void clearUI() {
+ mSensorValueView.setText(R.string.no_data);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.simple_detail_layout);
+
+ final Intent intent = getIntent();
+
+ mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
+
+ mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
+ mDeviceAddressView = (TextView) findViewById(R.id.device_address);
+ mDeviceAddressView.setText(mDeviceAddress);
+
+ mConnectionStateView = (TextView) findViewById(R.id.connection_state);
+
+ mSensorValueView = (TextView) findViewById(R.id.sensor_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() {
+ mConnectionStateView.setText(resourceId);
+ }
+ });
+ }
+
+ private void displayData(String data) {
+ if (data != null) {
+ mSensorValueView.setText(data);
+ }
+ }
+
+ private void displayValues() {
+ BluetoothGattService privateService = mBluetoothLeService.getPrivateService();
+ if (privateService == null) {
+ Log.w(TAG, "Service Gatt privé non détecté.");
+ return;
+ }
+ mSensorValueCharac =
+ privateService.getCharacteristic(SampleGattAttributes.SENSOR_CHARACTERISTIC_UUID);
+ final int charaProp = mSensorValueCharac.getProperties();
+ mBluetoothLeService.readCharacteristic(mSensorValueCharac);
+ if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
+ Log.d(TAG, "Demande de notification.");
+ mBluetoothLeService.setCharacteristicNotification(mSensorValueCharac, true);
+ }
+ }
+
+ 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;
+ }
+}
diff --git a/Application/src/main/res/layout/simple_detail_layout.xml b/Application/src/main/res/layout/simple_detail_layout.xml
new file mode 100644
index 0000000..5511b28
--- /dev/null
+++ b/Application/src/main/res/layout/simple_detail_layout.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Application/src/main/res/values/strings.xml b/Application/src/main/res/values/strings.xml
index 19f3dce..9148452 100644
--- a/Application/src/main/res/values/strings.xml
+++ b/Application/src/main/res/values/strings.xml
@@ -1,5 +1,4 @@
-
-