broadcast local repo via Bonjour/mDNS to enable auto-discovery
This adds support for registering the local repo with Bonjour/mDNS so that it is broadcast out to all devices on the local network. This makes it easy to discover and add local repos on the same wifi. refs #2900 https://dev.guardianproject.info/issues/2900
This commit is contained in:
parent
7ca966be05
commit
d25a395936
@ -34,7 +34,10 @@
|
||||
<string name="system_installer">Install using system-permissions</string>
|
||||
<string name="system_installer_on">Use system permissions to install, update, and remove packages</string>
|
||||
<string name="system_installer_off">Do not use system permissions to install, update, and remove packages</string>
|
||||
|
||||
<string name="local_repo_bonjour">Broadcast Local Repo</string>
|
||||
<string name="local_repo_bonjour_on">Advertize your local repo using Bonjour (mDNS)</string>
|
||||
<string name="local_repo_bonjour_off">Do not advertize your local repo.</string>
|
||||
|
||||
<string name="search_results">Search Results</string>
|
||||
<string name="app_details">App Details</string>
|
||||
<string name="no_such_app">No such app found</string>
|
||||
|
@ -43,6 +43,12 @@
|
||||
android:defaultValue="false"
|
||||
android:key="ignoreTouchscreen" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/local_repo">
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="localRepoBonjour"
|
||||
android:title="@string/local_repo_bonjour" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/other">
|
||||
<CheckBoxPreference android:title="@string/cache_downloaded"
|
||||
android:defaultValue="false"
|
||||
|
@ -38,12 +38,14 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
||||
public static final String PREF_UPD_LAST = "lastUpdateCheck";
|
||||
public static final String PREF_ROOT_INSTALLER = "rootInstaller";
|
||||
public static final String PREF_SYSTEM_INSTALLER = "systemInstaller";
|
||||
public static final String PREF_LOCAL_REPO_BONJOUR = "localRepoBonjour";
|
||||
|
||||
private static final boolean DEFAULT_COMPACT_LAYOUT = false;
|
||||
private static final boolean DEFAULT_ROOTED = true;
|
||||
private static final int DEFAULT_UPD_HISTORY = 14;
|
||||
private static final boolean DEFAULT_ROOT_INSTALLER = false;
|
||||
private static final boolean DEFAULT_SYSTEM_INSTALLER = false;
|
||||
private static final boolean DEFAULT_LOCAL_REPO_BONJOUR = true;
|
||||
|
||||
private boolean compactLayout = DEFAULT_COMPACT_LAYOUT;
|
||||
private boolean filterAppsRequiringRoot = DEFAULT_ROOTED;
|
||||
@ -53,6 +55,7 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
||||
private List<ChangeListener> compactLayoutListeners = new ArrayList<ChangeListener>();
|
||||
private List<ChangeListener> filterAppsRequiringRootListeners = new ArrayList<ChangeListener>();
|
||||
private List<ChangeListener> updateHistoryListeners = new ArrayList<ChangeListener>();
|
||||
private List<ChangeListener> localRepoBonjourListeners = new ArrayList<ChangeListener>();
|
||||
|
||||
private boolean isInitialized(String key) {
|
||||
return initialized.containsKey(key) && initialized.get(key);
|
||||
@ -74,6 +77,10 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
||||
return preferences.getBoolean(PREF_SYSTEM_INSTALLER, DEFAULT_SYSTEM_INSTALLER);
|
||||
}
|
||||
|
||||
public boolean isLocalRepoBonjourEnabled() {
|
||||
return preferences.getBoolean(PREF_LOCAL_REPO_BONJOUR, DEFAULT_LOCAL_REPO_BONJOUR);
|
||||
}
|
||||
|
||||
public boolean hasCompactLayout() {
|
||||
if (!isInitialized(PREF_COMPACT_LAYOUT)) {
|
||||
initialize(PREF_COMPACT_LAYOUT);
|
||||
@ -146,6 +153,10 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
||||
for ( ChangeListener listener : updateHistoryListeners ) {
|
||||
listener.onPreferenceChange();
|
||||
}
|
||||
} else if (key.equals(PREF_LOCAL_REPO_BONJOUR)) {
|
||||
for ( ChangeListener listener : localRepoBonjourListeners ) {
|
||||
listener.onPreferenceChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,6 +168,14 @@ public class Preferences implements SharedPreferences.OnSharedPreferenceChangeLi
|
||||
updateHistoryListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void registerLocalRepoBonjourListeners(ChangeListener listener) {
|
||||
localRepoBonjourListeners.add(listener);
|
||||
}
|
||||
|
||||
public void unregisterLocalRepoBonjourListeners(ChangeListener listener) {
|
||||
localRepoBonjourListeners.remove(listener);
|
||||
}
|
||||
|
||||
public static interface ChangeListener {
|
||||
public void onPreferenceChange();
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ public class PreferencesActivity extends PreferenceActivity implements
|
||||
Preferences.PREF_PERMISSIONS,
|
||||
Preferences.PREF_COMPACT_LAYOUT,
|
||||
Preferences.PREF_IGN_TOUCH,
|
||||
Preferences.PREF_LOCAL_REPO_BONJOUR,
|
||||
Preferences.PREF_CACHE_APK,
|
||||
Preferences.PREF_EXPERT,
|
||||
Preferences.PREF_ROOT_INSTALLER,
|
||||
@ -146,6 +147,10 @@ public class PreferencesActivity extends PreferenceActivity implements
|
||||
onoffSummary(key, R.string.ignoreTouch_on,
|
||||
R.string.ignoreTouch_off);
|
||||
|
||||
} else if (key.equals(Preferences.PREF_LOCAL_REPO_BONJOUR)) {
|
||||
onoffSummary(key, R.string.local_repo_bonjour_on,
|
||||
R.string.local_repo_bonjour_off);
|
||||
|
||||
} else if (key.equals(Preferences.PREF_CACHE_APK)) {
|
||||
onoffSummary(key, R.string.cache_downloaded_on,
|
||||
R.string.cache_downloaded_off);
|
||||
|
@ -2,26 +2,17 @@
|
||||
package org.fdroid.fdroid.localrepo;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.app.*;
|
||||
import android.content.*;
|
||||
import android.os.*;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.Preferences.ChangeListener;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.net.LocalHTTPD;
|
||||
import org.fdroid.fdroid.net.WifiStateChangeService;
|
||||
@ -29,8 +20,12 @@ import org.fdroid.fdroid.views.LocalRepoActivity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.BindException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.jmdns.JmDNS;
|
||||
import javax.jmdns.ServiceInfo;
|
||||
|
||||
public class LocalRepoService extends Service {
|
||||
private static final String TAG = "LocalRepoService";
|
||||
|
||||
@ -39,11 +34,15 @@ public class LocalRepoService extends Service {
|
||||
public static final String STOPPED = "org.fdroid.fdroid.category.LOCAL_REPO_STOPPED";
|
||||
|
||||
private NotificationManager notificationManager;
|
||||
private Notification notification;
|
||||
// Unique Identification Number for the Notification.
|
||||
// We use it on Notification start, and to cancel it.
|
||||
private int NOTIFICATION = R.string.local_repo_running;
|
||||
|
||||
private Handler webServerThreadHandler = null;
|
||||
private LocalHTTPD localHttpd;
|
||||
private JmDNS jmdns;
|
||||
private ServiceInfo pairService;
|
||||
|
||||
public static int START = 1111111;
|
||||
public static int STOP = 12345678;
|
||||
@ -61,12 +60,12 @@ public class LocalRepoService extends Service {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (msg.arg1 == START) {
|
||||
service.startWebServer();
|
||||
service.startNetworkServices();
|
||||
} else if (msg.arg1 == STOP) {
|
||||
service.stopWebServer();
|
||||
service.stopNetworkServices();
|
||||
} else if (msg.arg1 == RESTART) {
|
||||
service.stopWebServer();
|
||||
service.startWebServer();
|
||||
service.stopNetworkServices();
|
||||
service.startNetworkServices();
|
||||
} else {
|
||||
Log.e(TAG, "unsupported msg.arg1, ignored");
|
||||
}
|
||||
@ -76,8 +75,19 @@ public class LocalRepoService extends Service {
|
||||
private BroadcastReceiver onWifiChange = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent i) {
|
||||
stopWebServer();
|
||||
startWebServer();
|
||||
stopNetworkServices();
|
||||
startNetworkServices();
|
||||
}
|
||||
};
|
||||
|
||||
private ChangeListener localRepoBonjourChangeListener = new ChangeListener() {
|
||||
@Override
|
||||
public void onPreferenceChange() {
|
||||
if (localHttpd.isAlive())
|
||||
if (Preferences.get().isLocalRepoBonjourEnabled())
|
||||
registerMDNSService();
|
||||
else
|
||||
unregisterMDNSService();
|
||||
}
|
||||
};
|
||||
|
||||
@ -88,14 +98,16 @@ public class LocalRepoService extends Service {
|
||||
Intent intent = new Intent(this, LocalRepoActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
|
||||
Notification notification = new NotificationCompat.Builder(this)
|
||||
notification = new NotificationCompat.Builder(this)
|
||||
.setContentTitle(getText(R.string.local_repo_running))
|
||||
.setContentText(getText(R.string.touch_to_configure_local_repo))
|
||||
.setSmallIcon(android.R.drawable.ic_dialog_info)
|
||||
.setContentIntent(contentIntent)
|
||||
.build();
|
||||
startForeground(NOTIFICATION, notification);
|
||||
startWebServer();
|
||||
startNetworkServices();
|
||||
Preferences.get().registerLocalRepoBonjourListeners(localRepoBonjourChangeListener);
|
||||
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(onWifiChange,
|
||||
new IntentFilter(WifiStateChangeService.BROADCAST));
|
||||
}
|
||||
@ -109,9 +121,10 @@ public class LocalRepoService extends Service {
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
stopWebServer();
|
||||
stopNetworkServices();
|
||||
notificationManager.cancel(NOTIFICATION);
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(onWifiChange);
|
||||
Preferences.get().unregisterLocalRepoBonjourListeners(localRepoBonjourChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -119,6 +132,17 @@ public class LocalRepoService extends Service {
|
||||
return messenger.getBinder();
|
||||
}
|
||||
|
||||
private void startNetworkServices() {
|
||||
startWebServer();
|
||||
if (Preferences.get().isLocalRepoBonjourEnabled())
|
||||
registerMDNSService();
|
||||
}
|
||||
|
||||
private void stopNetworkServices() {
|
||||
unregisterMDNSService();
|
||||
stopWebServer();
|
||||
}
|
||||
|
||||
private void startWebServer() {
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
@ -127,7 +151,7 @@ public class LocalRepoService extends Service {
|
||||
@SuppressLint("HandlerLeak")
|
||||
@Override
|
||||
public void run() {
|
||||
final LocalHTTPD localHttpd = new LocalHTTPD(getFilesDir(),
|
||||
localHttpd = new LocalHTTPD(getFilesDir(),
|
||||
prefs.getBoolean("use_https", false));
|
||||
|
||||
Looper.prepare(); // must be run before creating a Handler
|
||||
@ -169,4 +193,46 @@ public class LocalRepoService extends Service {
|
||||
intent.putExtra(STATE, STOPPED);
|
||||
LocalBroadcastManager.getInstance(LocalRepoService.this).sendBroadcast(intent);
|
||||
}
|
||||
|
||||
private void registerMDNSService() {
|
||||
final HashMap<String, String> values = new HashMap<String, String>();
|
||||
values.put("path", "/fdroid/repo");
|
||||
values.put("name", FDroidApp.repo.name);
|
||||
// TODO set type based on "use HTTPS" pref
|
||||
// values.put("fingerprint", FDroidApp.repo.fingerprint);
|
||||
values.put("type", "fdroidrepo");
|
||||
pairService = ServiceInfo.create("_http._tcp.local.",
|
||||
FDroidApp.repo.name, FDroidApp.port, 0, 0, values);
|
||||
new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
jmdns = JmDNS.create();
|
||||
jmdns.registerService(pairService);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void unregisterMDNSService() {
|
||||
if (localRepoBonjourChangeListener != null) {
|
||||
Preferences.get().unregisterLocalRepoBonjourListeners(localRepoBonjourChangeListener);
|
||||
localRepoBonjourChangeListener = null;
|
||||
}
|
||||
if (jmdns != null) {
|
||||
if (pairService != null)
|
||||
jmdns.unregisterService(pairService);
|
||||
pairService = null;
|
||||
jmdns.unregisterAllServices();
|
||||
try {
|
||||
jmdns.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
jmdns = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user