scrcpy: Can no longer paste from Windows 10 to Android 13 (QPR Beta 1)

Device: Pixel 6 Pro Android OS: 13 QPR Beta 1 Windows 10 Scrcpy 1.24

Terminal output when I press CTRL-V in scrcpy window:

[server] ERROR: Could not invoke method
[server] ERROR: Could not invoke method
java.lang.NoSuchMethodException: android.content.IClipboard$Stub$Proxy.getPrimaryClip [class java.lang.String, int]
        at java.lang.Class.getMethod(Class.java:2103)
        at java.lang.Class.getMethod(Class.java:1724)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.getGetPrimaryClipMethod(ClipboardManager.java:28)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.getText(ClipboardManager.java:63)
        at com.genymobile.scrcpy.Device.getClipboardText(Device.java:251)
        at com.genymobile.scrcpy.Device.setClipboardText(Device.java:264)
        at com.genymobile.scrcpy.Controller.setClipboard(Controller.java:300)
        at com.genymobile.scrcpy.Controller.handleEvent(Controller.java:124)
        at com.genymobile.scrcpy.Controller.control(Controller.java:75)
        at com.genymobile.scrcpy.Server$3.run(Server.java:133)
        at java.lang.Thread.run(Thread.java:1012)
java.lang.NoSuchMethodException: android.content.IClipboard$Stub$Proxy.setPrimaryClip [class android.content.ClipData, class java.lang.String, int]
        at java.lang.Class.getMethod(Class.java:2103)
        at java.lang.Class.getMethod(Class.java:1724)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.getSetPrimaryClipMethod(ClipboardManager.java:39)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.setText(ClipboardManager.java:77)
        at com.genymobile.scrcpy.Device.setClipboardText(Device.java:274)
        at com.genymobile.scrcpy.Controller.setClipboard(Controller.java:300)
        at com.genymobile.scrcpy.Controller.handleEvent(Controller.java:124)
        at com.genymobile.scrcpy.Controller.control(Controller.java:75)
        at com.genymobile.scrcpy.Server$3.run(Server.java:133)
        at java.lang.Thread.run(Thread.java:1012)

EDIT by rom1v: Fixed in scrcpy v1.25.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 1
  • Comments: 22

Commits related to this issue

Most upvoted comments

Just FYI, alternatively, you could download it anywhere, and set the environment variable SCRCPY_SERVER_PATH:

export SCRCPY_SERVER_PATH=/path/to/your/scrcpy-server

However, I am not sure how I can access this fix without compiling the project myself.

Just take this binary: https://github.com/Genymobile/scrcpy/issues/3497#issuecomment-1246780900 and replace it in your v1.24 release.

Merged into dev: 82cb8ab870140403f244fba80ddf2bc5b26b2d78 (will be in the next release)

Confirmed to be working for Pixel 6 Pro as well. Thanks!

Please test this new binary and confirm that it works.

It’s working fine here on Pixel 7. Thanks!

They finally published the change in AOSP: 0e3e509b.

A new parameter attributionTag has been added. We can probably pass null as a value.

Please test this new binary and confirm that it works.

diff
diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
index e25b6e99..aeb59357 100644
--- a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
+++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
@@ -15,6 +15,9 @@ public class ClipboardManager {
     private Method getPrimaryClipMethod;
     private Method setPrimaryClipMethod;
     private Method addPrimaryClipChangedListener;
+    private boolean alternativeGetMethod;
+    private boolean alternativeSetMethod;
+    private boolean alternativeAddListenerMethod;
 
     public ClipboardManager(IInterface manager) {
         this.manager = manager;
@@ -25,7 +28,12 @@ public class ClipboardManager {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                 getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class);
             } else {
-                getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class);
+                try {
+                    getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, String.class, int.class);
+                    alternativeGetMethod = true;
+                }
             }
         }
         return getPrimaryClipMethod;
@@ -36,23 +44,34 @@ public class ClipboardManager {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                 setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class);
             } else {
-                setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, int.class);
+                try {
+                    setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, String.class, int.class);
+                    alternativeSetMethod = true;
+                }
             }
         }
         return setPrimaryClipMethod;
     }
 
-    private static ClipData getPrimaryClip(Method method, IInterface manager) throws InvocationTargetException, IllegalAccessException {
+    private static ClipData getPrimaryClip(Method method, boolean alternativeMethod, IInterface manager)
+            throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME);
         }
+        if (alternativeMethod) {
+            return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME, null, ServiceManager.USER_ID);
+        }
         return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
     }
 
-    private static void setPrimaryClip(Method method, IInterface manager, ClipData clipData)
+    private static void setPrimaryClip(Method method, boolean alternativeMethod, IInterface manager, ClipData clipData)
             throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME);
+        } else if (alternativeMethod) {
+            method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME, null, ServiceManager.USER_ID);
         } else {
             method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
         }
@@ -61,7 +80,7 @@ public class ClipboardManager {
     public CharSequence getText() {
         try {
             Method method = getGetPrimaryClipMethod();
-            ClipData clipData = getPrimaryClip(method, manager);
+            ClipData clipData = getPrimaryClip(method, alternativeGetMethod, manager);
             if (clipData == null || clipData.getItemCount() == 0) {
                 return null;
             }
@@ -76,7 +95,7 @@ public class ClipboardManager {
         try {
             Method method = getSetPrimaryClipMethod();
             ClipData clipData = ClipData.newPlainText(null, text);
-            setPrimaryClip(method, manager, clipData);
+            setPrimaryClip(method, alternativeSetMethod, manager, clipData);
             return true;
         } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
             Ln.e("Could not invoke method", e);
@@ -84,13 +103,14 @@ public class ClipboardManager {
         }
     }
 
-    private static void addPrimaryClipChangedListener(Method method, IInterface manager, IOnPrimaryClipChangedListener listener)
-            throws InvocationTargetException, IllegalAccessException {
+    private static void addPrimaryClipChangedListener(Method method, boolean alternativeMethod, IInterface manager,
+            IOnPrimaryClipChangedListener listener) throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             method.invoke(manager, listener, ServiceManager.PACKAGE_NAME);
-        } else {
+        } else if (alternativeMethod) {
+            method.invoke(manager, listener, ServiceManager.PACKAGE_NAME, null, ServiceManager.USER_ID);
+        } else
             method.invoke(manager, listener, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
-        }
     }
 
     private Method getAddPrimaryClipChangedListener() throws NoSuchMethodException {
@@ -99,8 +119,14 @@ public class ClipboardManager {
                 addPrimaryClipChangedListener = manager.getClass()
                         .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class);
             } else {
-                addPrimaryClipChangedListener = manager.getClass()
-                        .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class, int.class);
+                try {
+                    addPrimaryClipChangedListener = manager.getClass()
+                            .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    addPrimaryClipChangedListener = manager.getClass()
+                            .getMethod("addPrimaryClipChangedListener", IOnPrimaryClipChangedListener.class, String.class, String.class, int.class);
+                    alternativeAddListenerMethod = true;
+                }
             }
         }
         return addPrimaryClipChangedListener;
@@ -109,7 +135,7 @@ public class ClipboardManager {
     public boolean addPrimaryClipChangedListener(IOnPrimaryClipChangedListener listener) {
         try {
             Method method = getAddPrimaryClipChangedListener();
-            addPrimaryClipChangedListener(method, manager, listener);
+            addPrimaryClipChangedListener(method, alternativeAddListenerMethod, manager, listener);
             return true;
         } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
             Ln.e("Could not invoke method", e);

EDIT: new binary:

  • scrcpy-server SHA-256: f5e633584164bbd1105e58dedfd7bb1262e6a8a75553ec674737b8e7315dd2b2
public android.content.ClipData android.content.IClipboard$Stub$Proxy.getPrimaryClip(java.lang.String,java.lang.String,int) throws android.os.RemoteException

OK, the function signature has changed on your device, but this does not match the AOSP source code on tag android-13.0.0_r6.

So they probably changed something whose source code is not published yet, so I don’t know what is the meaning of this additional String parameter.

Let’s try to pass the package name twice:

diff
diff --git a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
index e25b6e99..916a690c 100644
--- a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
+++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
@@ -15,6 +15,8 @@ public class ClipboardManager {
     private Method getPrimaryClipMethod;
     private Method setPrimaryClipMethod;
     private Method addPrimaryClipChangedListener;
+    private boolean alternativeGetMethod;
+    private boolean alternativeSetMethod;
 
     public ClipboardManager(IInterface manager) {
         this.manager = manager;
@@ -25,7 +27,12 @@ public class ClipboardManager {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                 getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class);
             } else {
-                getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class);
+                try {
+                    getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, String.class, int.class);
+                    alternativeGetMethod = true;
+                }
             }
         }
         return getPrimaryClipMethod;
@@ -36,23 +43,33 @@ public class ClipboardManager {
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                 setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class);
             } else {
-                setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, int.class);
+                try {
+                    setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, int.class);
+                } catch (NoSuchMethodException e) {
+                    setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, String.class, int.class);
+                    alternativeSetMethod = true;
+                }
             }
         }
         return setPrimaryClipMethod;
     }
 
-    private static ClipData getPrimaryClip(Method method, IInterface manager) throws InvocationTargetException, IllegalAccessException {
+    private static ClipData getPrimaryClip(Method method, boolean alternativeMethod, IInterface manager) throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME);
         }
+        if (alternativeMethod) {
+            return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
+        }
         return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
     }
 
-    private static void setPrimaryClip(Method method, IInterface manager, ClipData clipData)
+    private static void setPrimaryClip(Method method, boolean alternativeMethod, IInterface manager, ClipData clipData)
             throws InvocationTargetException, IllegalAccessException {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME);
+        } else if (alternativeMethod) {
+            method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
         } else {
             method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
         }
@@ -61,7 +78,7 @@ public class ClipboardManager {
     public CharSequence getText() {
         try {
             Method method = getGetPrimaryClipMethod();
-            ClipData clipData = getPrimaryClip(method, manager);
+            ClipData clipData = getPrimaryClip(method, alternativeGetMethod, manager);
             if (clipData == null || clipData.getItemCount() == 0) {
                 return null;
             }
@@ -76,7 +93,7 @@ public class ClipboardManager {
         try {
             Method method = getSetPrimaryClipMethod();
             ClipData clipData = ClipData.newPlainText(null, text);
-            setPrimaryClip(method, manager, clipData);
+            setPrimaryClip(method, alternativeSetMethod, manager, clipData);
             return true;
         } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
             Ln.e("Could not invoke method", e);
  • scrcpy-server SHA-256: b22d8354e3792f88afa2697d45e3dcf9c77724337392683d99c8941c7b824b73