diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d88d9f0a..903ed8ab 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -18,6 +18,8 @@ + + diff --git a/src/org/kde/kdeconnect/Backends/BluetoothBackend/BluetoothLink.java b/src/org/kde/kdeconnect/Backends/BluetoothBackend/BluetoothLink.java new file mode 100644 index 00000000..4f092b3b --- /dev/null +++ b/src/org/kde/kdeconnect/Backends/BluetoothBackend/BluetoothLink.java @@ -0,0 +1,244 @@ +/* + * Copyright 2016 Saikrishna Arcot + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package org.kde.kdeconnect.Backends.BluetoothBackend; + +import android.annotation.TargetApi; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothServerSocket; +import android.bluetooth.BluetoothSocket; +import android.content.Context; +import android.os.Build; +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; +import org.kde.kdeconnect.Backends.BaseLink; +import org.kde.kdeconnect.Backends.BasePairingHandler; +import org.kde.kdeconnect.Device; +import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper; +import org.kde.kdeconnect.NetworkPackage; + +import java.io.*; +import java.nio.charset.Charset; +import java.security.PublicKey; +import java.util.UUID; + +@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) +public class BluetoothLink extends BaseLink { + private final BluetoothSocket socket; + private final BluetoothLinkProvider linkProvider; + + private boolean continueAccepting = true; + + private Thread receivingThread = new Thread(new Runnable() { + @Override + public void run() { + StringBuilder sb = new StringBuilder(); + try { + Reader reader = new InputStreamReader(socket.getInputStream(), "UTF-8"); + char[] buf = new char[512]; + while (continueAccepting) { + while (sb.indexOf("\n") == -1 && continueAccepting) { + int charsRead; + if ((charsRead = reader.read(buf)) > 0) { + sb.append(buf, 0, charsRead); + } + } + + int endIndex = sb.indexOf("\n"); + if (endIndex != -1) { + String message = sb.substring(0, endIndex + 1); + sb.delete(0, endIndex + 1); + processMessage(message); + } + } + } catch (IOException e) { + Log.e("BluetoothLink/receiving", "Connection to " + socket.getRemoteDevice().getAddress() + " likely broken.", e); + disconnect(); + } + } + + private void processMessage(String message) { + NetworkPackage np; + try { + np = NetworkPackage.unserialize(message); + } catch (JSONException e) { + Log.e("BluetoothLink/receiving", "Unable to parse message.", e); + return; + } + + if (np.getType().equals(NetworkPackage.PACKAGE_TYPE_ENCRYPTED)) { + try { + np = RsaHelper.decrypt(np, privateKey); + } catch(Exception e) { + Log.e("BluetoothLink/receiving", "Exception decrypting the package", e); + } + } + + if (np.hasPayloadTransferInfo()) { + BluetoothSocket transferSocket = null; + try { + UUID transferUuid = UUID.fromString(np.getPayloadTransferInfo().getString("uuid")); + transferSocket = socket.getRemoteDevice().createRfcommSocketToServiceRecord(transferUuid); + transferSocket.connect(); + np.setPayload(transferSocket.getInputStream(), np.getPayloadSize()); + } catch (Exception e) { + if (transferSocket != null) { + try { transferSocket.close(); } catch(IOException ignored) { } + } + Log.e("BluetoothLink/receiving", "Unable to get payload", e); + } + } + + packageReceived(np); + } + }); + + public BluetoothLink(Context context, BluetoothSocket socket, String deviceId, BluetoothLinkProvider linkProvider) { + super(context, deviceId, linkProvider); + this.socket = socket; + this.linkProvider = linkProvider; + receivingThread.start(); + } + + @Override + public String getName() { + return "BluetoothLink"; + } + + @Override + public BasePairingHandler getPairingHandler(Device device, BasePairingHandler.PairingHandlerCallback callback) { + return new BluetoothPairingHandler(device, callback); + } + + public void disconnect() { + if (socket == null) { + return; + } + continueAccepting = false; + try { + socket.close(); + } catch (IOException e) { + } + linkProvider.disconnectedLink(this, getDeviceId(), socket); + } + + private void sendMessage(NetworkPackage np) throws JSONException, IOException { + byte[] message = np.serialize().getBytes(Charset.forName("UTF-8")); + OutputStream socket = this.socket.getOutputStream(); + Log.i("BluetoothLink","Beginning to send message"); + socket.write(message); + Log.i("BluetoothLink","Finished sending message"); + } + + @Override + public boolean sendPackage(NetworkPackage np, Device.SendPackageStatusCallback callback) { + return sendPackageInternal(np, callback, null); + } + + @Override + public boolean sendPackageEncrypted(NetworkPackage np, Device.SendPackageStatusCallback callback, PublicKey key) { + return sendPackageInternal(np, callback, key); + } + + private boolean sendPackageInternal(NetworkPackage np, final Device.SendPackageStatusCallback callback, PublicKey key) { + + /*if (!isConnected()) { + Log.e("BluetoothLink", "sendPackageEncrypted failed: not connected"); + callback.sendFailure(new Exception("Not connected")); + return; + }*/ + + try { + BluetoothServerSocket serverSocket = null; + if (np.hasPayload()) { + UUID transferUuid = UUID.randomUUID(); + serverSocket = BluetoothAdapter.getDefaultAdapter() + .listenUsingRfcommWithServiceRecord("KDE Connect Transfer", transferUuid); + JSONObject payloadTransferInfo = new JSONObject(); + payloadTransferInfo.put("uuid", transferUuid.toString()); + np.setPayloadTransferInfo(payloadTransferInfo); + } + + if (key != null) { + try { + np = RsaHelper.encrypt(np, key); + } catch (Exception e) { + callback.onFailure(e); + return false; + } + } + + sendMessage(np); + + if (serverSocket != null) { + BluetoothSocket transferSocket = serverSocket.accept(); + try { + serverSocket.close(); + + int idealBufferLength = 4096; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + idealBufferLength = transferSocket.getMaxReceivePacketSize(); + } + byte[] buffer = new byte[idealBufferLength]; + int bytesRead; + long progress = 0; + InputStream stream = np.getPayload(); + while ((bytesRead = stream.read(buffer)) != -1) { + progress += bytesRead; + transferSocket.getOutputStream().write(buffer, 0, bytesRead); + if (np.getPayloadSize() > 0) { + callback.onProgressChanged((int) (100 * progress / np.getPayloadSize())); + } + } + transferSocket.getOutputStream().flush(); + stream.close(); + } catch (Exception e) { + callback.onFailure(e); + return false; + } finally { + try { transferSocket.close(); } catch (IOException ignored) { } + } + } + + callback.onSuccess(); + return true; + } catch (Exception e) { + callback.onFailure(e); + return false; + } + } + + @Override + public boolean linkShouldBeKeptAlive() { + return receivingThread.isAlive(); + } + + /* + public boolean isConnected() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { + return socket.isConnected(); + } else { + return true; + } + } +*/ +} diff --git a/src/org/kde/kdeconnect/Backends/BluetoothBackend/BluetoothLinkProvider.java b/src/org/kde/kdeconnect/Backends/BluetoothBackend/BluetoothLinkProvider.java new file mode 100644 index 00000000..20090ea7 --- /dev/null +++ b/src/org/kde/kdeconnect/Backends/BluetoothBackend/BluetoothLinkProvider.java @@ -0,0 +1,377 @@ +/* + * Copyright 2016 Saikrishna Arcot + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package org.kde.kdeconnect.Backends.BluetoothBackend; + +import android.annotation.TargetApi; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.bluetooth.BluetoothServerSocket; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Build; +import android.os.Parcelable; +import android.util.Log; + +import org.kde.kdeconnect.Backends.BaseLinkProvider; +import org.kde.kdeconnect.Device; +import org.kde.kdeconnect.NetworkPackage; + +import java.io.*; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.Set; + +@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) +public class BluetoothLinkProvider extends BaseLinkProvider { + + private static final UUID SERVICE_UUID = UUID.fromString("185f3df4-3268-4e3f-9fca-d4d5059915bd"); + private static final int REQUEST_ENABLE_BT = 48; + + private final Context context; + private final Map visibleComputers = new HashMap<>(); + private final Map sockets = new HashMap<>(); + + private BluetoothAdapter bluetoothAdapter = null; + + private ServerRunnable serverRunnable; + private ClientRunnable clientRunnable; + + private void addLink(NetworkPackage identityPackage, BluetoothLink link) { + String deviceId = identityPackage.getString("deviceId"); + Log.i("BluetoothLinkProvider","addLink to "+deviceId); + BluetoothLink oldLink = visibleComputers.get(deviceId); + if (oldLink == link) { + Log.e("KDEConnect", "BluetoothLinkProvider: oldLink == link. This should not happen!"); + return; + } + visibleComputers.put(deviceId, link); + connectionAccepted(identityPackage, link); + if (oldLink != null) { + Log.i("BluetoothLinkProvider","Removing old connection to same device"); + oldLink.disconnect(); + } + } + + public BluetoothLinkProvider(Context context) { + this.context = context; + + bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (bluetoothAdapter == null) { + Log.e("BluetoothLinkProvider","No bluetooth adapter found."); + } + } + + @Override + public void onStart() { + if (bluetoothAdapter == null) { + return; + } + + if (!bluetoothAdapter.isEnabled()) { + Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + Log.e("BluetoothLinkProvider","Bluetooth adapter not enabled."); + // TODO: next line needs to be called from an existing activity, so move it? + // startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); + // TODO: Check result of the previous command, whether the user allowed bluetooth or not. + return; + } + + //This handles the case when I'm the existing device in the network and receive a hello package + clientRunnable = new ClientRunnable(); + new Thread(clientRunnable).start(); + + // I'm on a new network, let's be polite and introduce myself + serverRunnable = new ServerRunnable(); + new Thread(serverRunnable).start(); + } + + @Override + public void onNetworkChange() { + onStop(); + onStart(); + } + + @Override + public void onStop() { + if (bluetoothAdapter == null || clientRunnable == null || serverRunnable == null) { + return; + } + + clientRunnable.stopProcessing(); + serverRunnable.stopProcessing(); + } + + @Override + public String getName() { + return "BluetoothLinkProvider"; + } + + public void disconnectedLink(BluetoothLink link, String deviceId, BluetoothSocket socket) { + sockets.remove(socket.getRemoteDevice()); + visibleComputers.remove(deviceId); + connectionLost(link); + } + + private class ServerRunnable implements Runnable { + + private boolean continueProcessing = true; + private BluetoothServerSocket serverSocket; + + void stopProcessing() { + continueProcessing = false; + if (serverSocket != null) { + try { + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + @Override + public void run() { + try { + serverSocket = bluetoothAdapter + .listenUsingRfcommWithServiceRecord("KDE Connect", SERVICE_UUID); + } catch (IOException e) { + e.printStackTrace(); + return; + } + + if (continueProcessing) { + try { + BluetoothSocket socket = serverSocket.accept(); + connect(socket); + } catch (Exception ignored) { + } + } + } + + private void connect(BluetoothSocket socket) throws Exception { + //socket.connect(); + OutputStream outputStream = socket.getOutputStream(); + if (sockets.containsKey(socket.getRemoteDevice())) { + Log.i("BTLinkProvider/Server", "Received duplicate connection from " + socket.getRemoteDevice().getAddress()); + socket.close(); + return; + } else { + sockets.put(socket.getRemoteDevice(), socket); + } + + Log.i("BTLinkProvider/Server", "Received connection from " + socket.getRemoteDevice().getAddress()); + + NetworkPackage np = NetworkPackage.createIdentityPackage(context); + byte[] message = np.serialize().getBytes("UTF-8"); + outputStream.write(message); + + Log.i("BTLinkProvider/Server", "Sent identity package"); + + // Listen for the response + StringBuilder sb = new StringBuilder(); + Reader reader = new InputStreamReader(socket.getInputStream(), "UTF-8"); + int charsRead; + char[] buf = new char[512]; + while(sb.lastIndexOf("\n") == -1 && (charsRead = reader.read(buf)) != -1) { + sb.append(buf, 0, charsRead); + } + + String response = sb.toString(); + final NetworkPackage identityPackage = NetworkPackage.unserialize(response); + + if (!identityPackage.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) { + Log.e("BTLinkProvider/Server", "2 Expecting an identity package"); + return; + } + + Log.i("BTLinkProvider/Server", "Received identity package"); + + BluetoothLink link = new BluetoothLink(context, socket, + identityPackage.getString("deviceId"), BluetoothLinkProvider.this); + + addLink(identityPackage, link); + } + } + + private class ClientRunnable extends BroadcastReceiver implements Runnable { + + private boolean continueProcessing = true; + private Map connectionThreads = new HashMap<>(); + + void stopProcessing() { + continueProcessing = false; + } + + @Override + public void run() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { + IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_UUID); + context.registerReceiver(this, filter); + } + + while (continueProcessing) { + connectToDevices(); + try { + Thread.sleep(15000); + } catch (InterruptedException ignored) { + } + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { + context.unregisterReceiver(this); + } + } + + private void connectToDevices() { + Set pairedDevices = bluetoothAdapter.getBondedDevices(); + Log.i("BluetoothLinkProvider", "Bluetooth adapter paired devices: " + pairedDevices.size()); + + // Loop through paired devices + for (BluetoothDevice device : pairedDevices) { + if (sockets.containsKey(device)) { + continue; + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { + device.fetchUuidsWithSdp(); + } else { + connectToDevice(device); + } + } + } + + @Override + @TargetApi(value=Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(BluetoothDevice.ACTION_UUID)) { + BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + Parcelable[] activeUuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID); + + if (sockets.containsKey(device)) { + return; + } + + if (activeUuids == null) { + return; + } + + for (Parcelable uuid: activeUuids) { + if (uuid.toString().equals(SERVICE_UUID.toString())) { + connectToDevice(device); + return; + } + } + } + } + + private void connectToDevice(BluetoothDevice device) { + if (!connectionThreads.containsKey(device) || !connectionThreads.get(device).isAlive()) { + Thread connectionThread = new Thread(new ClientConnect(device)); + connectionThread.start(); + connectionThreads.put(device, connectionThread); + } + } + + + } + + private class ClientConnect implements Runnable { + + private final BluetoothDevice device; + + public ClientConnect(BluetoothDevice device) { + this.device = device; + } + + @Override + public void run() { + connectToDevice(); + } + + private void connectToDevice() { + BluetoothSocket socket; + try { + socket = device.createRfcommSocketToServiceRecord(SERVICE_UUID); + socket.connect(); + sockets.put(device, socket); + } catch (IOException e) { + Log.e("BTLinkProvider/Client", "Could not connect to KDE Connect service on " + device.getAddress(), e); + return; + } + + Log.i("BTLinkProvider/Client", "Connected to " + device.getAddress()); + + try { + int character; + StringBuilder sb = new StringBuilder(); + while(sb.lastIndexOf("\n") == -1 && (character = socket.getInputStream().read()) != -1) { + sb.append((char)character); + } + + String message = sb.toString(); + final NetworkPackage identityPackage = NetworkPackage.unserialize(message); + + if (!identityPackage.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) { + Log.e("BTLinkProvider/Client", "1 Expecting an identity package"); + socket.close(); + return; + } + + Log.i("BTLinkProvider/Client", "Received identity package"); + + String myId = NetworkPackage.createIdentityPackage(context).getString("deviceId"); + if (identityPackage.getString("deviceId").equals(myId)) { + // Probably won't happen, but just to be safe + socket.close(); + return; + } + + if (visibleComputers.containsKey(identityPackage.getString("deviceId"))) { + return; + } + + Log.i("BTLinkProvider/Client", "Identity package received, creating link"); + + final BluetoothLink link = new BluetoothLink(context, socket, + identityPackage.getString("deviceId"), BluetoothLinkProvider.this); + + NetworkPackage np2 = NetworkPackage.createIdentityPackage(context); + link.sendPackage(np2,new Device.SendPackageStatusCallback() { + @Override + public void onSuccess() { + addLink(identityPackage, link); + } + + @Override + public void onFailure(Throwable e) { + + } + }); + } catch (Exception e) { + Log.e("BTLinkProvider/Client", "Connection lost/disconnected on " + device.getAddress(), e); + } + } + } +} diff --git a/src/org/kde/kdeconnect/Backends/BluetoothBackend/BluetoothPairingHandler.java b/src/org/kde/kdeconnect/Backends/BluetoothBackend/BluetoothPairingHandler.java new file mode 100644 index 00000000..1d380e05 --- /dev/null +++ b/src/org/kde/kdeconnect/Backends/BluetoothBackend/BluetoothPairingHandler.java @@ -0,0 +1,193 @@ +/* + * Copyright 2015 Vineet Garg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package org.kde.kdeconnect.Backends.BluetoothBackend; + +import android.util.Log; +import org.kde.kdeconnect.Backends.BasePairingHandler; +import org.kde.kdeconnect.Device; +import org.kde.kdeconnect.NetworkPackage; +import org.kde.kdeconnect_tp.R; + +import java.util.Timer; +import java.util.TimerTask; + +public class BluetoothPairingHandler extends BasePairingHandler { + + Timer mPairingTimer; + public BluetoothPairingHandler(Device device, final PairingHandlerCallback callback) { + super(device, callback); + + if (device.isPaired()) { + mPairStatus = PairStatus.Paired; + } else { + mPairStatus = PairStatus.NotPaired; + } + } + +// @Override + public NetworkPackage createPairPackage() { + NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR); + np.set("pair", true); + return np; + } + + @Override + public void packageReceived(NetworkPackage np) throws Exception{ + + boolean wantsPair = np.getBoolean("pair"); + + if (wantsPair == isPaired()) { + if (mPairStatus == PairStatus.Requested) { + //Log.e("Device","Unpairing (pair rejected)"); + mPairStatus = PairStatus.NotPaired; + hidePairingNotification(); + mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_canceled_by_other_peer)); + } + return; + } + + if (wantsPair) { + + if (mPairStatus == PairStatus.Requested) { //We started pairing + hidePairingNotification(); + pairingDone(); + } else { + + // If device is already paired, accept pairing silently + if (mDevice.isPaired()) { + acceptPairing(); + return; + } + + // Pairing notifications are still managed by device as there is no other way to + // know about notificationId to cancel notification when PairActivity is started + // Even putting notificationId in intent does not work because PairActivity can be + // started from MainActivity too, so then notificationId cannot be set + hidePairingNotification(); + mDevice.displayPairingNotification(); + + mPairingTimer = new Timer(); + + mPairingTimer.schedule(new TimerTask() { + @Override + public void run() { + Log.w("KDE/Device","Unpairing (timeout B)"); + mPairStatus = PairStatus.NotPaired; + hidePairingNotification(); + } + }, 25*1000); //Time to show notification, waiting for user to accept (peer will timeout in 30 seconds) + mPairStatus = PairStatus.RequestedByPeer; + mCallback.incomingRequest(); + + } + } else { + Log.i("KDE/Pairing", "Unpair request"); + + if (mPairStatus == PairStatus.Requested) { + hidePairingNotification(); + mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_canceled_by_other_peer)); + } else if (mPairStatus == PairStatus.Paired) { + mCallback.unpaired(); + } + + mPairStatus = PairStatus.NotPaired; + + } + + } + + @Override + public void requestPairing() { + + Device.SendPackageStatusCallback statusCallback = new Device.SendPackageStatusCallback() { + @Override + public void onSuccess() { + hidePairingNotification(); //Will stop the pairingTimer if it was running + mPairingTimer = new Timer(); + mPairingTimer.schedule(new TimerTask() { + @Override + public void run() { + mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_timed_out)); + Log.w("KDE/Device","Unpairing (timeout A)"); + mPairStatus = PairStatus.NotPaired; + } + }, 30*1000); //Time to wait for the other to accept + mPairStatus = PairStatus.Requested; + } + + @Override + public void onFailure(Throwable e) { + mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_could_not_send_package)); + } + }; + mDevice.sendPackage(createPairPackage(), statusCallback); + } + + public void hidePairingNotification() { + mDevice.hidePairingNotification(); + if (mPairingTimer != null) { + mPairingTimer .cancel(); + } + } + + @Override + public void acceptPairing() { + hidePairingNotification(); + Device.SendPackageStatusCallback statusCallback = new Device.SendPackageStatusCallback() { + @Override + public void onSuccess() { + pairingDone(); + } + + @Override + public void onFailure(Throwable e) { + mCallback.pairingFailed(mDevice.getContext().getString(R.string.error_not_reachable)); + } + }; + mDevice.sendPackage(createPairPackage(), statusCallback); + } + + @Override + public void rejectPairing() { + hidePairingNotification(); + mPairStatus = PairStatus.NotPaired; + NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR); + np.set("pair", false); + mDevice.sendPackage(np); + } + + //@Override + public void pairingDone() { + // Store device information needed to create a Device object in a future + //Log.e("KDE/PairingDone", "Pairing Done"); + mPairStatus = PairStatus.Paired; + mCallback.pairingDone(); + + } + + @Override + public void unpair() { + mPairStatus = PairStatus.NotPaired; + NetworkPackage np = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_PAIR); + np.set("pair", false); + mDevice.sendPackage(np); + } +} diff --git a/src/org/kde/kdeconnect/BackgroundService.java b/src/org/kde/kdeconnect/BackgroundService.java index ca6c2cca..f10ac1d1 100644 --- a/src/org/kde/kdeconnect/BackgroundService.java +++ b/src/org/kde/kdeconnect/BackgroundService.java @@ -26,11 +26,13 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.os.Binder; +import android.os.Build; import android.os.IBinder; import android.util.Log; import org.kde.kdeconnect.Backends.BaseLink; import org.kde.kdeconnect.Backends.BaseLinkProvider; +//import org.kde.kdeconnect.Backends.BluetoothBackend.BluetoothLinkProvider; import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider; import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper; import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper; @@ -140,11 +142,9 @@ public class BackgroundService extends Service { } private void registerLinkProviders() { - - //linkProviders.add(new LoopbackLinkProvider(this)); - linkProviders.add(new LanLinkProvider(this)); - +// linkProviders.add(new LoopbackLinkProvider(this)); +// linkProviders.add(new BluetoothLinkProvider(this)); } public ArrayList getLinkProviders() {