Како подићи дозволе апликације користећи Схизуку библиотеку

click fraud protection

Роотинг није за свакога. Ево како можете да добијете повећане дозволе на нивоу љуске у својој апликацији користећи Схизуку библиотеку.

Постоји много разлога због којих дозволе које се обично дају вашој апликацији можда неће бити довољне. Можда сте попут мене и уживате у креирању хакованих апликација које злоупотребљавају Андроид АПИ. Неки од АПИ-ја које користим су закључани иза посебних дозвола. Понекад само корисник љуске (АДБ) или систем могу да им приступе. Ипак, постоји решење - Шизуку.

Схизуку вам омогућава да позивате системске АПИ-је скоро директно, и то у потпуности у Јави или Котлину. Овај водич ће вам показати како да примените и користите Схизуку.

Шта је Шизуку?

Пре него што почнемо да користимо Схизуку, можда би било од помоћи да знамо шта је то тачно. Ако сте упознати са Магиск, онда је Шизуку сличан. Али уместо управљања роот приступом, он управља приступом љуске.

Схизуку покреће сопствени процес са дозволама на нивоу шкољке. Начин на који корисник активира тај процес зависи од његовог уређаја, верзије Андроид-а и избора. Схизуку се може активирати преко АДБ-а, преко бежичног АДБ-а на уређају (

на Андроид 11 и новијим верзијама), или преко роот приступа. Апликације које имплементирају Схизуку могу онда да траже дозволу да користе тај процес за обављање повишених операција.

СхизукуПрограмер: Ксингцхен & Рикка

Цена: бесплатно.

4.1.

Преузимање

Зашто Шизуку?

Док вам приступ систему на нивоу љуске не дозвољава да урадите онолико колико корен, и даље вам даје већи приступ него што би то учинила нормална апликација. Поврх тога, начин на који Схизуку функционише омогућава вам да користите Андроид АПИ-је скоро као нормално. Не морате да се ослањате на команде љуске (иако можете ако желите).

Ако су вашој апликацији потребне посебне дозволе које се могу доделити само преко АДБ-а (или са роот-ом), Схизуку и Андроид 11 су одлично упаривање. Можете само да користите Схизуку да доделите посебне дозволе у ​​потпуности на уређају.

Чак и са уређајима који немају Андроид 11, Схизуку може бити користан. Апликација пружа упутства и скрипте за кориснике тако да не морате.

Интеграција

Додавање Схизукуа вашој апликацији није најједноставније, али није ни тешко. Нажалост, тхе програмерску документацију није баш потпун, али овај чланак вас покрива. Ево како да интегришете Схизуку у своју апликацију.

Зависности

Први корак је да додате Схизуку зависности. У вашем буилд.градле на нивоу модула, додајте следеће блоку зависности.

def shizuku_version = '11.0.3'

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

Обавезно ажурирајте верзију ако је потребно. 11.0.3 је најновији у време писања.

Провајдер

Да би Схизуку функционисао, морате да додате блок добављача у манифест апликације. Отворите АндроидМанифест.кмл и додајте следеће у блок апликације.

 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.pingBinder()

Ако је Схизуку инсталиран и покренут, ово ће се вратити истина. У супротном, вратиће се нетачно.

Давање дозволе

Пошто Схизуку користи дозволу за време извршавања, она мора бити додељена вашој апликацији пре него што можете било шта да урадите са приступом љуске. У оптицају су и две верзије АПИ-ја, са различитим начинима доделе. Овај одељак ће вам показати како да рукујете оба.

Проверавам

Пре него што затражите дозволу, најбоље је да проверите да ли је већ имате. Ако то урадите, можете наставити са оним што треба да урадите. У супротном, мораћете да то затражите пре него што наставите.

Да бисте проверили да ли имате дозволу да користите Схизуку, можете користити следеће. Овај код претпоставља да га покрећете унутар активности.

Котлин:

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

Захтева

Ако треба да затражите дозволу да користите Схизуку, ево како.

Тхе СХИЗУКУ_ЦОДЕ променљива која се користи у наставку треба да буде цео број са сталном вредношћу (статичка променљива).

Котлин:

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

Да бисте слушали резултат, мораћете да замените активност онРекуестПермиссионсРесулт() методом. Такође ћете морати да примените Схизуку. ОнРекуестПермиссионРесултЛистенер. Пример који ћу показати претпоставља да ваша активност имплементира тај интерфејс, али можете га имплементирати у променљиву ако желите.

Котлин:

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

Коришћење АПИ-ја

Сада када је Схизуку подешен и дозволе су одобрене, можете почети да заправо позивате АПИ-је користећи Схизуку. Процес овде је мало другачији него што сте можда навикли. Уместо да зовем getSystemService() и ливење на нешто слично WindowManager, за њих ћете морати да користите интерне АПИ-је (нпр. IWindowManager).

Схизуку укључује заобилазницу за Андроид-ову скривену црну листу АПИ-ја, тако да нећете морати да бринете о томе када га користите. Ако сте знатижељни како то сами заобићи, погледајте мој претходни водич.

Ево кратког примера (користећи рефлексију) који вам показује како можете да добијете инстанцу 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);

Процес за друге АПИ-је је сличан. Добијте референце на класу и њену подкласу Стуб. Добијте референцу на asInterface метод за класу Стуб. Узмите референце на методе које желите из саме класе. Затим позовите asInterface референца методе коју имате, замена "package" горе са било којом услугом која вам је потребна. Та инстанца се затим може проследити за позивање метода.

Про врх: можете у потпуности да избегнете коришћење рефлексије ако инсталирате модификовани СДК. Погледајте ангграиудијево ГитХуб спремиште за модификоване СДК-ове и упутства за инсталацију. Са овим инсталираним, горњи код (у Котлину) постаје много једноставнији.

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

Било који АПИ-ји засновани на АИДЛ-у могу се користити са овим методом са било ког места у вашој апликацији, све док је Схизуку покренут и ваша апликација има дозволу.

Кориснички сервис

Иако метода Биндер покрива већину случајева употребе, може бити тренутака када вам треба АПИ који нема директан интерфејс Биндер-а. У том случају можете користити функцију корисничке услуге у Схизуку-у.

Овај метод функционише слично нормалној услузи у Андроиду. Ви га „покрећете“, комуницирате повезивањем са њим помоћу СервицеЦоннецтион-а и покрећете своју логику у класи услуге. Разлика је у томе што не користите Андроид-ову услугу и све што је унутар услуге ради са АДБ дозволама.

Сада постоје нека ограничења. Кориснички сервис ради у потпуно одвојеном процесу и кориснику, тако да не можете да комуницирате са остатком ваше апликације осим путем сопствених АИДЛ повратних позива и повезивача. Пошто такође не ради у одговарајућем процесу апликације, неке ствари попут везивања Андроид услуга можда неће радити исправно.

Ово такође захтева Схизуку верзију 10 или новију. Иако већина извора за апликацију тренутно има верзију 11, ипак би требало да укључите проверу верзије, која ће бити укључена у пример.

Дефинисање АИДЛ-а

Да бисте започели, мораћете да креирате нову АИДЛ датотеку. То можете да урадите у Андроид Студију тако што ћете десним тастером миша кликнути било шта у приказу Андроид датотека, прећи мишем изнад опције „Ново“ и изабрати опцију „АИДЛ“. Унесите назив датотеке (нпр. „ИУсерСервице“) и Андроид Студио ће креирати датотеку шаблона за вас.

Ако нисте упознати са начином на који АИДЛ функционишу, обавезно погледајте Гоогле-ова документација.

Уклоните методе шаблона из АИДЛ-а, а затим додајте а destroy() метода са одговарајућим ИД-ом за Шизуку. Ово ће бити позвано када Схизуку убије кориснички сервис и требало би да се користи за чишћење свих референци или текуће логике коју имате.

Пример АИДЛ:

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

Имплементација АИДЛ-а

Следећа ствар коју треба урадити је заправо имплементација АИДЛ-а.

Јава:

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

Горе наведени примери претпостављају да имате Андроид скривени АПИ СДК је инсталиран.

Подешавање сервисне везе

Сада када је кориснички сервис дефинисан и имплементиран, време је да га поставите за употребу. Прва ствар коју треба да урадите је да дефинишете СервицеЦоннецтион где желите да комуницирате са њом (нпр. из главне активности у вашој апликацији).

Јава:

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() враћа истина, баш као у горњем примеру кода.

Креирање аргумената корисничке услуге

Пре него што будете могли да контролишете кориснички сервис, мораћете да дефинишете неке аргументе које ће Схизуку користити приликом покретања и заустављања. То укључује ствари као што је стварно саопштавање Шизуку имена класе услуге, навођење суфикса процеса, да ли се може отклонити грешака или не, и која је верзија.

Јава:

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)

Покретање, заустављање и везивање корисничког сервиса

Акције покретања и везивања и акције заустављања и одвезивања су обједињене у Шизуку. Не постоје одвојене методе покретања и везивања или методе заустављања и одвезивања.

Ево како да започети и везати кориснички сервис.

Јава:

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 променљива није нулл и може се пинговати, а затим позовите свој метод.

Јава:

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

Закључак

Ако сте све то пратили, сада би требало да имате функционалну Схизуку интеграцију. Само запамтите да кажете својим корисницима да инсталирају Схизуку и да правилно провере да ли је Схизуку доступан пре него што покушају да га користе.