Rakenduse lubade tõstmine Shizuku raamatukogu abil

Juurdumine pole kõigi jaoks. Siit saate teada, kuidas saate Shizuku teeki kasutades oma rakendusele kõrgemaid kestataseme õigusi hankida.

On palju põhjuseid, miks teie rakendusele tavaliselt antud load ei pruugi olla piisavad. Võib-olla olete nagu mina ja naudite Android API-d kuritarvitavate häkkivate rakenduste loomist. Mõned minu kasutatavad API-d on lukustatud erilubade taha. Mõnikord pääseb neile juurde ainult shell kasutaja (ADB) või süsteem. Siiski on lahendus - Shizuku.

Shizuku võimaldab teil helistada süsteemi API-dele peaaegu otse ja täielikult Java või Kotlini keeles. See juhend näitab teile, kuidas Shizukut rakendada ja kasutada.

Mis on Shizuku?

Enne kui hakkame Shizuku kasutama, võib olla kasulik teada, mis see täpselt on. Kui olete tuttav Magisk, siis Shizuku on sarnane. Kuid juurjuurdepääsu haldamise asemel haldab see shell-juurdepääsu.

Shizuku käitab oma protsessi kestataseme lubadega. Kuidas kasutaja selle protsessi aktiveerib, sõltub tema seadmest, Androidi versioonist ja valikust. Shizuku saab aktiveerida läbi ADB, läbi seadmesisese juhtmevaba ADB (

Android 11 ja uuemates versioonides) või juurjuurdepääsu kaudu. Shizukut rakendavad rakendused saavad seejärel taotleda luba selle protsessi kasutamiseks kõrgendatud toimingute tegemiseks.

ShizukuArendaja: Xingchen ja Rikka

Hind: tasuta.

4.1.

Lae alla

Miks Shizuku?

Kuigi shell-tasemel juurdepääs süsteemile ei võimalda teil teha nii palju kui juur, annab see teile siiski rohkem juurdepääsu kui tavaline rakendus. Lisaks sellele võimaldab Shizuku toimimisviis kasutada Androidi API-sid peaaegu nagu tavaliselt. Te ei pea lootma shellikäsklustele (kuigi soovi korral saate seda teha).

Kui teie rakendus vajab erilubasid, mida saab anda ainult ADB kaudu (või root), on Shizuku ja Android 11 suurepärane sidumine. Saate lihtsalt kasutada Shizukut, et anda seadmes eriload.

Isegi seadmete puhul, millel pole operatsioonisüsteemi Android 11, võib Shizuku olla kasulik. Rakendus pakub kasutajatele juhiseid ja skripte, nii et te ei pea seda tegema.

Integratsioon

Shizuku lisamine oma rakendusse ei ole kõige lihtsam, kuid see pole ka raske. Kahjuks on arendaja dokumentatsioon ei ole täpselt täielik, kuid see artikkel on teid käsitlenud. Siit saate teada, kuidas integreerida Shizuku oma rakendusse.

Sõltuvused

Esimene samm on Shizuku sõltuvuste lisamine. Lisage oma mooduli tasemel build.gradle sõltuvuste plokki järgmine.

def shizuku_version = '11.0.3'

implementation "dev.rikka.shizuku: api:$shizuku_version"
implementation "dev.rikka.shizuku: provider:$shizuku_version"

Vajadusel värskendage kindlasti versiooni. 11.0.3 on kirjutamise ajal uusim.

Pakkuja

Shizuku toimimiseks peate lisama oma rakenduse manifesti teenusepakkuja ploki. Avage AndroidManifest.xml ja lisage rakenduste plokki järgmine.

 android: name="rikka.shizuku.ShizukuProvider"
android: authorities="${applicationId}.shizuku"
android: multiprocess="false"
android: enabled="true"
android: exported="true"
android: permission="android.permission.INTERACT_ACROSS_USERS_FULL" />

Luba

Autoriseerimiseks kasutab Shizuku käitusaja luba. Hakkame mõne aja pärast selle loa andmisega tegelema. Praegu lisage see manifestiploki faili AndroidManifest.xml.

Nüüd, kui see kõik on lisatud, on põhiline integreerimine tehtud. Laske Gradle'il projekt sünkroonida ja jätkake jaotisega Kasutus.


Kasutamine

Kättesaadavuse kontrollimine

Enne Shizuku kasutamise alustamist räägime sellest, kas see on tegelikult kasutamiseks saadaval.

Enne kui kontrollite, kas luba on antud, ja enne API-kõnede tegemist Shizuku kaudu, saate järgmise meetodiga veenduda, et need kontrollid ja kõned õnnestuvad.

Shizuku.pingBinder()

Kui Shizuku on installitud ja töötab, naaseb see tõsi. Vastasel juhul tagastab see vale.

Loa andmine

Kuna Shizuku kasutab käitusaja luba, tuleb see teie rakendusele anda, enne kui saate shell-juurdepääsuga midagi teha. Ringluses on ka kaks API versiooni, mille andmise viisid on erinevad. See jaotis näitab teile, kuidas mõlemat käsitleda.

Kontrollimine

Enne loa taotlemist on kõige parem kontrollida, kas see on juba olemas. Kui teete, võite jätkata sellega, mida vajate. Vastasel juhul peate seda enne jätkamist taotlema.

Et kontrollida, kas teil on Shizuku kasutamise luba, võite kasutada järgmist. See kood eeldab, et kasutate seda tegevuses.

Kotlin:

val isGranted = if (Shizuku.isPreV11() || Shizuku.getVersion() < 11) {
checkSelfPermission(ShizukuProvider.PERMISSION) == PackageManager.PERMISSION_GRANTED
} else {
Shizuku.checkSelfPermission() = PackageManager.PERMISSION_GRANTED
}

Java:

boolean isGranted;
if (Shizuku.isPreV11() || Shizuku.getVersion() < 11) {
isGranted = checkSelfPermission(ShizukuProvider.PERMISSION) == PackageManager.PERMISSION_GRANTED;
} else {
isGranted = Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED;
}

Taotlemine

Kui teil on vaja Shizuku kasutamiseks luba taotleda, toimige järgmiselt.

The SHIZUKU_CODE allpool kasutatav muutuja peaks olema püsiva väärtusega täisarv (staatiline muutuja).

Kotlin:

if (Shizuku.isPreV11() || Shizuku.getVersion() < 11) {
requestPermissions(arrayOf(ShizukuProvider.PERMISSION), SHIZUKU_CODE)
} else {
Shizuku.requestPermission(SHIZUKU_CODE)
}

Java:

if (Shizuku.isPreV11() || Shizuku.getVersion() < 11) {
requestPermissions(newString[] { ShizukuProvider.PERMISSION }, SHIZUKU_CODE);
} else {
Shizuku.requestPermissions(SHIZUKU_CODE);
}

Tulemuse kuulamiseks peate tegevused alistama onRequestPermissionsResult() meetod. Peate ka rakendama Shizuku. OnRequestPermissionResultListener. Näide, mida ma näitan, eeldab, et teie tegevus rakendab seda liidest, kuid soovi korral saate selle rakendada muutujana.

Kotlin:

classExampleActivity : AppCompatActivity, Shizuku.OnRequestPermissionResultListener {
...

override void onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
permissions.forEachIndexed { index, permission ->
if (permission == ShizukuProvider.PERMISSION) {
onRequestPermissionResult(requestCode, grantResults[index])
}
}
}

override voidonRequestPermissionResult(requestCode: Int, grantResult: Int){
val isGranted = grantResult == PackageManager.PERMISSION_GRANTED
//Dostuff based on the result.

}
}

Java:

publicclassExampleActivityextendsAppCompatActivityimplementsShizuku.OnRequestPermissionResultListener{
...

@Override
publicvoidonRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){
for (int i = 0; i < permissions.length; i++) {
String permission = permissions[i];
int result = grantResults[i];

if (permission.equals(ShizukuProvider.PERMISSION) {
onRequestPermissionResult(requestCode, result);
}
}
}

@Override
publicvoidonRequestPermissionResult(int requestCode, int grantResult){
boolean isGranted = grantResult == PackageManager.PERMISSION_GRANTED;
//Dostuff based on the result.
}
}

API-de kasutamine

Nüüd, kui Shizuku on seadistatud ja load antud, saate hakata tegelikult Shizuku abil API-dele helistama. Siinne protsess on veidi teistsugune, kui olete harjunud. Selle asemel, et helistada getSystemService() ja millegi sarnase ülekandmine WindowManager, peate nende jaoks kasutama selle asemel sisemisi API-sid (nt IWindowManager).

Shizuku sisaldab Androidi peidetud API musta nimekirja ümbersõitu, nii et te ei pea selle kasutamisel selle pärast muretsema. Kui teil on siiski huvi, kuidas sellest ise mööda minna, vaadake minu eelmist õpetust.

Siin on kiire näide (kasutades peegeldust), mis näitab, kuidas saate eksemplari hankida IPackageManager ja kasutage seda rakendusele käitusaja loa andmiseks.

Kotlin:

val iPmClass = Class.forName("android.content.pm.IPackageManager")
val iPmStub = Class.forName("android.content.pm.IPackageManager\$Stub")
val asInterfaceMethod = iPmStub.getMethod("asInterface", IBinder::class.java)
val grantRuntimePermissionMethod = iPmClass.getMethod("grantRuntimePermission", String:: class.java /* package name */, String:: class.java /* permission name */, Int:: class.java /* user ID */)

val iPmInstance = asInterfaceMethod.invoke(null, ShizukuBinderWrapper(SystemServiceHelper.getSystemService("package")))

grantRuntimePermissionMethod.invoke(iPmInstance, "com.zacharee1.systemuituner", android.Manifest.permission.WRITE_SECURE_SETTINGS, 0)

Java:

Class< ?>> iPmClass = Class.forName("android.content.pm.IPackageManager");
Class< ?>> iPmStub = Class.forName("android.content.pm.IPackageManager$Stub");
Method asInterfaceMethod = iPmStub.getMethod("asInterface", IBinder.class);
Method grantRuntimePermissionMethod = iPmClass.getMethod("grantRuntimePermission", String.class, String.class, int.class);

val iPmInstance = asInterfaceMethod.invoke(null, new ShizukuBinderWrapper(SystemServiceHelper.getSystemService("package")));

grantRuntimePermissionMethod.invoke(iPmInstance, "com.zacharee1.systemuituner", android.Manifest.permission.WRITE_SECURE_SETTINGS, 0);

Teiste API-de protsess on sarnane. Hankige viited klassile ja selle Stub-alaklassile. Hankige viide asInterface meetod Stub klassi jaoks. Hankige klassist endast viited soovitud meetoditele. Seejärel kutsuge esile asInterface meetodi viide teil on, asendades "package" mis tahes teenusega, mida vajate. Seejärel saab selle eksemplari meetodi kutsumiseks edasi anda.

Pro-näpunäide: Kui installite muudetud SDK, saate peegeldust täielikult vältida. Vaadake anggrayudi GitHubi hoidlat muudetud SDK-de ja installijuhiste jaoks. Selle installimisega muutub ülaltoodud kood (Kotlinis) palju lihtsamaks.

val iPm = IPackageManager.Stub.asInterface(ShizukuBinderWrapper(SystemServiceHelper.getService("package"))))
iPm.grantRuntimePermission("com.zacharee1.systemuituner", android.Manifest.permission.WRITE_SECURE_SETTINGS, 0)

Mis tahes AIDL-põhiseid API-sid saab selle meetodiga kasutada kõikjal teie rakenduses, kui Shizuku töötab ja teie rakendusel on luba.

Kasutajateenus

Kuigi Binderi meetod hõlmab enamikku kasutusjuhtudest, võib juhtuda, et vajate API-d, millel pole otsest Binderi liidest. Sel juhul saate kasutada Shizuku funktsiooni User Service.

See meetod töötab sarnaselt Androidi tavalise teenusega. Te "käivitate" selle, suhtlete sellega ServiceConnectioniga sidudes ja käivitate oma loogika teenuseklassis. Erinevus seisneb selles, et te ei kasuta Androidi teenust ja kõik teenuse sees töötab ADB-lubadega.

Nüüd on mõned piirangud. Kasutajateenus töötab täiesti eraldi protsessis ja kasutajas, nii et te ei saa ülejäänud rakendusega suhelda, välja arvatud oma AIDL-i tagasihelistuste ja sidujate kaudu. Kuna see ei tööta ka õiges rakendusprotsessis, ei pruugi mõned asjad, näiteks Androidi teenuste sidumine, korralikult töötada.

Selleks on vaja ka Shizuku versiooni 10 või uuemat. Kuigi enamikul rakenduse allikatest on praegu versioon 11, peaksite siiski lisama versioonikontrolli, mis sisaldub näites.

AIDL-i määratlemine

Alustamiseks peate looma uue AIDL-faili. Saate seda teha Android Studios, paremklõpsates Androidi failivaates ükskõik mida, hõljutades kursorit valiku „Uus” kohal ja valides suvandi „AIDL”. Sisestage faili nimi (nt "IUserService") ja Android Studio loob teie jaoks mallifaili.

Kui te pole AIDL-i tööpõhimõtetega kursis, vaadake kindlasti seda Google'i dokumentatsioon.

Eemaldage AIDL-ist mallimeetodid ja lisage seejärel a destroy() meetod Shizuku jaoks õige ID-ga. Seda kutsutakse siis, kui Shizuku tapab kasutajateenuse, ja seda tuleks kasutada kõigi viidete või käimasoleva loogika puhastamiseks.

AIDL näide:

packagetk.zwander.shizukudemo;

interfaceIUserService{
voiddestroy()= 16777114;

void grantPermission(String packageName, String permission, int userId) = 1; //You can specify your own method IDs in the AIDL. Check out the documentation for more details on this.
}

AIDL-i rakendamine

Järgmine asi, mida teha, on tegelikult AIDL-i rakendamine.

Java:

publicclassUserServiceextendsIUserService.Stub{
//Make sure to include an empty constructor.
publicUserService(){
}

@Override
publicvoiddestroy(){
//Shizuku wants the service to be killed. Clean up and then exit.
System.exit(0);
}

@Override
publicvoidgrantPermission(String packageName, String permission, int userId){
//No need to use ShizukuBinderWrapper.
IPackageManager.Stub.asInterface(SystemServiceHelper.getService("package")).grantRuntimePermission(packageName, permission, userId);
}
}

Kotlin:

classUserService : IUserService.Stub {
//Include an empty constructor.
constructor() {
}

override fun destroy(){
//Shizuku wants the service to be killed. Clean up and exit.
System.exit(0)
}

override fun grantPermission(packageName: String, permission: String, userId: Int) {
//No need for ShizukuBinderWrapper.
IPackageManager.Stub.asInterface(SystemServiceHelper.getService("package")).grantRuntimePermission(packageName, permission, userId)
}
}

Ülaltoodud näited eeldavad, et teil on Androidi peidetud API SDK installitud.

Teenusühenduse seadistamine

Nüüd, kui kasutajateenus on määratletud ja juurutatud, on aeg see kasutamiseks seadistada. Esimene asi, mida peaksite tegema, on määratleda ServiceConnection, kus soovite sellega suhelda (nt oma rakenduse põhitegevuse kaudu).

Java:

private IUserService binder = null;

privatefinal ServiceConnection connection = new ServiceConnection() {
@Override
publicvoidonServiceConnected(ComponentName componentName, IBinder binder){
if (binder != null && binder.pingBinder()) {
binder = IUserService.Stub.asInterface(binder);
}
}

@Override
publicvoidonServiceDisconnected(ComponentName componentName){
binder = null;
}
}

Kotlin:

privatevar binder: IUserService? = null

private val connection = object: ServiceConnection {
override fun onServiceConnected(componentName: ComponentName, binder: IBinder?){
if (binder != null && binder.pingBinder()) {
binder = IUserService.Stub.asInterface(binder)
}
}

override fun onServiceDisconnected(componentName: ComponentName){
binder = null;
}
}

The binder muutuja on see, mida kasutate oma rakenduse kaudu kasutajateenusega suhtlemiseks. Et kontrollida, kas see on kasutamiseks saadaval, kontrollige lihtsalt, et see poleks tühi ja seda pingBinder() naaseb tõsi, täpselt nagu ülaltoodud koodinäites.

Kasutajateenuse argumentide loomine

Enne kui saate kasutajateenust juhtida, peate määratlema mõned argumendid, mida Shizuku selle käivitamisel ja peatamisel kasutab. Nende hulka kuuluvad näiteks Shizukule teenuse klassinime ütlemine, protsessi järelliide täpsustamine, kas see on silutav või mitte, ja mis versioon see on.

Java:

privatefinal Shizuku.UserServiceArgs serviceArgs = new Shizuku.UserServiceArgs(
newComponentName(BuildConfig.APPLICATION_ID, UserService.class.getName()))
.processNameSuffix("user_service")
.debuggable(BuildConfig.DEBUG)
.version(BuildConfig.VERSION_CODE);

Kotlin:

private val serviceArgs = Shizuku.UserServiceArgs(
ComponentName(BuildConfig.APPLICATION_ID, UserService.class::java.getName()))
.processNameSuffix("user_service")
.debuggable(BuildCOnfig.DEBUG)
.version(BuildConfig.VERSION_CODE)

Kasutajateenuse käivitamine, peatamine ja sidumine

Käivitus- ja sidumistoimingud ning peatamise ja sidumise tühistamise toimingud on Shizukus ühendatud. Ei ole eraldi käivitus- ja sidumismeetodeid ega peatamis- ja lahtisidumise meetodeid.

Siin on, kuidas seda teha alustada ja siduda kasutajateenust.

Java:

if (Shizuku.getVersion >= 10) {
//This only works on Shizuku 10 or later.
Shizuku.bindUserService(serviceArgs, connection);
} else {
//Tell the user to upgrade Shizuku.
}

Kotlin:

if (Shizuku.getVersion() >= 10) {
//This only works on Shizuku 10 or later.
Shizuku.bindUserService(serviceArgs, connection)
} else {
//Tell the user to upgrade Shizuku.
}

Siin on, kuidas seda teha peatada ja lahti siduda kasutajateenust.

Java:

if (Shizuku.getVersion >= 10) {
Shizuku.unbindUserService(serviceArgs, connection, true);
}

Kotlin:

if (Shizuku.getVersion >= 10) {
Shizuku.unbindUserService(serviceArgs, connection, true)
}

Kasutajateenuse kutsumine

Kui kasutajateenus on käivitatud, saate seda kasutama hakata. Lihtsalt kontrollige, kas binder muutuja on mitte-null ja pingitav ning seejärel helistage oma meetodile.

Java:

if (binder != null && binder.pingBinder()) {
binder.grantPermission("com.zacharee1.systemuituner", android.Manifest.permission.WRITE_SECURE_SETTINGS, 0);
}

Kotlin:

if (binder?.pingBinder() == true) {
binder?.grantPermission("com.zacharee1.systemuituner", android.Manifest.permission.WRITE_SECURE_SETTINGS, 0)
}

Järeldus

Kui te seda kõike järgisite, peaks teil nüüd olema toimiv Shizuku integratsioon. Ärge unustage lihtsalt käskida oma kasutajatel Shizuku installida ja enne selle kasutamist korralikult kontrollida, kas Shizuku on saadaval.