└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Description 2 | Turn ON/OFF the display of your Android phone, like scrcpy, using ADB Shell or Root. 3 | 4 | Check **[Reddit Tasker](https://www.reddit.com/r/tasker/comments/12bcdnj/project_share_turn_display_onoff_dont_disturb/)** for Tasker users. 5 | 6 | Termux users can continue to the next section. 7 | 8 | # Building 9 | You can follow these steps to build it in **[Termux](https://f-droid.org/repo/com.termux_1020.apk)**. 10 | 11 | yes | pkg upgrade -y 12 | 13 |   14 | 15 | pkg install -y wget openjdk-21 dx android-tools 16 | 17 |   18 | 19 | wget -O ~/android.jar "https://github.com/Sable/android-platforms/blob/master/android-35/android.jar?raw=true" 20 | 21 |   22 | 23 | nano DisplayToggle.java 24 | 25 | Now copy paste this:- 26 | 27 | ``` 28 | import android.os.Build; 29 | import android.os.IBinder; 30 | import java.lang.reflect.Method; 31 | import java.lang.reflect.InvocationTargetException; 32 | 33 | public class DisplayToggle { 34 | 35 | private static final Class SURFACE_CONTROL_CLASS; 36 | private static final Class DISPLAY_CONTROL_CLASS; 37 | 38 | static { 39 | try { 40 | SURFACE_CONTROL_CLASS = Class.forName("android.view.SurfaceControl"); 41 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { 42 | Class classLoaderFactoryClass = Class.forName("com.android.internal.os.ClassLoaderFactory"); 43 | Method createClassLoaderMethod = classLoaderFactoryClass.getDeclaredMethod("createClassLoader", 44 | String.class, String.class, String.class, ClassLoader.class, int.class, boolean.class, String.class); 45 | ClassLoader classLoader = (ClassLoader) createClassLoaderMethod.invoke(null, 46 | "/system/framework/services.jar", null, null, ClassLoader.getSystemClassLoader(), 0, true, null); 47 | DISPLAY_CONTROL_CLASS = classLoader.loadClass("com.android.server.display.DisplayControl"); 48 | 49 | Method loadLibraryMethod = Runtime.class.getDeclaredMethod("loadLibrary0", Class.class, String.class); 50 | loadLibraryMethod.setAccessible(true); 51 | loadLibraryMethod.invoke(Runtime.getRuntime(), DISPLAY_CONTROL_CLASS, "android_servers"); 52 | } else { 53 | DISPLAY_CONTROL_CLASS = null; 54 | } 55 | } catch (Exception e) { 56 | throw new AssertionError(e); 57 | } 58 | } 59 | 60 | public static void main(String... args) { 61 | System.out.println("Display mode: " + args[0]); 62 | int mode = Integer.parseInt(args[0]); 63 | 64 | try { 65 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && DISPLAY_CONTROL_CLASS != null) { 66 | Method getPhysicalDisplayIdsMethod = DISPLAY_CONTROL_CLASS.getMethod("getPhysicalDisplayIds"); 67 | Method getPhysicalDisplayTokenMethod = DISPLAY_CONTROL_CLASS.getMethod("getPhysicalDisplayToken", long.class); 68 | 69 | long[] displayIds = (long[]) getPhysicalDisplayIdsMethod.invoke(null); 70 | if (displayIds != null) { 71 | for (long displayId : displayIds) { 72 | IBinder token = (IBinder) getPhysicalDisplayTokenMethod.invoke(null, displayId); 73 | setDisplayPowerMode(token, mode); 74 | } 75 | } 76 | } else { 77 | setDisplayPowerMode(getBuiltInDisplay(), mode); 78 | } 79 | } catch (Exception e) { 80 | e.printStackTrace(); 81 | } finally { 82 | System.exit(0); 83 | } 84 | } 85 | 86 | private static IBinder getBuiltInDisplay() throws Exception { 87 | Method method; 88 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { 89 | method = SURFACE_CONTROL_CLASS.getMethod("getBuiltInDisplay", int.class); 90 | return (IBinder) method.invoke(null, 0); 91 | } else { 92 | method = SURFACE_CONTROL_CLASS.getMethod("getInternalDisplayToken"); 93 | return (IBinder) method.invoke(null); 94 | } 95 | } 96 | 97 | private static void setDisplayPowerMode(IBinder displayToken, int mode) throws Exception { 98 | Method method = SURFACE_CONTROL_CLASS.getMethod("setDisplayPowerMode", IBinder.class, int.class); 99 | method.invoke(null, displayToken, mode); 100 | } 101 | } 102 | ``` 103 | 104 | Then press **CTRL+X+Y+ENTER** and save it. 105 | 106 | And then create its Java CLASS file:- 107 | 108 | javac -Xlint:none -source 1.8 -target 1.8 -cp ~/android.jar DisplayToggle.java 109 | 110 | Then DEX it using:- 111 | 112 | dx --dex --output DisplayToggle.dex DisplayToggle.class 113 | 114 | You have compiled the DisplayToggle.dex file (around 2.5kb). 115 | 116 | Now copy it to internal storage to use it later. 117 | 118 | termux-setup-storage 119 | 120 |   121 | 122 | cp -f DisplayToggle.dex /storage/emulated/0 123 | 124 | # How To Use It 125 | 126 | In an ADB Shell (from Termux or PC):- 127 | 128 | #### To Turn Display OFF 129 | 130 | adb shell CLASSPATH=/storage/emulated/0/DisplayToggle.dex app_process / DisplayToggle 0 131 | 132 | #### To Turn Display ON 133 | 134 | adb shell CLASSPATH=/storage/emulated/0/DisplayToggle.dex app_process / DisplayToggle 2 135 | 136 | #### Note:- 137 | 138 | In Termux if you are rooted, you can just replace every `adb shell` with `su -c`. 139 | 140 | # Credits 141 | 142 | **[rom1v](https://blog.rom1v.com/2018/03/introducing-scrcpy/#run-a-java-main-on-android) - Method to make java code executable** 143 | 144 | **[CheerfulPianissimo](https://github.com/Genymobile/scrcpy/issues/2888#issuecomment-1452140829) - Base Java code to make this possible** 145 | --------------------------------------------------------------------------------