summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoey Grover <joeygrover@gmail.com>2018-06-05 17:07:10 -0400
committerJoey Grover <joeygrover@gmail.com>2018-06-05 17:07:10 -0400
commit432a06a16f4a9390e32af668d8ffc9dcb726c006 (patch)
tree3ea0af2e81e617131f92e44f85891d8549274665
parentc2b524d7f436458552b90c5601f11ec8d98c11b7 (diff)
downloadsdl_android-432a06a16f4a9390e32af668d8ffc9dcb726c006.tar.gz
Add better logic to handle bluetooth connections and service notificaitons that are non SDL
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexBluetoothTransport.java13
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java24
-rw-r--r--sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java89
3 files changed, 102 insertions, 24 deletions
diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexBluetoothTransport.java b/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexBluetoothTransport.java
index cf5ace221..6e752217b 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexBluetoothTransport.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/transport/MultiplexBluetoothTransport.java
@@ -55,6 +55,7 @@ public class MultiplexBluetoothTransport {
private static final String NAME_SECURE =" SdlRouterService";
// Key names received from the BluetoothSerialServer Handler
public static final String DEVICE_NAME = "device_name";
+ public static final String DEVICE_ADDRESS = "device_address";
public static final String TOAST = "toast";
private static final long MS_TILL_TIMEOUT = 2500;
private static final int READ_BUFFER_SIZE = 4096;
@@ -259,15 +260,17 @@ public class MultiplexBluetoothTransport {
mConnectedWriteThread = new ConnectedWriteThread(socket);
mConnectedWriteThread.start();
- //Store a static name of the device that is connected.
- if(device!=null){
- currentlyConnectedDevice = device.getName();
- }
+
// Send the name of the connected device back to the UI Activity
Message msg = mHandler.obtainMessage(SdlRouterService.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
- bundle.putString(DEVICE_NAME, currentlyConnectedDevice);
+ //Store a static name of the device that is connected.
+ currentlyConnectedDevice = device.getName();
+ if(currentlyConnectedDevice != null){
+ bundle.putString(DEVICE_NAME, currentlyConnectedDevice);
+ bundle.putString(DEVICE_ADDRESS, device.getAddress());
+ }
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java b/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java
index ea406250a..dc40f43bf 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/transport/SdlBroadcastReceiver.java
@@ -4,6 +4,7 @@ import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -58,8 +59,9 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//Log.i(TAG, "Sdl Receiver Activated");
- String action = intent.getAction();
-
+ final String action = intent.getAction();
+ BluetoothDevice device = null;
+
if(action.equalsIgnoreCase(Intent.ACTION_PACKAGE_ADDED)
|| action.equalsIgnoreCase(Intent.ACTION_PACKAGE_REPLACED)){
//The package manager has sent out a new broadcast.
@@ -83,7 +85,11 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{
onSdlEnabled(context, intent);
return;
}
-
+
+ if(intent.hasExtra(BluetoothDevice.EXTRA_DEVICE)){ //Grab the bluetooth device if available
+ device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ }
+
boolean didStart = false;
if (localRouterClass == null){
localRouterClass = defineLocalSdlRouterClass();
@@ -133,13 +139,13 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{
}else if(intent.getBooleanExtra(TransportConstants.PING_ROUTER_SERVICE_EXTRA, false)){
//We were told to wake up our router services
boolean altServiceWake = intent.getBooleanExtra(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT, false);
- didStart = wakeUpRouterService(context, false,altServiceWake );
+ didStart = wakeUpRouterService(context, false,altServiceWake,device );
}
}
- if (intent.getAction().contains("android.bluetooth.adapter.action.STATE_CHANGED")){
+ if (action.contains("android.bluetooth.adapter.action.STATE_CHANGED")){
int state = intent.getIntExtra("android.bluetooth.adapter.extra.STATE",-1);
if (state == BluetoothAdapter.STATE_OFF ||
state == BluetoothAdapter.STATE_TURNING_OFF){
@@ -150,11 +156,12 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{
return;
}
}
+
Log.d(TAG, "Check for local router");
if(localRouterClass!=null){ //If there is a supplied router service lets run some logic regarding starting one
if(!didStart){Log.d(TAG, "attempting to wake up router service");
- didStart = wakeUpRouterService(context, true,false);
+ didStart = wakeUpRouterService(context, true,false, device);
}
//So even though we started our own version, on some older phones we find that two services are started up so we want to make sure we send our version that we are working with
@@ -169,7 +176,7 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{
}
}
- private boolean wakeUpRouterService(final Context context, final boolean ping, final boolean altTransportWake){
+ private boolean wakeUpRouterService(final Context context, final boolean ping, final boolean altTransportWake, final BluetoothDevice device){
new ServiceFinder(context, context.getPackageName(), new ServiceFinder.ServiceFinderCallback() {
@Override
public void onComplete(Vector<ComponentName> routerServices) {
@@ -191,6 +198,9 @@ public abstract class SdlBroadcastReceiver extends BroadcastReceiver{
if (altTransportWake) {
serviceIntent.setAction(TransportConstants.BIND_REQUEST_TYPE_ALT_TRANSPORT);
}
+ if(device != null){
+ serviceIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+ }
try {
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
context.startService(serviceIntent);
diff --git a/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java b/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
index eb83a3675..8e04c53b8 100644
--- a/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
+++ b/sdl_android/src/main/java/com/smartdevicelink/transport/SdlRouterService.java
@@ -6,7 +6,6 @@ import static com.smartdevicelink.transport.TransportConstants.HARDWARE_DISCONNE
import static com.smartdevicelink.transport.TransportConstants.SEND_PACKET_TO_APP_LOCATION_EXTRA_NAME;
import java.lang.ref.WeakReference;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
@@ -34,12 +33,12 @@ import android.app.NotificationManager;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -122,7 +121,12 @@ public class SdlRouterService extends Service{
@SuppressWarnings("FieldCanBeLocal")
private final int UNREGISTER_APP_INTERFACE_CORRELATION_ID = 65530;
-
+
+ /**
+ * Preference location where the service stores known SDL status based on device address
+ */
+ protected static final String SDL_DEVICE_STATUS_SHARED_PREFS = "sdl.device.status";
+
private MultiplexBluetoothTransport mSerialService = null;
private static boolean connectAsClient = false;
@@ -891,15 +895,14 @@ public class SdlRouterService extends Service{
}
if(intent != null ){
if(intent.getBooleanExtra(FOREGROUND_EXTRA, false)){
-
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- int timeout = FOREGROUND_TIMEOUT;
- int state = adapter.getProfileConnectionState(BluetoothProfile.A2DP);
- if(state == BluetoothAdapter.STATE_CONNECTED){
- //If we've just connected over A2DP there is a fair chance we want to wait to
- // listen for a connection so we double our wait time
- timeout *= 2;
+ String address = null;
+ if(intent.hasExtra(BluetoothDevice.EXTRA_DEVICE)){
+ BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ if(device != null){
+ address = device.getAddress();
+ }
}
+ int timeout = getNotificationTimeout(address);
enterForeground("Waiting for connection...", timeout);
resetForegroundTimeOut(timeout);
}
@@ -993,6 +996,31 @@ public class SdlRouterService extends Service{
}
}
+ /**
+ * Gets the correct timeout for the foreground notification.
+ * @param address the address of the device that is currently connected
+ * @return the amount of time for a timeout handler to remove the notification.
+ */
+ @SuppressLint("MissingPermission")
+ private int getNotificationTimeout(String address){
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if(address != null){
+ if(hasSDLConnected(address)){
+ return FOREGROUND_TIMEOUT * 2;
+ }else if(this.isFirstStatusCheck(address)){
+ // If this is the first time the service has ever connected to this device we want
+ // to give it a few extra seconds.
+ setSDLConnectedStatus(address,false);
+ return FOREGROUND_TIMEOUT;
+ }else{
+ // If the service has seen this device before but hasn't ever connected, the
+ // notification can be removed ASAP.
+ return FOREGROUND_TIMEOUT/100;
+ }
+ }
+ return FOREGROUND_TIMEOUT/100;
+ }
+
public void resetForegroundTimeOut(long delay){
if(android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2){
return;
@@ -1320,7 +1348,11 @@ public class SdlRouterService extends Service{
SdlRouterService service = this.provider.get();
switch (msg.what) {
case MESSAGE_DEVICE_NAME:
- service.connectedDeviceName = msg.getData().getString(MultiplexBluetoothTransport.DEVICE_NAME);
+ Bundle bundle = msg.getData();
+ if(bundle !=null) {
+ service.connectedDeviceName = bundle.getString(MultiplexBluetoothTransport.DEVICE_NAME);
+ service.setSDLConnectedStatus(bundle.getString(MultiplexBluetoothTransport.DEVICE_ADDRESS),true);
+ }
break;
case MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
@@ -1716,6 +1748,39 @@ public class SdlRouterService extends Service{
{
return 0;
}
+
+ /**
+ * Set the connection establishment status of the particular device
+ * @param address address of the device in quesiton
+ * @param hasSDLConnected true if a connection has been established, false if not
+ */
+ protected void setSDLConnectedStatus(String address, boolean hasSDLConnected){
+ SharedPreferences preferences = this.getSharedPreferences(SDL_DEVICE_STATUS_SHARED_PREFS, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putBoolean(address,hasSDLConnected);
+ editor.commit();
+ }
+
+ /**
+ * Checks to see if a device address has connected to SDL before.
+ * @param address the mac address of the device in quesiton
+ * @return if this is the first status check of this device
+ */
+ protected boolean isFirstStatusCheck(String address){
+ SharedPreferences preferences = this.getSharedPreferences(SDL_DEVICE_STATUS_SHARED_PREFS, Context.MODE_PRIVATE);
+ return !preferences.contains(address) ;
+ }
+ /**
+ * Checks to see if a device address has connected to SDL before.
+ * @param address the mac address of the device in quesiton
+ * @return if an SDL connection has ever been established with this device
+ */
+ protected boolean hasSDLConnected(String address){
+ SharedPreferences preferences = this.getSharedPreferences(SDL_DEVICE_STATUS_SHARED_PREFS, Context.MODE_PRIVATE);
+ return preferences.contains(address) && preferences.getBoolean(address,false);
+ }
+
+
/* ***********************************************************************************************************************************************************************
* ***************************************************************** CUSTOM ADDITIONS ************************************************************************************