Shizuku kütüphanesini kullanarak Uygulama İzinleri Nasıl Yükseltilir

Root yapmak herkes için uygun değildir. Shizuku kitaplığını kullanarak uygulamanızda yükseltilmiş kabuk düzeyinde izinleri nasıl alabileceğiniz aşağıda açıklanmıştır.

Normalde uygulamanıza verilen izinlerin yeterli olmamasının birçok nedeni olabilir. Belki siz de benim gibisiniz ve Android API'sini kötüye kullanan hileli uygulamalar oluşturmaktan hoşlanıyorsunuz. Kullandığım bazı API'ler özel izinlerle kilitlenmiş durumda. Bazen bunlara yalnızca kabuk kullanıcısı (ADB) veya sistem erişebilir. Yine de bir çözüm var: Shizuku.

Shizuku, sistem API'lerini neredeyse doğrudan ve tamamen Java veya Kotlin'de çağırmanıza olanak tanır. Bu kılavuz size Shizuku'yu nasıl uygulayacağınızı ve kullanacağınızı gösterecektir.

Şizuku nedir?

Shizuku'yu kullanmaya başlamadan önce onun tam olarak ne olduğunu bilmek faydalı olabilir. Eğer aşina iseniz Magisk, o zaman Shizuku da benzer. Ancak root erişimini yönetmek yerine kabuk erişimini yönetir.

Shizuku, kabuk düzeyindeki izinlerle kendi sürecini yürütür. Kullanıcının bu işlemi nasıl etkinleştirdiği, cihazına, Android sürümüne ve tercihine bağlıdır. Shizuku, cihazdaki kablosuz ADB (

Android 11 ve sonraki sürümlerde) veya root erişimi yoluyla. Shizuku'yu uygulayan uygulamalar daha sonra bu işlemi yükseltilmiş işlemleri gerçekleştirmek için kullanmak için izin isteyebilir.

ŞizukuGeliştirici: Xingchen ve Rikka

Fiyat: Ücretsiz.

4.1.

İndirmek

Neden Shizuku?

Sisteme kabuk düzeyinde erişim bu kadarını yapmanıza izin vermezken kökyine de size normal bir uygulamanın sağlayacağından daha fazla erişim sağlar. Üstelik Shizuku'nun çalışma şekli, Android API'lerini neredeyse normal şekilde kullanmanıza olanak tanır. Kabuk komutlarına güvenmeniz gerekmez (ancak isterseniz yapabilirsiniz).

Uygulamanızın yalnızca ADB (veya root ile) aracılığıyla verilebilecek özel izinlere ihtiyacı varsa Shizuku ve Android 11 mükemmel bir eşleşme oluşturur. Tamamen cihazda özel izinler vermek için Shizuku'yu kullanabilirsiniz.

Android 11'i desteklemeyen cihazlarda bile Shizuku faydalı olabilir. Uygulama, kullanıcılara talimatlar ve komut dosyaları sağlar, böylece sizin bunu yapmanıza gerek kalmaz.

Entegrasyon

Shizuku'yu uygulamanıza eklemek en kolayı olmasa da zor da değil. Ne yazık ki geliştirici belgeleri tam olarak tamamlanmadı, ancak bu makale sizi ele alıyor. Shizuku'yu uygulamanıza nasıl entegre edeceğiniz aşağıda açıklanmıştır.

Bağımlılıklar

İlk adım Shizuku bağımlılıklarını eklemektir. Modül düzeyinde build.gradle'ınızda bağımlılıklar bloğuna aşağıdakini ekleyin.

def shizuku_version = '11.0.3'

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

Gerekirse sürümü güncellediğinizden emin olun. 11.0.3, bu yazının yazıldığı tarihteki en son sürümdür.

Sağlayıcı

Shizuku'nun çalışması için uygulamanızın manifest dosyasına bir sağlayıcı bloğu eklemeniz gerekir. AndroidManifest.xml'yi açın ve uygulama bloğunun içine aşağıdakini ekleyin.

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

İzin

Yetkilendirme için Shizuku bir çalışma zamanı izni kullanır. Birazdan bu izni vermeye başlayacağız. Şimdilik bunu manifest bloğunun içindeki AndroidManifest.xml dosyasına ekleyin.

Artık bunların hepsi eklendiğinde temel entegrasyon tamamlandı. Gradle'ın bir proje senkronizasyonu yapmasına izin verin ve Kullanıma devam edin.


Kullanım

Kullanılabilirliği kontrol ediliyor

Shizuku'nun nasıl kullanılacağına geçmeden önce, onun gerçekten kullanılabilir olduğundan emin olmak hakkında konuşalım.

İznin verilip verilmediğini kontrol etmeden ve Shizuku üzerinden API çağrıları yapmadan önce aşağıdaki yöntemle bu kontrollerin ve çağrıların başarılı olacağından emin olabilirsiniz:

Shizuku.pingBinder()

Shizuku kurulu ve çalışıyorsa bu geri dönecektir doğru. Aksi taktirde false değerini döndürecektir.

İzin Verme

Shizuku bir çalışma zamanı izni kullandığından, kabuk erişimiyle herhangi bir şey yapabilmeniz için uygulamanıza bu iznin verilmesi gerekir. Ayrıca dolaşımda, bunu sağlamanın farklı yollarıyla iki API sürümü bulunmaktadır. Bu bölüm size her ikisini de nasıl kullanacağınızı gösterecektir.

Kontrol etme

İzni istemeden önce yapılacak en iyi şey, zaten izin alıp almadığınızı kontrol etmektir. Bunu yaparsanız, yapmanız gereken her şeye devam edebilirsiniz. Aksi takdirde devam etmeden önce talep etmeniz gerekecektir.

Shizuku'yu kullanma izniniz olup olmadığını kontrol etmek için aşağıdakileri kullanabilirsiniz. Bu kod, onu bir Faaliyet içinde çalıştırdığınızı varsayar.

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

İstemek

Shizuku'yu kullanmak için izin istemeniz gerekiyorsa bunu nasıl yapacağınızı burada bulabilirsiniz.

 SHIZUKU_CODE Aşağıda kullanılan değişken sabit değere sahip bir tamsayı (statik değişken) olmalıdır.

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

Sonucu dinlemek için Faaliyetleri geçersiz kılmanız gerekir onRequestPermissionsResult() yöntem. Ayrıca uygulamanız gerekecek Shizuku. OnRequestPermissionResultListener. Göstereceğim örnek, Faaliyetinizin bu arayüzü uyguladığını varsayar, ancak isterseniz bunu bir değişkene uygulayabilirsiniz.

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'leri kullanma

Artık Shizuku kurulduğuna ve izinler verildiğine göre, Shizuku'yu kullanarak API'leri çağırmaya başlayabilirsiniz. Buradaki süreç alıştığınızdan biraz farklı. Aramak yerine getSystemService() ve şöyle bir şeye döküm vermek WindowManagerbunun yerine dahili API'leri kullanmanız gerekir (ör. IWindowManager).

Shizuku, Android'in gizli API kara listesine yönelik bir bypass içerir, dolayısıyla onu kullanırken bu konuda endişelenmenize gerek kalmayacaktır. Bunu kendiniz nasıl atlatacağınızı merak ediyorsanız önceki eğitimime göz atın.

İşte size nasıl bir örneğini alabileceğinizi gösteren hızlı bir örnek (yansıtma kullanarak) IPackageManager ve bunu bir uygulamaya çalışma zamanı izni vermek için kullanın.

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

Diğer API'ler için süreç benzerdir. Sınıfın ve Stub alt sınıfının referanslarını alın. Referansı alın asInterface Stub sınıfı için yöntem. İstediğiniz yöntemlerin referanslarını sınıfın kendisinden alın. Ardından, şunu çağırın: asInterface Sahip olduğunuz yöntem referansı, değiştirilerek "package" yukarıda ihtiyacınız olan hizmetle birlikte. Bu örnek daha sonra yöntem çağrıları için iletilebilir.

Profesyonel ipucu: değiştirilmiş bir SDK yüklerseniz yansımayı kullanmaktan tamamen kaçınabilirsiniz. anggrayudi'nin GitHub deposuna göz atın Değiştirilen SDK'lar ve kurulum talimatları için. Bu yüklendiğinde yukarıdaki kod (Kotlin'de) çok daha basit hale gelir.

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

Shizuku çalıştığı ve uygulamanızın izni olduğu sürece herhangi bir AIDL tabanlı API, uygulamanızın herhangi bir yerinden bu yöntemle kullanılabilir.

Kullanıcı Hizmeti

Binder yöntemi çoğu kullanım durumunu kapsasa da, doğrudan Binder arayüzüne sahip olmayan bir API'ye ihtiyaç duyduğunuz zamanlar da olabilir. Bu durumda Shizuku'daki Kullanıcı Hizmeti özelliğini kullanabilirsiniz.

Bu yöntem Android'deki normal bir Hizmete benzer şekilde çalışır. Onu "başlatırsınız", ona bir ServiceConnection ile bağlanarak iletişim kurarsınız ve mantığınızı hizmet sınıfında çalıştırırsınız. Aradaki fark, Android Hizmetini kullanmamanız ve hizmetin içindeki her şeyin ADB izinleriyle çalışmasıdır.

Şimdi bazı sınırlamalar var. Kullanıcı Hizmeti tamamen ayrı bir işlem ve kullanıcıda çalışır, dolayısıyla kendi AIDL geri aramalarınız ve Bağlayıcılarınız dışında uygulamanızın geri kalanıyla etkileşim kuramazsınız. Aynı zamanda uygun bir uygulama sürecinde çalışmadığından, Android Hizmetlerini bağlama gibi bazı şeyler düzgün çalışmayabilir.

Bu aynı zamanda Shizuku sürüm 10 veya üstünü gerektirir. Uygulamaya ilişkin çoğu kaynak şu anda sürüm 11'e sahip olsa da yine de örneğe dahil edilecek bir sürüm kontrolü eklemelisiniz.

AIDL'yi tanımlama

Başlamak için yeni bir AIDL dosyası oluşturmanız gerekecek. Bunu Android Studio'da, Android dosya görünümünde herhangi bir şeye sağ tıklayarak, "Yeni" seçeneğinin üzerine gelip "AIDL" seçeneğini seçerek yapabilirsiniz. Dosyanın adını girin (örneğin, "IUserService") ve Android Studio sizin için bir şablon dosyası oluşturacaktır.

AIDL'lerin nasıl çalıştığına aşina değilseniz, mutlaka göz atın Google'ın belgeleri.

Şablon yöntemlerini AIDL'den kaldırın ve ardından destroy() Shizuku için uygun kimliğe sahip yöntem. Bu, Shizuku Kullanıcı Hizmetini sonlandırdığında çağrılacak ve sahip olduğunuz referansları veya devam eden mantığı temizlemek için kullanılmalıdır.

Örnek 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'nin uygulanması

Yapılacak bir sonraki şey aslında AIDL'yi uygulamaktır.

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

Yukarıdaki örnekler aşağıdaki özelliklere sahip olduğunuzu varsayar: Android Gizli API'si SDK yüklü.

Servis Bağlantısını Kurma

Artık Kullanıcı Hizmeti tanımlandığına ve uygulandığına göre, onu kullanıma hazırlamanın zamanı geldi. Yapmanız gereken ilk şey, onunla iletişim kurmak istediğiniz yerde bir ServiceConnection tanımlamaktır (örneğin, uygulamanızdaki ana Faaliyetten).

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

binder değişken, uygulamanızdan Kullanıcı Hizmetiyle iletişim kurmak için kullanacağınız şeydir. Kullanıma uygun olup olmadığını kontrol etmek için boş olup olmadığını ve pingBinder() İadeler doğrutıpkı yukarıdaki kod örneğinde olduğu gibi.

Kullanıcı Hizmeti bağımsız değişkenlerini oluşturma

Kullanıcı Hizmetini kontrol edebilmeniz için önce Shizuku'nun hizmeti başlatırken ve durdururken kullanacağı bazı argümanları tanımlamanız gerekir. Bunlar arasında Shizuku'ya hizmetin sınıf adının gerçekten söylenmesi, işlem sonekinin belirtilmesi, hata ayıklanabilir olup olmadığı ve hangi sürüm olduğu gibi şeyler yer alır.

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)

Kullanıcı Hizmetini Başlatma, Durdurma ve Bağlama

Başlatma ve bağlama eylemleri ile durdurma ve bağlantıyı kaldırma eylemleri Shizuku'da birleştirilmiştir. Ayrı başlatma ve bağlama yöntemleri veya durdurma ve bağlamayı kaldırma yöntemleri yoktur.

İşte nasıl yapılacağı başlat ve bağla Kullanıcı Hizmeti.

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

İşte nasıl yapılacağı dur ve bağlantıyı kes Kullanıcı Hizmeti.

Java:

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

Kotlin:

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

Kullanıcı Hizmetini Çağırma

Kullanıcı Hizmeti başlatıldığında kullanmaya başlayabilirsiniz. Basitçe olup olmadığını kontrol edin binder değişken boş değildir ve pinglenebilirdir ve ardından yöntem çağrınızı yapın.

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

Çözüm

Bunların hepsini takip ettiyseniz artık çalışan bir Shizuku entegrasyonuna sahip olmalısınız. Kullanıcılarınıza Shizuku'yu yüklemelerini ve onu kullanmaya çalışmadan önce Shizuku'nun mevcut olup olmadığını doğru şekilde kontrol etmelerini söylemeyi unutmayın.