### Start Shizuku Server via ADB (Shell) Source: https://context7.com/thedjchi/shizuku/llms.txt Provides instructions and an example command to start the Shizuku server on non-rooted devices (Android 7-10) using ADB. This requires enabling USB debugging and executing a shell script located on the device's storage. ```bash # Enable USB debugging on the device first # Settings > Developer Options > USB debugging # Connect device and verify connection adb devices # Execute the start command (example - actual command shown in app) adb shell sh /sdcard/Android/data/moe.shizuku.privileged.api/files/start.sh # For persistent wireless connection (optional) adb tcpip 5555 ``` -------------------------------- ### Start Shizuku Server (Java) Source: https://context7.com/thedjchi/shizuku/llms.txt Demonstrates the server startup process in Java for Shizuku, including setting the app name, library path, and initializing the service. It also includes a helper method to wait for system services to become available before proceeding with initialization. ```java public static void main(String[] args) { DdmHandleAppName.setAppName("shizuku_server", 0); RishConfig.setLibraryPath(System.getProperty("shizuku.library.path")); Looper.prepareMainLooper(); new ShizukuService(); Looper.loop(); } private static void waitSystemService(String name) { while (ServiceManager.getService(name) == null) { try { LOGGER.i("service " + name + " is not started, wait 1s."); Thread.sleep(1000); } catch (InterruptedException e) { LOGGER.w(e.getMessage(), e); } } } ``` -------------------------------- ### Implement Intent-Based Control Receivers Source: https://context7.com/thedjchi/shizuku/llms.txt Demonstrates how to create BroadcastReceivers that listen for specific intents to start or stop the Shizuku service programmatically. ```kotlin class ManualStartReceiver : AuthenticatedReceiver() { override fun onAuthenticated(context: Context, intent: Intent) { val applicationId = BuildConfig.APPLICATION_ID if (intent.action != "${applicationId}.START") return ShizukuReceiverStarter.start(context) } } class ManualStopReceiver : AuthenticatedReceiver() { override fun onAuthenticated(context: Context, intent: Intent) { val applicationId = BuildConfig.APPLICATION_ID if (intent.action != "${applicationId}.STOP") return if (!ShizukuStateMachine.isRunning()) return ShizukuStateMachine.set(ShizukuStateMachine.State.STOPPING) runCatching { Shizuku.exit() } } } ``` -------------------------------- ### Starting Shizuku via Wireless Debugging (Android 11+) Source: https://context7.com/thedjchi/shizuku/llms.txt This section explains how to establish a connection and authenticate with the device's ADB daemon using wireless debugging for Android 11+ devices. The provided Kotlin code demonstrates the `AdbClient` class for managing this connection. ```APIDOC ## Starting Shizuku via Wireless Debugging (Android 11+) For unrooted Android 11+ devices, use wireless debugging which requires a one-time pairing process. The AdbClient handles the connection and authentication with the device's ADB daemon. ### Code Example (Kotlin) ```kotlin // AdbClient.kt - Connect and authenticate with ADB daemon class AdbClient(private val host: String, private val port: Int, private val key: AdbKey) : Closeable { fun connect() { val socket = Socket() val address = InetSocketAddress(host, port) socket.connect(address, 5000) socket.tcpNoDelay = true plainInputStream = DataInputStream(socket.getInputStream()) plainOutputStream = DataOutputStream(socket.getOutputStream()) // Send connection request write(A_CNXN, A_VERSION, A_MAXDATA, "host::") var message = read() if (message.command == A_STLS) { // TLS handshake for secure connection (Android 9+) write(A_STLS, A_STLS_VERSION, 0) val sslContext = key.sslContext tlsSocket = sslContext.socketFactory.createSocket(socket, host, port, true) as SSLSocket tlsSocket.startHandshake() tlsInputStream = DataInputStream(tlsSocket.inputStream) tlsOutputStream = DataOutputStream(tlsSocket.outputStream) useTls = true message = read() } else if (message.command == A_AUTH) { // Authentication with RSA key write(A_AUTH, ADB_AUTH_SIGNATURE, 0, key.sign(message.data)) message = read() if (message.command != A_CNXN) { write(A_AUTH, ADB_AUTH_RSAPUBLICKEY, 0, key.adbPublicKey) message = read() } } if (message.command != A_CNXN) error("Connection failed") } // Execute shell command on connected device fun command(cmd: String, listener: ((ByteArray) -> Unit)? = null) { val localId = 1 write(A_OPEN, localId, 0, cmd) var message = read() when (message.command) { A_OKAY -> { while (true) { message = read() val remoteId = message.arg0 if (message.command == A_WRTE) { if (message.data_length > 0) { listener?.invoke(message.data!!) } write(A_OKAY, localId, remoteId) } else if (message.command == A_CLSE) { write(A_CLSE, localId, remoteId) break } } } A_CLSE -> { val remoteId = message.arg0 write(A_CLSE, localId, remoteId) } } } } ``` ``` -------------------------------- ### Execute Shizuku Command Source: https://github.com/thedjchi/shizuku/wiki/Setup This command is generated by the Shizuku app and is unique to your device. Pasting this command into your terminal starts the Shizuku service. ```bash adb -s shell sh /data/local/tmp/startshizuku.sh ``` -------------------------------- ### Intent-Based Start/Stop for Automation Apps Source: https://context7.com/thedjchi/shizuku/llms.txt This section describes how to control Shizuku programmatically using broadcast intents. This allows integration with automation applications like Tasker, MacroDroid, or Automate to start or stop Shizuku services. ```APIDOC ## Intent-Based Start/Stop for Automation Apps Shizuku can be controlled programmatically using broadcast intents, enabling integration with automation apps like Tasker, MacroDroid, or Automate. ### ManualStartReceiver Handles the intent to start Shizuku. ```kotlin // ManualStartReceiver.kt - Handle start intent class ManualStartReceiver : AuthenticatedReceiver() { override fun onAuthenticated(context: Context, intent: Intent) { val applicationId = BuildConfig.APPLICATION_ID if (intent.action != "${applicationId}.START") return ShizukuReceiverStarter.start(context) } } ``` ### ManualStopReceiver Handles the intent to stop Shizuku. ```kotlin // ManualStopReceiver.kt - Handle stop intent class ManualStopReceiver : AuthenticatedReceiver() { override fun onAuthenticated(context: Context, intent: Intent) { val applicationId = BuildConfig.APPLICATION_ID if (intent.action != "${applicationId}.STOP") return if (!ShizukuStateMachine.isRunning()) return ShizukuStateMachine.set(ShizukuStateMachine.State.STOPPING) runCatching { Shizuku.exit() } } } ``` ### Usage Examples **To start Shizuku from Tasker or other automation apps:** - **Action**: `moe.shizuku.privileged.api.START` - **Package**: `moe.shizuku.privileged.api` **To stop Shizuku from automation apps:** - **Action**: `moe.shizuku.privileged.api.STOP` - **Package**: `moe.shizuku.privileged.api` ``` -------------------------------- ### Build Shizuku Manager Application (Bash) Source: https://context7.com/thedjchi/shizuku/llms.txt Instructions for cloning the Shizuku project repository and building the manager application using Gradle. It covers building both debug and release versions of the APK. ```bash # Clone with submodules (includes Shizuku-API) git clone --recurse-submodules https://github.com/thedjchi/Shizuku.git cd Shizuku # Build debug version (debuggable server for development) ./gradlew :manager:assembleDebug # Build release version ./gradlew :manager:assembleRelease # Output APK locations: # Debug: manager/build/outputs/apk/debug/manager-debug.apk ``` -------------------------------- ### Execute Release Build with Beta Flag Source: https://context7.com/thedjchi/shizuku/llms.txt Command-line instruction to trigger a release build for the manager module while enabling the beta versioning logic. ```bash ./gradlew :manager:assembleRelease -Pbeta ``` -------------------------------- ### Connect and Execute Commands via AdbClient Source: https://context7.com/thedjchi/shizuku/llms.txt Handles the ADB connection lifecycle, including TLS handshakes and RSA authentication. It also provides a method to execute shell commands and stream the output back to the caller. ```kotlin class AdbClient(private val host: String, private val port: Int, private val key: AdbKey) : Closeable { fun connect() { val socket = Socket() val address = InetSocketAddress(host, port) socket.connect(address, 5000) socket.tcpNoDelay = true plainInputStream = DataInputStream(socket.getInputStream()) plainOutputStream = DataOutputStream(socket.getOutputStream()) write(A_CNXN, A_VERSION, A_MAXDATA, "host::") var message = read() if (message.command == A_STLS) { write(A_STLS, A_STLS_VERSION, 0) val sslContext = key.sslContext tlsSocket = sslContext.socketFactory.createSocket(socket, host, port, true) as SSLSocket tlsSocket.startHandshake() tlsInputStream = DataInputStream(tlsSocket.inputStream) tlsOutputStream = DataOutputStream(tlsSocket.outputStream) useTls = true message = read() } else if (message.command == A_AUTH) { write(A_AUTH, ADB_AUTH_SIGNATURE, 0, key.sign(message.data)) message = read() if (message.command != A_CNXN) { write(A_AUTH, ADB_AUTH_RSAPUBLICKEY, 0, key.adbPublicKey) message = read() } } if (message.command != A_CNXN) error("Connection failed") } fun command(cmd: String, listener: ((ByteArray) -> Unit)? = null) { val localId = 1 write(A_OPEN, localId, 0, cmd) var message = read() when (message.command) { A_OKAY -> { while (true) { message = read() val remoteId = message.arg0 if (message.command == A_WRTE) { if (message.data_length > 0) { listener?.invoke(message.data!!) } write(A_OKAY, localId, remoteId) } else if (message.command == A_CLSE) { write(A_CLSE, localId, remoteId) break } } } A_CLSE -> { val remoteId = message.arg0 write(A_CLSE, localId, remoteId) } } } } ``` -------------------------------- ### Attach Application to Shizuku Server (Java) Source: https://context7.com/thedjchi/shizuku/llms.txt Handles the initial handshake between client applications and the Shizuku privileged service. It validates the client's package name, manages permission states, and establishes a connection by sending server information back to the client. ```java import android.content.pm.PackageManager; import android.os.Binder; import android.os.Bundle; import android.os.UserHandle; import android.util.Log; import java.util.List; import moe.shizuku.api.ShizukuApiConstants; import moe.shizuku.internal.content.IContentProviderUtils; import moe.shizuku.internal.content.IShizukuApplication; import moe.shizuku.internal.provider.BinderContainer; import moe.shizuku.internal.utils.ActivityManagerApis; import moe.shizuku.internal.utils.DeviceIdleControllerApis; import moe.shizuku.internal.utils.OsUtils; import moe.shizuku.internal.utils.PackageManagerApis; import moe.shizuku.internal.utils.PermissionManagerApis; import moe.shizuku.internal.utils.UserHandleCompat; // Assuming ClientManager, ClientRecord, and LOGGER are defined elsewhere public class ShizukuService extends /* BaseService */ { private static final String TAG = "ShizukuService"; private static final String ATTACH_APPLICATION_PACKAGE_NAME = "attach_application_package_name"; private static final String ATTACH_APPLICATION_API_VERSION = "attach_application_api_version"; private static final String BIND_APPLICATION_SERVER_UID = "bind_application_server_uid"; private static final String BIND_APPLICATION_SERVER_VERSION = "bind_application_server_version"; private static final String BIND_APPLICATION_SERVER_SECONTEXT = "bind_application_server_secontext"; private static final String BIND_APPLICATION_SERVER_PATCH_VERSION = "bind_application_server_patch_version"; private static final String BIND_APPLICATION_PERMISSION_GRANTED = "bind_application_permission_granted"; private static final String BIND_APPLICATION_SHOULD_SHOW_REQUEST_PERMISSION_RATIONALE = "bind_application_should_show_request_permission_rationale"; private static final String MANAGER_APPLICATION_ID = "moe.shizuku.manager"; private static final String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS"; private ClientManager clientManager = new ClientManager(); // Placeholder // ShizukuService.java - Handle client application attachment @Override public void attachApplication(IShizukuApplication application, Bundle args) { if (application == null || args == null) return; String requestPackageName = args.getString(ATTACH_APPLICATION_PACKAGE_NAME); if (requestPackageName == null) return; int apiVersion = args.getInt(ATTACH_APPLICATION_API_VERSION, -1); int callingPid = Binder.getCallingPid(); int callingUid = Binder.getCallingUid(); // Verify package belongs to calling UID List packages = PackageManagerApis.getPackagesForUidNoThrow(callingUid); if (!packages.contains(requestPackageName)) { throw new SecurityException("Request package does not belong to uid " + callingUid); } boolean isManager = MANAGER_APPLICATION_ID.equals(requestPackageName); ClientRecord clientRecord = null; if (clientManager.findClient(callingUid, callingPid) == null) { synchronized (this) { clientRecord = clientManager.addClient(callingUid, callingPid, application, requestPackageName, apiVersion); } } // Build reply with server info Bundle reply = new Bundle(); reply.putInt(BIND_APPLICATION_SERVER_UID, OsUtils.getUid()); reply.putInt(BIND_APPLICATION_SERVER_VERSION, ShizukuApiConstants.SERVER_VERSION); reply.putString(BIND_APPLICATION_SERVER_SECONTEXT, OsUtils.getSELinuxContext()); reply.putInt(BIND_APPLICATION_SERVER_PATCH_VERSION, ShizukuApiConstants.SERVER_PATCH_VERSION); if (!isManager) { reply.putBoolean(BIND_APPLICATION_PERMISSION_GRANTED, clientRecord.allowed); reply.putBoolean(BIND_APPLICATION_SHOULD_SHOW_REQUEST_PERMISSION_RATIONALE, false); } else { // Grant WRITE_SECURE_SETTINGS to manager app PermissionManagerApis.grantRuntimePermission(MANAGER_APPLICATION_ID, WRITE_SECURE_SETTINGS, UserHandleCompat.getUserId(callingUid)); } application.bindApplication(reply); } // Placeholder classes for compilation private static class ClientManager { public ClientRecord findClient(int uid, int pid) { return null; } public ClientRecord addClient(int uid, int pid, IShizukuApplication app, String packageName, int apiVersion) { return new ClientRecord(true); } // Placeholder } private static class ClientRecord { boolean allowed; ClientRecord(boolean allowed) { this.allowed = allowed; } } // Assume LOGGER is an instance of a logging class private static final Logger LOGGER = Logger.getLogger("ShizukuService"); private static class Logger { public static void e(Throwable tr, String msg, Object... args) { Log.e(TAG, String.format(msg, args), tr); } public static void i(String msg, Object... args) { Log.i(TAG, String.format(msg, args)); } public static Logger getLogger(String name) { return new Logger(); } } } ``` -------------------------------- ### Grant Required Permissions via ADB Source: https://github.com/thedjchi/shizuku/wiki/Troubleshooting These commands grant the necessary permissions for Shizuku to manage secure settings and run in the background, which is essential for automatic startup functionality. ```bash adb shell pm grant moe.shizuku.privileged.api android.permission.WRITE_SECURE_SETTINGS adb shell cmd appops set moe.shizuku.privileged.api RUN_IN_BACKGROUND allow adb shell cmd appops set moe.shizuku.privileged.api RUN_ANY_IN_BACKGROUND allow ``` -------------------------------- ### Define Project Targets and Dependencies Source: https://github.com/thedjchi/shizuku/blob/master/manager/src/main/jni/CMakeLists.txt Defines the libshizuku.so and adb shared library targets, linking necessary dependencies like BoringSSL and CXX. It also includes post-build commands to strip metadata from the resulting binaries in release mode. ```cmake find_package(boringssl REQUIRED CONFIG) find_package(cxx REQUIRED CONFIG) add_executable(libshizuku.so starter.cpp misc.cpp selinux.cpp cgroup.cpp) target_link_libraries(libshizuku.so log cxx::cxx) add_library(adb SHARED adb_pairing.cpp misc.cpp) target_link_libraries(adb log boringssl::crypto_static cxx::cxx) if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") add_custom_command(TARGET libshizuku.so POST_BUILD COMMAND ${CMAKE_STRIP} --remove-section=.comment "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libshizuku.so") add_custom_command(TARGET adb POST_BUILD COMMAND ${CMAKE_STRIP} --remove-section=.comment "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libadb.so") endif () ``` -------------------------------- ### Send Binder to Client Apps via ContentProvider (Java) Source: https://context7.com/thedjchi/shizuku/llms.txt Proactively sends the Shizuku server's binder interface to apps declared with the Shizuku permission. It utilizes Android's ContentProvider mechanism for inter-process communication and adds the app to a temporary power save whitelist to ensure delivery. ```java import android.os.Binder; import android.os.Bundle; import android.util.Log; import moe.shizuku.internal.content.IContentProviderUtils; import moe.shizuku.internal.provider.BinderContainer; import moe.shizuku.internal.utils.ActivityManagerApis; import moe.shizuku.internal.utils.DeviceIdleControllerApis; import moe.shizuku.internal.utils.IContentProvider; // Assuming LOGGER is an instance of a logging class public class ShizukuServiceUtils { private static final String TAG = "ShizukuServiceUtils"; // Assuming LOGGER is an instance of a logging class private static final Logger LOGGER = Logger.getLogger("ShizukuServiceUtils"); // ShizukuService.java - Send binder to authorized apps static boolean sendBinderToUserApp(Binder binder, String packageName, int userId) { // Add to power save whitelist to ensure delivery try { DeviceIdleControllerApis.addPowerSaveTempWhitelistApp(packageName, 30 * 1000, userId, 316/* PowerExemptionManager#REASON_SHELL */, "shell"); } catch (Throwable tr) { LOGGER.e(tr, "Failed to add %d:%s to power save temp whitelist", userId, packageName); } String name = packageName + ".shizuku"; IContentProvider provider = null; IBinder token = null; try { provider = ActivityManagerApis.getContentProviderExternal(name, userId, token, name); if (provider == null) { LOGGER.e("provider is null %s %d", name, userId); return false; } if (!provider.asBinder().pingBinder()) { LOGGER.e("provider is dead %s %d", name, userId); return false; } Bundle extra = new Bundle(); extra.putParcelable("moe.shizuku.privileged.api.intent.extra.BINDER", new BinderContainer(binder)); Bundle reply = IContentProviderUtils.callCompat(provider, null, name, "sendBinder", null, extra); if (reply != null) { LOGGER.i("send binder to user app %s in user %d", packageName, userId); return true; } return false; } catch (Throwable tr) { LOGGER.e(tr, "failed to send binder to user app %s in user %d", packageName, userId); return false; } finally { if (provider != null) { ActivityManagerApis.removeContentProviderExternal(name, token); } } } // Placeholder classes for compilation private static class Logger { public static void e(Throwable tr, String msg, Object... args) { Log.e(TAG, String.format(msg, args), tr); } public static void i(String msg, Object... args) { Log.i(TAG, String.format(msg, args)); } public static Logger getLogger(String name) { return new Logger(); } } } ``` -------------------------------- ### Implement Watchdog Service for Auto-Restart Source: https://context7.com/thedjchi/shizuku/llms.txt The WatchdogService monitors the Shizuku state machine and automatically triggers a restart if a crash is detected. It runs as a foreground service to ensure it remains active and provides high availability for dependent applications. ```kotlin class WatchdogService : Service() { private val stateListener: (ShizukuStateMachine.State) -> Unit = { if (it == ShizukuStateMachine.State.CRASHED) { showCrashNotification() ShizukuReceiverStarter.start(applicationContext) } } override fun onCreate() { super.onCreate() isRunning.set(true) ShizukuStateMachine.addListener(stateListener) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { if (intent?.action == "ACTION_STOP_SERVICE") { stopSelf() return START_NOT_STICKY } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { startForeground(NOTIFICATION_ID_WATCHDOG, buildNotification(), ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE) } else { startForeground(NOTIFICATION_ID_WATCHDOG, buildNotification()) } return START_STICKY } companion object { @JvmStatic fun start(context: Context) { try { context.startForegroundService(Intent(context, WatchdogService::class.java)) } catch (e: Exception) { Log.e("ShizukuApplication", "Failed to start WatchdogService: ${e.message}") } } @JvmStatic fun stop(context: Context) { context.stopService(Intent(context, WatchdogService::class.java)) } @JvmStatic fun isRunning(): Boolean = isRunning.get() } } ``` -------------------------------- ### Configure Dynamic Versioning in Gradle Source: https://context7.com/thedjchi/shizuku/llms.txt This script dynamically generates version codes and names based on the Git commit count and build properties. It supports a beta flag to append a suffix to the version name, ensuring unique identifiers for every build. ```groovy def gitCommitCount = Integer.parseInt("git rev-list --count HEAD".execute([], project.rootDir).text.trim()) def baseVersionName = "13.6.0" def isBeta = project.hasProperty("beta") ext { versionCode = gitCommitCount versionName = "${baseVersionName}.r${gitCommitCount}-thedjchi${if (isBeta) "-beta" else ""}" } ``` -------------------------------- ### Configure CMake Build and Optimization Flags Source: https://github.com/thedjchi/shizuku/blob/master/manager/src/main/jni/CMakeLists.txt Sets the C++ standard to 17 and applies global compiler flags to enforce strict code quality and optimize binary size. It includes conditional logic to apply link-time optimizations and symbol stripping for release builds. ```cmake cmake_minimum_required(VERSION 3.31) project("shizuku") set(CMAKE_CXX_STANDARD 17) add_compile_options(-Werror=format -fdata-sections -ffunction-sections -fno-exceptions -fno-rtti -fno-threadsafe-statics) if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") add_compile_options(-Os -flto -fvisibility=hidden -fvisibility-inlines-hidden) add_link_options(-flto -Wl,--exclude-libs,ALL -Wl,--gc-sections -Wl,--strip-all) else () add_definitions(-DDEBUG) endif () ``` -------------------------------- ### Authorization Management API Source: https://context7.com/thedjchi/shizuku/llms.txt API for managing app permissions within the Shizuku environment. ```APIDOC ## GET /auth/packages ### Description Retrieves a list of all packages that have requested Shizuku permissions. ### Method GET ### Endpoint /auth/packages ### Response #### Success Response (200) - **packages** (List) - A list of installed packages supporting Shizuku API. ## POST /auth/grant ### Description Grants Shizuku permission to a specific application. ### Method POST ### Endpoint /auth/grant ### Parameters #### Request Body - **packageName** (string) - Required - The package name of the app. - **uid** (int) - Required - The unique user ID of the app. ## POST /auth/revoke ### Description Revokes Shizuku permission from a specific application. ### Method POST ### Endpoint /auth/revoke ### Parameters #### Request Body - **packageName** (string) - Required - The package name of the app. - **uid** (int) - Required - The unique user ID of the app. ``` -------------------------------- ### Manage App Authorization Permissions Source: https://context7.com/thedjchi/shizuku/llms.txt The AuthorizationManager provides methods to list, check, grant, and revoke Shizuku permissions for specific packages. It handles legacy compatibility for older Shizuku versions and uses UID-based flag management for modern versions. ```kotlin object AuthorizationManager { private const val FLAG_ALLOWED = 1 shl 1 private const val FLAG_DENIED = 1 shl 2 private const val MASK_PERMISSION = FLAG_ALLOWED or FLAG_DENIED fun getPackages(): List { val packages: MutableList = ArrayList() if (Shizuku.isPreV11() || (Shizuku.getVersion() == 11 && Shizuku.getServerPatchVersion() < 3)) { for (user in ShizukuSystemApis.getUsers(useCache = false)) { val allPackages = ShizukuSystemApis.getInstalledPackages( (PackageManager.GET_META_DATA or PackageManager.GET_PERMISSIONS).toLong(), user.id ) for (pi in allPackages) { if (pi.applicationInfo?.metaData?.getBoolean("moe.shizuku.client.V3_SUPPORT") == true && pi.requestedPermissions?.contains(Manifest.permission.API_V23) == true) { packages.add(pi) } } } } else { packages.addAll(getApplications(-1)) } return packages } fun granted(packageName: String, uid: Int): Boolean { return if (Shizuku.isPreV11()) { ShizukuSystemApis.checkPermission(Manifest.permission.API_V23, packageName, uid / 100000) == PackageManager.PERMISSION_GRANTED } else { (Shizuku.getFlagsForUid(uid, MASK_PERMISSION) and FLAG_ALLOWED) == FLAG_ALLOWED } } fun grant(packageName: String, uid: Int) { if (Shizuku.isPreV11()) { ShizukuSystemApis.grantRuntimePermission(packageName, Manifest.permission.API_V23, uid / 100000) } else { Shizuku.updateFlagsForUid(uid, MASK_PERMISSION, FLAG_ALLOWED) } } fun revoke(packageName: String, uid: Int) { if (Shizuku.isPreV11()) { ShizukuSystemApis.revokeRuntimePermission(packageName, Manifest.permission.API_V23, uid / 100000) } else { Shizuku.updateFlagsForUid(uid, MASK_PERMISSION, 0) } } } ``` -------------------------------- ### Check ADB Devices Connection Source: https://github.com/thedjchi/shizuku/wiki/Setup This command verifies that your Android device is connected to your computer and recognized by ADB (Android Debug Bridge). Ensure your device is in USB debugging mode and authorized. ```bash adb devices ``` -------------------------------- ### Watchdog Service Management Source: https://context7.com/thedjchi/shizuku/llms.txt Endpoints for controlling the Shizuku Watchdog service, which ensures the server remains active. ```APIDOC ## POST /service/watchdog/start ### Description Starts the Shizuku Watchdog service as a foreground service to monitor server status. ### Method POST ### Endpoint /service/watchdog/start ### Parameters #### Request Body - **context** (Context) - Required - The application context to start the service. ### Request Example { "action": "start" } ### Response #### Success Response (200) - **status** (string) - Returns success status of service initialization. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.