We now have a "connecting" state in the ControlActivity.
This commit is contained in:
@@ -39,22 +39,20 @@ import java.util.List;
|
||||
*/
|
||||
public class BluetoothLeService extends Service {
|
||||
public final static String ACTION_GATT_CONNECTED = BluetoothLeService.class.getName() + ".ACTION_GATT_CONNECTED";
|
||||
public final static String ACTION_GATT_CONNECTING = BluetoothLeService.class.getName() + ".ACTION_GATT_CONNECTING";
|
||||
public final static String ACTION_GATT_DISCONNECTED = BluetoothLeService.class.getName() + ".ACTION_GATT_DISCONNECTED";
|
||||
public final static String ACTION_GATT_SERVICES_DISCOVERED = BluetoothLeService.class.getName() + ".ACTION_GATT_SERVICES_DISCOVERED";
|
||||
public final static String ACTION_DATA_AVAILABLE = BluetoothLeService.class.getName() + ".ACTION_DATA_AVAILABLE";
|
||||
public final static String EXTRA_DATA_RAW = BluetoothLeService.class.getName() + ".EXTRA_DATA_RAW";
|
||||
public final static String EXTRA_UUID_CHAR = BluetoothLeService.class.getName() + ".EXTRA_UUID_CHAR";
|
||||
private final static String TAG = BluetoothLeService.class.getSimpleName();
|
||||
|
||||
private static final int STATE_DISCONNECTED = 0;
|
||||
private static final int STATE_CONNECTING = 1;
|
||||
private static final int STATE_CONNECTED = 2;
|
||||
private final IBinder mBinder = new LocalBinder();
|
||||
private BluetoothManager mBluetoothManager;
|
||||
private BluetoothAdapter mBluetoothAdapter;
|
||||
private String mBluetoothDeviceAddress;
|
||||
private BluetoothGatt mBluetoothGatt;
|
||||
private int mConnectionState = STATE_DISCONNECTED;
|
||||
private State mConnectionState = State.DISCONNECTED;
|
||||
|
||||
// Implements callback methods for GATT events that the app cares about. For example,
|
||||
// connection change and services discovered.
|
||||
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
|
||||
@@ -64,28 +62,35 @@ public class BluetoothLeService extends Service {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCharacteristicRead(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final int status) {
|
||||
public void onCharacteristicRead(final BluetoothGatt gatt,
|
||||
final BluetoothGattCharacteristic characteristic,
|
||||
final int status) {
|
||||
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) {
|
||||
final String intentAction;
|
||||
public void onConnectionStateChange(final BluetoothGatt gatt,
|
||||
final int status,
|
||||
final int newState) {
|
||||
|
||||
Log.d(TAG, "onConnectionStateChange: status=" + status + ", newState=" + newState);
|
||||
|
||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
intentAction = ACTION_GATT_CONNECTED;
|
||||
mConnectionState = STATE_CONNECTED;
|
||||
broadcastUpdate(intentAction);
|
||||
setConnectionState(State.CONNECTED, true);
|
||||
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;
|
||||
// Make sure we tidy up. On certain devices reusing a Gatt after a disconnection
|
||||
// can cause problems.
|
||||
disconnect();
|
||||
|
||||
setConnectionState(State.DISCONNECTED, true);
|
||||
Log.i(TAG, "Disconnected from GATT server.");
|
||||
broadcastUpdate(intentAction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,37 +144,73 @@ public class BluetoothLeService extends Service {
|
||||
* callback.
|
||||
*/
|
||||
public boolean connect(final String address) {
|
||||
|
||||
final boolean retVal;
|
||||
if (mBluetoothAdapter == null || address == null) {
|
||||
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
|
||||
return false;
|
||||
}
|
||||
retVal = false;
|
||||
|
||||
// Previously connected device. Try to reconnect.
|
||||
if (mBluetoothDeviceAddress != null
|
||||
// Previously connected device. Try to reconnect.
|
||||
} else 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;
|
||||
Log.d(TAG, "Connection attempt OK.");
|
||||
setConnectionState(State.CONNECTING, true);
|
||||
retVal = true;
|
||||
} else {
|
||||
return false;
|
||||
Log.w(TAG, "Connection attempt failed.");
|
||||
setConnectionState(State.DISCONNECTED, true);
|
||||
retVal = false;
|
||||
}
|
||||
} else {
|
||||
|
||||
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
|
||||
if (device == null) {
|
||||
Log.w(TAG, "Device not found. Unable to connect.");
|
||||
retVal = false;
|
||||
} else {
|
||||
// We want to directly connect to the device, so we are setting the autoConnect
|
||||
// parameter to false.
|
||||
|
||||
Log.d(TAG, "Trying to create a new connection.");
|
||||
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
|
||||
mBluetoothDeviceAddress = address;
|
||||
setConnectionState(State.CONNECTING, true);
|
||||
retVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
|
||||
if (device == null) {
|
||||
Log.w(TAG, "Device not found. Unable to connect.");
|
||||
return false;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private synchronized void setConnectionState(final State newState, final boolean broadCast) {
|
||||
Log.i(TAG, "Setting internal state to " + newState);
|
||||
mConnectionState = newState;
|
||||
|
||||
final String broadcastAction;
|
||||
|
||||
switch (newState) {
|
||||
case CONNECTED:
|
||||
broadcastAction = ACTION_GATT_CONNECTED;
|
||||
break;
|
||||
case CONNECTING:
|
||||
broadcastAction = ACTION_GATT_CONNECTING;
|
||||
break;
|
||||
case DISCONNECTED:
|
||||
broadcastAction = ACTION_GATT_DISCONNECTED;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown state: " + newState);
|
||||
}
|
||||
// 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;
|
||||
|
||||
if (broadCast) {
|
||||
Log.i(TAG, "Broadcasting " + broadcastAction);
|
||||
broadcastUpdate(broadcastAction);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,6 +225,9 @@ public class BluetoothLeService extends Service {
|
||||
return;
|
||||
}
|
||||
mBluetoothGatt.disconnect();
|
||||
|
||||
// Reusing a Gatt after disconnecting can cause problems
|
||||
mBluetoothGatt = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,4 +315,10 @@ public class BluetoothLeService extends Service {
|
||||
return BluetoothLeService.this;
|
||||
}
|
||||
}
|
||||
|
||||
private enum State {
|
||||
DISCONNECTED,
|
||||
CONNECTING,
|
||||
CONNECTED
|
||||
}
|
||||
}
|
||||
+52
-17
@@ -121,7 +121,8 @@ public class DeviceControlActivity extends AppCompatActivity {
|
||||
}
|
||||
};
|
||||
private BluetoothLeDevice mDevice;
|
||||
private boolean mConnected = false;
|
||||
private State mCurrentState = State.DISCONNECTED;
|
||||
|
||||
private String mExportString;
|
||||
// Handles various events fired by the Service.
|
||||
// ACTION_GATT_CONNECTED: connected to a GATT server.
|
||||
@@ -134,14 +135,16 @@ public class DeviceControlActivity extends AppCompatActivity {
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
|
||||
mConnected = true;
|
||||
updateConnectionState(R.string.connected);
|
||||
updateConnectionState(State.CONNECTED);
|
||||
invalidateOptionsMenu();
|
||||
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
|
||||
mConnected = false;
|
||||
updateConnectionState(R.string.disconnected);
|
||||
invalidateOptionsMenu();
|
||||
clearUI();
|
||||
updateConnectionState(State.DISCONNECTED);
|
||||
invalidateOptionsMenu();
|
||||
} else if (BluetoothLeService.ACTION_GATT_CONNECTING.equals(action)) {
|
||||
clearUI();
|
||||
updateConnectionState(State.CONNECTING);
|
||||
invalidateOptionsMenu();
|
||||
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
|
||||
// Show all the supported services and characteristics on the user interface.
|
||||
displayGattServices(mBluetoothLeService.getSupportedGattServices());
|
||||
@@ -159,6 +162,7 @@ public class DeviceControlActivity extends AppCompatActivity {
|
||||
};
|
||||
|
||||
private void clearUI() {
|
||||
mExportString = null;
|
||||
mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
|
||||
mGattUUID.setText(R.string.no_data);
|
||||
mGattUUIDDesc.setText(R.string.no_data);
|
||||
@@ -206,12 +210,26 @@ public class DeviceControlActivity extends AppCompatActivity {
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(final 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);
|
||||
|
||||
switch (mCurrentState) {
|
||||
|
||||
case DISCONNECTED:
|
||||
menu.findItem(R.id.menu_connect).setVisible(true);
|
||||
menu.findItem(R.id.menu_disconnect).setVisible(false);
|
||||
menu.findItem(R.id.menu_refresh).setActionView(null);
|
||||
break;
|
||||
case CONNECTING:
|
||||
menu.findItem(R.id.menu_connect).setVisible(false);
|
||||
menu.findItem(R.id.menu_disconnect).setVisible(false);
|
||||
menu.findItem(R.id.menu_refresh).setActionView(R.layout.actionbar_progress_indeterminate);
|
||||
break;
|
||||
case CONNECTED:
|
||||
menu.findItem(R.id.menu_connect).setVisible(false);
|
||||
menu.findItem(R.id.menu_disconnect).setVisible(true);
|
||||
menu.findItem(R.id.menu_refresh).setActionView(null);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Don't know how to handle: " + mCurrentState);
|
||||
}
|
||||
|
||||
if (mExportString == null) {
|
||||
@@ -278,25 +296,35 @@ public class DeviceControlActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateConnectionState(final int resourceId) {
|
||||
private void updateConnectionState(final State state) {
|
||||
mCurrentState = state;
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final int colourId;
|
||||
final int resId;
|
||||
|
||||
switch (resourceId) {
|
||||
case R.string.connected:
|
||||
switch (state) {
|
||||
case CONNECTED:
|
||||
colourId = android.R.color.holo_green_dark;
|
||||
resId = R.string.connected;
|
||||
break;
|
||||
case R.string.disconnected:
|
||||
case DISCONNECTED:
|
||||
colourId = android.R.color.holo_red_dark;
|
||||
resId = R.string.disconnected;
|
||||
break;
|
||||
case CONNECTING:
|
||||
colourId = android.R.color.black;
|
||||
resId = R.string.connecting;
|
||||
break;
|
||||
default:
|
||||
colourId = android.R.color.black;
|
||||
resId = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
mConnectionState.setText(resourceId);
|
||||
mConnectionState.setText(resId);
|
||||
mConnectionState.setTextColor(ContextCompat.getColor(DeviceControlActivity.this, colourId));
|
||||
}
|
||||
});
|
||||
@@ -308,6 +336,7 @@ public class DeviceControlActivity extends AppCompatActivity {
|
||||
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
|
||||
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
|
||||
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
|
||||
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTING);
|
||||
return intentFilter;
|
||||
}
|
||||
|
||||
@@ -324,4 +353,10 @@ public class DeviceControlActivity extends AppCompatActivity {
|
||||
intent.putExtra(DeviceControlActivity.EXTRA_DEVICE, device);
|
||||
return intent;
|
||||
}
|
||||
|
||||
private enum State {
|
||||
DISCONNECTED,
|
||||
CONNECTING,
|
||||
CONNECTED
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
<string name="app_name">Bluetooth LE Scanner</string>
|
||||
<string name="connected">Connected</string>
|
||||
<string name="disconnected">Disconnected</string>
|
||||
<string name="connecting">Connecting</string>
|
||||
<string name="invalid_device_data">Invalid Device Data!</string>
|
||||
<string name="no_data">No data</string>
|
||||
<string name="not_supported">Not supported</string>
|
||||
|
||||
Reference in New Issue
Block a user