用户服务 UserService:在你的代码跑进服务进程时用
特权命令能做的事有限,真正强大的玩法是:把自己写的代码(Binder 服务)放进 Stellar 的服务进程里,以特权身份运行。这就是用户服务机制,接口形态与 Shizuku 的 UserService 一脉相承。
绑定流程
val args = UserServiceArgs.Builder(MyUserService::class.java)
.processNameSuffix("myservice") // 进程名后缀,默认 "userservice"
.versionCode(BuildConfig.VERSION_CODE.toLong())
.tag("my-tag") // 可选标签
.serviceMode(ServiceMode.DAEMON) // 服务模式
.build()
StellarUserService.bindUserService(args, object : StellarUserService.ServiceCallback {
override fun onServiceConnected(service: IBinder) { /* 拿到 Binder,开始调用 */ }
override fun onServiceDisconnected() { /* 服务断开 */ }
override fun onServiceStartFailed(errorCode: Int, message: String) { /* 可选实现 */ }
})
UserServiceArgs 参数表
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| className | 必填 | — | 服务类完整类名 |
| processNameSuffix | String | userservice | 进程名后缀 |
| debug | Boolean | false | 调试模式 |
| use32Bit | Boolean | false | 32 位进程 |
| versionCode | Long | 0 | 服务版本号 |
| tag | String? | null | 可选标签 |
| serviceMode | ServiceMode | ONE_TIME | 运行模式 |
两种服务模式
- ONE_TIME:一次性服务,客户端断开后服务自动停止,适合短事务;
- DAEMON:守护模式,服务持续运行直到显式停止,适合常驻监听。
配套接口
unbindUserService(args):解绑;peekUserService(args):拿现有 Binder(若存活);getUserServiceCount():当前活跃用户服务数;UserServiceHelper:destroy/isAlive/getUid/getPid四个辅助方法。
两个注意点
- 命名约定:AIDL 接口按
I<ServiceName>命名(服务类MyUserService对应IMyUserService); - 独立 DEX 模式已临时删除:相关构建配置在当前文档中标记为暂不可用,按普通方式编译即可。
服务随主服务停止而终止(v1.0.10 起主服务停止会自动终止所有用户服务),驻留策略见双进程互守。