diff --git a/res/drawable-hdpi/ic_accept_pairing.png b/res/drawable-hdpi/ic_accept_pairing.png new file mode 100644 index 00000000..b95ffdb3 Binary files /dev/null and b/res/drawable-hdpi/ic_accept_pairing.png differ diff --git a/res/drawable-hdpi/ic_reject_pairing.png b/res/drawable-hdpi/ic_reject_pairing.png new file mode 100644 index 00000000..1669ea3d Binary files /dev/null and b/res/drawable-hdpi/ic_reject_pairing.png differ diff --git a/res/drawable-mdpi/ic_accept_pairing.png b/res/drawable-mdpi/ic_accept_pairing.png new file mode 100644 index 00000000..fad8a0e9 Binary files /dev/null and b/res/drawable-mdpi/ic_accept_pairing.png differ diff --git a/res/drawable-mdpi/ic_reject_pairing.png b/res/drawable-mdpi/ic_reject_pairing.png new file mode 100644 index 00000000..cc28d134 Binary files /dev/null and b/res/drawable-mdpi/ic_reject_pairing.png differ diff --git a/res/drawable-xhdpi/ic_accept_pairing.png b/res/drawable-xhdpi/ic_accept_pairing.png new file mode 100644 index 00000000..72fa0108 Binary files /dev/null and b/res/drawable-xhdpi/ic_accept_pairing.png differ diff --git a/res/drawable-xhdpi/ic_reject_pairing.png b/res/drawable-xhdpi/ic_reject_pairing.png new file mode 100644 index 00000000..e8589a72 Binary files /dev/null and b/res/drawable-xhdpi/ic_reject_pairing.png differ diff --git a/res/drawable-xxhdpi/ic_accept_pairing.png b/res/drawable-xxhdpi/ic_accept_pairing.png new file mode 100644 index 00000000..a49f451d Binary files /dev/null and b/res/drawable-xxhdpi/ic_accept_pairing.png differ diff --git a/res/drawable-xxhdpi/ic_reject_pairing.png b/res/drawable-xxhdpi/ic_reject_pairing.png new file mode 100644 index 00000000..892d07c9 Binary files /dev/null and b/res/drawable-xxhdpi/ic_reject_pairing.png differ diff --git a/res/drawable-xxxhdpi/ic_accept_pairing.png b/res/drawable-xxxhdpi/ic_accept_pairing.png new file mode 100644 index 00000000..c4596d11 Binary files /dev/null and b/res/drawable-xxxhdpi/ic_accept_pairing.png differ diff --git a/res/drawable-xxxhdpi/ic_reject_pairing.png b/res/drawable-xxxhdpi/ic_reject_pairing.png new file mode 100644 index 00000000..5ffd8d00 Binary files /dev/null and b/res/drawable-xxxhdpi/ic_reject_pairing.png differ diff --git a/src/org/kde/kdeconnect/Device.java b/src/org/kde/kdeconnect/Device.java index 41b8a1e9..3da45204 100644 --- a/src/org/kde/kdeconnect/Device.java +++ b/src/org/kde/kdeconnect/Device.java @@ -368,7 +368,23 @@ public class Device implements BaseLink.PackageReceiver { Intent intent = new Intent(getContext(), MaterialActivity.class); intent.putExtra("deviceId", getDeviceId()); intent.putExtra("notificationId", notificationId); - PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT); + PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); + + Intent acceptIntent = new Intent(getContext(), MaterialActivity.class); + Intent rejectIntent = new Intent(getContext(), MaterialActivity.class); + + acceptIntent.putExtra("deviceId", getDeviceId()); + acceptIntent.putExtra("notificationId", notificationId); + acceptIntent.setAction("action "+System.currentTimeMillis()); + acceptIntent.putExtra(MaterialActivity.PAIR_REQUEST_STATUS, MaterialActivity.PAIRING_ACCEPTED); + + rejectIntent.putExtra("deviceId", getDeviceId()); + rejectIntent.putExtra("notificationId", notificationId); + rejectIntent.setAction("action "+System.currentTimeMillis()); + rejectIntent.putExtra(MaterialActivity.PAIR_REQUEST_STATUS, MaterialActivity.PAIRING_REJECTED); + + PendingIntent acceptedPendingIntent = PendingIntent.getActivity(getContext(), 2, acceptIntent, PendingIntent.FLAG_ONE_SHOT); + PendingIntent rejectedPendingIntent = PendingIntent.getActivity(getContext(), 4, rejectIntent, PendingIntent.FLAG_ONE_SHOT); Resources res = getContext().getResources(); @@ -378,6 +394,8 @@ public class Device implements BaseLink.PackageReceiver { .setContentIntent(pendingIntent) .setTicker(res.getString(R.string.pair_requested)) .setSmallIcon(R.drawable.ic_notification) + .addAction(R.drawable.ic_accept_pairing, res.getString(R.string.pairing_accept), acceptedPendingIntent) + .addAction(R.drawable.ic_reject_pairing, res.getString(R.string.pairing_reject), rejectedPendingIntent) .setAutoCancel(true) .setDefaults(Notification.DEFAULT_ALL) .build(); diff --git a/src/org/kde/kdeconnect/UserInterface/DeviceFragment.java b/src/org/kde/kdeconnect/UserInterface/DeviceFragment.java index f94efa4c..290f1903 100644 --- a/src/org/kde/kdeconnect/UserInterface/DeviceFragment.java +++ b/src/org/kde/kdeconnect/UserInterface/DeviceFragment.java @@ -84,6 +84,13 @@ public class DeviceFragment extends Fragment { this.setArguments(args); } + public DeviceFragment(String deviceId, MaterialActivity activity){ + this.mActivity = activity; + Bundle args = new Bundle(); + args.putString(ARG_DEVICE_ID, deviceId); + this.setArguments(args); + } + @Override public void onAttach(Activity activity) { super.onAttach(activity); @@ -183,7 +190,6 @@ public class DeviceFragment extends Fragment { return rootView; } - private final Device.PluginsChangedListener pluginsChangedListener = new Device.PluginsChangedListener() { @Override public void onPluginsChanged(final Device device) { @@ -460,4 +466,54 @@ public class DeviceFragment extends Fragment { }; + public static void acceptPairing(final String devId, final MaterialActivity activity){ + final DeviceFragment frag = new DeviceFragment(devId, activity); + BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() { + public void onServiceStart(BackgroundService service) { + Device dev = service.getDevice(devId); + activity.getSupportActionBar().setTitle(dev.getName()); + + dev.addPairingCallback(frag.pairingCallback); + dev.addPluginsChangedListener(frag.pluginsChangedListener); + + frag.refreshUI(); + + frag.device = dev; + } + }); + + BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() { + @Override + public void onServiceStart(BackgroundService service) { + frag.device.acceptPairing(); + } + }); + } + + public static void rejectPairing(final String devId, final MaterialActivity activity){ + final DeviceFragment frag = new DeviceFragment(devId, activity); + BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() { + public void onServiceStart(BackgroundService service) { + Device dev = service.getDevice(devId); + activity.getSupportActionBar().setTitle(dev.getName()); + + dev.addPairingCallback(frag.pairingCallback); + dev.addPluginsChangedListener(frag.pluginsChangedListener); + + frag.refreshUI(); + + frag.device = dev; + } + }); + BackgroundService.RunCommand(activity, new BackgroundService.InstanceCallback() { + @Override + public void onServiceStart(BackgroundService service) { + //Remove listener so buttons don't show for a while before changing the view + frag.device.removePluginsChangedListener(frag.pluginsChangedListener); + frag.device.removePairingCallback(frag.pairingCallback); + frag.device.rejectPairing(); + activity.onDeviceSelected(null); + } + }); + } } diff --git a/src/org/kde/kdeconnect/UserInterface/MaterialActivity.java b/src/org/kde/kdeconnect/UserInterface/MaterialActivity.java index 7c35baa4..4eeed193 100644 --- a/src/org/kde/kdeconnect/UserInterface/MaterialActivity.java +++ b/src/org/kde/kdeconnect/UserInterface/MaterialActivity.java @@ -38,6 +38,10 @@ public class MaterialActivity extends AppCompatActivity { public static final int RESULT_NEEDS_RELOAD = Activity.RESULT_FIRST_USER; + public static final String PAIR_REQUEST_STATUS = "pair_req_status"; + public static final String PAIRING_ACCEPTED = "accepted"; + public static final String PAIRING_REJECTED = "rejected"; + private NavigationView mNavigationView; private DrawerLayout mDrawerLayout; @@ -102,12 +106,16 @@ public class MaterialActivity extends AppCompatActivity { preferences = getSharedPreferences(STATE_SELECTED_DEVICE, Context.MODE_PRIVATE); String savedDevice; + String pairStatus = ""; if (getIntent().hasExtra("forceOverview")) { Log.i("MaterialActivity", "Requested to start main overview"); savedDevice = null; } else if (getIntent().hasExtra("deviceId")) { Log.i("MaterialActivity", "Loading selected device from parameter"); savedDevice = getIntent().getStringExtra("deviceId"); + if(getIntent().hasExtra(PAIR_REQUEST_STATUS)){ + pairStatus = getIntent().getStringExtra(PAIR_REQUEST_STATUS); + } } else if (savedInstanceState != null) { Log.i("MaterialActivity", "Loading selected device from saved activity state"); savedDevice = savedInstanceState.getString(STATE_SELECTED_DEVICE); @@ -115,8 +123,31 @@ public class MaterialActivity extends AppCompatActivity { Log.i("MaterialActivity", "Loading selected device from persistent storage"); savedDevice = preferences.getString(STATE_SELECTED_DEVICE, null); } + //if pairStatus is not empty, then the decision has been made... + if (!pairStatus.equals("")) { + Log.i("MaterialActivity", "pair status is "+pairStatus); + onNewDeviceSelected(savedDevice, pairStatus); + } onDeviceSelected(savedDevice); + } + //like onNewDeviceSelected but assumes that the new device is simply requesting to be paired + //and can't be null + private void onNewDeviceSelected(String deviceId, String pairStatus){ + mCurrentDevice = deviceId; + + preferences.edit().putString(STATE_SELECTED_DEVICE, mCurrentDevice).apply(); + + for (HashMap.Entry entry : mMapMenuToDeviceId.entrySet()) { + boolean selected = TextUtils.equals(entry.getValue(), deviceId); //null-safe + entry.getKey().setChecked(selected); + } + + if (pairStatus.equals(PAIRING_ACCEPTED)) { + DeviceFragment.acceptPairing(deviceId, this); + } else { + DeviceFragment.rejectPairing(deviceId, this); + } } @Override