diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java index 291ce1a60..3b376095b 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java @@ -39,6 +39,7 @@ import org.fdroid.fdroid.localrepo.peers.BluetoothFinder; import org.fdroid.fdroid.localrepo.peers.BonjourFinder; import org.fdroid.fdroid.localrepo.peers.Peer; import org.fdroid.fdroid.localrepo.type.BluetoothSwap; +import org.fdroid.fdroid.localrepo.type.BonjourBroadcast; import org.fdroid.fdroid.localrepo.type.SwapType; import org.fdroid.fdroid.localrepo.type.WifiSwap; import org.fdroid.fdroid.net.WifiStateChangeService; @@ -412,12 +413,8 @@ public class SwapService extends Service { return bluetoothSwap.isConnected(); } - private boolean isWifiConnected() { - return !TextUtils.isEmpty(FDroidApp.ssid); - } - public boolean isBonjourDiscoverable() { - return isWifiConnected() && isEnabled(); + return wifiSwap.isConnected() && wifiSwap.getBonjour().isConnected(); } public boolean isScanningForPeers() { @@ -434,6 +431,7 @@ public class SwapService extends Service { public static final String BONJOUR_STATE_CHANGE = "org.fdroid.fdroid.BONJOUR_STATE_CHANGE"; public static final String BLUETOOTH_STATE_CHANGE = "org.fdroid.fdroid.BLUETOOTH_STATE_CHANGE"; + public static final String WIFI_STATE_CHANGE = "org.fdroid.fdroid.WIFI_STATE_CHANGE"; public static final String EXTRA_STARTING = "STARTING"; public static final String EXTRA_STARTED = "STARTED"; public static final String EXTRA_STOPPED = "STOPPED"; @@ -459,7 +457,7 @@ public class SwapService extends Service { return bluetoothSwap; } - public SwapType getWifiSwap() { + public WifiSwap getWifiSwap() { return wifiSwap; } @@ -485,8 +483,31 @@ public class SwapService extends Service { Preferences.get().registerLocalRepoHttpsListeners(httpsEnabledListener); LocalBroadcastManager.getInstance(this).registerReceiver(onWifiChange, new IntentFilter(WifiStateChangeService.BROADCAST)); + + IntentFilter filter = new IntentFilter(BLUETOOTH_STATE_CHANGE); + filter.addAction(WIFI_STATE_CHANGE); + LocalBroadcastManager.getInstance(this).registerReceiver(receiveSwapStatusChanged, filter); } + /** + * Responsible for moving the service into the foreground or the background, depending on + * whether or not there are any swap services (i.e. bluetooth or wifi) running or not. + */ + private final BroadcastReceiver receiveSwapStatusChanged = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.hasExtra(EXTRA_STARTED)) { + if (getWifiSwap().isConnected() || getBluetoothSwap().isConnected()) { + attachService(); + } + } else if (intent.hasExtra(EXTRA_STOPPED)) { + if (!getWifiSwap().isConnected() && !getBluetoothSwap().isConnected()) { + detachService(); + } + } + } + }; + @Override public int onStartCommand(Intent intent, int flags, int startId) { @@ -517,6 +538,7 @@ public class SwapService extends Service { disableAllSwapping(); Preferences.get().unregisterLocalRepoHttpsListeners(httpsEnabledListener); LocalBroadcastManager.getInstance(this).unregisterReceiver(onWifiChange); + LocalBroadcastManager.getInstance(this).unregisterReceiver(receiveSwapStatusChanged); } private Notification createNotification() { diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothFinder.java b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothFinder.java index f87edd018..6de94e849 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothFinder.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothFinder.java @@ -8,6 +8,8 @@ import android.content.Intent; import android.content.IntentFilter; import android.util.Log; +import org.fdroid.fdroid.net.bluetooth.BluetoothServer; + // TODO: Still to be implemented public class BluetoothFinder extends PeerFinder { @@ -20,6 +22,9 @@ public class BluetoothFinder extends PeerFinder { adapter = BluetoothAdapter.getDefaultAdapter(); } + private BroadcastReceiver deviceFoundReceiver; + private BroadcastReceiver scanCompleteReceiver; + @Override public void scan() { @@ -28,35 +33,45 @@ public class BluetoothFinder extends PeerFinder { return; } - if (isScanning) { - // TODO: Can we reset the discovering timeout, so that it doesn't, e.g. time out - // in 3 seconds because we had already almost completed the previous scan? - Log.d(TAG, "Requested bluetooth scan when already scanning, will ignore request."); - return; - } - isScanning = true; - final BroadcastReceiver deviceFoundReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) { - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - onDeviceFound(device); + if (deviceFoundReceiver == null) { + deviceFoundReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) { + BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + onDeviceFound(device); + } } - } - }; + }; + context.registerReceiver(deviceFoundReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND)); + } - final BroadcastReceiver scanCompleteReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Log.d(TAG, "Scan complete: " + intent.getAction()); - isScanning = false; - } - }; + if (scanCompleteReceiver == null) { + scanCompleteReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (isScanning) { + Log.d(TAG, "Scan complete, but we haven't been asked to stop scanning yet, so will restart scan."); + startDiscovery(); + } + } + }; + context.registerReceiver(scanCompleteReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)); + } - context.registerReceiver(deviceFoundReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND)); - context.registerReceiver(scanCompleteReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)); + startDiscovery(); + } + + private void startDiscovery() { + + if (adapter.isDiscovering()) { + // TODO: Can we reset the discovering timeout, so that it doesn't, e.g. time out + // in 3 seconds because we had already almost completed the previous scan? + Log.d(TAG, "Requested bluetooth scan when already scanning, will cancel previous scan before continuing."); + adapter.cancelDiscovery(); + } if (!adapter.startDiscovery()) { Log.e(TAG, "Couldn't start bluetooth scanning."); @@ -75,7 +90,9 @@ public class BluetoothFinder extends PeerFinder { } private void onDeviceFound(BluetoothDevice device) { - foundPeer(new BluetoothPeer(device)); + if (device != null && device.getName() != null && device.getName().startsWith(BluetoothServer.BLUETOOTH_NAME_TAG)) { + foundPeer(new BluetoothPeer(device)); + } } } diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothPeer.java b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothPeer.java index 814e64cc1..ca3f58210 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothPeer.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothPeer.java @@ -4,6 +4,7 @@ import android.bluetooth.BluetoothDevice; import android.os.Parcel; import org.fdroid.fdroid.R; +import org.fdroid.fdroid.net.bluetooth.BluetoothServer; // TODO: Still to be implemented. public class BluetoothPeer implements Peer { @@ -21,7 +22,7 @@ public class BluetoothPeer implements Peer { @Override public String getName() { - return device.getName(); + return device.getName().replaceAll("^" + BluetoothServer.BLUETOOTH_NAME_TAG, ""); } @Override diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/type/BluetoothSwap.java b/F-Droid/src/org/fdroid/fdroid/localrepo/type/BluetoothSwap.java index 3898b1c17..e7d4504dd 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/type/BluetoothSwap.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/type/BluetoothSwap.java @@ -103,5 +103,10 @@ public class BluetoothSwap extends SwapType { @Override public void stop() {} + + @Override + protected String getBroadcastAction() { + return null; + } } } diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/type/SwapType.java b/F-Droid/src/org/fdroid/fdroid/localrepo/type/SwapType.java index 47b37b3be..9f8d48371 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/type/SwapType.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/type/SwapType.java @@ -30,9 +30,7 @@ public abstract class SwapType { abstract public void stop(); - protected String getBroadcastAction() { - return null; - } + abstract protected String getBroadcastAction(); protected final void setConnected(boolean connected) { if (connected) { diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/type/WifiSwap.java b/F-Droid/src/org/fdroid/fdroid/localrepo/type/WifiSwap.java index 91008ef83..774b2a4ee 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/type/WifiSwap.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/type/WifiSwap.java @@ -10,6 +10,7 @@ import android.util.Log; import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.Preferences; +import org.fdroid.fdroid.localrepo.SwapService; import org.fdroid.fdroid.net.LocalHTTPD; import org.fdroid.fdroid.net.WifiStateChangeService; @@ -23,13 +24,21 @@ public class WifiSwap extends SwapType { private Handler webServerThreadHandler = null; private LocalHTTPD localHttpd; - private final SwapType bonjourBroadcast; + private final BonjourBroadcast bonjourBroadcast; public WifiSwap(Context context) { super(context); bonjourBroadcast = new BonjourBroadcast(context); } + protected String getBroadcastAction() { + return SwapService.WIFI_STATE_CHANGE; + } + + public BonjourBroadcast getBonjour() { + return bonjourBroadcast; + } + @Override public void start() { diff --git a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothServer.java b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothServer.java index 35268a6d1..8328e8ec7 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothServer.java +++ b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothServer.java @@ -63,7 +63,7 @@ public class BluetoothServer extends Thread { } BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - adapter.setName(deviceBluetoothName.replace(BLUETOOTH_NAME_TAG,"")); + adapter.setName(deviceBluetoothName.replaceAll("/^" + BLUETOOTH_NAME_TAG + "/","")); } @@ -76,7 +76,7 @@ public class BluetoothServer extends Thread { //store the original bluetoothname, and update this one to be unique deviceBluetoothName = adapter.getName(); - if (!deviceBluetoothName.contains(BLUETOOTH_NAME_TAG)) + if (!deviceBluetoothName.startsWith(BLUETOOTH_NAME_TAG)) adapter.setName(BLUETOOTH_NAME_TAG + deviceBluetoothName); diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java index f9546b394..53589a841 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java @@ -42,8 +42,12 @@ import org.fdroid.fdroid.localrepo.peers.Peer; import org.fdroid.fdroid.net.bluetooth.BluetoothServer; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; /** * This activity will do its best to show the most relevant screen about swapping to the user. @@ -156,6 +160,8 @@ public class SwapWorkflowActivity extends AppCompatActivity { setSupportActionBar(toolbar); container = (ViewGroup) findViewById(R.id.fragment_container); + + new SwapDebug().logStatus(); } @Override @@ -603,4 +609,50 @@ public class SwapWorkflowActivity extends AppCompatActivity { } + class SwapDebug { + + private StringBuilder status = new StringBuilder("\n"); + + public void logStatus() { + append("service = " + service); + if (service != null) { + append("Swap Services:"); + append(" service.getBluetoothSwap() = " + service.getBluetoothSwap()); + append(" service.getBluetoothSwap().isConnected() = " + service.getBluetoothSwap().isConnected()); + append(" service.getWifiSwap() = " + service.getWifiSwap()); + append(" service.getWifiSwap().isConnected() = " + service.getWifiSwap().isConnected()); + append(" service.getWifiSwap().getBonjour() = " + service.getWifiSwap().getBonjour()); + append(" service.getWifiSwap().getBonjour().isConnected() = " + service.getWifiSwap().getBonjour().isConnected()); + append("Discovering Services:"); + + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if (adapter != null) { + + Map scanModes = new HashMap<>(3); + scanModes.put(BluetoothAdapter.SCAN_MODE_CONNECTABLE, "SCAN_MODE_CONNECTABLE"); + scanModes.put(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, "SCAN_MODE_CONNECTABLE_DISCOVERABLE"); + scanModes.put(BluetoothAdapter.SCAN_MODE_NONE, "SCAN_MODE_NONE"); + + append(" Bluetooth.isEnabled() = " + adapter.isEnabled()); + append(" Bluetooth.isDiscovering() = " + adapter.isDiscovering()); + append(" Bluetooth.getScanMode() = " + scanModes.get(adapter.getScanMode())); + } + } + Log.d("SwapStatus", status.toString()); + + new Timer().schedule(new TimerTask() { + @Override + public void run() { + new SwapDebug().logStatus(); + } + }, + 2000 + ); + } + + private void append(String line) { + status.append(" ").append(line).append("\n"); + } + } + }