rikkaapps / shizuku-api Goto Github PK
View Code? Open in Web Editor NEWThe API and the developer guide for Shizuku and Sui.
License: MIT License
The API and the developer guide for Shizuku and Sui.
License: MIT License
I've noticed that the demo shows only about getting the instance via SystemServiceHelper.getSystemService
.
But what about other types of classes? For example Singleton classes like Runtime
, which you need to reach its instance via a static function (Runtime.getRuntime()
) ?
And what about classes that need to be instantiated by the library, including those that have multiple arguments for the CTOR (such as ProcessBuilder
, which is created via Runtime.getRuntime().exec
)?
Are both of these possible to reach?
I want send system broadcast
adb shell settings put global airplane_mode_on 0/1
# and send broadcast android.intent.action.AIRPLANE_MODE
Can it complete?
Thanks!
I'm try
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL"
tools:ignore="ProtectedPermissions" />
SystemServiceHelper.getSystemService(Context.CONNECTIVITY_SERVICE);
but error...
I'm attempting to load an APK using DexClassLoader within the Shizuku service. It all seems to work well and I can call methods (and have also got LSPlant working via Aliucord's Hook library too), but when trying to call JNI from within the APK, it seems to stop working.
My intentions are to try to run the recognition code for Ambient Music within Shell, which in theory would work - I've already got a PoC working as a system app (no Xposed or model loading needed as LSPlant can stop the framework calls and instead trigger it manually), but the ultimate goal is to get it working with just Shizuku. Shell has access to record audio using the hotword mic, but simply recording the audio and sending it back to a client isn't sufficient as there's also something in the recognition (not this crash) that requires being a system app.
Minimal setup:
/data/local/tmp/aiai.apk
. Make sure it is this build, as for this setup we'll be using an obfuscated class name.libsense.so
from the APK into the project as a JNI libval context = Class.forName("android.app.ActivityThread")
.getMethod("currentApplication")
.invoke(null) as Context
val apkPath = File("/data/local/tmp", "aiai.apk").absolutePath
val sourceDir = context.packageManager.getApplicationInfo(BuildConfig.APPLICATION_ID, 0).sourceDir
var librarySearchPath: String = sourceDir.toString() + "!/lib/" + Build.SUPPORTED_ABIS[0]
val systemLibrarySearchPath = System.getProperty("java.library.path")
if (!TextUtils.isEmpty(systemLibrarySearchPath)) {
librarySearchPath += File.pathSeparatorChar.toString() + systemLibrarySearchPath
}
val classLoader = DexClassLoader(apkPath, ".", librarySearchPath, ClassLoader.getSystemClassLoader())
System.loadLibrary("sense")
val lfr = classLoader.loadClass("lfr").getDeclaredConstructor().apply {
isAccessible = true
}.newInstance()
val nnfpRecognizer = classLoader.loadClass("com.google.audio.ambientmusic.NnfpRecognizer")
.getConstructor(lfr::class.java, Array<String>::class.java, Array<String>::class.java)
.newInstance(lfr, emptyArray<String>(), emptyArray<String>())
04-22 01:46:26.851 22051 22074 E com.kieronquinn.app.shizukutest:shizuku: No implementation found for long com.google.audio.ambientmusic.NnfpRecognizer.init(java.lang.String[], java.lang.String[], byte[]) (tried Java_com_google_audio_ambientmusic_NnfpRecognizer_init and Java_com_google_audio_ambientmusic_NnfpRecognizer_init___3Ljava_lang_String_2_3Ljava_lang_String_2_3B)
04-22 01:46:26.851 22051 22074 E JavaBinder: *** Uncaught remote exception! (Exceptions are not yet supported across processes.)
04-22 01:46:26.851 22051 22074 E JavaBinder: java.lang.reflect.InvocationTargetException
04-22 01:46:26.851 22051 22074 E JavaBinder: at java.lang.reflect.Constructor.newInstance0(Native Method)
04-22 01:46:26.851 22051 22074 E JavaBinder: at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
04-22 01:46:26.851 22051 22074 E JavaBinder: at com.kieronquinn.app.shizukutest.ShizukuService.start(ShizukuService.kt:77)
04-22 01:46:26.851 22051 22074 E JavaBinder: at com.kieronquinn.app.shizukutest.IShizukuService$Stub.onTransact(IShizukuService.java:59)
04-22 01:46:26.851 22051 22074 E JavaBinder: at android.os.Binder.execTransactInternal(Binder.java:1179)
04-22 01:46:26.851 22051 22074 E JavaBinder: at android.os.Binder.execTransact(Binder.java:1143)
04-22 01:46:26.851 22051 22074 E JavaBinder: Caused by: java.lang.UnsatisfiedLinkError: No implementation found for long com.google.audio.ambientmusic.NnfpRecognizer.init(java.lang.String[], java.lang.String[], byte[]) (tried Java_com_google_audio_ambientmusic_NnfpRecognizer_init and Java_com_google_audio_ambientmusic_NnfpRecognizer_init___3Ljava_lang_String_2_3Ljava_lang_String_2_3B)
04-22 01:46:26.851 22051 22074 E JavaBinder: at com.google.audio.ambientmusic.NnfpRecognizer.init(Native Method)
04-22 01:46:26.851 22051 22074 E JavaBinder: at com.google.audio.ambientmusic.NnfpRecognizer.<init>(PG:2)
04-22 01:46:26.851 22051 22074 E JavaBinder: ... 6 more
I've made the code identical to how Shizuku starts the Java code from a shell service, other than loading the source directory using PackageManager.
I've also tried:
static {}
None of these make any difference, the exception is identical.
I've also verified that the function in the library is exported:
There's no other relevant logcat output either.
What's really strange is that using Hook does work, even though it also uses native libraries in exactly the same way. Those are loaded fine, and methods are hooked without a problem.
Obviously this is quite a specific edge case, so if there's something that prevents this working in the system that simply isn't surfacing in the logcat, I'll happily move on and make the mod require a Magisk module to make it a system app.
Thanks!
This is a massive edge case, but I've found a scenario that it's needed. Not sure if it's a "bug" in the Manager or an API feature request, so I've put it here, but feel free to move it.
Basically, if you start Shizuku on a rooted device, subsequent calls to getCallingUid()
(when not handling a transaction from the app) will return 0
, root
. If the Shizuku service has been started by ADB, it will return 2000
(com.android.shell
). This is expected, as the service has been started by those UIDs originally.
However, there are some cases (eg. the launcherapps
and shortcut
system services), where root
is worse than shell
, and the system service will actually reject calls from root, but take them from shell. Here's an example:
ILauncherApps.aidl
(you'll also need to create the stubs for ParceledListSlice + its parent and ShortcutQueryWrapper, sorry - I can provide more if needed)
package android.content.pm;
import android.os.UserHandle;
import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutQueryWrapper;
interface ILauncherApps {
ParceledListSlice getShortcuts(String callingPackage, in ShortcutQueryWrapper query, in UserHandle user) = 13;
}
In a Shizuku service:
private val launcherApps by lazy {
val launcherAppsProxy = SystemServiceHelper.getSystemService("launcherapps")
ILauncherApps.Stub.asInterface(launcherAppsProxy)
}
//context is the system context, get it however you prefer
private fun getUserHandle(): UserHandle {
return Context::class.java.getMethod("getUser").invoke(context) as UserHandle
}
override fun getShortcuts(query: ShortcutQueryWrapper) {
val token = clearCallingIdentity()
Log.d("TTSS", "getShortcuts ${getCallingUid()}")
val shortcuts = launcherApps.getShortcuts("com.android.shell", query, getUserHandle()) as ParceledListSlice<ShortcutInfo>
Log.d("TTSS", "Got shortcuts! Size ${shortcuts.list.size}")
restoreCallingIdentity(token)
}
For the query you can use the generic:
val query = ShortcutQueryWrapper(LauncherApps.ShortcutQuery().apply {
setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC or LauncherApps.ShortcutQuery.FLAG_MATCH_MANIFEST)
})
When running from Shizuku started with root, the call will result in a crash:
11-09 00:14:12.617 30021 30021 E AndroidRuntime: Process: com.kieronquinn.app.taptap, PID: 30021
11-09 00:14:12.617 30021 30021 E AndroidRuntime: java.lang.SecurityException: Calling package name mismatch
11-09 00:14:12.617 30021 30021 E AndroidRuntime: at android.os.Parcel.createExceptionOrNull(Parcel.java:2425)
11-09 00:14:12.617 30021 30021 E AndroidRuntime: at android.os.Parcel.createException(Parcel.java:2409)
11-09 00:14:12.617 30021 30021 E AndroidRuntime: at android.os.Parcel.readException(Parcel.java:2392)
11-09 00:14:12.617 30021 30021 E AndroidRuntime: at android.os.Parcel.readException(Parcel.java:2334)
11-09 00:14:12.617 30021 30021 E AndroidRuntime: at com.kieronquinn.app.taptap.shizuku.ITapTapShizukuService$Stub$Proxy.getShortcuts(ITapTapShizukuService.java:151)
When running from Shizuku started with ADB, the call will work fine and a list of shortcuts will be returned.
We can trace the crash back to here:
void verifyCallingPackage(String callingPackage) {
int packageUid = -1;
try {
packageUid = AppGlobals.getPackageManager().getPackageUid(callingPackage,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_UNINSTALLED_PACKAGES,
UserHandle.getUserId(getCallingUid()));
} catch (RemoteException ignore) {
}
if (packageUid < 0) {
Log.e(TAG, "Package not found: " + callingPackage);
}
if (packageUid != injectBinderCallingUid()) {
throw new SecurityException("Calling package name mismatch");
}
}
//...
int injectBinderCallingUid() {
return getCallingUid();
}
Which as you can see is checking the calling UID against the one found for the package name. It's worth noting that passing "android" as the package name does not work here either, and there's no package name for root, so it will always fail with that.
Just for the sake of it you can also prove this in the shell:
When running as shell
:
raven:/ $ service call launcherapps 13 s16 com.android.shell
Result: Parcel(
0x00000000: fffffffc 00000067 00740041 00650074 '....g...A.t.t.e.'
0x00000010: 0070006d 00200074 006f0074 00690020 'm.p.t. .t.o. .i.'
0x00000020: 0076006e 006b006f 00200065 00690076 'n.v.o.k.e. .v.i.'
0x00000030: 00740072 00610075 0020006c 0065006d 'r.t.u.a.l. .m.e.'
0x00000040: 00680074 0064006f 00270020 006e0069 't.h.o.d. .'.i.n.'
0x00000050: 00200074 006e0061 00720064 0069006f 't. .a.n.d.r.o.i.'
0x00000060: 002e0064 0073006f 0055002e 00650073 'd...o.s...U.s.e.'
0x00000070: 00480072 006e0061 006c0064 002e0065 'r.H.a.n.d.l.e...'
0x00000080: 00650067 00490074 00650064 0074006e 'g.e.t.I.d.e.n.t.'
0x00000090: 00660069 00650069 00280072 00270029 'i.f.i.e.r.(.).'.'
(etc., it's passed the package name check that's what matters)
When running as root
:
raven:/ # service call launcherapps 13 s16 com.android.shell
Result: Parcel(
0x00000000: ffffffff 0000001d 00610043 006c006c '........C.a.l.l.'
0x00000010: 006e0069 00200067 00610070 006b0063 'i.n.g. .p.a.c.k.'
0x00000020: 00670061 00200065 0061006e 0065006d 'a.g.e. .n.a.m.e.'
0x00000030: 006d0020 00730069 0061006d 00630074 ' .m.i.s.m.a.t.c.'
0x00000040: 00000068 00000000 'h....... ')
My suggestion for getting around this would be to simply run the start command from the manager as shell
, with su -l 2000
- if that is possible with how Shizuku works (admittedly I've not checked). If possible, to maintain compatibility, it could also be an API option (hence making the issue here).
If you need any more code, I can send a WIP version of Tap, Tap that has this issue.
Cheers
我运行了demo,点击bindUserService,然后屏幕上输出了一串字符串。接着,我修改了UserService doSomething()方法, 在原本的字符串后面加上了一些内容,可是当我再次运行demo,点击bindUserService,得到的还是上次的结果。
While using lambda to add listener in Kotlin, it seems that the listener cannot be removed in this case.
For example,
Shizuku.addRequestPermissionResultListener { _, _ -> doSomething() }
There is no way to remove this particular listener. Since I only added this one listener, it would be better to remove them all at once.
Maybe we can add a function named removeAllListeners
in a easy case.
public static void removeAllListeners() {
RECEIVED_LISTENERS.clear();
DEAD_LISTENERS.clear();
PERMISSION_LISTENERS.clear();
}
or divide this function into 3 cases
I got a compilation error:
Manifest merger failed : uses-sdk:minSdkVersion 23 cannot be smaller than version 24 declared in library [:api] C:\StudioProjects\Shizuku-API\api\build\intermediates\merged_manifest\debug\AndroidManifest.xml as the library might be using APIs not available in 23
Suggestion: use a compatible library with a minSdk of at most 23,
or increase this project's minSdk version to at least 24,
or use tools:overrideLibrary="rikka.shizuku.api" to force usage (may lead to runtime failures)
Delete all
Delete all
Originally posted by @Ofa234 in #14 (comment)
I am confused about why i dont get rish use without preceeding it with sh.
Sh wouldnt work termix previously. Now it worka without really working and rish doesnt work on its own.
I read the README, but I wasn't able to find.
rish/src/main/java/rikka/rish/RishTerminal.java
这行写错了吧:
ttyFd = start(tty, getFd(stdin, 1), getFd(stdout, 0), getFd(stdout, 0));
When editing the rish file to add a package name, can multiple packages be added in the same file?
from ApplicationUtils.getApplication() inside UserService, I'm getting null.
Anyone knows How to use app context in UserService?
Shizuku API 拿到權限后,需要怎麽樣才能調用 adb 的指令?
請求各位大佬指點。
I'm working on moving DarQ [I think you suggested I move it a long time ago and it was rejected due to libsuperuser being more suited to the task, which with the advent of local ADB is no longer the case] to use a hybrid of Shizuku for ADB and libsu's bound services for root, and it's working well - except that I need the service to outlast the Application.
libsu handles this gracefully by allowing services to be daemons (see here), which seems to be similarly possible with Shizuku by simply not unbinding the service.
However, when the app needs to bind the service again (for example when the user launches the settings for config), Shizuku doesn't have a way of cleaning up the running daemon service to start a new one for binding. I can do it easily with libsu using RootService.stop(...)
, which removes any remote services with that intent, but the Shizuku.unbindUserService()
method expects a service connection which I no longer have - and passing a dummy one doesn't remove the remote service. This means that when I call RootService.bindUserService
it starts a new one and I end up with two running.
Could a similar stop()
method to libsu's be added please?
Settings.Secure.putString(resolver,
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
String.format("%s/%s",packageName,serviceName));
Settings.Secure.putInt(resolver,
Settings.Secure.ACCESSIBILITY_ENABLED, 1);
The "resolver" object here cannot be obtained from UserService.
Currently every call of rish will result in a dex process creation, which is very resources inefficient. Why not use c++ binding instead like described here?
我想在授权shizuku后执行shell命令,但是在demo没有翻到此类的操作,看了其他issue有提到,是需在service里执行命令吗?然后在bindservice后调用?
Shizuku.OnBinderReceivedListener
事件接收不到,请求权限就会抛出异常,问题出现在rikka.sui.Sui
的IBinder received = reply.readStrongBinder();
,received
是null
。
步骤:
provider
,添加FreeReflectionApplication
,调用Sui.init(BuildConfig.APPLICATION_ID);
Activity
绑定事件I hope I'm asking this in the correct place. Couldn't find a forum for this...
About my question, suppose you reach the PackageManager class function to disable some app.
If for some reason this API changes in some Android version, can I use Shizuku to call more official commands like on adb?
Meaning in adb it's :
adb shell pm disable PACKAGE_NAME
Is the same thing possible via Shizuku?
Hi
I can't seem to find any info about APP - API version compatibility other than the "preV11" check
Will the current version of the API (12.1.0) continue to work correctly with newer versions of Shizuku e.g. when shizuku 14 and shizuku-api 14 come out? Is compatibility guaranteed until a specific version?
please don't deprecate the Shizuku.newProcess.
This is a great tool for non-root systems. Everything is working well when in screen on state. however after screen off with 5 minutes, we get no response when executing the shell scripts. So may know if it supports? Thanks!
adb shell pm grant com.arumcomm.crashlogviewer android.permission.PACKAGE_USAGE_STATS
adb shell pm grant com.arumcomm.crashlogviewer android.permission.READ_LOGS
没打完字就提交了,按错了,在编辑 已编辑完成
测试的Shizuku版本为v12.6.2
测试过程中使用了Tasker和MacroDroid,均已经修改了RISH_APPLICATION_ID
(MacroDroid需要使用MD-Helper,因为高版本Android受到Google Play政策限制MD无法申请到存储空间权限)。
将rish与dex文件释放在/storage/emulated/0/shizuku
文件夹,根据文档提示,在两者的shell脚本任务中尝试执行命令。
sh /storage/emulated/0/shizuku/rish -c "ls"
但没有任何的输出,具体表现为命令卡在了这里,没有任何的输出,设定的超时时间之后执行中断。
我不太确定是否是我对这个工具的一些使用理解上出了一些问题,能否提示一些调试这个功能有关的细节以便我分析问题?谢谢
我尝试以以下方式调用非SDK系统API,但是不起作用。
public static final Singleton<IPowerManager> POWER_MANAGER = new Singleton<IPowerManager>() {
@Override
protected IPowerManager create() {
return IPowerManager.Stub.asInterface(new ShizukuBinderWrapper(SystemServiceHelper.getSystemService(Context.POWER_SERVICE)));
}
};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
//这个不是隐藏api,可以访问到值
HiddenApiBypass.invoke(IPowerManager::class.java, ShizukuSystemServerApi.POWER_MANAGER.get(), "isPowerSaveMode", true);
//这个是隐藏api,调用后没有反应
HiddenApiBypass.invoke(IPowerManager::class.java, ShizukuSystemServerApi.POWER_MANAGER.get(), "setPowerSaveModeEnabled", true);
}
请问如果我要调用PowerManager里的隐藏方法我应该如何操作呢?
因为项目需要,故要调用以下Shell:
/system/xbin/bstk/su
mount /system -o remount,rw
但看了半天开发文档还是摸不着头脑,故发个issue求解答
My Redmi Note 9 Pro is rooted and running Android 12. http://bit.ly/amirooted #android
启用coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.0.2'
对高版本API进行脱糖后,List的removeIf方法会被替换成调用iterator遍历,然后调用remove删除。
巧的是CopyOnWriteArrayList.COWIterator不支持remove方法,这导致Shizuku类里面几个调用removeIf的方法都会报错。
修改建议是把字段类型均改成CopyOnWriteArrayListCompat而不是List:
private static final CopyOnWriteArrayListCompat<ListenerHolder<OnBinderReceivedListener>> RECEIVED_LISTENERS = new CopyOnWriteArrayListCompat<>();
private static final CopyOnWriteArrayListCompat<ListenerHolder<OnBinderDeadListener>> DEAD_LISTENERS = new CopyOnWriteArrayListCompat<>();
private static final CopyOnWriteArrayListCompat<ListenerHolder<OnRequestPermissionResultListener>> PERMISSION_LISTENERS = new CopyOnWriteArrayListCompat<>();
I want to try some other strategies if shizuku setup fail, so I try to make this into coroutine. The shizuku permision dialog appeared and i clicked yes, but onRequestPermissionResult never called. It works well without coroutine. Any one know why.
suspend fun tryShizuku() = runCatching {
suspendCoroutine { cont ->
Log.d(TAG, "try shizuki") // <-- this called
Shizuku.addRequestPermissionResultListener(
object : OnRequestPermissionResultListener {
override fun onRequestPermissionResult(requestCode: Int, grantResult: Int) {
Log.d(TAG, "onRequestPermissionResult") // <--- this not called
Shizuku.removeRequestPermissionResultListener(this)
if (grantResult != PERMISSION_GRANTED) {
cont.resumeWithException(Exception())
return
}
val userServiceArgs = UserServiceArgs(
ComponentName(
BuildConfig.LIBRARY_PACKAGE_NAME.replace(".task", ".host"),
shizukiServiceClass.getName()
)
)
.daemon(false)
.processNameSuffix("service")
.debuggable(BuildConfig.DEBUG)
.version(1)
Shizuku.bindUserService(userServiceArgs, RootServiceConnection())
cont.resume(Unit)
}
})
Shizuku.requestPermission(0)
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.