Set up a new account on the XDA Developers Forums
Sign in to the XDA Developers Forums
Add swipe gestures to any Android, no root
Make your phone easier to use with one hand, no root
The best way to access XDA on your phone
A sweet, feature-filled launcher with a beautiful UX.
XDA’s official marketplace for buying and selling tech
Premium videos
There are a lot of reasons the permissions normally granted to your app might not be enough. Maybe you’re like me and enjoy creating hacky apps that abuse the Android API. Some of the APIs I use are locked behind special permissions. Sometimes only the shell user (ADB) or system can access them. There’s a solution though — Shizuku.
Shizuku allows you to call system APIs almost directly, and entirely in Java or Kotlin. This guide will show you how to implement and use Shizuku.
Before we go about using Shizuku, it might be helpful to know what exactly it is. If you’re familiar with Magisk, then Shizuku is similar. But instead of managing root access, it manages shell access.
Shizuku runs its own process with shell-level permissions. How the user activates that process depends on their device, Android version, and choice. Shizuku can be activated through ADB, through on-device wireless ADB (on Android 11 and later), or through root access. Apps implementing Shizuku can then request permission to use that process to perform elevated operations.
While shell-level access to the system doesn’t let you do as much as root, it still gives you more access than a normal app would. On top of that, the way Shizuku works lets you use the Android APIs almost like normal. You don’t have to rely on shell commands (although you can if you want to).
If your app needs special permissions that can only be granted through ADB (or with root), Shizuku and Android 11 make a great pairing. You can just use Shizuku to grant special permissions fully on-device.
Even with devices that aren’t on Android 11, Shizuku can be useful. The app provides instructions and scripts for users so you don’t have to.
Adding Shizuku to your app isn’t the simplest, but it’s not hard, either. Unfortunately, the developer documentation isn’t exactly complete, but this article has you covered. Here’s how to integrate Shizuku into your app.
The first step is to add the Shizuku dependencies. In your module-level build.gradle, add the following to the dependencies block.
Make sure to update the version if needed. 11.0.3 is the latest at the time of writing.
In order for Shizuku to work, you need to add a provider block to your app’s manifest. Open AndroidManifest.xml and add the following inside the application block.
For authorization, Shizuku uses a runtime permission. We’ll get into granting that permission in a bit. For now, add it to AndroidManifest.xml inside the manifest block.
Now that all of that is added, the basic integration is done. Let Gradle do a project sync, and continue on to Usage.
Before going into how to use Shizuku, let’s talk about making sure it’s actually available to use.
Before checking to see if the permission is granted, and before making API calls through Shizuku, you can make sure those checks and calls will succeed with the following method:
Shizuku.pingBinder()
If Shizuku is installed and running, this will return true. Otherwise, it will return false.
Since Shizuku uses a runtime permission, it has to be granted to your app before you can do anything with shell access. There are also two API versions in circulation, with different ways of granting it. This section will show you how to handle both.
Before you request the permission, the best thing to do is to check if you already have it. If you do, you can continue with whatever you need to do. Otherwise, you’ll need to request it before continuing.
To check if you have permission to use Shizuku, you can use the following. This code is assuming you’re running it inside an Activity.
Kotlin:
Java:
If you need to request permission to use Shizuku, here’s how.
The SHIZUKU_CODE variable used below should be an integer with a steady value (static variable).
Kotlin:
Java:
To listen for the result, you’ll need to override Activity’s onRequestPermissionsResult() method. You’ll also need to implement Shizuku.OnRequestPermissionResultListener. The example I’m going to show assumes your Activity implements that interface, but you can implement it in a variable if you want.
Kotlin:
Java:
Now that Shizuku is set up and permissions are granted, you can start actually calling APIs using Shizuku. The process here is a little different than you might be used to. Instead of calling getSystemService() and casting to something like WindowManager, you’ll have to use the internal APIs for these instead (e.g., IWindowManager).
Shizuku includes a bypass for Android’s hidden API blacklist, so you won’t need to worry about that when using it. If you’re curious how to bypass that yourself though, check out my previous tutorial.
Here’s a quick example (using reflection) showing you how you can get an instance of IPackageManager and use it to grant an app a runtime permission.
Kotlin:
Java:
The process for other APIs is similar. Get the references to the class and its Stub sub-class. Get the reference to the asInterface method for the Stub class. Get the references to the methods you want from the class itself. Then, invoke the asInterface method reference you have, replacing "package" above with whatever service you need. That instance can then be passed for method invocations.
Pro-tip: you can avoid using reflection altogether if you install a modified SDK. Check out anggrayudi’s GitHub repository for the modified SDKs and installation instructions. With this installed, the above code (in Kotlin) becomes a whole lot simpler.
Any AIDL-based APIs can be used with this method from anywhere in your app, as long as Shizuku is running and your app has permission.
While the Binder method covers most use-cases, there may be times where you need an API that doesn’t have a direct Binder interface. In that case, you can use the User Service feature in Shizuku.
This method works similarly to a normal Service in Android. You “start” it, communicate by binding to it with a ServiceConnection, and run your logic in the service class. The difference is you aren’t using Android’s Service, and anything inside the service runs with ADB permissions.
Now there are some limitations. The User Service runs in a completely separate process and user, so you can’t interact with the rest of your app except through your own AIDL callbacks and Binders. Since it’s also not running in a proper app process, some things like binding Android Services may not work properly.
This also requires Shizuku version 10 or later. While most sources for the app have version 11 currently, you should still include a version check, which will be included in the example.
To get started, you’ll need to create a new AIDL file. You can do this in Android Studio by right-clicking anything in the Android file-view, hovering over the “New” option, and choosing the “AIDL” option. Enter the name of the file (e.g., “IUserService”), and Android Studio will create a template file for you.
If you aren’t familiar with how AIDLs work, be sure to check out Google’s documentation.
Remove the template methods from the AIDL and then add a destroy() method with the proper ID for Shizuku. This will be called when Shizuku is killing the User Service, and should be used to clean up any references or ongoing logic you have.
Example AIDL:
The next thing to do is actually implement the AIDL.
Java:
Kotlin:
The above examples assume you have the Android Hidden API SDK installed.
Now that the User Service is defined and implemented, it’s time to get it set up for use. The first thing you should do is define a ServiceConnection where you want to communicate with it (e.g., from the main Activity in your app).
Java:
Kotlin:
The binder variable is what you’ll be using to communicate with the User Service from your app. To check if it’s available for use, just check that it’s not null and that pingBinder() returns true, just like in the code example above.
Before you can control the User Service, you’ll need to define some arguments for Shizuku to use when starting and stopping it. These include things like actually telling Shizuku the class name of the service, specifying the process suffix, whether or not it’s debuggable, and what version it is.
Java:
Kotlin:
The start and bind actions and the stop and unbind actions are unified in Shizuku. There aren’t separate start and bind methods or stop and unbind methods.
Here’s how to start and bind the User Service.
Java:
Kotlin:
Here’s how to stop and unbind the User Service.
Java:
Kotlin:
Once the User Service is started, you can start using it. Simply check whether the binder variable is non-null and pingable, and then make your method call.
Java:
Kotlin:
If you followed through all of that, you should now have a working Shizuku integration. Just remember to tell your users to install Shizuku, and to properly check that Shizuku is available before trying to use it.


XDA » Tutorials » Advanced Android Development: Elevate app permissions using Shizuku
Started out rooting and installing custom ROMs before moving onto modifying Android apps in Smali and subsequently developing various customization and utility apps for Android, such as SystemUI Tuner. Check me out on Twitter: https://twitter.com/wander1236.
Receive the freshest Android & development news right in your inbox!

XDA Developers was founded by developers, for developers. It is now a valuable resource for people who want to make the most of their mobile devices, from customizing the look and feel to adding new functionality.
Are you a developer? | Terms of Service
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
Copyright © XDA

source