Most of the bluetooth connection stuff is stock standard stuff from the Android SDK. However, once we move beyond connecting, and to requesting and serving information over Bluetooth, it becomes more specific. Most bluetooth stuff (communication related, not UI related) should be in org.fdroid.fdroid.net.bluetooth.* and the .httpish package below that.

I figured there was going to be a bit of arbitrary information exchange, so I went ahead and made something which works essentially like HTTP (hence the .httpish package name). Each request will begin with a request type (GET or HEAD) and then HTTP headers. The server responses have headers and optionally a body.

The BluetoothServerSocket is encapsulated in a BluetoothServer, which continually listens for incoming connections, then handles them in a BluetoothServer.Connection object.

The BluetoothServer.Connection object will continually monitor its socket for incoming info, and parse them as if they were HTTP requests (i.e. request method, headers and body).

I'll try to ensure that I (pserwylo) don't push directly to that, but rather create MR's so that others can review code if necessary. In the near future, I'm also going to create a Milestone in the issue tracker on gitlab to deal with bluetooth swap, so that we can create issues and assign them to that milestone, and see progress towards a stable implementation.

Currently, you are able to start a Bluetooth swap server, which is able to listen for incoming client connections, parse any incoming data, forward it to a local proxy webserver which is the same thing that handles WiFi swapping, and serves relevant files from the webroot in response.

The client side still needs much more work though, in that the infrastructure which downloads icons, repo indexes, and .apk files does not yet know about how to do this over Bluetooth.

This is distinct from creating a swap (which is already implemented). We need to be able to create a new repo on the swap client, so that the UpdateService is able to pull down an index from that repo and populate the database with apps from that repo.

There are two ways in which this happens with the WiFi swap right now.

Scan the QR code which is displayed

Over NFC

Visit the displayed URL, and then click the link in the resulting web page

All three of them have the same effect, which is to send an intent to F-Droid which tells it to add a repo (e.g. "http://10.0.0.1:8888/fdroid/repo?swap=1&fingerprint=ABC"). Thus, they all end up in the same location, but use a different method to get there.

For Bluetooth, it could happen in a similar way, but this time the intent would look like, e.g. "bluetooth://aa:bb:cc:00:11:22/?fingerprint=ABC" (probably doesn't even need "swap=1", at least not until someone builds an fdroidserver repo which works over Bluetooth somehow):

Scanning a QR code

Over NFC

We can't get people to visit a URL over the browser, because that will depend on the devices being on the same TCP/IP network. But if they are using Bluetooth, than this is not the case. That is, even though I've mimicked HTTP with my bluetooth protocol (see above), it is not for the purpose of interoperating with existing HTTP clients.

The end goal is to have the clients F-Droid end up here, which will require modification of the NewRepoConfig class so that it doesn't assume HTTP, and also have the manifest register interest in the relevant bluetooth URLs.

Decide more on the UX (not exactly UI at this point) for Bluetooth swap¶

The server is relatively straightforward.

Person X thinks "I want to share my apps with Person Y".

Person X initiates swap through Main Menu -> Start Swap.

They select apps they want to swap.

Proceed to the "Select WiFi network" screen.

Indicate somehow that they don't want WiFi, but want to use Bluetooth (e.g. through a button on that screen)

Ensures they have bluetooth running.

Starts a bluetooth swap server.

I'm presuming from here, that we do the same as with WiFi, which is to offer NFC, and then display a QR Code with the relevant "bluetooth://.../" URL encoded in it.

The things which are different from wifi though, are:

If they don't have F-Droid installed, but use a barcode scanner to scan the QR Code, how do you bootstrap the process?

If they don't have a barcode scanner, how can we get them to connect? The WiFi swap asks them to enter a URL in the browser.

Currently, you can instantiate a BluetoothDownloader, and actually send http(ish) requests to a F-Droid app with a running BluetoothServer running. An example of this can be seen in some test code here.

However, notice that that code requires a BluetoothConnection to be passed to it?

The typical way in which F-Droid connects to a remote repository to download either an icon, an index, or indeed a .apk is to use the DownloaderFactory to create the relevant downloader for a URL. The API for this class does not know about BluetoothConnections, nor should it need to (because the vast majority of downloads will be from a HTTP repo).

To solve this, we need one of two things:

A way for a BluetoothConnection to be stored globally somewhere

The ability to construct a BluetoothConnection from a url such as "bluetooth://aa:bb:cc:00:11:22/fdroid/repo/index.jar" using the MAC address in the URL.

The second would be more resiliant to Bluetooth turning off and on again, because between requests for files, it wont try and maintain an open socket, whereas the global connection would. To make the global connection (option 1) resiliant in this way, it will essentially have to work like 2. anyway, and be able to reconnect when required. However, I'm not sure about the other implications of option 2, such as having to prompt the user to connect to bluetooth because F-Droid needs to download an icon, or the performance overhead of continually creating new connections, e.g. for downloading several icons to display in the swap app list.