From c831cf77ccf9ecfa792d0ffdc84f272053fa945a Mon Sep 17 00:00:00 2001 From: n8fr8 Date: Thu, 10 Sep 2015 04:23:58 -0400 Subject: [PATCH 1/7] Many changes to swap workflow to get Bluetooth to work - don't try to start BT in the background. you can only start/stop a BT server once, else new connections don't work - be more mindful of reading/writing bytes from the input/output streams... make sure bytes are available, because you will block forever if you do not do that - use the device class tag to filter devices in discovery instead of the fdroid name tag - this now successfully connects but there is an error in the certificate fingerprint verification still --- F-Droid/src/org/fdroid/fdroid/data/App.java | 2 +- .../fdroid/localrepo/LocalRepoManager.java | 7 +- .../fdroid/fdroid/localrepo/SwapService.java | 9 ++- .../localrepo/peers/BluetoothFinder.java | 11 ++- .../fdroid/localrepo/type/BluetoothSwap.java | 54 +++++++++----- .../fdroid/localrepo/type/SwapType.java | 4 +- .../fdroid/net/BluetoothDownloader.java | 10 ++- .../src/org/fdroid/fdroid/net/Downloader.java | 26 +++++-- .../org/fdroid/fdroid/net/HttpDownloader.java | 14 +++- .../fdroid/net/bluetooth/BluetoothClient.java | 2 + .../net/bluetooth/BluetoothConnection.java | 6 +- .../net/bluetooth/BluetoothConstants.java | 2 + .../fdroid/net/bluetooth/BluetoothServer.java | 4 +- .../fdroid/net/bluetooth/httpish/Request.java | 71 ++++++++++++++----- .../views/swap/SwapWorkflowActivity.java | 2 +- 15 files changed, 171 insertions(+), 53 deletions(-) diff --git a/F-Droid/src/org/fdroid/fdroid/data/App.java b/F-Droid/src/org/fdroid/fdroid/data/App.java index d759ece7d..f7d9261e4 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/App.java +++ b/F-Droid/src/org/fdroid/fdroid/data/App.java @@ -241,7 +241,7 @@ public class App extends ValueObject implements Comparable { PackageManager.GET_META_DATA); installerPackageLabel = installerAppInfo.loadLabel(pm); } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Could not get app info", e); + Log.w(TAG, "Could not get app info: " + installerPackageName); } } if (TextUtils.isEmpty(installerPackageLabel)) diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/LocalRepoManager.java b/F-Droid/src/org/fdroid/fdroid/localrepo/LocalRepoManager.java index c23278e83..7af43940d 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/LocalRepoManager.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/LocalRepoManager.java @@ -486,8 +486,12 @@ public class LocalRepoManager { } public void writeIndexJar() throws IOException { + + FileWriter writer; + try { - new IndexXmlBuilder(context, apps).build(xmlIndex); + writer = new FileWriter(xmlIndex); + new IndexXmlBuilder(context, apps).build(writer); } catch (Exception e) { Log.e(TAG, "Could not write index jar", e); Toast.makeText(context, R.string.failed_to_create_index, Toast.LENGTH_LONG).show(); @@ -512,6 +516,7 @@ public class LocalRepoManager { bi.close(); jo.close(); bo.close(); + writer.close(); try { LocalRepoKeyStore.get(context).signZip(xmlIndexJarUnsigned, xmlIndexJar); diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java index b5aa52b27..0be6ac6ea 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java @@ -108,13 +108,17 @@ public class SwapService extends Service { public void scanForPeers() { Log.d(TAG, "Scanning for nearby devices to swap with..."); + bonjourFinder.scan(); bluetoothFinder.scan(); + } public void stopScanningForPeers() { + bonjourFinder.cancel(); bluetoothFinder.cancel(); + } @@ -530,10 +534,11 @@ public class SwapService extends Service { filter.addAction(WIFI_STATE_CHANGE); LocalBroadcastManager.getInstance(this).registerReceiver(receiveSwapStatusChanged, filter); + /** if (wasBluetoothEnabled()) { Log.d(TAG, "Previously the user enabled Bluetooth swap, so enabling again automatically."); bluetoothSwap.startInBackground(); - } + }*/ if (wasWifiEnabled()) { Log.d(TAG, "Previously the user enabled Wifi swap, so enabling again automatically."); @@ -574,7 +579,7 @@ public class SwapService extends Service { public void disableAllSwapping() { Log.i(TAG, "Asked to stop swapping, will stop bluetooth, wifi, and move service to BG for GC."); - getBluetoothSwap().stopInBackground(); + // getBluetoothSwap().stopInBackground(); getWifiSwap().stopInBackground(); // Ensure the user is sent back go the first screen when returning if we have just forceably 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 fc74cd245..2bc86a8bd 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothFinder.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothFinder.java @@ -1,6 +1,7 @@ package org.fdroid.fdroid.localrepo.peers; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; @@ -92,9 +93,17 @@ public class BluetoothFinder extends PeerFinder { } private void onDeviceFound(BluetoothDevice device) { - if (device != null && device.getName() != null && device.getName().startsWith(BluetoothSwap.BLUETOOTH_NAME_TAG)) { + + if(device != null && device.getName() != null && + (device.getBluetoothClass().getDeviceClass() == BluetoothClass.Device.COMPUTER_HANDHELD_PC_PDA|| + device.getBluetoothClass().getDeviceClass() == BluetoothClass.Device.COMPUTER_PALM_SIZE_PC_PDA|| + device.getBluetoothClass().getDeviceClass() == BluetoothClass.Device.PHONE_SMART)) + { foundPeer(new BluetoothPeer(device)); } + // if (device != null && device.getName() != null && device.getName().startsWith(BluetoothSwap.BLUETOOTH_NAME_TAG)) { + // foundPeer(new BluetoothPeer(device)); + // } } } 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 10dab0ea8..333fca470 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/type/BluetoothSwap.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/type/BluetoothSwap.java @@ -5,6 +5,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.os.AsyncTask; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; @@ -17,8 +18,11 @@ public class BluetoothSwap extends SwapType { private static final String TAG = "BluetoothBroadcastType"; public final static String BLUETOOTH_NAME_TAG = "FDroid:"; + private static BluetoothSwap mInstance = null; + @NonNull private final BluetoothAdapter adapter; + private BroadcastReceiver receiver; @Nullable private BluetoothServer server; @@ -30,7 +34,10 @@ public class BluetoothSwap extends SwapType { if (adapter == null) { return new NoBluetoothType(context); } else { - return new BluetoothSwap(context, adapter); + if (mInstance == null) + mInstance = new BluetoothSwap(context, adapter); + + return mInstance; } } @@ -38,7 +45,21 @@ public class BluetoothSwap extends SwapType { super(context); this.adapter = adapter; - context.registerReceiver(new BroadcastReceiver() { + + } + + @Override + public boolean isConnected() { + return server != null && server.isRunning() && super.isConnected(); + } + + @Override + public synchronized void start() { + + if (isConnected()) + return; + + receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { switch (intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, -1)) { @@ -55,29 +76,25 @@ public class BluetoothSwap extends SwapType { // Only other is BluetoothAdapter.SCAN_MODE_CONNECTABLE. For now don't handle that. } } - }, new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)); - } + }; + context.registerReceiver(receiver, new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)); - @Override - public boolean isConnected() { - return server != null && server.isRunning() && super.isConnected(); - } - - @Override - public void start() { + /* if (server != null) { Log.d(TAG, "Attempting to start Bluetooth swap, but it appears to be running already. Will cancel it so it can be restarted."); server.close(); server = null; - } + }*/ - server = new BluetoothServer(this, context.getFilesDir()); + if (server == null) + server = new BluetoothServer(this, context.getFilesDir()); sendBroadcast(SwapService.EXTRA_STARTING); //store the original bluetoothname, and update this one to be unique deviceBluetoothName = adapter.getName(); + /* Log.d(TAG, "Prefixing Bluetooth adapter name with " + BLUETOOTH_NAME_TAG + " to make it identifiable as a swap device."); if (!deviceBluetoothName.startsWith(BLUETOOTH_NAME_TAG)) adapter.setName(BLUETOOTH_NAME_TAG + deviceBluetoothName); @@ -85,7 +102,7 @@ public class BluetoothSwap extends SwapType { if (!adapter.getName().startsWith(BLUETOOTH_NAME_TAG)) { Log.e(TAG, "Couldn't change the name of the Bluetooth adapter, it will not get recognized by other swap clients."); // TODO: Should we bail here? - } + }*/ if (!adapter.isEnabled()) { Log.d(TAG, "Bluetooth adapter is disabled, attempting to enable."); @@ -96,8 +113,8 @@ public class BluetoothSwap extends SwapType { } } - if (adapter.isEnabled()) { - server.start(); + if (adapter.isEnabled()) + { setConnected(true); } else { Log.i(TAG, "Didn't start Bluetooth swapping server, because Bluetooth is disabled and couldn't be enabled."); @@ -110,6 +127,11 @@ public class BluetoothSwap extends SwapType { if (server != null && server.isAlive()) { server.close(); setConnected(false); + + // if (receiver != null) { +// context.unregisterReceiver(receiver); + // receiver = null; + // } } else { Log.i(TAG, "Attempting to stop Bluetooth swap, but it is not currently running."); } 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 1e6f781a1..afb82b1a3 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/type/SwapType.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/type/SwapType.java @@ -64,13 +64,15 @@ public abstract class SwapType { } public void startInBackground() { + start(); + /** new AsyncTask() { @Override protected Void doInBackground(Void... params) { start(); return null; } - }.execute(); + }.execute();*/ } public void ensureRunning() { diff --git a/F-Droid/src/org/fdroid/fdroid/net/BluetoothDownloader.java b/F-Droid/src/org/fdroid/fdroid/net/BluetoothDownloader.java index b9d6e2e40..610a30ee4 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/BluetoothDownloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/BluetoothDownloader.java @@ -3,6 +3,7 @@ package org.fdroid.fdroid.net; import android.content.Context; import android.util.Log; import org.apache.commons.io.input.BoundedInputStream; +import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.net.bluetooth.BluetoothClient; import org.fdroid.fdroid.net.bluetooth.BluetoothConnection; import org.fdroid.fdroid.net.bluetooth.FileDetails; @@ -13,6 +14,8 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.nio.Buffer; +import java.io.BufferedReader; public class BluetoothDownloader extends Downloader { @@ -30,9 +33,11 @@ public class BluetoothDownloader extends Downloader { @Override public InputStream getInputStream() throws IOException { - Response response = Request.createGET(sourcePath, connection).send(); + Request request = Request.createGET(sourcePath, connection); + Response response = request.send(); fileDetails = response.toFileDetails(); + // TODO: Manage the dependency which includes this class better? // Right now, I only needed the one class from apache commons. // There are countless classes online which provide this functionality, @@ -76,7 +81,8 @@ public class BluetoothDownloader extends Downloader { @Override public void download() throws IOException, InterruptedException { - downloadFromStream(); + downloadFromStream(1024); + connection.closeQuietly(); } @Override diff --git a/F-Droid/src/org/fdroid/fdroid/net/Downloader.java b/F-Droid/src/org/fdroid/fdroid/net/Downloader.java index 90a4e4f05..ffe250669 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/Downloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/Downloader.java @@ -7,12 +7,15 @@ import android.util.Log; import org.fdroid.fdroid.Utils; +import java.io.BufferedInputStream; +import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.Reader; import java.net.MalformedURLException; import java.net.URL; @@ -98,7 +101,7 @@ public abstract class Downloader { public abstract boolean isCached(); - protected void downloadFromStream() throws IOException, InterruptedException { + protected void downloadFromStream(int bufferSize) throws IOException, InterruptedException { Utils.DebugLog(TAG, "Downloading from stream"); InputStream input = null; try { @@ -108,7 +111,7 @@ public abstract class Downloader { // we were interrupted before proceeding to the download. throwExceptionIfInterrupted(); - copyInputToOutputStream(input); + copyInputToOutputStream(input, bufferSize); } finally { Utils.closeQuietly(outputStream); Utils.closeQuietly(input); @@ -143,20 +146,30 @@ public abstract class Downloader { * keeping track of the number of bytes that have flowed through for the * progress counter. */ - protected void copyInputToOutputStream(InputStream input) throws IOException, InterruptedException { + protected void copyInputToOutputStream(InputStream input, int bufferSize) throws IOException, InterruptedException { - byte[] buffer = new byte[Utils.BUFFER_SIZE]; int bytesRead = 0; this.totalBytes = totalDownloadSize(); + byte[] buffer = new byte[bufferSize]; // Getting the total download size could potentially take time, depending on how // it is implemented, so we may as well check this before we proceed. throwExceptionIfInterrupted(); sendProgress(bytesRead, totalBytes); - while (true) { + while (bytesRead < totalBytes) { + + int count = -1; + + if (input.available()>0) { + + int readLength = Math.min(input.available(), buffer.length); + count = input.read(buffer, 0, readLength); + } + else { + count = input.read(buffer); + } - int count = input.read(buffer); throwExceptionIfInterrupted(); if (count == -1) { @@ -167,6 +180,7 @@ public abstract class Downloader { bytesRead += count; sendProgress(bytesRead, totalBytes); outputStream.write(buffer, 0, count); + } outputStream.flush(); } diff --git a/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java b/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java index 241a73cee..495827e6e 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java @@ -9,10 +9,13 @@ import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.Utils; +import java.io.BufferedInputStream; +import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.MalformedURLException; @@ -58,10 +61,15 @@ public class HttpDownloader extends Downloader { * same one twice, bail with an exception). * @throws IOException */ - @Override + public InputStream getInputStream() throws IOException { setupConnection(); - return connection.getInputStream(); + return new BufferedInputStream(connection.getInputStream()); + } + + public BufferedReader getBufferedReader () throws IOException + { + return new BufferedReader(new InputStreamReader(getInputStream())); } // Get a remote file. Returns the HTTP response code. @@ -117,7 +125,7 @@ public class HttpDownloader extends Downloader { Utils.DebugLog(TAG, sourceUrl + " is cached, so not downloading (HTTP " + statusCode + ")"); } else { Utils.DebugLog(TAG, "Downloading from " + sourceUrl); - downloadFromStream(); + downloadFromStream(4096); updateCacheCheck(); } } diff --git a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothClient.java b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothClient.java index b488f552e..831ed64f0 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothClient.java +++ b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothClient.java @@ -25,6 +25,8 @@ public class BluetoothClient { } public BluetoothConnection openConnection() throws IOException { + + BluetoothSocket socket = null; try { socket = device.createInsecureRfcommSocketToServiceRecord(BluetoothConstants.fdroidUuid()); diff --git a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConnection.java b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConnection.java index bc1d5bcf5..fec164087 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConnection.java +++ b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConnection.java @@ -7,6 +7,8 @@ import android.os.Build; import android.util.Log; import org.fdroid.fdroid.Utils; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -39,8 +41,8 @@ public class BluetoothConnection { socket.connect(); } - input = socket.getInputStream(); - output = socket.getOutputStream(); + input = new BufferedInputStream(socket.getInputStream()); + output = new BufferedOutputStream(socket.getOutputStream()); Log.d(TAG, "Opened connection to Bluetooth device"); } diff --git a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConstants.java b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConstants.java index 35d7024cf..5d38d71a0 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConstants.java +++ b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConstants.java @@ -13,6 +13,8 @@ public class BluetoothConstants { // want to do so. // This UUID is just from mashing random hex characters on the keyboard. return UUID.fromString("cd59ba31-5729-b3bb-cb29-732b59eb61aa"); + + } } 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 2379ceba6..a895dfd98 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothServer.java +++ b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothServer.java @@ -40,6 +40,8 @@ public class BluetoothServer extends Thread { public BluetoothServer(BluetoothSwap swap, File webRoot) { this.webRoot = webRoot; this.swap = swap; + + start(); } public boolean isRunning() { return isRunning; } @@ -81,7 +83,7 @@ public class BluetoothServer extends Thread { try { BluetoothSocket clientSocket = serverSocket.accept(); if (clientSocket != null) { - if (!isInterrupted()) { + if (isInterrupted()) { Log.d(TAG, "Server stopped after socket accepted from client, but before initiating connection."); break; } diff --git a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/httpish/Request.java b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/httpish/Request.java index afed47312..ec55f7591 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/httpish/Request.java +++ b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/httpish/Request.java @@ -5,9 +5,14 @@ import org.fdroid.fdroid.net.bluetooth.BluetoothConnection; import java.io.BufferedReader; import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -27,16 +32,16 @@ public class Request { private Map headers; private BluetoothConnection connection; - private BufferedWriter output; - private BufferedReader input; + private Writer output; + private InputStream input; private Request(String method, String path, BluetoothConnection connection) { this.method = method; this.path = path; this.connection = connection; - output = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream())); - input = new BufferedReader(new InputStreamReader(connection.getInputStream())); + output = new OutputStreamWriter(connection.getOutputStream()); + input = connection.getInputStream(); } public static Request createHEAD(String path, BluetoothConnection connection) @@ -93,7 +98,7 @@ public class Request { */ private boolean listen() throws IOException { - String requestLine = input.readLine(); + String requestLine = readLine(); if (requestLine == null || requestLine.trim().length() == 0) return false; @@ -125,11 +130,8 @@ public class Request { * a space, and then the status label (which may contain spaces). */ private int readResponseCode() throws IOException { - String line = input.readLine(); - if (line == null) { - // TODO: What to do? - return -1; - } + + String line = readLine(); // TODO: Error handling int firstSpace = line.indexOf(' '); @@ -139,6 +141,36 @@ public class Request { return Integer.parseInt(status); } + private String readLine () throws IOException + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + String line = null; + + while (line == null) { + + while (input.available()>0) { + + int b = input.read(); + + + if (((char)b) == '\n') { + if (baos.size() > 0) + line = new String(baos.toByteArray()); + + return line; + } + + baos.write(b); + + } + + try { Thread.sleep(100); } + catch (Exception e){}; + } + + return line; + } + /** * Subsequent lines (after the status line) represent the headers, which are case * insensitive and may be multi-line. We don't deal with multi-line headers in @@ -146,15 +178,22 @@ public class Request { */ private Map readHeaders() throws IOException { Map headers = new HashMap<>(); - String responseLine = input.readLine(); - while (responseLine != null && responseLine.length() > 0) { + String responseLine = readLine(); + while (responseLine != null) { // TODO: Error handling String[] parts = responseLine.split(":"); - String header = parts[0].trim(); - String value = parts[1].trim(); - headers.put(header, value); - responseLine = input.readLine(); + if (parts.length > 1) { + String header = parts[0].trim(); + String value = parts[1].trim(); + headers.put(header, value); + } + + if (input.available()>0) + responseLine = readLine(); + else + break; + } return headers; } 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 df2f96cdd..6b0cbca16 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java @@ -625,7 +625,7 @@ public class SwapWorkflowActivity extends AppCompatActivity { Log.d(TAG, "Not currently in discoverable mode, so prompting user to enable."); Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); - intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); // TODO: What about when this expires? What if user manually disables discovery? + intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 3600); // 3600 is new maximum! TODO: What about when this expires? What if user manually disables discovery? startActivityForResult(intent, REQUEST_BLUETOOTH_DISCOVERABLE); } From 0a96d17dd1052201c07ebb4322288643e66699fb Mon Sep 17 00:00:00 2001 From: n8fr8 Date: Thu, 10 Sep 2015 11:21:00 -0400 Subject: [PATCH 2/7] now handling empty repo fingerprint during check - also support icondownloading over bluetooth - also check for null repoUrl variable --- .../src/org/fdroid/fdroid/RepoUpdater.java | 2 +- .../org/fdroid/fdroid/net/IconDownloader.java | 22 ++++++++++++++----- .../fdroid/views/swap/SwapAppsView.java | 3 ++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java b/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java index 4ce038e6c..a3eb101d6 100644 --- a/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java +++ b/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java @@ -278,7 +278,7 @@ public class RepoUpdater { * actually in the index.jar itself. If no fingerprint, just store the * signing certificate */ boolean trustNewSigningCertificate = false; - if (repo.fingerprint == null) { + if (repo.fingerprint == null || repo.fingerprint.length() == 0) { // no info to check things are valid, so just Trust On First Use trustNewSigningCertificate = true; } else { diff --git a/F-Droid/src/org/fdroid/fdroid/net/IconDownloader.java b/F-Droid/src/org/fdroid/fdroid/net/IconDownloader.java index b90876df8..334ceb314 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/IconDownloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/IconDownloader.java @@ -19,13 +19,25 @@ public class IconDownloader extends BaseImageDownloader { @Override public InputStream getStream(String imageUri, Object extra) throws IOException { - switch (Scheme.ofUri(imageUri)) { - case HTTP: - case HTTPS: + + Scheme scheme = Scheme.ofUri(imageUri); + + switch (scheme) { + case HTTP: + case HTTPS: + Downloader downloader = DownloaderFactory.create(context, imageUri); + return downloader.getInputStream(); + } + + //bluetooth isn't a scheme in the Scheme. library, so we can add a check here + if (imageUri.toLowerCase().startsWith("bluetooth")) + { Downloader downloader = DownloaderFactory.create(context, imageUri); return downloader.getInputStream(); - default: - return super.getStream(imageUri, extra); } + + + return super.getStream(imageUri, extra); + } } diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppsView.java b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppsView.java index 63777cd4c..87a577d1b 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppsView.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppsView.java @@ -282,7 +282,8 @@ public class SwapAppsView extends ListView implements public void onReceive(Context context, Intent intent) { Apk apk = getApkToInstall(); String broadcastUrl = intent.getStringExtra(Downloader.EXTRA_ADDRESS); - if (!TextUtils.equals(Utils.getApkUrl(apk.repoAddress, apk), broadcastUrl)) { + + if (apk.repoAddress != null && (!TextUtils.equals(Utils.getApkUrl(apk.repoAddress, apk), broadcastUrl))) { return; } From b3f8ac0a5bfe1f75bc3d2dc1e413f2bdfcb0aaff Mon Sep 17 00:00:00 2001 From: n8fr8 Date: Thu, 10 Sep 2015 14:44:59 -0400 Subject: [PATCH 3/7] related to #404 improvement to patterns to support close and discoverable You must, must, must close the BT sockets else you run out of them. This code tries to handle all the places where BT sockets may not get closed. It also tries to tweak user experience/UI integration pieces in a few areas, and handle some NPEs that can occur when BT fails. --- .../src/org/fdroid/fdroid/RepoUpdater.java | 4 ++++ .../fdroid/fdroid/localrepo/SwapService.java | 2 +- .../localrepo/peers/BluetoothFinder.java | 2 ++ .../fdroid/localrepo/type/BluetoothSwap.java | 8 +++++++ .../fdroid/localrepo/type/SwapType.java | 5 +++++ .../fdroid/net/BluetoothDownloader.java | 8 +++++++ .../src/org/fdroid/fdroid/net/Downloader.java | 1 + .../org/fdroid/fdroid/net/HttpDownloader.java | 4 ++++ .../org/fdroid/fdroid/net/IconDownloader.java | 21 ++++++++++++++++++- .../fdroid/net/bluetooth/BluetoothClient.java | 13 ++++++++++-- .../net/bluetooth/BluetoothConnection.java | 8 +------ .../fdroid/net/bluetooth/BluetoothServer.java | 2 ++ .../fdroid/views/swap/SwapAppsView.java | 10 +++++++-- .../views/swap/SwapWorkflowActivity.java | 3 ++- 14 files changed, 77 insertions(+), 14 deletions(-) diff --git a/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java b/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java index a3eb101d6..3c4fe6219 100644 --- a/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java +++ b/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java @@ -98,7 +98,9 @@ public class RepoUpdater { } catch (IOException e) { if (downloader != null && downloader.getFile() != null) { downloader.getFile().delete(); + downloader.close(); } + throw new UpdateException(repo, "Error getting index file from " + repo.address, e); } return downloader; @@ -121,6 +123,8 @@ public class RepoUpdater { // successful download, then we will have a file ready to use: processDownloadedFile(downloader.getFile(), downloader.getCacheTag()); } + + downloader.close(); } protected void processDownloadedFile(File downloadedFile, String cacheTag) throws UpdateException { diff --git a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java index 0be6ac6ea..5b2072688 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/SwapService.java @@ -456,7 +456,7 @@ public class SwapService extends Service { } public boolean isBluetoothDiscoverable() { - return bluetoothSwap.isConnected(); + return bluetoothSwap.isDiscoverable(); } public boolean isBonjourDiscoverable() { 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 2bc86a8bd..bfb91127b 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothFinder.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/peers/BluetoothFinder.java @@ -15,6 +15,8 @@ public class BluetoothFinder extends PeerFinder { private static final String TAG = "BluetoothFinder"; + public final static int DISCOVERABLE_TIMEOUT = 3600; + private final BluetoothAdapter adapter; public BluetoothFinder(Context context) { 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 333fca470..c66531cf2 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/type/BluetoothSwap.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/type/BluetoothSwap.java @@ -23,6 +23,7 @@ public class BluetoothSwap extends SwapType { @NonNull private final BluetoothAdapter adapter; private BroadcastReceiver receiver; + private boolean isDiscoverable = false; @Nullable private BluetoothServer server; @@ -48,6 +49,11 @@ public class BluetoothSwap extends SwapType { } + @Override + public boolean isDiscoverable () { + return isDiscoverable; + } + @Override public boolean isConnected() { return server != null && server.isRunning() && super.isConnected(); @@ -68,6 +74,7 @@ public class BluetoothSwap extends SwapType { break; case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE: + isDiscoverable = true; if (server != null && server.isRunning()) { setConnected(true); } @@ -163,5 +170,6 @@ public class BluetoothSwap extends SwapType { 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 afb82b1a3..89e03a041 100644 --- a/F-Droid/src/org/fdroid/fdroid/localrepo/type/SwapType.java +++ b/F-Droid/src/org/fdroid/fdroid/localrepo/type/SwapType.java @@ -33,6 +33,11 @@ public abstract class SwapType { abstract protected String getBroadcastAction(); + public boolean isDiscoverable () + { + return isConnected(); + } + protected final void setConnected(boolean connected) { if (connected) { isConnected = true; diff --git a/F-Droid/src/org/fdroid/fdroid/net/BluetoothDownloader.java b/F-Droid/src/org/fdroid/fdroid/net/BluetoothDownloader.java index 610a30ee4..498b69214 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/BluetoothDownloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/BluetoothDownloader.java @@ -48,6 +48,7 @@ public class BluetoothDownloader extends Downloader { // to us). BoundedInputStream stream = new BoundedInputStream(response.toContentStream(), fileDetails.getFileSize()); stream.setPropagateClose(false); + return stream; } @@ -95,4 +96,11 @@ public class BluetoothDownloader extends Downloader { ); } + @Override + public void close () + { + if (connection != null) + connection.closeQuietly(); + } + } diff --git a/F-Droid/src/org/fdroid/fdroid/net/Downloader.java b/F-Droid/src/org/fdroid/fdroid/net/Downloader.java index ffe250669..470dfd698 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/Downloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/Downloader.java @@ -40,6 +40,7 @@ public abstract class Downloader { protected int totalBytes = 0; public abstract InputStream getInputStream() throws IOException; + public abstract void close(); Downloader(Context context, URL url, File destFile) throws FileNotFoundException, MalformedURLException { diff --git a/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java b/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java index 495827e6e..6aa5f857d 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java @@ -167,4 +167,8 @@ public class HttpDownloader extends Downloader { return statusCode; } + public void close () + { + connection.disconnect(); + } } diff --git a/F-Droid/src/org/fdroid/fdroid/net/IconDownloader.java b/F-Droid/src/org/fdroid/fdroid/net/IconDownloader.java index 334ceb314..3a20304e1 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/IconDownloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/IconDownloader.java @@ -3,7 +3,10 @@ package org.fdroid.fdroid.net; import android.content.Context; import com.nostra13.universalimageloader.core.download.BaseImageDownloader; +import com.nostra13.universalimageloader.utils.IoUtils; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -33,11 +36,27 @@ public class IconDownloader extends BaseImageDownloader { if (imageUri.toLowerCase().startsWith("bluetooth")) { Downloader downloader = DownloaderFactory.create(context, imageUri); - return downloader.getInputStream(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + InputStream is = downloader.getInputStream(); + + int b = -1; + + while ((b = is.read())!=-1) + baos.write(b); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + + downloader.close(); + + return bais; + } return super.getStream(imageUri, extra); } + + } diff --git a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothClient.java b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothClient.java index 831ed64f0..81a590195 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothClient.java +++ b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothClient.java @@ -28,12 +28,20 @@ public class BluetoothClient { BluetoothSocket socket = null; + BluetoothConnection connection = null; try { socket = device.createInsecureRfcommSocketToServiceRecord(BluetoothConstants.fdroidUuid()); - BluetoothConnection connection = new BluetoothConnection(socket); + connection = new BluetoothConnection(socket); connection.open(); return connection; } catch (IOException e1) { + + if (connection != null) + connection.closeQuietly(); + + throw e1; + + /* Log.e(TAG, "There was an error while establishing Bluetooth connection. Falling back to using reflection..."); Class clazz = socket.getRemoteDevice().getClass(); Class[] paramTypes = new Class[]{Integer.TYPE}; @@ -43,6 +51,7 @@ public class BluetoothClient { method = clazz.getMethod("createInsecureRfcommSocket", paramTypes); Object[] params = new Object[]{1}; BluetoothSocket sockFallback = (BluetoothSocket) method.invoke(socket.getRemoteDevice(), params); + BluetoothConnection connection = new BluetoothConnection(sockFallback); connection.open(); return connection; @@ -52,7 +61,7 @@ public class BluetoothClient { throw e1; } catch (InvocationTargetException e) { throw e1; - } + }*/ // Don't catch exceptions this time, let it bubble up as we did our best but don't // have anythign else to offer in terms of resolving the problem right now. diff --git a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConnection.java b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConnection.java index fec164087..ca6fef59a 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConnection.java +++ b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConnection.java @@ -53,12 +53,6 @@ public class BluetoothConnection { } public void close() throws IOException { - if (input == null || output == null) { - throw new RuntimeException("Cannot close() a BluetoothConnection before calling open()" ); - } - - input.close(); - output.close(); - socket.close(); + closeQuietly(); } } \ No newline at end of file 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 a895dfd98..71a8b0bab 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothServer.java +++ b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothServer.java @@ -137,6 +137,8 @@ public class BluetoothServer extends Thread { break; } + connection.closeQuietly(); + } private Response handleRequest(Request request) throws IOException { diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppsView.java b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppsView.java index 87a577d1b..bb7161be2 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppsView.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppsView.java @@ -283,7 +283,7 @@ public class SwapAppsView extends ListView implements Apk apk = getApkToInstall(); String broadcastUrl = intent.getStringExtra(Downloader.EXTRA_ADDRESS); - if (apk.repoAddress != null && (!TextUtils.equals(Utils.getApkUrl(apk.repoAddress, apk), broadcastUrl))) { + if (apk != null && apk.repoAddress != null && (!TextUtils.equals(Utils.getApkUrl(apk.repoAddress, apk), broadcastUrl))) { return; } @@ -374,9 +374,15 @@ public class SwapAppsView extends ListView implements private void resetView() { + if (app == null) + return; + progressView.setVisibility(View.GONE); progressView.setIndeterminate(true); - nameView.setText(app.name); + + if (app.name != null) + nameView.setText(app.name); + ImageLoader.getInstance().displayImage(app.iconUrl, iconView, displayImageOptions); btnInstall.setVisibility(View.GONE); 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 6b0cbca16..729d995e9 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapWorkflowActivity.java @@ -44,6 +44,7 @@ import org.fdroid.fdroid.data.NewRepoConfig; import org.fdroid.fdroid.installer.Installer; import org.fdroid.fdroid.localrepo.LocalRepoManager; import org.fdroid.fdroid.localrepo.SwapService; +import org.fdroid.fdroid.localrepo.peers.BluetoothFinder; import org.fdroid.fdroid.localrepo.peers.Peer; import org.fdroid.fdroid.net.ApkDownloader; @@ -625,7 +626,7 @@ public class SwapWorkflowActivity extends AppCompatActivity { Log.d(TAG, "Not currently in discoverable mode, so prompting user to enable."); Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); - intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 3600); // 3600 is new maximum! TODO: What about when this expires? What if user manually disables discovery? + intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, BluetoothFinder.DISCOVERABLE_TIMEOUT); // 3600 is new maximum! TODO: What about when this expires? What if user manually disables discovery? startActivityForResult(intent, REQUEST_BLUETOOTH_DISCOVERABLE); } From b6939dcce440c8e6fc7259db81b9e0c0e0dc8e98 Mon Sep 17 00:00:00 2001 From: n8fr8 Date: Thu, 10 Sep 2015 14:58:51 -0400 Subject: [PATCH 4/7] for #404 a few more tweaks to make sure things are getting closed! --- F-Droid/src/org/fdroid/fdroid/net/Downloader.java | 1 + F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/F-Droid/src/org/fdroid/fdroid/net/Downloader.java b/F-Droid/src/org/fdroid/fdroid/net/Downloader.java index 470dfd698..81028239f 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/Downloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/Downloader.java @@ -184,6 +184,7 @@ public abstract class Downloader { } outputStream.flush(); + outputStream.close(); } protected void sendProgress(int bytesRead, int totalBytes) { diff --git a/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java b/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java index 6aa5f857d..3258f4ac0 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java +++ b/F-Droid/src/org/fdroid/fdroid/net/HttpDownloader.java @@ -34,6 +34,7 @@ public class HttpDownloader extends Downloader { protected static final String HEADER_FIELD_ETAG = "ETag"; protected HttpURLConnection connection; + private InputStream stream; private int statusCode = -1; private boolean onlyStream = false; @@ -64,7 +65,8 @@ public class HttpDownloader extends Downloader { public InputStream getInputStream() throws IOException { setupConnection(); - return new BufferedInputStream(connection.getInputStream()); + stream = new BufferedInputStream(connection.getInputStream()); + return stream; } public BufferedReader getBufferedReader () throws IOException @@ -169,6 +171,12 @@ public class HttpDownloader extends Downloader { public void close () { + try { + if (stream != null) + stream.close(); + } + catch (IOException e) {} + connection.disconnect(); } } From 988f5dbfdc4185146008aca667ba9787cc5253b5 Mon Sep 17 00:00:00 2001 From: n8fr8 Date: Thu, 10 Sep 2015 21:18:04 -0400 Subject: [PATCH 5/7] use TextUtils.isEmpty() - a better solution! --- F-Droid/src/org/fdroid/fdroid/RepoUpdater.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java b/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java index 3c4fe6219..456e898f1 100644 --- a/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java +++ b/F-Droid/src/org/fdroid/fdroid/RepoUpdater.java @@ -282,7 +282,7 @@ public class RepoUpdater { * actually in the index.jar itself. If no fingerprint, just store the * signing certificate */ boolean trustNewSigningCertificate = false; - if (repo.fingerprint == null || repo.fingerprint.length() == 0) { + if (repo.fingerprint == null || TextUtils.isEmpty(repo.fingerprint)) { // no info to check things are valid, so just Trust On First Use trustNewSigningCertificate = true; } else { From 884c8219fd86fc9b45439eb1645f6ec82f6022c4 Mon Sep 17 00:00:00 2001 From: n8fr8 Date: Thu, 10 Sep 2015 21:20:23 -0400 Subject: [PATCH 6/7] put exception back into Log per this comment: https://gitlab.com/fdroid/fdroidclient/merge_requests/137 --- F-Droid/src/org/fdroid/fdroid/data/App.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/F-Droid/src/org/fdroid/fdroid/data/App.java b/F-Droid/src/org/fdroid/fdroid/data/App.java index f7d9261e4..f2561dbf2 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/App.java +++ b/F-Droid/src/org/fdroid/fdroid/data/App.java @@ -241,7 +241,7 @@ public class App extends ValueObject implements Comparable { PackageManager.GET_META_DATA); installerPackageLabel = installerAppInfo.loadLabel(pm); } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Could not get app info: " + installerPackageName); + Log.w(TAG, "Could not get app info: " + installerPackageName,e); } } if (TextUtils.isEmpty(installerPackageLabel)) From 6dec9fb928af000a1512319557ad6d9abd1a946c Mon Sep 17 00:00:00 2001 From: n8fr8 Date: Thu, 10 Sep 2015 21:21:27 -0400 Subject: [PATCH 7/7] remove unnecessary whitespace --- .../src/org/fdroid/fdroid/net/bluetooth/BluetoothConstants.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConstants.java b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConstants.java index 5d38d71a0..35d7024cf 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConstants.java +++ b/F-Droid/src/org/fdroid/fdroid/net/bluetooth/BluetoothConstants.java @@ -13,8 +13,6 @@ public class BluetoothConstants { // want to do so. // This UUID is just from mashing random hex characters on the keyboard. return UUID.fromString("cd59ba31-5729-b3bb-cb29-732b59eb61aa"); - - } }