Skip to content

Commit

Permalink
Bugs fixed in Proximity profile
Browse files Browse the repository at this point in the history
  • Loading branch information
philips77 committed Oct 19, 2016
1 parent 3c8c13f commit 4bbd88b
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,12 @@

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;
Expand Down Expand Up @@ -142,6 +139,8 @@ private void bind(final BluetoothDevice device) {
batteryView.setVisibility(View.VISIBLE);
batteryView.setText(batteryView.getResources().getString(R.string.battery, batteryValue));
batteryView.setAlpha(state == BluetoothGatt.STATE_CONNECTED ? 1.0f : 0.5f);
} else {
batteryView.setVisibility(View.GONE);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*/
package no.nordicsemi.android.nrftoolbox.proximity;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
Expand Down Expand Up @@ -126,7 +127,10 @@ public void onDeviceNotSupported(final BluetoothDevice device) {
public void onLinklossOccur(final BluetoothDevice device) {
if (mAdapter != null)
mAdapter.onDeviceStateChanged(device);
showLinklossDialog(device.getName());

// The link loss may also be called when Bluetooth adapter was disabled
if (BluetoothAdapter.getDefaultAdapter().isEnabled())
showLinklossDialog(device.getName());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.Handler;
import android.util.Log;

import java.util.UUID;

Expand Down Expand Up @@ -60,38 +61,110 @@ public class ProximityServerManager {
private IDeviceLogger mLogger;
private Handler mHandler;
private OnServerOpenCallback mOnServerOpenCallback;
private boolean mServerReady;

public interface OnServerOpenCallback {
/** Method called when the GATT server was created and all services were added successfully. */
void onGattServerOpen();
/** Method called when the GATT server failed to open and initialize services. -1 is returned when the server failed to start. */
void onGattServerFailed(final int error);
}

public ProximityServerManager(final ProximityServerManagerCallbacks callbacks) {
mHandler = new Handler();
mCallbacks = callbacks;
}

/**
* Sets the logger object. Logger is used to create logs in nRF Logger application.
* @param logger the logger object
*/
public void setLogger(final IDeviceLogger logger) {
mLogger = logger;
}

/**
* Opens GATT server and creates 2 services: Link Loss Service and Immediate Alert Service.
* The callback is called when initialization is complete.
* @param context the context
* @param callback optional callback notifying when all services has been added
*/
public void openGattServer(final Context context, final OnServerOpenCallback callback) {
// Is the server already open?
if (mBluetoothGattServer != null) {
if (callback != null)
callback.onGattServerOpen();
return;
}

mOnServerOpenCallback = callback;

final BluetoothManager manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothGattServer = manager.openGattServer(context, mGattServerCallbacks);
addImmediateAlertService();
if (mBluetoothGattServer != null) {
// Start adding services one by one. The onServiceAdded method will be called when it completes.
addImmediateAlertService();
} else {
if (callback != null)
callback.onGattServerFailed(-1);
mOnServerOpenCallback = null;
}
}

/**
* Returns true if GATT server was opened and configured correctly.
* False if hasn't been opened, was closed, of failed to start.
*/
public boolean isServerReady() {
return mServerReady;
}

/**
* Closes the GATT server. It will also disconnect all existing connections.
* If the service has already been closed, or hasn't been open, this method does nothing.
*/
public void closeGattServer() {
if (mBluetoothGattServer != null) {
mBluetoothGattServer.close();
mBluetoothGattServer = null;
mOnServerOpenCallback = null;
mServerReady = false;
}
}

/**
* This method notifies the Android that the Proximity profile will use the server connection to given device.
* If the server hasn't been open this method does nothing. The {@link #cancelConnection(BluetoothDevice)} method
* should be called when the connection is no longer used.
* @param device target device
*/
public void openConnection(final BluetoothDevice device) {
if (mBluetoothGattServer != null) {
mLogger.log(device, LogContract.Log.Level.VERBOSE, "[Server] Creating server connection...");
mLogger.log(device, LogContract.Log.Level.DEBUG, "server.connect(device, autoConnect = true)");
mBluetoothGattServer.connect(device, true); // In proximity the autoConnect is true
}
}

public void cancelConnection(final BluetoothDevice device) {
/**
* Cancels the connection to the given device. This notifies Android that this profile will no longer
* use this connection and it can be disconnected. In practice, this method does not disconnect, so
* if the remote device decides still to use the phone's GATT server it will be able to do so.
* <p>This bug/feature can be tested using a proximity tag that does not release its connection when it got
* disconnected:
* <ol>
* <li>Connect to your Proximity Tag.</li>
* <li>Verify that the bidirectional connection works - test the FIND ME button in nRF Toolbox and
* the FIND PHONE button on the tag.</li>
* <li>Disconnect from the tag</li>
* <li>When the device disappear from the list of devices click the FIND PHONE button on the tag.
* Your phone should still trigger an alarm, as the connection tag-&gt;phone is still active.</li>
* </ol>
* In order to avoid this issue make sure that your tag disconnects gently from phone when it got disconnected itself.
* </p>
* @param device the device that will no longer be used
*/
public void cancelConnection(final BluetoothDevice device) {
if (mBluetoothGattServer != null) {
mLogger.log(device, LogContract.Log.Level.VERBOSE, "[Server] Cancelling server connection...");
mLogger.log(device, LogContract.Log.Level.DEBUG, "server.cancelConnection(device)");
Expand Down Expand Up @@ -126,18 +199,28 @@ private void addLinklossService() {
private final BluetoothGattServerCallback mGattServerCallbacks = new BluetoothGattServerCallback() {
@Override
public void onServiceAdded(final int status, final BluetoothGattService service) {
// Adding another service from callback thread fails on Samsung S4 with Android 4.3
mHandler.post(new Runnable() {
@Override
public void run() {
if (IMMEDIATE_ALERT_SERVICE_UUID.equals(service.getUuid())) {
addLinklossService();
} else if (mOnServerOpenCallback != null) {
mOnServerOpenCallback.onGattServerOpen();
mOnServerOpenCallback = null;
if (status == BluetoothGatt.GATT_SUCCESS) {
// Adding another service from callback thread fails on Samsung S4 with Android 4.3
mHandler.post(new Runnable() {
@Override
public void run() {
if (IMMEDIATE_ALERT_SERVICE_UUID.equals(service.getUuid())) {
addLinklossService();
} else {
mServerReady = true;
// Both services has been added
if (mOnServerOpenCallback != null)
mOnServerOpenCallback.onGattServerOpen();
mOnServerOpenCallback = null;
}
}
}
});
});
} else {
Log.e(TAG, "GATT Server failed to add service, status: " + status);
if (mOnServerOpenCallback != null)
mOnServerOpenCallback.onGattServerFailed(status);
mOnServerOpenCallback = null;
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
Expand Down Expand Up @@ -142,6 +143,9 @@ public void onReceive(final Context context, final Intent intent) {

@Override
protected void onServiceCreated() {
mServerManager = new ProximityServerManager(this);
mServerManager.setLogger(mBinder);

initializeAlarm();

registerReceiver(mDisconnectActionBroadcastReceiver, new IntentFilter(ACTION_DISCONNECT));
Expand All @@ -155,10 +159,8 @@ protected void onServiceCreated() {
public void onServiceStopped() {
cancelNotifications();

// GATT server might have not been created if Bluetooth was disabled
if (mServerManager != null) {
mServerManager.closeGattServer();
}
// Close the GATT server. If it hasn't been opened this method does nothing
mServerManager.closeGattServer();

unregisterReceiver(mDisconnectActionBroadcastReceiver);
unregisterReceiver(mToggleAlarmActionBroadcastReceiver);
Expand All @@ -169,29 +171,31 @@ public void onServiceStopped() {
@Override
protected void onBluetoothEnabled() {
// Start the GATT Server only if Bluetooth is enabled
mServerManager = new ProximityServerManager(this);
mServerManager.setLogger(mBinder);
mServerManager.openGattServer(this, new ProximityServerManager.OnServerOpenCallback() {
@Override
public void onGattServerOpen() {
// We are now ready to reconnect devices
ProximityService.super.onBluetoothEnabled();
}

@Override
public void onGattServerFailed(final int error) {
mServerManager.closeGattServer();
showToast(getString(R.string.proximity_server_error, error));
}
});
}

@Override
protected void onBluetoothDisabled() {
super.onBluetoothDisabled();
if (mServerManager != null) {
mServerManager.closeGattServer();
mServerManager = null;
}
// Close the GATT server
mServerManager.closeGattServer();
}

@Override
protected void onRebind() {
// when the activity rebinds to the service, remove the notification
// When the activity rebinds to the service, remove the notification
cancelNotifications();
}

Expand All @@ -209,22 +213,30 @@ public void onDeviceConnected(final BluetoothDevice device) {
}
}

@Override
public void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound) {
super.onServicesDiscovered(device, optionalServicesFound);
mServerManager.openConnection(device);
}

@Override
public void onLinklossOccur(final BluetoothDevice device) {
mServerManager.cancelConnection(device);
stopAlarm(device);
super.onLinklossOccur(device);

if (!mBinded) {
createBackgroundNotification();
createLinklossNotification(device);
if (BluetoothAdapter.getDefaultAdapter().isEnabled())
createLinklossNotification(device);
else
cancelNotification(device);
}
}

@Override
public void onDeviceDisconnected(final BluetoothDevice device) {
if (mServerManager != null) {
mServerManager.cancelConnection(device);
}
mServerManager.cancelConnection(device);
stopAlarm(device);
super.onDeviceDisconnected(device);

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/values/strings_proximity.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<string name="proximity_notification_linkloss_alert">%s is getting away!</string>

<string name="proximity_devices_title">YOUR TAGS</string>
<string name="proximity_enable_server">GATT Server enabled</string>
<string name="proximity_server_error">GATT Server failed to start (error %d).</string>

<string name="proximity_about_text">PROXIMITY profile allows you to connect to multiple Proximity sensors.
\nYou can find your valuables attached with Proximity tag by pressing the Locate button next to your device.
Expand Down

0 comments on commit 4bbd88b

Please sign in to comment.