diff --git a/src/org/kde/kdeconnect/BackgroundService.java b/src/org/kde/kdeconnect/BackgroundService.java index 9f651588..8fe6b791 100644 --- a/src/org/kde/kdeconnect/BackgroundService.java +++ b/src/org/kde/kdeconnect/BackgroundService.java @@ -347,10 +347,10 @@ public class BackgroundService extends Service { } ArrayList connectedDevices = new ArrayList<>(); - ArrayList deviceIds = new ArrayList<>(); + ArrayList connectedDeviceIds = new ArrayList<>(); for (Device device : getDevices().values()) { if (device.isReachable() && device.isPaired()) { - deviceIds.add(device.getDeviceId()); + connectedDeviceIds.add(device.getDeviceId()); connectedDevices.add(device.getName()); } } @@ -359,28 +359,30 @@ public class BackgroundService extends Service { notification.setContentText(getString(R.string.foreground_notification_no_devices)); } else { notification.setContentText(getString(R.string.foreground_notification_devices, TextUtils.join(", ", connectedDevices))); - if (deviceIds.size() == 1) { + + // Adding an action button to send clipboard manually in Android 10 and later. + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { + Intent sendClipboard = new Intent(this, ClipboardFloatingActivity.class); + sendClipboard.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); + sendClipboard.putExtra("connectedDeviceIds", connectedDeviceIds); + PendingIntent sendPendingClipboard = PendingIntent.getActivity(this, 3, sendClipboard, PendingIntent.FLAG_UPDATE_CURRENT); + notification.addAction(0, getString(R.string.foreground_notification_send_clipboard), sendPendingClipboard); + } + + if (connectedDeviceIds.size() == 1) { // Adding two action buttons only when there is a single device connected. // Setting up Send File Intent. Intent sendFile = new Intent(this, SendFileActivity.class); - sendFile.putExtra("deviceId", deviceIds.get(0)); + sendFile.putExtra("deviceId", connectedDeviceIds.get(0)); PendingIntent sendPendingFile = PendingIntent.getActivity(this, 1, sendFile, PendingIntent.FLAG_UPDATE_CURRENT); notification.addAction(0, getString(R.string.send_files), sendPendingFile); - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { - Intent sendClipboard = new Intent(this, ClipboardFloatingActivity.class); - sendClipboard.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); - sendClipboard.putExtra("deviceId", deviceIds.get(0)); - PendingIntent sendPendingClipboard = PendingIntent.getActivity(this, 3, sendClipboard, PendingIntent.FLAG_UPDATE_CURRENT); - notification.addAction(0, getString(R.string.foreground_notification_send_clipboard), sendPendingClipboard); - } - // Checking if there are registered commands and adding the button. - Device device = getDevice(deviceIds.get(0)); + Device device = getDevice(connectedDeviceIds.get(0)); RunCommandPlugin plugin = (RunCommandPlugin) device.getPlugin("RunCommandPlugin"); if (plugin != null && !plugin.getCommandList().isEmpty()) { Intent runCommand = new Intent(this, RunCommandActivity.class); - runCommand.putExtra("deviceId", deviceIds.get(0)); + runCommand.putExtra("deviceId", connectedDeviceIds.get(0)); PendingIntent runPendingCommand = PendingIntent.getActivity(this, 2, runCommand, PendingIntent.FLAG_UPDATE_CURRENT); notification.addAction(0, getString(R.string.pref_plugin_runcommand), runPendingCommand); } diff --git a/src/org/kde/kdeconnect/Plugins/ClibpoardPlugin/ClipboardFloatingActivity.java b/src/org/kde/kdeconnect/Plugins/ClibpoardPlugin/ClipboardFloatingActivity.java index a5b8480d..57e7abcf 100644 --- a/src/org/kde/kdeconnect/Plugins/ClibpoardPlugin/ClipboardFloatingActivity.java +++ b/src/org/kde/kdeconnect/Plugins/ClibpoardPlugin/ClipboardFloatingActivity.java @@ -1,3 +1,23 @@ +/* + * Copyright 2020 Anjani Kumar + * + * 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.Plugins.ClibpoardPlugin; import androidx.appcompat.app.AppCompatActivity; @@ -13,24 +33,43 @@ import org.kde.kdeconnect.BackgroundService; import org.kde.kdeconnect.Device; import org.kde.kdeconnect_tp.R; +import java.util.ArrayList; + +/* + An activity to access the clipboard on Android 10 and later by raising over other apps. + This is invisible and doesn't require any interaction from the user. + This should be called when a change in clipboard is detected. This can be done by manually + when user wants to send the clipboard or by reading system log files which requires a special + privileged permission android.permission.READ_LOGS. + https://developer.android.com/reference/android/Manifest.permission#READ_LOGS + This permission can be gained by only from the adb by the user. + https://www.reddit.com/r/AndroidBusters/comments/fh60lt/how_to_solve_a_problem_with_the_clipboard_on/ + + Currently this activity is bering triggered from a button in Foreground Notification. +* */ public class ClipboardFloatingActivity extends AppCompatActivity { - private Device device; + private ArrayList connectedDevices = new ArrayList<>(); @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { + // We are now sure that clipboard can be accessed from here. ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); ClipData.Item item; if (clipboardManager.hasPrimaryClip()) { item = clipboardManager.getPrimaryClip().getItemAt(0); String content = item.coerceToText(this).toString(); - ClipboardPlugin plugin = (ClipboardPlugin) device.getPlugin("ClipboardPlugin"); - plugin.propagateClipboard(content); + for (Device device : connectedDevices) { + ClipboardPlugin clipboardPlugin = (ClipboardPlugin) device.getPlugin("ClipboardPlugin"); + if (clipboardPlugin != null) { + clipboardPlugin.propagateClipboard(content); + } + } Toast.makeText(this, R.string.pref_plugin_clipboard_sent, Toast.LENGTH_SHORT).show(); - finish(); } + finish(); } } @@ -43,8 +82,12 @@ public class ClipboardFloatingActivity extends AppCompatActivity { WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; getWindow().setAttributes(wlp); - String deviceId = getIntent().getStringExtra("deviceId"); - device = BackgroundService.getInstance().getDevice(deviceId); + ArrayList connectedDeviceIds = getIntent().getStringArrayListExtra("connectedDeviceIds"); + if (connectedDeviceIds != null) { + for (String deviceId : connectedDeviceIds) { + connectedDevices.add(BackgroundService.getInstance().getDevice(deviceId)); + } + } } }