mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 11:05:59 +00:00
initialize Dhizuku, get DevicePolicyManager using binder wrapper
This commit is contained in:
@@ -106,6 +106,8 @@ dependencies {
|
|||||||
implementation(libs.androidx.navigation.compose)
|
implementation(libs.androidx.navigation.compose)
|
||||||
implementation(libs.shizuku.provider)
|
implementation(libs.shizuku.provider)
|
||||||
implementation(libs.shizuku.api)
|
implementation(libs.shizuku.api)
|
||||||
|
implementation(libs.dhizuku.api)
|
||||||
implementation(libs.androidx.biometric)
|
implementation(libs.androidx.biometric)
|
||||||
implementation(libs.androidx.fragment)
|
implementation(libs.androidx.fragment)
|
||||||
|
implementation(libs.hiddenApiBypass)
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package android.app.admin;
|
||||||
|
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.IInterface;
|
||||||
|
|
||||||
|
public interface IDevicePolicyManager extends IInterface {
|
||||||
|
abstract class Stub extends Binder implements IDevicePolicyManager {
|
||||||
|
public static IDevicePolicyManager asInterface(IBinder obj) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.bintianqi.owndroid
|
|||||||
import android.app.admin.DevicePolicyManager
|
import android.app.admin.DevicePolicyManager
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
import android.os.Build.VERSION
|
import android.os.Build.VERSION
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@@ -40,7 +41,9 @@ import androidx.navigation.compose.rememberNavController
|
|||||||
import com.bintianqi.owndroid.dpm.*
|
import com.bintianqi.owndroid.dpm.*
|
||||||
import com.bintianqi.owndroid.ui.Animations
|
import com.bintianqi.owndroid.ui.Animations
|
||||||
import com.bintianqi.owndroid.ui.theme.OwnDroidTheme
|
import com.bintianqi.owndroid.ui.theme.OwnDroidTheme
|
||||||
|
import com.rosan.dhizuku.api.Dhizuku
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import org.lsposed.hiddenapibypass.HiddenApiBypass
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
var backToHomeStateFlow = MutableStateFlow(false)
|
var backToHomeStateFlow = MutableStateFlow(false)
|
||||||
@@ -54,6 +57,12 @@ class MainActivity : FragmentActivity() {
|
|||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
val sharedPref = applicationContext.getSharedPreferences("data", Context.MODE_PRIVATE)
|
val sharedPref = applicationContext.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||||
|
if (sharedPref.getBoolean("dhizuku", false)) {
|
||||||
|
if (VERSION.SDK_INT >= 28) HiddenApiBypass.setHiddenApiExemptions("")
|
||||||
|
if(!Dhizuku.init(applicationContext)) {
|
||||||
|
Toast.makeText(applicationContext, R.string.failed_to_init_dhizuku, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
if(sharedPref.getBoolean("auth", false)) {
|
if(sharedPref.getBoolean("auth", false)) {
|
||||||
showAuth.value = true
|
showAuth.value = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,22 @@
|
|||||||
package com.bintianqi.owndroid.dpm
|
package com.bintianqi.owndroid.dpm
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.app.admin.DevicePolicyManager
|
import android.app.admin.DevicePolicyManager
|
||||||
|
import android.app.admin.IDevicePolicyManager
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageInstaller
|
import android.content.pm.PackageInstaller
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build.VERSION
|
import android.os.Build.VERSION
|
||||||
|
import androidx.activity.ComponentActivity.CONTEXT_IGNORE_SECURITY
|
||||||
|
import androidx.activity.ComponentActivity.DEVICE_POLICY_SERVICE
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import com.bintianqi.owndroid.PackageInstallerReceiver
|
import com.bintianqi.owndroid.PackageInstallerReceiver
|
||||||
|
import com.rosan.dhizuku.api.Dhizuku
|
||||||
|
import com.rosan.dhizuku.api.Dhizuku.binderWrapper
|
||||||
|
import com.rosan.dhizuku.api.DhizukuBinderWrapper
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
@@ -46,3 +54,26 @@ fun installPackage(context: Context, inputStream: InputStream) {
|
|||||||
val pendingIntent = PendingIntent.getBroadcast(context, sessionId, intent, PendingIntent.FLAG_IMMUTABLE).intentSender
|
val pendingIntent = PendingIntent.getBroadcast(context, sessionId, intent, PendingIntent.FLAG_IMMUTABLE).intentSender
|
||||||
session.commit(pendingIntent)
|
session.commit(pendingIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("PrivateApi")
|
||||||
|
fun binderWrapperDevicePolicyManager(appContext: Context): DevicePolicyManager {
|
||||||
|
try {
|
||||||
|
val context = appContext.createPackageContext(Dhizuku.getOwnerComponent().packageName, CONTEXT_IGNORE_SECURITY)
|
||||||
|
val manager = context.getSystemService(DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||||
|
val field = manager.javaClass.getDeclaredField("mService")
|
||||||
|
field.isAccessible = true
|
||||||
|
val oldInterface = field[manager] as IDevicePolicyManager
|
||||||
|
if (oldInterface is DhizukuBinderWrapper) return manager
|
||||||
|
val oldBinder = oldInterface.asBinder()
|
||||||
|
val newBinder = binderWrapper(oldBinder)
|
||||||
|
val newInterface = IDevicePolicyManager.Stub.asInterface(newBinder)
|
||||||
|
field[manager] = newInterface
|
||||||
|
return manager
|
||||||
|
} catch (e: NoSuchFieldException) {
|
||||||
|
throw RuntimeException(e)
|
||||||
|
} catch (e: IllegalAccessException) {
|
||||||
|
throw RuntimeException(e)
|
||||||
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
|
throw RuntimeException(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import android.content.ActivityNotFoundException
|
|||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build.VERSION
|
import android.os.Build.VERSION
|
||||||
|
import android.os.RemoteException
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
@@ -38,6 +40,8 @@ import com.bintianqi.owndroid.R
|
|||||||
import com.bintianqi.owndroid.Receiver
|
import com.bintianqi.owndroid.Receiver
|
||||||
import com.bintianqi.owndroid.backToHomeStateFlow
|
import com.bintianqi.owndroid.backToHomeStateFlow
|
||||||
import com.bintianqi.owndroid.ui.*
|
import com.bintianqi.owndroid.ui.*
|
||||||
|
import com.rosan.dhizuku.api.Dhizuku
|
||||||
|
import com.rosan.dhizuku.api.DhizukuRequestPermissionListener
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@@ -88,12 +92,42 @@ private fun Home(localNavCtrl:NavHostController,listScrollState:ScrollState) {
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||||
val receiver = ComponentName(context, Receiver::class.java)
|
val receiver = ComponentName(context, Receiver::class.java)
|
||||||
|
val sharedPref = LocalContext.current.getSharedPreferences("data", Context.MODE_PRIVATE)
|
||||||
|
var dhizukuStatus by remember { mutableStateOf(sharedPref.getBoolean("dhizuku", false)) }
|
||||||
Column(modifier = Modifier.fillMaxSize().verticalScroll(listScrollState)) {
|
Column(modifier = Modifier.fillMaxSize().verticalScroll(listScrollState)) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.permission),
|
text = stringResource(R.string.permission),
|
||||||
style = typography.headlineLarge,
|
style = typography.headlineLarge,
|
||||||
modifier = Modifier.padding(top = 8.dp, bottom = 5.dp, start = 15.dp)
|
modifier = Modifier.padding(top = 8.dp, bottom = 5.dp, start = 15.dp)
|
||||||
)
|
)
|
||||||
|
SwitchItem(
|
||||||
|
R.string.dhizuku, "", null,
|
||||||
|
{ dhizukuStatus },
|
||||||
|
{
|
||||||
|
if(!it) {
|
||||||
|
sharedPref.edit().putBoolean("dhizuku", false).apply()
|
||||||
|
dhizukuStatus = sharedPref.getBoolean("dhizuku", false)
|
||||||
|
return@SwitchItem
|
||||||
|
}
|
||||||
|
Dhizuku.init(context)
|
||||||
|
if(Dhizuku.isPermissionGranted()) {
|
||||||
|
sharedPref.edit().putBoolean("dhizuku", true).apply()
|
||||||
|
dhizukuStatus = sharedPref.getBoolean("dhizuku", false)
|
||||||
|
} else {
|
||||||
|
Dhizuku.requestPermission(object: DhizukuRequestPermissionListener() {
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
override fun onRequestPermission(grantResult: Int) {
|
||||||
|
if(grantResult == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
sharedPref.edit().putBoolean("dhizuku", true).apply()
|
||||||
|
dhizukuStatus = sharedPref.getBoolean("dhizuku", false)
|
||||||
|
} else {
|
||||||
|
Toast.makeText(context, R.string.permission_not_granted, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
SubPageItem(
|
SubPageItem(
|
||||||
R.string.device_admin, stringResource(if(dpm.isAdminActive(receiver)) R.string.activated else R.string.deactivated),
|
R.string.device_admin, stringResource(if(dpm.isAdminActive(receiver)) R.string.activated else R.string.deactivated),
|
||||||
operation = { localNavCtrl.navigate("DeviceAdmin") }
|
operation = { localNavCtrl.navigate("DeviceAdmin") }
|
||||||
|
|||||||
@@ -99,6 +99,9 @@
|
|||||||
<string name="onDisabled">OwnDroid: Devre Dışı</string>
|
<string name="onDisabled">OwnDroid: Devre Dışı</string>
|
||||||
<string name="create_work_profile_success">OwnDroid: İş Profili Başarıyla Oluşturuldu</string>
|
<string name="create_work_profile_success">OwnDroid: İş Profili Başarıyla Oluşturuldu</string>
|
||||||
|
|
||||||
|
<!--Dhizuku-->
|
||||||
|
<string name="permission_not_granted">Permission not granted</string> <!--TODO-->
|
||||||
|
<string name="failed_to_init_dhizuku">Failed to initialize Dhizuku</string> <!--TODO-->
|
||||||
<!--Shizuku-->
|
<!--Shizuku-->
|
||||||
<string name="check_shizuku">İzni Kontrol Et</string>
|
<string name="check_shizuku">İzni Kontrol Et</string>
|
||||||
<string name="list_owners">Sahipleri Listele</string>
|
<string name="list_owners">Sahipleri Listele</string>
|
||||||
|
|||||||
@@ -94,6 +94,9 @@
|
|||||||
<string name="onDisabled">OwnDroid:已禁用</string>
|
<string name="onDisabled">OwnDroid:已禁用</string>
|
||||||
<string name="create_work_profile_success">OwnDroid:创建工作资料成功</string>
|
<string name="create_work_profile_success">OwnDroid:创建工作资料成功</string>
|
||||||
|
|
||||||
|
<!--Dhizuku-->
|
||||||
|
<string name="permission_not_granted">未授权</string>
|
||||||
|
<string name="failed_to_init_dhizuku">Dhizuku初始化失败</string>
|
||||||
<!--Shizuku-->
|
<!--Shizuku-->
|
||||||
<string name="check_shizuku">检查Shizuku</string>
|
<string name="check_shizuku">检查Shizuku</string>
|
||||||
<string name="list_owners">列出Owners</string>
|
<string name="list_owners">列出Owners</string>
|
||||||
|
|||||||
@@ -101,6 +101,10 @@
|
|||||||
<string name="onDisabled">OwnDroid: Disabled</string>
|
<string name="onDisabled">OwnDroid: Disabled</string>
|
||||||
<string name="create_work_profile_success">OwnDroid: Create work profile success</string>
|
<string name="create_work_profile_success">OwnDroid: Create work profile success</string>
|
||||||
|
|
||||||
|
<!--Dhizuku-->
|
||||||
|
<string name="dhizuku" translatable="false">Dhizuku</string>
|
||||||
|
<string name="permission_not_granted">Permission not granted</string>
|
||||||
|
<string name="failed_to_init_dhizuku">Failed to initialize Dhizuku</string>
|
||||||
<!--Shizuku-->
|
<!--Shizuku-->
|
||||||
<string name="shizuku" translatable="false">Shizuku</string>
|
<string name="shizuku" translatable="false">Shizuku</string>
|
||||||
<string name="check_shizuku">Check permission</string>
|
<string name="check_shizuku">Check permission</string>
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ accompanist-drawablepainter = "0.35.0-alpha"
|
|||||||
shizuku = "13.1.5"
|
shizuku = "13.1.5"
|
||||||
biometric = "1.2.0-alpha05"
|
biometric = "1.2.0-alpha05"
|
||||||
fragment = "1.8.0-beta01"
|
fragment = "1.8.0-beta01"
|
||||||
|
dhizuku = "2.5.2"
|
||||||
|
hiddenApiBypass = "4.3"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity-compose" }
|
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity-compose" }
|
||||||
@@ -23,6 +25,8 @@ androidx-biometric = { group = "androidx.biometric", name = "biometric", version
|
|||||||
|
|
||||||
shizuku-provider = { module = "dev.rikka.shizuku:provider", version.ref = "shizuku" }
|
shizuku-provider = { module = "dev.rikka.shizuku:provider", version.ref = "shizuku" }
|
||||||
shizuku-api = { module = "dev.rikka.shizuku:api", version.ref = "shizuku" }
|
shizuku-api = { module = "dev.rikka.shizuku:api", version.ref = "shizuku" }
|
||||||
|
dhizuku-api = { module = "io.github.iamr0s:Dhizuku-API", version.ref = "dhizuku" }
|
||||||
|
hiddenApiBypass = { module = "org.lsposed.hiddenapibypass:hiddenapibypass", version.ref = "hiddenApiBypass" }
|
||||||
androidx-fragment = { group = "androidx.fragment", name = "fragment", version.ref = "fragment" }
|
androidx-fragment = { group = "androidx.fragment", name = "fragment", version.ref = "fragment" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
|
|||||||
Reference in New Issue
Block a user