create BonjourManager to manage jmdns in HandlerThread, with tests
This commit is contained in:
parent
79e7e78e7f
commit
46472ba7a4
@ -0,0 +1,125 @@
|
||||
package org.fdroid.fdroid.localrepo;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import javax.jmdns.ServiceEvent;
|
||||
import javax.jmdns.ServiceListener;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BonjourManagerTest {
|
||||
|
||||
private static final String NAME = "Robolectric-test";
|
||||
private static final String LOCALHOST = "localhost";
|
||||
private static final int PORT = 8888;
|
||||
|
||||
@Test
|
||||
public void testStartStop() throws InterruptedException {
|
||||
Context context = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
FDroidApp.ipAddressString = LOCALHOST;
|
||||
FDroidApp.port = PORT;
|
||||
|
||||
final CountDownLatch addedLatch = new CountDownLatch(1);
|
||||
final CountDownLatch resolvedLatch = new CountDownLatch(1);
|
||||
final CountDownLatch removedLatch = new CountDownLatch(1);
|
||||
BonjourManager.start(context, NAME, false,
|
||||
new ServiceListener() {
|
||||
@Override
|
||||
public void serviceAdded(ServiceEvent serviceEvent) {
|
||||
System.out.println("Service added: " + serviceEvent.getInfo());
|
||||
if (NAME.equals(serviceEvent.getName())) {
|
||||
addedLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceRemoved(ServiceEvent serviceEvent) {
|
||||
System.out.println("Service removed: " + serviceEvent.getInfo());
|
||||
removedLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceResolved(ServiceEvent serviceEvent) {
|
||||
System.out.println("Service resolved: " + serviceEvent.getInfo());
|
||||
if (NAME.equals(serviceEvent.getName())) {
|
||||
resolvedLatch.countDown();
|
||||
}
|
||||
}
|
||||
}, getBlankServiceListener());
|
||||
BonjourManager.setVisible(context, true);
|
||||
assertTrue(addedLatch.await(30, TimeUnit.SECONDS));
|
||||
assertTrue(resolvedLatch.await(30, TimeUnit.SECONDS));
|
||||
BonjourManager.setVisible(context, false);
|
||||
assertTrue(removedLatch.await(30, TimeUnit.SECONDS));
|
||||
BonjourManager.stop(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestart() throws InterruptedException {
|
||||
Context context = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
FDroidApp.ipAddressString = LOCALHOST;
|
||||
FDroidApp.port = PORT;
|
||||
|
||||
BonjourManager.start(context, NAME, false, getBlankServiceListener(), getBlankServiceListener());
|
||||
|
||||
final CountDownLatch addedLatch = new CountDownLatch(1);
|
||||
final CountDownLatch resolvedLatch = new CountDownLatch(1);
|
||||
final CountDownLatch removedLatch = new CountDownLatch(1);
|
||||
BonjourManager.restart(context, NAME, false,
|
||||
new ServiceListener() {
|
||||
@Override
|
||||
public void serviceAdded(ServiceEvent serviceEvent) {
|
||||
System.out.println("Service added: " + serviceEvent.getInfo());
|
||||
if (NAME.equals(serviceEvent.getName())) {
|
||||
addedLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceRemoved(ServiceEvent serviceEvent) {
|
||||
System.out.println("Service removed: " + serviceEvent.getInfo());
|
||||
removedLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceResolved(ServiceEvent serviceEvent) {
|
||||
System.out.println("Service resolved: " + serviceEvent.getInfo());
|
||||
if (NAME.equals(serviceEvent.getName())) {
|
||||
resolvedLatch.countDown();
|
||||
}
|
||||
}
|
||||
}, getBlankServiceListener());
|
||||
BonjourManager.setVisible(context, true);
|
||||
assertTrue(addedLatch.await(30, TimeUnit.SECONDS));
|
||||
assertTrue(resolvedLatch.await(30, TimeUnit.SECONDS));
|
||||
BonjourManager.setVisible(context, false);
|
||||
assertTrue(removedLatch.await(30, TimeUnit.SECONDS));
|
||||
BonjourManager.stop(context);
|
||||
}
|
||||
|
||||
private ServiceListener getBlankServiceListener() {
|
||||
return new ServiceListener() {
|
||||
@Override
|
||||
public void serviceAdded(ServiceEvent serviceEvent) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceRemoved(ServiceEvent serviceEvent) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceResolved(ServiceEvent serviceEvent) {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,269 @@
|
||||
package org.fdroid.fdroid.localrepo;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
|
||||
import javax.jmdns.JmDNS;
|
||||
import javax.jmdns.ServiceEvent;
|
||||
import javax.jmdns.ServiceInfo;
|
||||
import javax.jmdns.ServiceListener;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.InetAddress;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Manage {@link JmDNS} in a {@link HandlerThread}. The start process is in
|
||||
* {@link HandlerThread#onLooperPrepared()} so that it is always started before
|
||||
* any messages get delivered from the queue.
|
||||
*/
|
||||
public class BonjourManager {
|
||||
private static final String TAG = "BonjourManager";
|
||||
|
||||
public static final String ACTION_ADDED = "BonjourAdded";
|
||||
public static final String ACTION_RESOLVED = "BonjourResolved";
|
||||
public static final String ACTION_REMOVED = "BonjourRemoved";
|
||||
|
||||
public static final String ACTION_STATUS = "BonjourStatus";
|
||||
public static final String EXTRA_STATUS = "BonjourStatusExtra";
|
||||
public static final int STATUS_STARTING = 0;
|
||||
public static final int STATUS_STARTED = 1;
|
||||
public static final int STATUS_STOPPING = 2;
|
||||
public static final int STATUS_STOPPED = 3;
|
||||
public static final int STATUS_VISIBLE = 4;
|
||||
public static final int STATUS_NOT_VISIBLE = 5;
|
||||
public static final int STATUS_ERROR = 0xffff;
|
||||
|
||||
public static final String HTTP_SERVICE_TYPE = "_http._tcp.local.";
|
||||
public static final String HTTPS_SERVICE_TYPE = "_https._tcp.local.";
|
||||
|
||||
private static final int STOP = 5709;
|
||||
private static final int VISIBLE = 4151873;
|
||||
private static final int NOT_VISIBLE = 144151873;
|
||||
|
||||
private static WeakReference<Context> context;
|
||||
private static Handler handler;
|
||||
private static volatile HandlerThread handlerThread;
|
||||
private static ServiceInfo pairService;
|
||||
private static JmDNS jmdns;
|
||||
|
||||
public static boolean isAlive() {
|
||||
return handlerThread != null && handlerThread.isAlive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the Bonjour/mDNS, triggering a status broadcast via {@link #ACTION_STATUS}.
|
||||
* {@link #STATUS_STOPPED} can be broadcast multiple times for the same session,
|
||||
* so make sure {@link android.content.BroadcastReceiver}s handle duplicates.
|
||||
*/
|
||||
public static void stop(Context context) {
|
||||
BonjourManager.context = new WeakReference<>(context);
|
||||
if (handler == null || handlerThread == null || !handlerThread.isAlive()) {
|
||||
sendBroadcast(STATUS_STOPPED, null);
|
||||
return;
|
||||
}
|
||||
sendBroadcast(STATUS_STOPPING, null);
|
||||
handler.sendEmptyMessage(STOP);
|
||||
}
|
||||
|
||||
public static void setVisible(Context context, boolean visible) {
|
||||
BonjourManager.context = new WeakReference<>(context);
|
||||
if (handler == null || handlerThread == null || !handlerThread.isAlive()) {
|
||||
Log.e(TAG, "handlerThread is stopped, not changing visibility!");
|
||||
return;
|
||||
}
|
||||
if (visible) {
|
||||
handler.sendEmptyMessage(VISIBLE);
|
||||
} else {
|
||||
handler.sendEmptyMessage(NOT_VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the service, triggering a status broadcast via {@link #ACTION_STATUS}.
|
||||
* {@link #STATUS_STARTED} can be broadcast multiple times for the same session,
|
||||
* so make sure {@link android.content.BroadcastReceiver}s handle duplicates.
|
||||
*/
|
||||
public static void start(Context context) {
|
||||
start(context,
|
||||
Preferences.get().getLocalRepoName(),
|
||||
Preferences.get().isLocalRepoHttpsEnabled(),
|
||||
httpServiceListener, httpsServiceListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Testable version, not for regular use.
|
||||
*
|
||||
* @see #start(Context)
|
||||
*/
|
||||
static void start(final Context context,
|
||||
final String localRepoName, final boolean useHttps,
|
||||
final ServiceListener httpServiceListener, final ServiceListener httpsServiceListener) {
|
||||
BonjourManager.context = new WeakReference<>(context);
|
||||
if (handlerThread != null && handlerThread.isAlive()) {
|
||||
sendBroadcast(STATUS_STARTED, null);
|
||||
return;
|
||||
}
|
||||
sendBroadcast(STATUS_STARTING, null);
|
||||
|
||||
handlerThread = new HandlerThread("BonjourManager", Process.THREAD_PRIORITY_LESS_FAVORABLE) {
|
||||
@Override
|
||||
protected void onLooperPrepared() {
|
||||
try {
|
||||
InetAddress address = InetAddress.getByName(FDroidApp.ipAddressString);
|
||||
jmdns = JmDNS.create(address);
|
||||
jmdns.addServiceListener(HTTP_SERVICE_TYPE, httpServiceListener);
|
||||
jmdns.addServiceListener(HTTPS_SERVICE_TYPE, httpsServiceListener);
|
||||
sendBroadcast(STATUS_STARTED, null);
|
||||
} catch (IOException e) {
|
||||
if (handler != null) {
|
||||
handler.removeMessages(VISIBLE);
|
||||
handler.sendMessageAtFrontOfQueue(handler.obtainMessage(STOP));
|
||||
}
|
||||
Log.e(TAG, "Error while registering jmdns service", e);
|
||||
sendBroadcast(STATUS_ERROR, e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
};
|
||||
handlerThread.start();
|
||||
handler = new Handler(handlerThread.getLooper()) {
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case VISIBLE:
|
||||
handleVisible(localRepoName, useHttps);
|
||||
break;
|
||||
case NOT_VISIBLE:
|
||||
handleNotVisible();
|
||||
break;
|
||||
case STOP:
|
||||
handleStop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleVisible(String localRepoName, boolean useHttps) {
|
||||
HashMap<String, String> values = new HashMap<>();
|
||||
values.put("path", "/fdroid/repo");
|
||||
values.put("name", localRepoName);
|
||||
values.put("fingerprint", FDroidApp.repo.fingerprint);
|
||||
String type;
|
||||
if (useHttps) {
|
||||
values.put("type", "fdroidrepos");
|
||||
type = HTTPS_SERVICE_TYPE;
|
||||
} else {
|
||||
values.put("type", "fdroidrepo");
|
||||
type = HTTP_SERVICE_TYPE;
|
||||
}
|
||||
ServiceInfo newPairService = ServiceInfo.create(type, localRepoName, FDroidApp.port, 0, 0, values);
|
||||
if (!newPairService.equals(pairService)) try {
|
||||
if (pairService != null) {
|
||||
jmdns.unregisterService(pairService);
|
||||
}
|
||||
jmdns.registerService(newPairService);
|
||||
pairService = newPairService;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
sendBroadcast(STATUS_ERROR, e.getLocalizedMessage());
|
||||
return;
|
||||
}
|
||||
sendBroadcast(STATUS_VISIBLE, null);
|
||||
}
|
||||
|
||||
private void handleNotVisible() {
|
||||
if (pairService != null) {
|
||||
jmdns.unregisterService(pairService);
|
||||
pairService = null;
|
||||
}
|
||||
sendBroadcast(STATUS_NOT_VISIBLE, null);
|
||||
}
|
||||
|
||||
private void handleStop() {
|
||||
if (jmdns != null) {
|
||||
jmdns.unregisterAllServices();
|
||||
Utils.closeQuietly(jmdns);
|
||||
pairService = null;
|
||||
jmdns = null;
|
||||
}
|
||||
handlerThread.quit();
|
||||
handlerThread = null;
|
||||
sendBroadcast(STATUS_STOPPED, null);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
public static void restart(Context context) {
|
||||
restart(context,
|
||||
Preferences.get().getLocalRepoName(),
|
||||
Preferences.get().isLocalRepoHttpsEnabled(),
|
||||
httpServiceListener, httpsServiceListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Testable version, not for regular use.
|
||||
*
|
||||
* @see #restart(Context)
|
||||
*/
|
||||
static void restart(final Context context,
|
||||
final String localRepoName, final boolean useHttps,
|
||||
final ServiceListener httpServiceListener, final ServiceListener httpsServiceListener) {
|
||||
stop(context);
|
||||
try {
|
||||
handlerThread.join(10000);
|
||||
} catch (InterruptedException | NullPointerException e) {
|
||||
// ignored
|
||||
}
|
||||
start(context, localRepoName, useHttps, httpServiceListener, httpsServiceListener);
|
||||
}
|
||||
|
||||
private static void sendBroadcast(String action, String message) {
|
||||
Intent intent = new Intent(action);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, message);
|
||||
LocalBroadcastManager.getInstance(context.get()).sendBroadcast(intent);
|
||||
}
|
||||
|
||||
private static void sendBroadcast(int status, String message) {
|
||||
|
||||
Intent intent = new Intent(ACTION_STATUS);
|
||||
intent.putExtra(EXTRA_STATUS, status);
|
||||
if (!TextUtils.isEmpty(message)) {
|
||||
intent.putExtra(Intent.EXTRA_TEXT, message);
|
||||
}
|
||||
LocalBroadcastManager.getInstance(context.get()).sendBroadcast(intent);
|
||||
}
|
||||
|
||||
private static final ServiceListener httpServiceListener = new SwapServiceListener();
|
||||
private static final ServiceListener httpsServiceListener = new SwapServiceListener();
|
||||
|
||||
private static class SwapServiceListener implements ServiceListener {
|
||||
@Override
|
||||
public void serviceAdded(ServiceEvent serviceEvent) {
|
||||
Utils.debugLog(TAG, "Service added: " + serviceEvent.getInfo());
|
||||
sendBroadcast(ACTION_ADDED, serviceEvent.getInfo().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceRemoved(ServiceEvent serviceEvent) {
|
||||
Utils.debugLog(TAG, "Service removed: " + serviceEvent.getInfo());
|
||||
sendBroadcast(ACTION_REMOVED, serviceEvent.getInfo().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serviceResolved(ServiceEvent serviceEvent) {
|
||||
Utils.debugLog(TAG, "Service resolved: " + serviceEvent.getInfo());
|
||||
sendBroadcast(ACTION_RESOLVED, serviceEvent.getInfo().toString());
|
||||
}
|
||||
}
|
||||
}
|
@ -369,10 +369,6 @@ public class SwapService extends Service {
|
||||
return bluetoothSwap.isDiscoverable();
|
||||
}
|
||||
|
||||
public boolean isBonjourDiscoverable() {
|
||||
return wifiSwap.isConnected() && wifiSwap.getBonjour().isConnected();
|
||||
}
|
||||
|
||||
// ===============================================================
|
||||
// Old SwapService stuff being merged into that.
|
||||
// ===============================================================
|
||||
|
@ -16,6 +16,9 @@ import javax.jmdns.ServiceListener;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import static org.fdroid.fdroid.localrepo.BonjourManager.HTTPS_SERVICE_TYPE;
|
||||
import static org.fdroid.fdroid.localrepo.BonjourManager.HTTP_SERVICE_TYPE;
|
||||
|
||||
@SuppressWarnings("LineLength")
|
||||
final class BonjourFinder extends PeerFinder implements ServiceListener {
|
||||
|
||||
@ -39,9 +42,6 @@ final class BonjourFinder extends PeerFinder implements ServiceListener {
|
||||
|
||||
private static final String TAG = "BonjourFinder";
|
||||
|
||||
private static final String HTTP_SERVICE_TYPE = "_http._tcp.local.";
|
||||
private static final String HTTPS_SERVICE_TYPE = "_https._tcp.local.";
|
||||
|
||||
private JmDNS jmdns;
|
||||
private WifiManager wifiManager;
|
||||
private WifiManager.MulticastLock multicastLock;
|
||||
|
@ -1,112 +0,0 @@
|
||||
package org.fdroid.fdroid.localrepo.type;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.localrepo.SwapService;
|
||||
|
||||
import javax.jmdns.JmDNS;
|
||||
import javax.jmdns.ServiceInfo;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Sends a {@link SwapService#BONJOUR_STATE_CHANGE} broadcasts when starting, started or stopped.
|
||||
*/
|
||||
public class BonjourBroadcast extends SwapType {
|
||||
|
||||
private static final String TAG = "BonjourBroadcast";
|
||||
|
||||
private JmDNS jmdns;
|
||||
private ServiceInfo pairService;
|
||||
|
||||
public BonjourBroadcast(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
Utils.debugLog(TAG, "Preparing to start Bonjour service.");
|
||||
sendBroadcast(SwapService.EXTRA_STARTING);
|
||||
|
||||
InetAddress address = getDeviceAddress();
|
||||
if (address == null) {
|
||||
Log.e(TAG, "Starting Bonjour service, but couldn't ascertain IP address."
|
||||
+ " Seems we are not connected to a network.");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* a ServiceInfo can only be registered with a single instance
|
||||
* of JmDNS, and there is only ever a single LocalHTTPD port to
|
||||
* advertise anyway.
|
||||
*/
|
||||
if (pairService != null || jmdns != null) {
|
||||
clearCurrentMDNSService();
|
||||
}
|
||||
|
||||
String repoName = Preferences.get().getLocalRepoName();
|
||||
HashMap<String, String> values = new HashMap<>();
|
||||
values.put("path", "/fdroid/repo");
|
||||
values.put("name", repoName);
|
||||
values.put("fingerprint", FDroidApp.repo.fingerprint);
|
||||
String type;
|
||||
if (Preferences.get().isLocalRepoHttpsEnabled()) {
|
||||
values.put("type", "fdroidrepos");
|
||||
type = "_https._tcp.local.";
|
||||
} else {
|
||||
values.put("type", "fdroidrepo");
|
||||
type = "_http._tcp.local.";
|
||||
}
|
||||
try {
|
||||
Utils.debugLog(TAG, "Starting bonjour service...");
|
||||
pairService = ServiceInfo.create(type, repoName, FDroidApp.port, 0, 0, values);
|
||||
jmdns = JmDNS.create(address);
|
||||
jmdns.registerService(pairService);
|
||||
setConnected(true);
|
||||
Utils.debugLog(TAG, "... Bounjour service started.");
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Error while registering jmdns service", e);
|
||||
setConnected(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
Utils.debugLog(TAG, "Unregistering MDNS service...");
|
||||
clearCurrentMDNSService();
|
||||
setConnected(false);
|
||||
}
|
||||
|
||||
private void clearCurrentMDNSService() {
|
||||
if (jmdns != null) {
|
||||
jmdns.unregisterAllServices();
|
||||
Utils.closeQuietly(jmdns);
|
||||
pairService = null;
|
||||
jmdns = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBroadcastAction() {
|
||||
return SwapService.BONJOUR_STATE_CHANGE;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private InetAddress getDeviceAddress() {
|
||||
if (FDroidApp.ipAddressString != null) {
|
||||
try {
|
||||
return InetAddress.getByName(FDroidApp.ipAddressString);
|
||||
} catch (UnknownHostException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -2,29 +2,20 @@ package org.fdroid.fdroid.localrepo.type;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.util.Log;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.localrepo.BonjourManager;
|
||||
import org.fdroid.fdroid.localrepo.LocalHTTPDManager;
|
||||
import org.fdroid.fdroid.localrepo.SwapService;
|
||||
import rx.Single;
|
||||
import rx.SingleSubscriber;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.functions.Action1;
|
||||
import rx.functions.Func2;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
@SuppressWarnings("LineLength")
|
||||
public class WifiSwap extends SwapType {
|
||||
|
||||
private static final String TAG = "WifiSwap";
|
||||
|
||||
private final BonjourBroadcast bonjourBroadcast;
|
||||
private final WifiManager wifiManager;
|
||||
|
||||
public WifiSwap(Context context, WifiManager wifiManager) {
|
||||
super(context);
|
||||
bonjourBroadcast = new BonjourBroadcast(context);
|
||||
this.wifiManager = wifiManager;
|
||||
}
|
||||
|
||||
@ -32,89 +23,26 @@ public class WifiSwap extends SwapType {
|
||||
return SwapService.WIFI_STATE_CHANGE;
|
||||
}
|
||||
|
||||
public BonjourBroadcast getBonjour() {
|
||||
return bonjourBroadcast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
sendBroadcast(SwapService.EXTRA_STARTING);
|
||||
wifiManager.setWifiEnabled(true);
|
||||
|
||||
LocalHTTPDManager.start(context);
|
||||
BonjourManager.start(context);
|
||||
BonjourManager.setVisible(context, SwapService.getWifiVisibleUserPreference());
|
||||
|
||||
if (FDroidApp.ipAddressString == null) {
|
||||
Log.e(TAG, "Not starting swap webserver, because we don't seem to be connected to a network.");
|
||||
setConnected(false);
|
||||
} else {
|
||||
setConnected(true);
|
||||
}
|
||||
|
||||
Single.zip(
|
||||
Single.create(getWebServerTask()),
|
||||
Single.create(getBonjourTask()),
|
||||
new Func2<Boolean, Boolean, Boolean>() {
|
||||
@Override
|
||||
public Boolean call(Boolean webServerTask, Boolean bonjourServiceTask) {
|
||||
return bonjourServiceTask && webServerTask;
|
||||
}
|
||||
})
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.subscribe(new Action1<Boolean>() {
|
||||
@Override
|
||||
public void call(Boolean success) {
|
||||
setConnected(success);
|
||||
}
|
||||
},
|
||||
new Action1<Throwable>() {
|
||||
@Override
|
||||
public void call(Throwable throwable) {
|
||||
setConnected(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A task which starts the {@link WifiSwap#bonjourBroadcast} and then emits a `true` value at
|
||||
* the end.
|
||||
*/
|
||||
private Single.OnSubscribe<Boolean> getBonjourTask() {
|
||||
return new Single.OnSubscribe<Boolean>() {
|
||||
@Override
|
||||
public void call(SingleSubscriber<? super Boolean> singleSubscriber) {
|
||||
bonjourBroadcast.start();
|
||||
|
||||
// TODO: Be more intelligent about failures here so that we can invoke
|
||||
// singleSubscriber.onError() in the appropriate circumstances.
|
||||
singleSubscriber.onSuccess(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link Thread} for the webserver to run on. If successful, it will also
|
||||
* populate the webServerThreadHandler property and bind it to that particular thread. This
|
||||
* allows messages to be sent to the webserver thread by posting messages to that handler.
|
||||
*/
|
||||
private Single.OnSubscribe<Boolean> getWebServerTask() {
|
||||
return new Single.OnSubscribe<Boolean>() {
|
||||
@Override
|
||||
public void call(SingleSubscriber<? super Boolean> singleSubscriber) {
|
||||
singleSubscriber.onSuccess(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
sendBroadcast(SwapService.EXTRA_STOPPING); // This needs to be per-SwapType
|
||||
Utils.debugLog(TAG, "Sending message to swap webserver to stop it.");
|
||||
LocalHTTPDManager.stop(context);
|
||||
|
||||
// Stop the Bonjour stuff after asking the webserver to stop. This is not required in this
|
||||
// order, but it helps. In practice, the Bonjour stuff takes a second or two to stop. This
|
||||
// should give enough time for the message we posted above to reach the web server thread
|
||||
// and for the webserver to thus be stopped.
|
||||
bonjourBroadcast.stop();
|
||||
BonjourManager.stop(context);
|
||||
setConnected(false);
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ import cc.mvdan.accesspoint.WifiApControl;
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
import org.fdroid.fdroid.localrepo.BonjourManager;
|
||||
import org.fdroid.fdroid.localrepo.SwapService;
|
||||
import org.fdroid.fdroid.localrepo.SwapView;
|
||||
import org.fdroid.fdroid.localrepo.peers.Peer;
|
||||
@ -318,15 +319,15 @@ public class StartSwapView extends SwapView {
|
||||
viewWifiNetwork = (TextView) findViewById(R.id.wifi_network);
|
||||
|
||||
wifiSwitch = (SwitchCompat) findViewById(R.id.switch_wifi);
|
||||
wifiSwitch.setOnCheckedChangeListener(onWifiSwitchToggled);
|
||||
setWifiSwitchState(getActivity().getSwapService().isBonjourDiscoverable(), true);
|
||||
wifiSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
BonjourManager.setVisible(getContext(), isChecked);
|
||||
SwapService.putWifiVisibleUserPreference(isChecked);
|
||||
}
|
||||
});
|
||||
|
||||
textWifiVisible = findViewById(R.id.wifi_visible);
|
||||
if (getActivity().getSwapService().isBonjourDiscoverable()) {
|
||||
textWifiVisible.setText(R.string.swap_visible_wifi);
|
||||
} else {
|
||||
textWifiVisible.setText(R.string.swap_not_visible_wifi);
|
||||
}
|
||||
|
||||
// Note that this is only listening for the WifiSwap, whereas we start both the WifiSwap
|
||||
// and the Bonjour service at the same time. Technically swap will work fine without
|
||||
|
@ -816,8 +816,6 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
||||
} else {
|
||||
String bluetooth = service.getBluetoothSwap().isConnected() ? "Y" : " N";
|
||||
String wifi = service.getWifiSwap().isConnected() ? "Y" : " N";
|
||||
String mdns = service.getWifiSwap().getBonjour().isConnected() ? "Y" : " N";
|
||||
message += "Swap { BT: " + bluetooth + ", WiFi: " + wifi + ", mDNS: " + mdns + "}, ";
|
||||
|
||||
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
bluetooth = "N/A";
|
||||
|
Loading…
x
Reference in New Issue
Block a user