diff --git a/F-Droid/res/menu/manage_repos.xml b/F-Droid/res/menu/manage_repos.xml index ef440e3dc..be6c8b271 100644 --- a/F-Droid/res/menu/manage_repos.xml +++ b/F-Droid/res/menu/manage_repos.xml @@ -12,9 +12,5 @@ android:icon="@drawable/ic_add_white" android:title="@string/menu_add_repo" app:showAsAction="always|withText"/> - \ No newline at end of file diff --git a/F-Droid/res/values/strings.xml b/F-Droid/res/values/strings.xml index 75fb2cb77..8231a9e7a 100644 --- a/F-Droid/res/values/strings.xml +++ b/F-Droid/res/values/strings.xml @@ -113,7 +113,6 @@ Search New Repository Remove Repository - Find Local Repos Run Share diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapManager.java b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapManager.java index cf4067415..0c2479cf3 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapManager.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapManager.java @@ -12,8 +12,13 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; +import org.fdroid.fdroid.localrepo.peers.Peer; +import org.fdroid.fdroid.localrepo.peers.PeerFinder; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -43,9 +48,13 @@ public class SwapManager { @NonNull private Set appsToSwap; + @NonNull + private Collection peers; + private SwapManager(@NonNull Context context, @NonNull Set appsToSwap) { this.context = context.getApplicationContext(); this.appsToSwap = appsToSwap; + this.peers = new ArrayList<>(); setupService(); } @@ -60,6 +69,32 @@ public class SwapManager { return context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_APPEND); } + // ========================================================== + // Search for peers to swap + // ========================================================== + + public void scanForPeers() { + if (service != null) { + Log.d(TAG, "Scanning for nearby devices to swap with..."); + service.scanForPeers(); + } else { + Log.e(TAG, "Couldn't scan for peers, because service was not running."); + } + } + + public void cancelScanningForPeers() { + if (service != null) { + service.cancelScanningForPeers(); + } else { + Log.e(TAG, "Couldn't cancel scanning for peers, because service was not running."); + } + } + + public void onPeerFound(Peer peer) { + peers.add(peer); + } + + // ========================================================== // Manage the current step // ("Step" refers to the current view being shown in the UI) diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java index d41ec66e5..8d504ea6e 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java @@ -16,6 +16,12 @@ import android.util.Log; import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.R; +import org.fdroid.fdroid.localrepo.peers.BluetoothFinder; +import org.fdroid.fdroid.localrepo.peers.BluetoothPeer; +import org.fdroid.fdroid.localrepo.peers.BonjourFinder; +import org.fdroid.fdroid.localrepo.peers.BonjourPeer; +import org.fdroid.fdroid.localrepo.peers.Peer; +import org.fdroid.fdroid.localrepo.peers.PeerFinder; import org.fdroid.fdroid.localrepo.type.BonjourType; import org.fdroid.fdroid.localrepo.type.NfcType; import org.fdroid.fdroid.localrepo.type.WebServerType; @@ -42,6 +48,10 @@ public class SwapService extends Service { private final BonjourType bonjourType; private final WebServerType webServerType; + private final BonjourFinder bonjourFinder; + private final BluetoothFinder bluetoothFinder; + + // TODO: The NFC type can't really be managed by the service, because it is intrinsically tied // to a specific _Activity_, and will only be active while that activity is shown. This service // knows nothing about activities. @@ -65,6 +75,22 @@ public class SwapService extends Service { nfcType = new NfcType(this); bonjourType = new BonjourType(this); webServerType = new WebServerType(this); + + bonjourFinder = new BonjourFinder(this); + bluetoothFinder = new BluetoothFinder(this); + + bonjourFinder.setListener(new PeerFinder.Listener() { + @Override + public void onPeerFound(BonjourPeer peer) { + SwapManager.load(SwapService.this).onPeerFound(peer); + } + }); + bluetoothFinder.setListener(new PeerFinder.Listener() { + @Override + public void onPeerFound(BluetoothPeer peer) { + SwapManager.load(SwapService.this).onPeerFound(peer); + } + }); } public void onCreate() { @@ -104,6 +130,20 @@ public class SwapService extends Service { .build(); } + public void scanForPeers() { + bonjourFinder.scan(); + bluetoothFinder.scan(); + } + + public void cancelScanningForPeers() { + bonjourFinder.cancel(); + bluetoothFinder.cancel(); + } + + public void onPeerFound(Peer peer) { + SwapManager.load(this).onPeerFound(peer); + } + private boolean enabled = false; /** diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothFinder.java b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothFinder.java new file mode 100644 index 000000000..663a9363c --- /dev/null +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothFinder.java @@ -0,0 +1,21 @@ +package org.fdroid.fdroid.localrepo.peers; + +import android.content.Context; + +// TODO: Still to be implemented +public class BluetoothFinder extends PeerFinder { + + private static final String TAG = "BluetoothFinder"; + + public BluetoothFinder(Context context) { + } + + @Override + public void scan() { + } + + @Override + public void cancel() { + } + +} diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothPeer.java b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothPeer.java new file mode 100644 index 000000000..90dfd801a --- /dev/null +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothPeer.java @@ -0,0 +1,24 @@ +package org.fdroid.fdroid.localrepo.peers; + +import android.bluetooth.BluetoothDevice; + +// TODO: Still to be implemented. +public class BluetoothPeer implements Peer { + + private BluetoothDevice device; + + public BluetoothPeer(BluetoothDevice device) { + this.device = device; + } + + @Override + public String getName() { + return "Bluetooth: " + device.getName(); + } + + @Override + public int getIcon() { + return android.R.drawable.stat_sys_data_bluetooth; + } + +} diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BonjourFinder.java b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BonjourFinder.java new file mode 100644 index 000000000..a964ddc1f --- /dev/null +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BonjourFinder.java @@ -0,0 +1,114 @@ +package org.fdroid.fdroid.localrepo.peers; + +import android.content.Context; +import android.net.wifi.WifiManager; +import android.os.AsyncTask; +import android.util.Log; + +import java.io.IOException; +import java.net.InetAddress; + +import javax.jmdns.JmDNS; +import javax.jmdns.ServiceEvent; +import javax.jmdns.ServiceInfo; +import javax.jmdns.ServiceListener; + +public class BonjourFinder extends PeerFinder implements ServiceListener { + + private static final String TAG = "BonjourFinder"; + + public static final String HTTP_SERVICE_TYPE = "_http._tcp.local."; + public static final String HTTPS_SERVICE_TYPE = "_https._tcp.local."; + + private final Context context; + private JmDNS mJmdns; + private WifiManager wifiManager; + private WifiManager.MulticastLock mMulticastLock; + + public BonjourFinder(Context context) { + this.context = context; + } + + @Override + public void scan() { + + if (wifiManager == null) { + wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + mMulticastLock = wifiManager.createMulticastLock(context.getPackageName()); + mMulticastLock.setReferenceCounted(false); + } + + mMulticastLock.acquire(); + new AsyncTask() { + + @Override + protected Void doInBackground(Void... params) { + try { + int ip = wifiManager.getConnectionInfo().getIpAddress(); + byte[] byteIp = { + (byte) (ip & 0xff), + (byte) (ip >> 8 & 0xff), + (byte) (ip >> 16 & 0xff), + (byte) (ip >> 24 & 0xff) + }; + Log.d(TAG, "Searching for mDNS clients..."); + mJmdns = JmDNS.create(InetAddress.getByAddress(byteIp)); + Log.d(TAG, "Finished searching for mDNS clients."); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + Log.d(TAG, "Cleaning up mDNS service listeners."); + if (mJmdns != null) { + mJmdns.addServiceListener(HTTP_SERVICE_TYPE, BonjourFinder.this); + mJmdns.addServiceListener(HTTPS_SERVICE_TYPE, BonjourFinder.this); + } + } + }.execute(); + + } + + @Override + public void serviceRemoved(ServiceEvent event) { + } + + @Override + public void serviceAdded(final ServiceEvent event) { + addFDroidService(event); + new AsyncTask() { + @Override + protected Void doInBackground(Void... params) { + mJmdns.requestServiceInfo(event.getType(), event.getName(), true); + return null; + } + }.execute(); + } + + @Override + public void serviceResolved(ServiceEvent event) { + addFDroidService(event); + } + + private void addFDroidService(ServiceEvent event) { + final ServiceInfo serviceInfo = event.getInfo(); + if (serviceInfo.getPropertyString("type").startsWith("fdroidrepo")) { + foundPeer(new BonjourPeer(serviceInfo)); + } + } + + @Override + public void cancel() { + mMulticastLock.release(); + if (mJmdns == null) + return; + mJmdns.removeServiceListener(HTTP_SERVICE_TYPE, this); + mJmdns.removeServiceListener(HTTPS_SERVICE_TYPE, this); + mJmdns = null; + + } + +} diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BonjourPeer.java b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BonjourPeer.java new file mode 100644 index 000000000..5c1f50472 --- /dev/null +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BonjourPeer.java @@ -0,0 +1,25 @@ +package org.fdroid.fdroid.localrepo.peers; + +import org.fdroid.fdroid.R; + +import javax.jmdns.ServiceInfo; + +public class BonjourPeer implements Peer { + + private ServiceInfo serviceInfo; + + public BonjourPeer(ServiceInfo serviceInfo) { + this.serviceInfo = serviceInfo; + } + + @Override + public String getName() { + return "Bonjour: " + serviceInfo.getName(); + } + + @Override + public int getIcon() { + return R.drawable.wifi; + } + +} diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/peers/Peer.java b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/Peer.java new file mode 100644 index 000000000..9969888cf --- /dev/null +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/Peer.java @@ -0,0 +1,11 @@ +package org.fdroid.fdroid.localrepo.peers; + +import android.support.annotation.DrawableRes; + +public interface Peer { + + String getName(); + + @DrawableRes int getIcon(); + +} diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/peers/PeerFinder.java b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/PeerFinder.java new file mode 100644 index 000000000..1342c7f18 --- /dev/null +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/PeerFinder.java @@ -0,0 +1,41 @@ +package org.fdroid.fdroid.localrepo.peers; + +import android.content.Intent; +import android.util.Log; + +/** + * Searches for other devices in the vicinity, using specific technologies. + * Once found, alerts a listener through the + * {@link org.fdroid.fdroid.localrepo.peers.PeerFinder.Listener#onPeerFound(Object)} + * method. Note that this could have instead been done with {@link android.content.Context#sendBroadcast(Intent)} + * and {@link android.content.BroadcastReceiver}, but that would require making the {@link Peer}s + * {@link android.os.Parcelable}, which is difficult. The main reason it is difficult is because + * they encapsulate information about network connectivity, such as {@link android.bluetooth.BluetoothDevice} + * and {@link javax.jmdns.ServiceInfo}, which may be difficult to serialize and reconstruct again. + */ +public abstract class PeerFinder { + + private static final String TAG = "PeerFinder"; + + private Listener listener; + + public abstract void scan(); + public abstract void cancel(); + + protected void foundPeer(T peer) { + Log.i(TAG, "Found peer " + peer.getName()); + if (listener != null) { + listener.onPeerFound(peer); + } + } + + public void setListener(Listener listener) { + this.listener = listener; + } + + public interface Listener { + void onPeerFound(T peer); + // TODO: What about peers removed, e.g. as with jmdns ServiceListener#serviceRemoved() + } + +} diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/type/BonjourType.java b/F-Droid/src/org/fdroid/fdroid/localrepo/type/BonjourType.java index 4c4a87bed..0d4a2aee7 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/type/BonjourType.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/type/BonjourType.java @@ -15,7 +15,7 @@ import javax.jmdns.ServiceInfo; public class BonjourType implements SwapType { - private static final String TAG = "BonjourType"; + private static final String TAG = "BonjourBroadcastType"; private JmDNS jmdns; private ServiceInfo pairService; diff --git a/F-Droid/src/org/fdroid/fdroid/net/MDnsHelper.java b/F-Droid/src/org/fdroid/fdroid/net/MDnsHelper.java deleted file mode 100644 index 43b8205df..000000000 --- a/F-Droid/src/org/fdroid/fdroid/net/MDnsHelper.java +++ /dev/null @@ -1,270 +0,0 @@ -package org.fdroid.fdroid.net; - -import android.app.Activity; -import android.content.Context; -import android.net.wifi.WifiManager; -import android.net.wifi.WifiManager.MulticastLock; -import android.os.AsyncTask; -import android.os.Handler; -import android.os.Looper; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import org.fdroid.fdroid.R; - -import java.io.IOException; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.List; - -import javax.jmdns.JmDNS; -import javax.jmdns.ServiceEvent; -import javax.jmdns.ServiceInfo; -import javax.jmdns.ServiceListener; - -public class MDnsHelper implements ServiceListener { - - private static final String TAG = "MDnsHelper"; - public static final String HTTP_SERVICE_TYPE = "_http._tcp.local."; - public static final String HTTPS_SERVICE_TYPE = "_https._tcp.local."; - - final Activity mActivity; - final RepoScanListAdapter mAdapter; - - private JmDNS mJmdns; - private final WifiManager wifiManager; - private final MulticastLock mMulticastLock; - - public MDnsHelper(Activity activity, final RepoScanListAdapter adapter) { - mActivity = activity; - mAdapter = adapter; - wifiManager = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE); - mMulticastLock = wifiManager.createMulticastLock(activity.getPackageName()); - mMulticastLock.setReferenceCounted(false); - } - - @Override - public void serviceRemoved(ServiceEvent event) { - // a ListView Adapter can only be updated on the UI thread - final ServiceInfo serviceInfo = event.getInfo(); - mActivity.runOnUiThread(new Runnable() { - @Override - public void run() { - mAdapter.removeItem(serviceInfo); - } - }); - } - - @Override - public void serviceAdded(final ServiceEvent event) { - addFDroidService(event); - new AsyncTask() { - @Override - protected Void doInBackground(Void... params) { - mJmdns.requestServiceInfo(event.getType(), event.getName(), true); - return null; - } - }.execute(); - } - - @Override - public void serviceResolved(ServiceEvent event) { - addFDroidService(event); - } - - private void addFDroidService(ServiceEvent event) { - // a ListView Adapter can only be updated on the UI thread - final ServiceInfo serviceInfo = event.getInfo(); - String type = serviceInfo.getPropertyString("type"); - if (type.startsWith("fdroidrepo")) - mActivity.runOnUiThread(new Runnable() { - @Override - public void run() { - mAdapter.addItem(serviceInfo); - } - }); - } - - public void discoverServices() { - mMulticastLock.acquire(); - new AsyncTask() { - - @Override - protected Void doInBackground(Void... params) { - try { - int ip = wifiManager.getConnectionInfo().getIpAddress(); - byte[] byteIp = { - (byte) (ip & 0xff), - (byte) (ip >> 8 & 0xff), - (byte) (ip >> 16 & 0xff), - (byte) (ip >> 24 & 0xff) - }; - mJmdns = JmDNS.create(InetAddress.getByAddress(byteIp)); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - @Override - protected void onPostExecute(Void result) { - if (mJmdns != null) { - mJmdns.addServiceListener(HTTP_SERVICE_TYPE, MDnsHelper.this); - mJmdns.addServiceListener(HTTPS_SERVICE_TYPE, MDnsHelper.this); - } - } - }.execute(); - } - - public void stopDiscovery() { - mMulticastLock.release(); - if (mJmdns == null) - return; - mJmdns.removeServiceListener(HTTP_SERVICE_TYPE, MDnsHelper.this); - mJmdns.removeServiceListener(HTTPS_SERVICE_TYPE, MDnsHelper.this); - mJmdns = null; - } - - public static class RepoScanListAdapter extends BaseAdapter { - private final Context mContext; - private final LayoutInflater mLayoutInflater; - private final List mEntries = new ArrayList<>(); - - public RepoScanListAdapter(Context context) { - mContext = context; - mLayoutInflater = (LayoutInflater) mContext - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - } - - @Override - public int getCount() { - return mEntries.size(); - } - - @Override - public Object getItem(int position) { - return mEntries.get(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public boolean isEnabled(int position) { - DiscoveredRepo service = mEntries.get(position); - ServiceInfo serviceInfo = service.getServiceInfo(); - InetAddress[] addresses = serviceInfo.getInetAddresses(); - return (addresses != null && addresses.length > 0); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - RelativeLayout itemView; - if (convertView == null) { - itemView = (RelativeLayout) mLayoutInflater.inflate( - R.layout.repodiscoveryitem, parent, false); - } else { - itemView = (RelativeLayout) convertView; - } - - TextView nameLabel = (TextView) itemView.findViewById(R.id.reposcanitemname); - TextView addressLabel = (TextView) itemView.findViewById(R.id.reposcanitemaddress); - - final DiscoveredRepo service = mEntries.get(position); - final ServiceInfo serviceInfo = service.getServiceInfo(); - - nameLabel.setText(serviceInfo.getName()); - - InetAddress[] addresses = serviceInfo.getInetAddresses(); - if (addresses != null && addresses.length > 0) { - String addressTxt = "Hosted @ " + addresses[0] + ":" + serviceInfo.getPort(); - addressLabel.setText(addressTxt); - } - - return itemView; - } - - public void addItem(ServiceInfo item) { - if (item == null || item.getName() == null) - return; - - // Construct a DiscoveredRepo wrapper for the service being - // added in order to use a name based equals(). - DiscoveredRepo newDRepo = new DiscoveredRepo(item); - // if an unresolved entry with the same name exists, remove it - for (DiscoveredRepo dr : mEntries) - if (dr.equals(newDRepo)) { - InetAddress[] addresses = dr.mServiceInfo.getInetAddresses(); - if (addresses == null || addresses.length == 0) - mEntries.remove(dr); - } - mEntries.add(newDRepo); - - notifyUpdate(); - } - - public void removeItem(ServiceInfo item) { - if (item == null || item.getName() == null) - return; - - // Construct a DiscoveredRepo wrapper for the service being - // removed in order to use a name based equals(). - DiscoveredRepo lostServiceBean = new DiscoveredRepo(item); - - if (mEntries.contains(lostServiceBean)) { - mEntries.remove(lostServiceBean); - notifyUpdate(); - } - } - - private void notifyUpdate() { - // Need to call notifyDataSetChanged from the UI thread - // in order for it to update the ListView without error - Handler refresh = new Handler(Looper.getMainLooper()); - refresh.post(new Runnable() { - @Override - public void run() { - notifyDataSetChanged(); - } - }); - } - } - - public static class DiscoveredRepo { - private final ServiceInfo mServiceInfo; - - public DiscoveredRepo(ServiceInfo serviceInfo) { - if (serviceInfo == null || serviceInfo.getName() == null) - throw new IllegalArgumentException( - "Parameters \"serviceInfo\" and \"name\" must not be null."); - mServiceInfo = serviceInfo; - } - - public ServiceInfo getServiceInfo() { - return mServiceInfo; - } - - public String getName() { - return mServiceInfo.getName(); - } - - @Override - public boolean equals(Object other) { - if (!(other instanceof DiscoveredRepo)) - return false; - - // Treat two services the same based on name. Eventually - // there should be a persistent mapping between fingerprint - // of the repo key and the discovered service such that we - // could maintain trust across hostnames/ips/networks - DiscoveredRepo otherRepo = (DiscoveredRepo) other; - return getName().equals(otherRepo.getName()); - } - } -} diff --git a/F-Droid/src/org/fdroid/fdroid/views/ManageReposActivity.java b/F-Droid/src/org/fdroid/fdroid/views/ManageReposActivity.java index efc938962..4c2407c55 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/ManageReposActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/ManageReposActivity.java @@ -71,9 +71,6 @@ import org.fdroid.fdroid.compat.ClipboardCompat; import org.fdroid.fdroid.data.NewRepoConfig; import org.fdroid.fdroid.data.Repo; import org.fdroid.fdroid.data.RepoProvider; -import org.fdroid.fdroid.net.MDnsHelper; -import org.fdroid.fdroid.net.MDnsHelper.DiscoveredRepo; -import org.fdroid.fdroid.net.MDnsHelper.RepoScanListAdapter; import org.fdroid.fdroid.views.fragments.RepoDetailsFragment; import java.io.IOException; @@ -84,8 +81,6 @@ import java.net.URL; import java.util.Date; import java.util.Locale; -import javax.jmdns.ServiceInfo; - public class ManageReposActivity extends ActionBarActivity { /** @@ -212,9 +207,6 @@ public class ManageReposActivity extends ActionBarActivity { case R.id.action_update_repo: updateRepos(); return true; - case R.id.action_find_local_repos: - scanForRepos(); - return true; } return super.onOptionsItemSelected(item); } @@ -239,55 +231,6 @@ public class ManageReposActivity extends ActionBarActivity { }); } - private void scanForRepos() { - final RepoScanListAdapter adapter = new RepoScanListAdapter(this); - final MDnsHelper mDnsHelper = new MDnsHelper(this, adapter); - - final View view = getLayoutInflater().inflate(R.layout.repodiscoverylist, null); - final ListView repoScanList = (ListView) view.findViewById(R.id.reposcanlist); - - final AlertDialog alrt = new AlertDialog.Builder(this).setView(view) - .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mDnsHelper.stopDiscovery(); - dialog.dismiss(); - } - }).create(); - - alrt.setTitle(R.string.local_repos_title); - alrt.setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - mDnsHelper.stopDiscovery(); - } - }); - - repoScanList.setAdapter(adapter); - repoScanList.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, final View view, - int position, long id) { - - final DiscoveredRepo discoveredService = - (DiscoveredRepo) parent.getItemAtPosition(position); - - final ServiceInfo serviceInfo = discoveredService.getServiceInfo(); - String type = serviceInfo.getPropertyString("type"); - String protocol = type.contains("fdroidrepos") ? "https:/" : "http:/"; - String path = serviceInfo.getPropertyString("path"); - if (TextUtils.isEmpty(path)) - path = "/fdroid/repo"; - String serviceUrl = protocol + serviceInfo.getInetAddresses()[0] - + ":" + serviceInfo.getPort() + path; - showAddRepo(serviceUrl, serviceInfo.getPropertyString("fingerprint")); - } - }); - - alrt.show(); - mDnsHelper.discoverServices(); - } - private void showAddRepo() { /* * If there is text in the clipboard, and it looks like a URL, use that. 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 f77c986eb..831e5ffa4 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java @@ -165,6 +165,7 @@ public class SwapWorkflowActivity extends ActionBarActivity { } private void showIntro() { + SwapManager.load(this).scanForPeers(); inflateInnerView(R.layout.swap_blank); }