| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- package com.example.modifier
- import android.accessibilityservice.AccessibilityServiceInfo
- import android.content.Context
- import android.content.pm.PackageManager
- import android.text.TextUtils
- import android.util.Log
- import android.view.accessibility.AccessibilityManager
- import androidx.core.app.ActivityCompat
- import com.example.modifier.http.ktorClient
- import com.example.modifier.service.ModifierService
- import io.ktor.client.request.head
- import kotlinx.coroutines.Dispatchers
- import kotlinx.coroutines.coroutineScope
- import kotlinx.coroutines.launch
- import kotlinx.coroutines.withContext
- import java.time.ZoneId
- import java.time.ZonedDateTime
- import java.time.format.DateTimeFormatter
- import java.util.Locale
- private const val TAG = "Modifier"
- suspend fun shellRun(vararg commands: String): Pair<String, String> {
- var output = ""
- var error = ""
- Log.i(TAG, "shellRun: \t${commands.joinToString("\n\t\t\t")}")
- withContext(Dispatchers.IO) {
- val p = ProcessBuilder("su", "-M").start()
- p.outputStream.bufferedWriter().use { writer ->
- commands.forEach { command ->
- writer.write(command)
- writer.newLine()
- writer.flush()
- }
- }
- coroutineScope {
- launch {
- p.inputStream.bufferedReader().useLines {
- it.forEach {
- output += it + "\n"
- Log.i(TAG, "shellRunOut: $it")
- }
- }
- }
- launch {
- p.errorStream.bufferedReader().useLines {
- it.forEach {
- error += it + "\n"
- Log.e(TAG, "shellRunErr: $it")
- }
- }
- }
- }
- p.waitFor()
- }
- return Pair(output, error)
- }
- fun getContext(): Context? {
- try {
- val activityThreadClass = Class.forName("android.app.ActivityThread")
- val currentActivityThreadMethod = activityThreadClass.getMethod("currentActivityThread")
- currentActivityThreadMethod.isAccessible = true
- val currentActivityThread = currentActivityThreadMethod.invoke(null)
- val getApplicationMethod = activityThreadClass.getMethod("getApplication")
- getApplicationMethod.isAccessible = true
- return getApplicationMethod.invoke(currentActivityThread) as Context
- } catch (e: java.lang.Exception) {
- e.printStackTrace()
- }
- return null
- }
- suspend fun hasRootAccess(): Boolean {
- var rootAccess = false
- try {
- val (output, _) = shellRun("echo \"imrooted\"")
- if (output.contains("imrooted")) {
- rootAccess = true
- }
- } catch (e: Exception) {
- e.printStackTrace()
- }
- return rootAccess
- }
- fun hasPermission(permission: String): Boolean {
- return ActivityCompat.checkSelfPermission(
- getContext()!!,
- permission
- ) == PackageManager.PERMISSION_GRANTED
- }
- fun isAccessibilityEnabled(): Boolean {
- val context = getContext()!!
- val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
- val enabledServices =
- am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK)
- for (enabledService in enabledServices) {
- Log.i(
- TAG,
- "Enabled service: " + enabledService.resolveInfo.serviceInfo.packageName + "/" + enabledService.resolveInfo.serviceInfo.name
- )
- val enabledServiceInfo = enabledService.resolveInfo.serviceInfo
- if (enabledServiceInfo.packageName == context.packageName && enabledServiceInfo.name == ModifierService.NAME) return true
- }
- return false
- }
- suspend fun enableAccessibility(): Boolean {
- if (isAccessibilityEnabled()) return true
- val context = getContext()!!
- val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
- val enabledServices =
- am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK)
- val names: MutableList<String?> = ArrayList()
- for (enabledService in enabledServices) {
- names.add(enabledService.resolveInfo.serviceInfo.packageName + "/" + enabledService.resolveInfo.serviceInfo.name)
- }
- names.add(context.packageName + "/" + ModifierService.NAME)
- try {
- shellRun(
- "settings put secure enabled_accessibility_services " + TextUtils.join(":", names),
- "settings put secure accessibility_enabled 1"
- )
- return true
- } catch (e: java.lang.Exception) {
- e.printStackTrace()
- }
- return false
- }
- suspend fun enableOverlay() {
- try {
- shellRun("appops set " + BuildConfig.APPLICATION_ID + " SYSTEM_ALERT_WINDOW allow")
- } catch (e: java.lang.Exception) {
- e.printStackTrace()
- }
- }
- suspend fun syncTime() {
- try {
- Log.i("Modifier", "syncTime: start")
- val response = ktorClient("").head("http://www.baidu.com")
- val dateHeader = response.headers["Date"]
- val date = ZonedDateTime.parse(
- dateHeader,
- DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH)
- )
- // convert to Asia/Shanghai
- val dateInZone = date.withZoneSameInstant(ZoneId.of("Asia/Shanghai"))
- Log.i(
- TAG,
- "CurrentTime from Baidu: ${dateInZone.format(DateTimeFormatter.ISO_DATE_TIME)}"
- )
- shellRun(
- "settings put system time_12_24 24",
- "settings put global auto_time 0",
- "settings put global auto_time_zone 0",
- "setprop persist.sys.timezone Asia/Shanghai",
- "date \"${dateInZone.format(DateTimeFormatter.ofPattern("MMddHHmmyyyy.ss"))}\""
- )
- } catch (e: Exception) {
- Log.e(TAG, "Error SyncTime", e)
- }
- }
|