scrcpy icon indicating copy to clipboard operation
scrcpy copied to clipboard

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

Open Icarus3000 opened this issue 3 years ago • 6 comments

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)

Icarus3000 avatar Sep 13 '22 14:09 Icarus3000

Please replace scrcpy-server in your v1.24 release, run scrcpy, then copy-paste the whole console output:

  • scrcpy-server SHA-256: 21546900831d0f6d0c2ba6debd8d04fb1fd9686527db65f9d10d0d94fd60e2b3
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..b178d18d 100644
--- a/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
+++ b/server/src/main/java/com/genymobile/scrcpy/wrappers/ClipboardManager.java
@@ -18,6 +18,9 @@ public class ClipboardManager {
 
     public ClipboardManager(IInterface manager) {
         this.manager = manager;
+        for (Method m : manager.getClass().getDeclaredMethods()) {
+            Ln.i("=== " + m);
+        }
     }
 
     private Method getGetPrimaryClipMethod() throws NoSuchMethodException {

rom1v avatar Sep 13 '22 14:09 rom1v

scrcpy 1.24 <https://github.com/Genymobile/scrcpy>
C:\Users\cschneider\scrcpy\scrcpy-server: 1 file pushed, 0 skipped. 38.9 MB/s (61134 bytes in 0.002s)
[server] INFO: Device: Google Pixel 6 Pro (Android 13)
[server] INFO: === public void android.content.IClipboard$Stub$Proxy.addPrimaryClipChangedListener(android.content.IOnPrimaryClipChangedListener,java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public android.os.IBinder android.content.IClipboard$Stub$Proxy.asBinder()
[server] INFO: === public void android.content.IClipboard$Stub$Proxy.clearPrimaryClip(java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public java.lang.String android.content.IClipboard$Stub$Proxy.getInterfaceDescriptor()
[server] INFO: === public android.content.ClipData android.content.IClipboard$Stub$Proxy.getPrimaryClip(java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public android.content.ClipDescription android.content.IClipboard$Stub$Proxy.getPrimaryClipDescription(java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public java.lang.String android.content.IClipboard$Stub$Proxy.getPrimaryClipSource(java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public boolean android.content.IClipboard$Stub$Proxy.hasClipboardText(java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public boolean android.content.IClipboard$Stub$Proxy.hasPrimaryClip(java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public void android.content.IClipboard$Stub$Proxy.removePrimaryClipChangedListener(android.content.IOnPrimaryClipChangedListener,java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public void android.content.IClipboard$Stub$Proxy.setPrimaryClip(android.content.ClipData,java.lang.String,java.lang.String,int) throws android.os.RemoteException
[server] INFO: === public void android.content.IClipboard$Stub$Proxy.setPrimaryClipAsPackage(android.content.ClipData,java.lang.String,java.lang.String,int,java.lang.String) throws android.os.RemoteException
[server] ERROR: Could not invoke method
java.lang.NoSuchMethodException: android.content.IClipboard$Stub$Proxy.addPrimaryClipChangedListener [interface android.content.IOnPrimaryClipChangedListener, 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.getAddPrimaryClipChangedListener(ClipboardManager.java:106)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.addPrimaryClipChangedListener(ClipboardManager.java:114)
        at com.genymobile.scrcpy.Device.<init>(Device.java:103)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:65)
        at com.genymobile.scrcpy.Server.main(Server.java:335)
        at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
        at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:355)
INFO: Renderer: direct3d
INFO: Initial texture: 1440x3120

Icarus3000 avatar Sep 13 '22 21:09 Icarus3000

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

rom1v avatar Sep 14 '22 07:09 rom1v

It works again!

The console output still shows an error, but i don't know if that's important;

scrcpy 1.24 <https://github.com/Genymobile/scrcpy>
C:\Users\cschneider\scrcpy\scrcpy-server: 1 file pushed, 0 skipped. 52.1 MB/s (71762 bytes in 0.001s)
[server] INFO: Device: Google Pixel 6 Pro (Android 13)
[server] ERROR: Could not invoke method
java.lang.NoSuchMethodException: android.content.IClipboard$Stub$Proxy.addPrimaryClipChangedListener [interface android.content.IOnPrimaryClipChangedListener, 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.getAddPrimaryClipChangedListener(ClipboardManager.java:120)
        at com.genymobile.scrcpy.wrappers.ClipboardManager.addPrimaryClipChangedListener(ClipboardManager.java:128)
        at com.genymobile.scrcpy.Device.<init>(Device.java:103)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:65)
        at com.genymobile.scrcpy.Server.main(Server.java:335)
        at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
        at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:355)
INFO: Renderer: direct3d
INFO: Initial texture: 1440x3120
[server] INFO: Device clipboard set

Icarus3000 avatar Sep 14 '22 13:09 Icarus3000

java.lang.NoSuchMethodException: android.content.IClipboard$Stub$Proxy.addPrimaryClipChangedListener [interface android.content.IOnPrimaryClipChangedListener, class java.lang.String, int]

Oh, they also added a String parameter to addPrimaryClipChangedListener().

but i don't know if that's important;

Yes, it's to synchronize the clipboard from Android to the computer.

Here is a version with a fix for this method too:

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..bfed7442 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, 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 +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, ServiceManager.PACKAGE_NAME, 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);
  • scrcpy-server SHA-256: 9215973603e4e8210aef92527add4498ad4445167a71621c14576fa4d0b8f7ab

rom1v avatar Sep 14 '22 13:09 rom1v

Perfect fix! no error message. Thank you so much!

Icarus3000 avatar Sep 14 '22 18:09 Icarus3000

Having this fixed is great, thx!

However, I am not sure how I can access this fix without compiling the project myself. Having to type in long and complex texts maually instead of c&p is a huge productivity stepping stone. Will there be a release that contains this fix anytime soon?

markusressel avatar Sep 26 '22 10:09 markusressel

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.

rom1v avatar Sep 26 '22 11:09 rom1v

Thx, it works. It was a little tricky to find the path on a homebrew install, its located here: /usr/local/Cellar/scrcpy/1.24/share/scrcpy/scrcpy-server

markusressel avatar Sep 26 '22 12:09 markusressel

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

rom1v avatar Sep 26 '22 12:09 rom1v

Same issue here with Pixel 6 Pro. I don't work for Android team, but I may be running on an unreleased build. I got this issue after a security update, and it took some time to update, so I wonder if the changes were quite major. The date of the security update is a future time around early December 2022. I think that's all I can provide for now. :P Many thanks for your work including the fix in this thread, rom1v!

alex310110 avatar Nov 19 '22 07:11 alex310110

Can we get this (or even better a true fix) as a proper release, please? makes installing and managing versions easier.

Zettymaster avatar Dec 18 '22 16:12 Zettymaster

That last binary, https://github.com/Genymobile/scrcpy/issues/3497#issuecomment-1246780900, and

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

also worked for me, thanks! Only stopped working with the latest Android security patch:

Phone: Pixel 4a Android Version: 13 Security Update: 5 Dec 2022 Build Number: TQ1A.221205.011

Laptop: macOS Montery 12.6.1

GetOutOfMyBakery avatar Dec 19 '22 20:12 GetOutOfMyBakery

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

rom1v avatar Dec 20 '22 09:12 rom1v

Please test this new binary and confirm that it works.

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

drothenberger avatar Dec 20 '22 22:12 drothenberger

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

alex310110 avatar Dec 21 '22 02:12 alex310110

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

rom1v avatar Dec 21 '22 12:12 rom1v

Confirmed on Pixel 4a on Mac 👍 Thanks for the update!

GetOutOfMyBakery avatar Dec 21 '22 20:12 GetOutOfMyBakery

Fixed in v1.25.

rom1v avatar Dec 22 '22 12:12 rom1v

I'm seeing this error with the default packages on Linux Mint 21.1 Vera. Should I pester them to update the package? Where should I do that? Many thanks,

CholoTook avatar Jul 18 '23 10:07 CholoTook

Uninstall the package and install the latest version manually: https://github.com/Genymobile/scrcpy/blob/master/doc/linux.md#latest-version

rom1v avatar Jul 18 '23 10:07 rom1v

Great, working. I'm just wondering when the deb / flatpak will be updated :-/

CholoTook avatar Jul 18 '23 16:07 CholoTook