Πώς να αυξήσετε τα δικαιώματα εφαρμογών χρησιμοποιώντας τη βιβλιοθήκη Shizuku

click fraud protection

Το Rooting δεν είναι για όλους. Δείτε πώς μπορείτε να λάβετε αυξημένα δικαιώματα σε επίπεδο κελύφους στην εφαρμογή σας χρησιμοποιώντας τη βιβλιοθήκη Shizuku.

Υπάρχουν πολλοί λόγοι για τους οποίους τα δικαιώματα που συνήθως χορηγούνται στην εφαρμογή σας μπορεί να μην είναι αρκετά. Ίσως είστε σαν εμένα και απολαμβάνετε τη δημιουργία εφαρμογών που καταχρώνται το Android API. Ορισμένα από τα API που χρησιμοποιώ είναι κλειδωμένα πίσω από ειδικά δικαιώματα. Μερικές φορές μόνο ο χρήστης του κελύφους (ADB) ή το σύστημα μπορεί να έχει πρόσβαση σε αυτά. Υπάρχει μια λύση όμως — Σιζούκου.

Το Shizuku σάς επιτρέπει να καλείτε API συστήματος σχεδόν απευθείας και εξ ολοκλήρου σε Java ή Kotlin. Αυτός ο οδηγός θα σας δείξει πώς να εφαρμόσετε και να χρησιμοποιήσετε το Shizuku.

Τι είναι το Shizuku;

Πριν προχωρήσουμε στη χρήση του Shizuku, ίσως είναι χρήσιμο να γνωρίζουμε τι ακριβώς είναι. Εάν είστε εξοικειωμένοι με Magisk, τότε το Shizuku είναι παρόμοιο. Αλλά αντί να διαχειρίζεται την πρόσβαση root, διαχειρίζεται την πρόσβαση φλοιού.

Το Shizuku εκτελεί τη δική του διαδικασία με δικαιώματα σε επίπεδο κελύφους. Ο τρόπος με τον οποίο ο χρήστης ενεργοποιεί αυτήν τη διαδικασία εξαρτάται από τη συσκευή, την έκδοση Android και την επιλογή του. Το Shizuku μπορεί να ενεργοποιηθεί μέσω ADB, μέσω ασύρματης ADB στη συσκευή (σε Android 11 και μεταγενέστερες εκδόσεις), ή μέσω πρόσβασης root. Οι εφαρμογές που εφαρμόζουν το Shizuku μπορούν στη συνέχεια να ζητήσουν άδεια χρήσης αυτής της διαδικασίας για την εκτέλεση υψηλών λειτουργιών.

ΣιζούκουΠρογραμματιστής: Xingchen & Rikka

Τιμή: Δωρεάν.

4.1.

Κατεβάστε

Γιατί Σιζούκου;

Ενώ η πρόσβαση σε επίπεδο κελύφους στο σύστημα δεν σας επιτρέπει να κάνετε τόσα πολλά ρίζα, εξακολουθεί να σας δίνει περισσότερη πρόσβαση από μια κανονική εφαρμογή. Επιπλέον, ο τρόπος που λειτουργεί το Shizuku σάς επιτρέπει να χρησιμοποιείτε τα API Android σχεδόν όπως συνήθως. Δεν χρειάζεται να βασίζεστε σε εντολές φλοιού (αν και μπορείτε αν θέλετε).

Εάν η εφαρμογή σας χρειάζεται ειδικά δικαιώματα που μπορούν να παραχωρηθούν μόνο μέσω ADB (ή με root), το Shizuku και το Android 11 κάνουν μια εξαιρετική αντιστοίχιση. Μπορείτε απλώς να χρησιμοποιήσετε το Shizuku για να εκχωρήσετε ειδικά δικαιώματα πλήρως στη συσκευή.

Ακόμη και με συσκευές που δεν είναι σε Android 11, το Shizuku μπορεί να είναι χρήσιμο. Η εφαρμογή παρέχει οδηγίες και σενάρια για τους χρήστες, ώστε να μην χρειάζεται.

Ενσωμάτωση

Η προσθήκη Shizuku στην εφαρμογή σας δεν είναι η πιο απλή, αλλά ούτε και δύσκολη. Δυστυχώς, το τεκμηρίωση προγραμματιστή δεν είναι ακριβώς πλήρες, αλλά αυτό το άρθρο σας καλύπτει. Δείτε πώς μπορείτε να ενσωματώσετε το Shizuku στην εφαρμογή σας.

Εξαρτήσεις

Το πρώτο βήμα είναι να προσθέσετε τις εξαρτήσεις Shizuku. Στο build.gradle σε επίπεδο ενότητας, προσθέστε τα ακόλουθα στο μπλοκ εξαρτήσεων.

def shizuku_version = '11.0.3'

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

Φροντίστε να ενημερώσετε την έκδοση εάν χρειάζεται. Η 11.0.3 είναι η πιο πρόσφατη τη στιγμή της σύνταξης.

Προμηθευτής

Για να λειτουργήσει το Shizuku, πρέπει να προσθέσετε ένα μπλοκ παρόχου στο μανιφέστο της εφαρμογής σας. Ανοίξτε το AndroidManifest.xml και προσθέστε τα ακόλουθα μέσα στο μπλοκ της εφαρμογής.

 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" />

Αδεια

Για εξουσιοδότηση, το Shizuku χρησιμοποιεί μια άδεια χρόνου εκτέλεσης. Θα αρχίσουμε να δίνουμε αυτήν την άδεια σε λίγο. Προς το παρόν, προσθέστε το στο AndroidManifest.xml μέσα στο μπλοκ δήλωσης.

Τώρα που προστέθηκαν όλα αυτά, η βασική ενσωμάτωση έχει ολοκληρωθεί. Αφήστε το Gradle να κάνει ένα συγχρονισμό έργου και συνεχίστε στη Χρήση.


Χρήση

Ελεγχος διαθεσιμότητας

Πριν προχωρήσουμε στο πώς να χρησιμοποιήσετε το Shizuku, ας μιλήσουμε για να βεβαιωθούμε ότι είναι πραγματικά διαθέσιμο για χρήση.

Πριν ελέγξετε εάν έχει εκχωρηθεί η άδεια και προτού πραγματοποιήσετε κλήσεις API μέσω του Shizuku, μπορείτε να βεβαιωθείτε ότι αυτοί οι έλεγχοι και οι κλήσεις θα είναι επιτυχείς με την ακόλουθη μέθοδο:

Shizuku.pingBinder()

Εάν το Shizuku είναι εγκατεστημένο και εκτελείται, αυτό θα επιστρέψει αληθής. Διαφορετικά, θα επιστρέψει ψευδής.

Χορήγηση Άδειας

Εφόσον το Shizuku χρησιμοποιεί μια άδεια χρόνου εκτέλεσης, πρέπει να εκχωρηθεί στην εφαρμογή σας για να μπορέσετε να κάνετε οτιδήποτε με την πρόσβαση φλοιού. Υπάρχουν επίσης δύο εκδόσεις API σε κυκλοφορία, με διαφορετικούς τρόπους χορήγησης του. Αυτή η ενότητα θα σας δείξει πώς να χειριστείτε και τα δύο.

Ελεγχος

Πριν ζητήσετε την άδεια, το καλύτερο που έχετε να κάνετε είναι να ελέγξετε αν την έχετε ήδη. Εάν το κάνετε, μπορείτε να συνεχίσετε με ό, τι χρειαστεί να κάνετε. Διαφορετικά, θα πρέπει να το ζητήσετε πριν συνεχίσετε.

Για να ελέγξετε εάν έχετε άδεια να χρησιμοποιήσετε το Shizuku, μπορείτε να χρησιμοποιήσετε τα παρακάτω. Αυτός ο κώδικας υποθέτει ότι τον εκτελείτε μέσα σε μια Δραστηριότητα.

Κότλιν:

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

Ιάβα:

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

Ζητώντας

Εάν πρέπει να ζητήσετε άδεια για να χρησιμοποιήσετε το Shizuku, δείτε πώς.

ο SHIZUKU_CODE Η μεταβλητή που χρησιμοποιείται παρακάτω θα πρέπει να είναι ακέραιος με σταθερή τιμή (στατική μεταβλητή).

Κότλιν:

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

Ιάβα:

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

Για να ακούσετε το αποτέλεσμα, θα πρέπει να παρακάμψετε τη Δραστηριότητα onRequestPermissionsResult() μέθοδος. Θα χρειαστεί επίσης να εφαρμόσετε Σιζούκου. OnRequestPermissionResultListener. Το παράδειγμα που θα δείξω υποθέτει ότι η Δραστηριότητά σας υλοποιεί αυτήν τη διεπαφή, αλλά μπορείτε να την εφαρμόσετε σε μια μεταβλητή εάν θέλετε.

Κότλιν:

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.

}
}

Ιάβα:

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

Τώρα που έχει ρυθμιστεί το Shizuku και έχουν παραχωρηθεί τα δικαιώματα, μπορείτε να αρχίσετε να καλείτε API χρησιμοποιώντας το Shizuku. Η διαδικασία εδώ είναι λίγο διαφορετική από αυτή που μπορεί να έχετε συνηθίσει. Αντί να καλέσετε getSystemService() και casting σε κάτι σαν WindowManager, θα πρέπει να χρησιμοποιήσετε τα εσωτερικά API για αυτά (π.χ. IWindowManager).

Το Shizuku περιλαμβάνει μια παράκαμψη για την κρυφή μαύρη λίστα API του Android, επομένως δεν θα χρειάζεται να ανησυχείτε για αυτό όταν το χρησιμοποιείτε. Εάν είστε περίεργοι πώς να το παρακάμψετε μόνοι σας, ρίξτε μια ματιά στο προηγούμενο σεμινάριο μου.

Ακολουθεί ένα γρήγορο παράδειγμα (χρησιμοποιώντας την αντανάκλαση) που σας δείχνει πώς μπορείτε να πάρετε ένα παράδειγμα IPackageManager και χρησιμοποιήστε το για να εκχωρήσετε σε μια εφαρμογή άδεια χρόνου εκτέλεσης.

Κότλιν:

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)

Ιάβα:

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);

Η διαδικασία για άλλα API είναι παρόμοια. Λάβετε τις αναφορές στην κλάση και την υποκατηγορία Stub της. Λάβετε την αναφορά στο asInterface μέθοδος για την κλάση Stub. Λάβετε τις αναφορές στις μεθόδους που θέλετε από την ίδια την τάξη. Στη συνέχεια, επικαλέστε το asInterface αναφορά μεθόδου που έχετε, αντικαθιστώντας "package" παραπάνω με όποια υπηρεσία χρειάζεστε. Αυτή η περίπτωση μπορεί στη συνέχεια να περάσει για επικλήσεις μεθόδων.

Επαγγελματική συμβουλή: μπορείτε να αποφύγετε εντελώς τη χρήση του προβληματισμού εάν εγκαταστήσετε ένα τροποποιημένο SDK. Ρίξτε μια ματιά στο αποθετήριο GitHub του anggrayudi για τα τροποποιημένα SDK και οδηγίες εγκατάστασης. Με την εγκατάσταση αυτού, ο παραπάνω κώδικας (στο Kotlin) γίνεται πολύ πιο απλός.

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

Οποιαδήποτε API που βασίζονται στο AIDL μπορούν να χρησιμοποιηθούν με αυτήν τη μέθοδο από οπουδήποτε στην εφαρμογή σας, εφόσον εκτελείται το Shizuku και η εφαρμογή σας έχει άδεια.

Υπηρεσία χρήστη

Ενώ η μέθοδος Binder καλύπτει τις περισσότερες περιπτώσεις χρήσης, μπορεί να υπάρχουν φορές που χρειάζεστε ένα API που δεν έχει άμεση διεπαφή Binder. Σε αυτήν την περίπτωση, μπορείτε να χρησιμοποιήσετε τη δυνατότητα Υπηρεσίας χρήστη στο Shizuku.

Αυτή η μέθοδος λειτουργεί παρόμοια με μια κανονική Υπηρεσία στο Android. Το "ξεκινάτε", επικοινωνείτε δεσμεύοντάς το με ένα ServiceConnection και τρέχετε τη λογική σας στην κλάση υπηρεσιών. Η διαφορά είναι ότι δεν χρησιμοποιείτε την Υπηρεσία του Android και οτιδήποτε εντός της υπηρεσίας εκτελείται με δικαιώματα ADB.

Τώρα υπάρχουν κάποιοι περιορισμοί. Η Υπηρεσία Χρήστη εκτελείται σε μια εντελώς ξεχωριστή διαδικασία και χρήστη, επομένως δεν μπορείτε να αλληλεπιδράσετε με την υπόλοιπη εφαρμογή σας παρά μόνο μέσω των δικών σας επιστροφών κλήσης AIDL και Binders. Καθώς επίσης δεν εκτελείται σε μια σωστή διαδικασία εφαρμογής, ορισμένα πράγματα όπως η δέσμευση Υπηρεσιών Android ενδέχεται να μην λειτουργούν σωστά.

Αυτό απαιτεί επίσης Shizuku έκδοση 10 ή νεότερη. Αν και οι περισσότερες πηγές για την εφαρμογή έχουν αυτήν τη στιγμή την έκδοση 11, θα πρέπει να συμπεριλάβετε έναν έλεγχο έκδοσης, ο οποίος θα συμπεριληφθεί στο παράδειγμα.

Ορισμός AIDL

Για να ξεκινήσετε, θα χρειαστεί να δημιουργήσετε ένα νέο αρχείο AIDL. Μπορείτε να το κάνετε αυτό στο Android Studio κάνοντας δεξί κλικ σε οτιδήποτε στην προβολή αρχείου Android, τοποθετώντας το δείκτη του ποντικιού πάνω από την επιλογή "Νέο" και επιλέγοντας την επιλογή "AIDL". Εισαγάγετε το όνομα του αρχείου (π.χ. "IUserService") και το Android Studio θα δημιουργήσει ένα αρχείο προτύπου για εσάς.

Εάν δεν είστε εξοικειωμένοι με το πώς λειτουργούν τα AIDL, φροντίστε να το ελέγξετε τεκμηρίωση της Google.

Αφαιρέστε τις μεθόδους προτύπου από το AIDL και, στη συνέχεια, προσθέστε a destroy() μέθοδος με το κατάλληλο αναγνωριστικό για το Shizuku. Αυτό θα καλείται όταν το Shizuku σκοτώνει την Υπηρεσία Χρήστη και θα πρέπει να χρησιμοποιείται για να καθαρίσει τυχόν αναφορές ή συνεχή λογική που έχετε.

Παράδειγμα AIDL:

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

Το επόμενο πράγμα που πρέπει να κάνετε είναι να εφαρμόσετε πραγματικά το AIDL.

Ιάβα:

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);
}
}

Κότλιν:

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)
}
}

Τα παραπάνω παραδείγματα υποθέτουν ότι έχετε το Android Hidden API SDK εγκατεστημένο.

Ρύθμιση της σύνδεσης υπηρεσίας

Τώρα που ορίστηκε και υλοποιήθηκε η Υπηρεσία Χρήστη, ήρθε η ώρα να τη ρυθμίσετε για χρήση. Το πρώτο πράγμα που πρέπει να κάνετε είναι να ορίσετε μια Σύνδεση Υπηρεσίας όπου θέλετε να επικοινωνήσετε μαζί της (π.χ. από την κύρια Δραστηριότητα στην εφαρμογή σας).

Ιάβα:

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;
}
}

Κότλιν:

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;
}
}

ο binder μεταβλητή είναι αυτό που θα χρησιμοποιήσετε για να επικοινωνήσετε με την Υπηρεσία Χρήστη από την εφαρμογή σας. Για να ελέγξετε αν είναι διαθέσιμο για χρήση, απλώς ελέγξτε ότι δεν είναι μηδενικό και αυτό pingBinder() επιστρέφει αληθής, ακριβώς όπως στο παραπάνω παράδειγμα κώδικα.

Δημιουργία των ορισμάτων της υπηρεσίας χρήστη

Για να μπορέσετε να ελέγξετε την Υπηρεσία Χρήστη, θα πρέπει να ορίσετε ορισμένα ορίσματα για χρήση του Shizuku κατά την εκκίνηση και τη διακοπή της. Αυτά περιλαμβάνουν πράγματα όπως το να λέτε στην πραγματικότητα το όνομα της κλάσης της υπηρεσίας στον Shizuku, να προσδιορίζετε το επίθημα διεργασίας, αν είναι με δυνατότητα εντοπισμού σφαλμάτων ή όχι και ποια έκδοση είναι.

Ιάβα:

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

Κότλιν:

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

Έναρξη, διακοπή και δέσμευση της υπηρεσίας χρήστη

Οι ενέργειες έναρξης και δέσμευσης και οι ενέργειες διακοπής και αποδέσμευσης ενοποιούνται στο Shizuku. Δεν υπάρχουν ξεχωριστές μέθοδοι έναρξης και σύνδεσης ή μέθοδοι διακοπής και αποδέσμευσης.

Δείτε πώς να έναρξη και δέσμευση την Υπηρεσία Χρήστη.

Ιάβα:

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

Κότλιν:

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

Δείτε πώς να σταματήστε και αποδεσμεύστε την Υπηρεσία Χρήστη.

Ιάβα:

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

Κότλιν:

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

Επίκληση της Υπηρεσίας Χρήστη

Μόλις ξεκινήσει η Υπηρεσία Χρήστη, μπορείτε να αρχίσετε να τη χρησιμοποιείτε. Απλώς ελέγξτε αν το binder Η μεταβλητή είναι μη μηδενική και με δυνατότητα ping και, στη συνέχεια, πραγματοποιήστε κλήση της μεθόδου σας.

Ιάβα:

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

Κότλιν:

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

συμπέρασμα

Εάν παρακολουθήσατε όλα αυτά, θα πρέπει τώρα να έχετε μια λειτουργική ενσωμάτωση Shizuku. Απλώς θυμηθείτε να πείτε στους χρήστες σας να εγκαταστήσουν το Shizuku και να ελέγξουν σωστά ότι το Shizuku είναι διαθέσιμο πριν προσπαθήσετε να το χρησιμοποιήσετε.