mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-22 01:51:47 +00:00
## Summary A basic mouse receiver implementation. You can now control your Android Device remotely which might be useful when it's connected to a bigger screen (via HDMI). Unfortunately Android does not provide moving mouse by software (other than adb and without root). Therefore this implementation uses Android [AccessibilityService](https://developer.android.com/reference/android/accessibilityservice/AccessibilityService) to create an ImageView Overlay as mouse pointer and simulate touch gestures. This is quite hacky but I think the best way to do so. ## Demo Here is a small demo 
139 lines
4.9 KiB
Java
139 lines
4.9 KiB
Java
/*
|
|
* SPDX-FileCopyrightText: 2021 SohnyBohny <sohny.bean@streber24.de>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
|
*/
|
|
|
|
package org.kde.kdeconnect.Plugins.MouseReceiverPlugin;
|
|
|
|
import android.os.Build;
|
|
import android.provider.Settings;
|
|
import android.util.Log;
|
|
|
|
import androidx.annotation.RequiresApi;
|
|
import androidx.fragment.app.DialogFragment;
|
|
|
|
import org.kde.kdeconnect.NetworkPacket;
|
|
import org.kde.kdeconnect.Plugins.Plugin;
|
|
import org.kde.kdeconnect.Plugins.PluginFactory;
|
|
import org.kde.kdeconnect.UserInterface.MainActivity;
|
|
import org.kde.kdeconnect.UserInterface.StartActivityAlertDialogFragment;
|
|
import org.kde.kdeconnect_tp.R;
|
|
|
|
@PluginFactory.LoadablePlugin
|
|
@RequiresApi(api = Build.VERSION_CODES.N)
|
|
public class MouseReceiverPlugin extends Plugin {
|
|
private final static String PACKET_TYPE_MOUSEPAD_REQUEST = "kdeconnect.mousepad.request";
|
|
|
|
@Override
|
|
public boolean onCreate() {
|
|
Log.e("MouseReceiverPlugin", "onCreate()");
|
|
return super.onCreate();
|
|
}
|
|
|
|
@Override
|
|
public boolean checkRequiredPermissions() {
|
|
return MouseReceiverService.instance != null;
|
|
}
|
|
|
|
@Override
|
|
public DialogFragment getPermissionExplanationDialog() {
|
|
return new StartActivityAlertDialogFragment.Builder()
|
|
.setTitle(R.string.mouse_receiver_plugin_description)
|
|
.setMessage(R.string.mouse_receiver_no_permissions)
|
|
.setPositiveButton(R.string.open_settings)
|
|
.setNegativeButton(R.string.cancel)
|
|
.setIntentAction(Settings.ACTION_ACCESSIBILITY_SETTINGS)
|
|
.setStartForResult(true)
|
|
.setRequestCode(MainActivity.RESULT_NEEDS_RELOAD)
|
|
.create();
|
|
}
|
|
|
|
@Override
|
|
public void onDestroy() {
|
|
Log.e("MouseReceiverPlugin", "onDestroy()");
|
|
super.onDestroy();
|
|
}
|
|
|
|
@Override
|
|
public boolean onPacketReceived(NetworkPacket np) {
|
|
if (!np.getType().equals(PACKET_TYPE_MOUSEPAD_REQUEST)) {
|
|
Log.e("MouseReceiverPlugin", "cannot receive packets of type: " + np.getType());
|
|
return false;
|
|
}
|
|
|
|
double dx = np.getDouble("dx", 0);
|
|
double dy = np.getDouble("dy", 0);
|
|
|
|
boolean isSingleClick = np.getBoolean("singleclick", false);
|
|
boolean isDoubleClick = np.getBoolean("doubleclick", false);
|
|
boolean isMiddleClick = np.getBoolean("middleclick", false);
|
|
boolean isRightClick = np.getBoolean("rightclick", false);
|
|
boolean isSingleHold = np.getBoolean("singlehold", false);
|
|
boolean isScroll = np.getBoolean("scroll", false);
|
|
|
|
if (isSingleClick || isDoubleClick || isMiddleClick || isRightClick || isSingleHold || isScroll) {
|
|
// Perform click
|
|
if (isSingleClick) {
|
|
// Log.i("MouseReceiverPlugin", "singleClick");
|
|
return MouseReceiverService.click();
|
|
} else if (isDoubleClick) { // left & right
|
|
// Log.i("MouseReceiverPlugin", "doubleClick");
|
|
return MouseReceiverService.recentButton();
|
|
} else if (isMiddleClick) {
|
|
// Log.i("MouseReceiverPlugin", "middleClick");
|
|
return MouseReceiverService.homeButton();
|
|
} else if (isRightClick) {
|
|
// Log.i("MouseReceiverPlugin", "rightClick");
|
|
return MouseReceiverService.backButton();
|
|
} else if (isSingleHold){
|
|
// For drag'n drop
|
|
// Log.i("MouseReceiverPlugin", "singleHold");
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
return MouseReceiverService.longClickSwipe();
|
|
} else {
|
|
return MouseReceiverService.longClick();
|
|
}
|
|
} else if (isScroll) {
|
|
// Log.i("MouseReceiverPlugin", "scroll dx: " + dx + " dy: " + dy);
|
|
return MouseReceiverService.scroll(dx, dy); // dx is always 0
|
|
}
|
|
|
|
} else {
|
|
// Mouse Move
|
|
if (dx != 0 || dy != 0) {
|
|
// Log.i("MouseReceiverPlugin", "move Mouse dx: " + dx + " dy: " + dy);
|
|
return MouseReceiverService.move(dx, dy);
|
|
}
|
|
}
|
|
|
|
return super.onPacketReceived(np);
|
|
}
|
|
|
|
@Override
|
|
public int getMinSdk() {
|
|
return Build.VERSION_CODES.N;
|
|
}
|
|
|
|
@Override
|
|
public String getDisplayName() {
|
|
return context.getString(R.string.mouse_receiver_plugin_name);
|
|
}
|
|
|
|
@Override
|
|
public String getDescription() {
|
|
return "MouseReceiverPlugin.getDescription()";
|
|
//return context.getString(R.string.pref_plugin_remotekeyboard_desc);
|
|
}
|
|
|
|
@Override
|
|
public String[] getSupportedPacketTypes() {
|
|
return new String[]{PACKET_TYPE_MOUSEPAD_REQUEST};
|
|
}
|
|
|
|
@Override
|
|
public String[] getOutgoingPacketTypes() {
|
|
return new String[0];
|
|
}
|
|
}
|