This commit is contained in:
parent
b504984268
commit
fc62906c0e
|
@ -4,6 +4,14 @@
|
||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
<DropdownSelection timestamp="2025-07-07T06:37:35.266033300Z">
|
||||||
|
<Target type="DEFAULT_BOOT">
|
||||||
|
<handle>
|
||||||
|
<DeviceId pluginId="Default" identifier="serial=8.217.74.194:8924;connection=1af33e42" />
|
||||||
|
</handle>
|
||||||
|
</Target>
|
||||||
|
</DropdownSelection>
|
||||||
|
<DialogSelection />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||||
|
|
|
@ -9,8 +9,7 @@
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.BIND_VPN_SERVICE"
|
<uses-permission android:name="android.permission.BIND_VPN_SERVICE"
|
||||||
tools:ignore="ProtectedPermissions" />
|
tools:ignore="ProtectedPermissions" />
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||||
android:maxSdkVersion="32"/>
|
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.VPN_SERVICE" />
|
<uses-permission android:name="android.permission.VPN_SERVICE" />
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.android.grape
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
@ -11,11 +12,11 @@ import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import com.android.grape.databinding.ActivityMainBinding
|
import com.android.grape.databinding.ActivityMainBinding
|
||||||
|
import com.android.grape.job.MonitorService
|
||||||
import com.android.grape.util.ClashUtil
|
import com.android.grape.util.ClashUtil
|
||||||
import com.android.grape.util.NotificationPermissionHandler
|
import com.android.grape.util.NotificationPermissionHandler
|
||||||
import com.android.grape.util.ScriptUtil
|
import com.android.grape.util.ScriptUtil
|
||||||
import com.android.grape.util.StoragePermissionHelper
|
import com.android.grape.util.StoragePermissionHelper
|
||||||
import com.blankj.utilcode.util.LogUtils
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
private val viewModel by viewModels<MainViewModel>()
|
private val viewModel by viewModels<MainViewModel>()
|
||||||
|
@ -34,21 +35,22 @@ class MainActivity : AppCompatActivity() {
|
||||||
checkPermission()
|
checkPermission()
|
||||||
ScriptUtil.registerScriptResultReceiver()
|
ScriptUtil.registerScriptResultReceiver()
|
||||||
viewBinding.start.setOnClickListener {
|
viewBinding.start.setOnClickListener {
|
||||||
try {
|
MonitorService.onEvent(MainApplication.instance)
|
||||||
ClashUtil.startProxy(this)
|
// try {
|
||||||
ClashUtil.switchProxyGroup(
|
// ClashUtil.startProxy(this)
|
||||||
"GLOBAL",
|
// ClashUtil.switchProxyGroup(
|
||||||
ClashUtil.getRandomLocale(),
|
// "GLOBAL",
|
||||||
"http://127.0.0.1:6170"
|
// ClashUtil.getRandomLocale(),
|
||||||
)
|
// "http://127.0.0.1:6170"
|
||||||
} catch (e: Exception) {
|
// )
|
||||||
LogUtils.e("startProxyVpn: Failed to start VPN", e)
|
// } catch (e: Exception) {
|
||||||
Toast.makeText(
|
// LogUtils.e("startProxyVpn: Failed to start VPN", e)
|
||||||
this,
|
// Toast.makeText(
|
||||||
"Failed to start VPN: " + (if (e.message != null) e.message else "Unknown error"),
|
// this,
|
||||||
Toast.LENGTH_SHORT
|
// "Failed to start VPN: " + (if (e.message != null) e.message else "Unknown error"),
|
||||||
).show()
|
// Toast.LENGTH_SHORT
|
||||||
}
|
// ).show()
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
viewBinding.stop.setOnClickListener {
|
viewBinding.stop.setOnClickListener {
|
||||||
ClashUtil.stopProxy(this)
|
ClashUtil.stopProxy(this)
|
||||||
|
@ -63,6 +65,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPermission() {
|
private fun checkPermission() {
|
||||||
|
Log.d("TAG", "checkPermission: ")
|
||||||
permissionHandler = NotificationPermissionHandler(this) { result ->
|
permissionHandler = NotificationPermissionHandler(this) { result ->
|
||||||
handlePermissionResult(result)
|
handlePermissionResult(result)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.android.grape
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.work.PeriodicWorkRequest
|
import androidx.work.PeriodicWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
|
import com.android.grape.job.MonitorService
|
||||||
import com.android.grape.service.MyAccessibilityService
|
import com.android.grape.service.MyAccessibilityService
|
||||||
import com.android.grape.work.CheckAccessibilityWorker
|
import com.android.grape.work.CheckAccessibilityWorker
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
@ -21,6 +22,5 @@ class MainViewModel:ViewModel() {
|
||||||
.build()
|
.build()
|
||||||
WorkManager.getInstance(MainApplication.instance).enqueue(workRequest)
|
WorkManager.getInstance(MainApplication.instance).enqueue(workRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -23,7 +23,8 @@ class DownloadAppJobService : JobIntentService() {
|
||||||
|
|
||||||
if (succ) {
|
if (succ) {
|
||||||
errTime = 0L
|
errTime = 0L
|
||||||
StartVpnServerJobService.onEvent(this)
|
InstallService.onEvent(this)
|
||||||
|
// StartVpnServerJobService.onEvent(this)
|
||||||
// StartVpnPortJobService.onEvent(this)
|
// StartVpnPortJobService.onEvent(this)
|
||||||
} else {
|
} else {
|
||||||
Util.isClickRet = false
|
Util.isClickRet = false
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.app.JobIntentService
|
import androidx.core.app.JobIntentService
|
||||||
|
import com.android.grape.net.ChangeCallBack
|
||||||
import com.android.grape.util.ChangeDeviceInfoUtil
|
import com.android.grape.util.ChangeDeviceInfoUtil
|
||||||
import com.android.grape.util.MockTools
|
import com.android.grape.util.MockTools
|
||||||
import com.android.grape.util.ServiceUtils
|
import com.android.grape.util.ServiceUtils
|
||||||
|
@ -23,9 +24,9 @@ class OpenAppService : JobIntentService() {
|
||||||
ServiceUtils.setEnableApp("com.android.chrome", true)
|
ServiceUtils.setEnableApp("com.android.chrome", true)
|
||||||
ServiceUtils.setEnableApp("com.UCMobile", true)
|
ServiceUtils.setEnableApp("com.UCMobile", true)
|
||||||
if (Util.isCanAuto && Util.canAutoLc.isNotEmpty()) {
|
if (Util.isCanAuto && Util.canAutoLc.isNotEmpty()) {
|
||||||
MockTools.exec("pm grant org.autojs.autojs android.permission.READ_EXTERNAL_STORAGE") //sdcard权限
|
MockTools.exec("pm grant ${Util.AUTO_JSPACKAGENAME} android.permission.READ_EXTERNAL_STORAGE") //sdcard权限
|
||||||
MockTools.exec("pm grant org.autojs.autojs android.permission.SYSTEM_ALERT_WINDOW") //悬浮窗权限
|
MockTools.exec("pm grant ${Util.AUTO_JSPACKAGENAME} android.permission.SYSTEM_ALERT_WINDOW") //悬浮窗权限
|
||||||
MockTools.exec("settings put secure enabled_accessibility_services org.autojs.autojs/com.stardust.autojs.core.accessibility.AccessibilityService")
|
MockTools.exec("settings put secure enabled_accessibility_services ${Util.AUTO_JSPACKAGENAME}/${Util.AUTO_JSPACKAGENAME}.core.accessibility.AccessibilityService")
|
||||||
Util.doScript(this, Util.AUTO_JSPACKAGENAME) //autojs
|
Util.doScript(this, Util.AUTO_JSPACKAGENAME) //autojs
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -37,13 +38,21 @@ class OpenAppService : JobIntentService() {
|
||||||
// Log.d("IOSTQ:", "执行新装任务")
|
// Log.d("IOSTQ:", "执行新装任务")
|
||||||
// Util.setInfo(this)
|
// Util.setInfo(this)
|
||||||
// }
|
// }
|
||||||
ChangeDeviceInfoUtil.changeDeviceInfo()
|
// ChangeDeviceInfoUtil.changeDeviceInfo()
|
||||||
|
ChangeDeviceInfoUtil.changeDevice(callBack = object : ChangeCallBack {
|
||||||
|
override fun changeSuccess() {
|
||||||
|
Util.openRecordApp(this@OpenAppService)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun changeFailed() {
|
||||||
|
Util.setFinish(this@OpenAppService)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Util.hookOpenApp(this);
|
// Util.hookOpenApp(this);
|
||||||
Util.openRecordApp(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.android.grape.net
|
||||||
|
|
||||||
|
interface ChangeCallBack {
|
||||||
|
fun changeSuccess()
|
||||||
|
fun changeFailed()
|
||||||
|
}
|
|
@ -2,22 +2,28 @@ package com.android.grape.net
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.blankj.utilcode.util.LogUtils
|
import com.blankj.utilcode.util.LogUtils
|
||||||
|
import com.google.gson.Gson
|
||||||
import okhttp3.*
|
import okhttp3.*
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor.Level
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor.Logger
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
object HttpUtils {
|
object HttpUtils {
|
||||||
|
const val HOST: String = "https://openapi-hk.armcloud.net"
|
||||||
// OkHttp客户端配置
|
// OkHttp客户端配置
|
||||||
private val client: OkHttpClient by lazy {
|
private val client: OkHttpClient by lazy {
|
||||||
OkHttpClient.Builder()
|
OkHttpClient.Builder()
|
||||||
.connectTimeout(15, TimeUnit.SECONDS)
|
.connectTimeout(15, TimeUnit.SECONDS)
|
||||||
.readTimeout(15, TimeUnit.SECONDS)
|
.readTimeout(15, TimeUnit.SECONDS)
|
||||||
.writeTimeout(15, TimeUnit.SECONDS)
|
.writeTimeout(15, TimeUnit.SECONDS)
|
||||||
.addInterceptor(LoggingInterceptor()) // 添加日志拦截器
|
.addInterceptor(HttpLoggingInterceptor().apply {
|
||||||
|
level = Level.BODY
|
||||||
|
})
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,47 +36,6 @@ object HttpUtils {
|
||||||
fun onFailure(error: String, code: Int?)
|
fun onFailure(error: String, code: Int?)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 日志拦截器
|
|
||||||
private class LoggingInterceptor : Interceptor {
|
|
||||||
override fun intercept(chain: Interceptor.Chain): Response {
|
|
||||||
val request = chain.request()
|
|
||||||
val url = request.url.toString()
|
|
||||||
val method = request.method
|
|
||||||
|
|
||||||
// 记录请求信息
|
|
||||||
LogUtils.d("HTTP_REQUEST", "URL: $url")
|
|
||||||
LogUtils.d("HTTP_REQUEST", "Method: $method")
|
|
||||||
|
|
||||||
if ("POST" == method) {
|
|
||||||
request.body?.let { body ->
|
|
||||||
if (body is FormBody) {
|
|
||||||
val formBody = StringBuilder()
|
|
||||||
for (i in 0 until body.size) {
|
|
||||||
formBody.append("${body.name(i)}:${body.value(i)}; ")
|
|
||||||
}
|
|
||||||
Log.d("HTTP_REQUEST", "Form Data: $formBody")
|
|
||||||
} else if (body is MultipartBody) {
|
|
||||||
Log.d("HTTP_REQUEST", "Multipart Form Data")
|
|
||||||
} else {
|
|
||||||
Log.d("HTTP_REQUEST", "Body: ${body.contentType()}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val response = chain.proceed(request)
|
|
||||||
val responseBody = response.peekBody(Long.MAX_VALUE)
|
|
||||||
val responseString = responseBody.string()
|
|
||||||
|
|
||||||
// 记录响应信息
|
|
||||||
LogUtils.d("HTTP_RESPONSE", "Code: ${response.code}")
|
|
||||||
LogUtils.d("HTTP_RESPONSE", "Response: $responseString")
|
|
||||||
|
|
||||||
return response.newBuilder()
|
|
||||||
.body(responseBody)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET 请求(异步)
|
* GET 请求(异步)
|
||||||
*
|
*
|
||||||
|
@ -82,10 +47,9 @@ object HttpUtils {
|
||||||
fun getAsync(
|
fun getAsync(
|
||||||
url: String,
|
url: String,
|
||||||
params: Map<String, String>? = null,
|
params: Map<String, String>? = null,
|
||||||
headers: Map<String, String>? = null,
|
|
||||||
callback: HttpCallback
|
callback: HttpCallback
|
||||||
) {
|
) {
|
||||||
val request = buildGetRequest(url, params, headers)
|
val request = buildGetRequest(url, params)
|
||||||
executeRequestAsync(request, callback)
|
executeRequestAsync(request, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,31 +63,10 @@ object HttpUtils {
|
||||||
*/
|
*/
|
||||||
fun postAsync(
|
fun postAsync(
|
||||||
url: String,
|
url: String,
|
||||||
body: String,
|
body: String? = null,
|
||||||
headers: Map<String, String>? = null,
|
|
||||||
callback: HttpCallback
|
callback: HttpCallback
|
||||||
) {
|
) {
|
||||||
val requestBody = body.toRequestBody(JSON_MEDIA_TYPE)
|
val request = buildPostRequest(url, body)
|
||||||
val request = buildPostRequest(url, requestBody, headers)
|
|
||||||
executeRequestAsync(request, callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* POST Form Data 请求(异步)
|
|
||||||
*
|
|
||||||
* @param url 请求URL
|
|
||||||
* @param formData 表单数据
|
|
||||||
* @param headers 请求头(可选)
|
|
||||||
* @param callback 回调接口
|
|
||||||
*/
|
|
||||||
fun postFormAsync(
|
|
||||||
url: String,
|
|
||||||
formData: Map<String, String>,
|
|
||||||
headers: Map<String, String>? = null,
|
|
||||||
callback: HttpCallback
|
|
||||||
) {
|
|
||||||
val formBody = buildFormBody(formData)
|
|
||||||
val request = buildPostRequest(url, formBody, headers)
|
|
||||||
executeRequestAsync(request, callback)
|
executeRequestAsync(request, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,9 +81,8 @@ object HttpUtils {
|
||||||
fun getSync(
|
fun getSync(
|
||||||
url: String,
|
url: String,
|
||||||
params: Map<String, String>? = null,
|
params: Map<String, String>? = null,
|
||||||
headers: Map<String, String>? = null
|
|
||||||
): Pair<String?, Int> {
|
): Pair<String?, Int> {
|
||||||
val request = buildGetRequest(url, params, headers)
|
val request = buildGetRequest(url, params)
|
||||||
return executeRequestSync(request)
|
return executeRequestSync(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,11 +96,9 @@ object HttpUtils {
|
||||||
*/
|
*/
|
||||||
fun postSync(
|
fun postSync(
|
||||||
url: String,
|
url: String,
|
||||||
body: String,
|
body: String? = null
|
||||||
headers: Map<String, String>? = null
|
|
||||||
): Pair<String?, Int> {
|
): Pair<String?, Int> {
|
||||||
val requestBody = body.toRequestBody(JSON_MEDIA_TYPE)
|
val request = buildPostRequest(url, body)
|
||||||
val request = buildPostRequest(url, requestBody, headers)
|
|
||||||
return executeRequestSync(request)
|
return executeRequestSync(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,46 +112,72 @@ object HttpUtils {
|
||||||
// 内部方法 --------------------------------
|
// 内部方法 --------------------------------
|
||||||
|
|
||||||
private fun buildGetRequest(
|
private fun buildGetRequest(
|
||||||
url: String,
|
path: String ,
|
||||||
params: Map<String, String>?,
|
params: Map<String, String>?,
|
||||||
headers: Map<String, String>?
|
|
||||||
): Request {
|
): Request {
|
||||||
|
val url = "$HOST$path"
|
||||||
val httpUrlBuilder = url.toHttpUrlOrNull()?.newBuilder()
|
val httpUrlBuilder = url.toHttpUrlOrNull()?.newBuilder()
|
||||||
?: throw IllegalArgumentException("Invalid URL: $url")
|
?: throw IllegalArgumentException("Invalid URL: $url")
|
||||||
|
|
||||||
// 添加查询参数
|
var param = ""
|
||||||
params?.forEach { (key, value) ->
|
params?.forEach { (key, value) ->
|
||||||
httpUrlBuilder.addQueryParameter(key, value)
|
httpUrlBuilder.addQueryParameter(key, value)
|
||||||
|
param += "&${key}=${value}"
|
||||||
|
}
|
||||||
|
if (param.isNotEmpty()){
|
||||||
|
param = param.substring(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
val requestBuilder = Request.Builder().url(httpUrlBuilder.build())
|
val requestBuilder = Request.Builder().url(httpUrlBuilder.build())
|
||||||
|
|
||||||
// 添加请求头
|
val authver = "2.0"
|
||||||
addHeaders(requestBuilder, headers)
|
val timestamp = System.currentTimeMillis()
|
||||||
|
val sign =
|
||||||
|
ArmCloudSignatureV2.calculateSignature(timestamp.toString(), path, param)
|
||||||
|
addHeaders(
|
||||||
|
requestBuilder,
|
||||||
|
mapOf(
|
||||||
|
"authver" to authver,
|
||||||
|
"x-ak" to ArmCloudSignatureV2.SECRET_KEY,
|
||||||
|
"x-timestamp" to timestamp.toString(),
|
||||||
|
"x-sign" to sign
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return requestBuilder.build()
|
return requestBuilder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildPostRequest(
|
private fun buildPostRequest(
|
||||||
url: String,
|
path: String,
|
||||||
body: RequestBody,
|
body: String? = null
|
||||||
headers: Map<String, String>?
|
|
||||||
): Request {
|
): Request {
|
||||||
|
val url = "$HOST$path"
|
||||||
|
val bodyString = body?:""
|
||||||
val requestBuilder = Request.Builder()
|
val requestBuilder = Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(body)
|
.post(bodyString.toRequestBody(JSON_MEDIA_TYPE))
|
||||||
|
val authver = "2.0"
|
||||||
// 添加请求头
|
val timestamp = System.currentTimeMillis()
|
||||||
addHeaders(requestBuilder, headers)
|
val sign =
|
||||||
|
ArmCloudSignatureV2.calculateSignature(timestamp.toString(), path, body)
|
||||||
|
addHeaders(
|
||||||
|
requestBuilder,
|
||||||
|
mapOf(
|
||||||
|
"authver" to authver,
|
||||||
|
"x-ak" to ArmCloudSignatureV2.SECRET_KEY,
|
||||||
|
"x-timestamp" to timestamp.toString(),
|
||||||
|
"x-sign" to sign
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return requestBuilder.build()
|
return requestBuilder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addHeaders(
|
private fun addHeaders(
|
||||||
builder: Request.Builder,
|
builder: Request.Builder,
|
||||||
headers: Map<String, String>?
|
headers: Map<String, String>
|
||||||
) {
|
) {
|
||||||
headers?.forEach { (key, value) ->
|
headers.forEach { (key, value) ->
|
||||||
builder.addHeader(key, value)
|
builder.addHeader(key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,13 +218,13 @@ object HttpUtils {
|
||||||
private fun executeRequestSync(request: Request): Pair<String?, Int> {
|
private fun executeRequestSync(request: Request): Pair<String?, Int> {
|
||||||
return try {
|
return try {
|
||||||
val response = client.newCall(request).execute()
|
val response = client.newCall(request).execute()
|
||||||
val responseBody = response.body?.string()
|
val responseBody = response.peekBody(Long.MAX_VALUE).string()
|
||||||
val code = response.code
|
val code = response.code
|
||||||
|
Log.d("TAG", "executeRequestSync: $responseBody")
|
||||||
if (response.isSuccessful && responseBody != null) {
|
if (response.isSuccessful && responseBody.isNotEmpty()) {
|
||||||
Pair(responseBody, code)
|
Pair(responseBody, code)
|
||||||
} else {
|
} else {
|
||||||
Pair(null, code)
|
Pair(null, -1)
|
||||||
}
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
Pair(null, -1) // 网络错误状态码
|
Pair(null, -1) // 网络错误状态码
|
||||||
|
|
|
@ -140,7 +140,7 @@ object MyGet {
|
||||||
httpUrlConnection = url.openConnection() as HttpURLConnection
|
httpUrlConnection = url.openConnection() as HttpURLConnection
|
||||||
|
|
||||||
httpUrlConnection.allowUserInteraction = true
|
httpUrlConnection.allowUserInteraction = true
|
||||||
httpUrlConnection!!.doOutput = false
|
httpUrlConnection.doOutput = false
|
||||||
httpUrlConnection.doInput = true
|
httpUrlConnection.doInput = true
|
||||||
httpUrlConnection.useCaches = false
|
httpUrlConnection.useCaches = false
|
||||||
httpUrlConnection.instanceFollowRedirects = false
|
httpUrlConnection.instanceFollowRedirects = false
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
package com.android.grape.net
|
|
||||||
|
|
||||||
class NetworkHelper {
|
|
||||||
|
|
||||||
}
|
|
|
@ -5,14 +5,168 @@ import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.android.grape.MainApplication
|
import com.android.grape.MainApplication
|
||||||
import com.android.grape.data.Device
|
import com.android.grape.data.Device
|
||||||
|
import com.android.grape.net.Api
|
||||||
|
import com.android.grape.net.ChangeCallBack
|
||||||
import com.android.grape.util.Util.paramsJson
|
import com.android.grape.util.Util.paramsJson
|
||||||
import com.blankj.utilcode.util.LogUtils
|
import com.blankj.utilcode.util.LogUtils
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONException
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.lang.reflect.InvocationTargetException
|
import java.lang.reflect.InvocationTargetException
|
||||||
|
|
||||||
object ChangeDeviceInfoUtil {
|
object ChangeDeviceInfoUtil {
|
||||||
|
val scope = CoroutineScope(Dispatchers.IO)
|
||||||
|
fun changeDevice(callBack: ChangeCallBack){
|
||||||
|
try {
|
||||||
|
val deviceObject = paramsJson?.getJSONObject("device")
|
||||||
|
if (deviceObject == null) {
|
||||||
|
LogUtils.d("ERROR", "ChangeDeviceInfoUtil", "device is null")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val device = GsonUtils.fromJsonObject(deviceObject.toString(), Device::class.java)
|
||||||
|
val padCode = ShellUtils.execRootCmdAndGetResult("getprop ro.boot.pad_code")
|
||||||
|
Log.d("TAG", "changeDevice: $padCode")
|
||||||
|
val jsonString = JSONObject().apply {
|
||||||
|
put("padCodes", JSONArray().apply {
|
||||||
|
put(padCode)
|
||||||
|
})
|
||||||
|
put("modemPropertiesList", JSONArray().apply {
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "MCCMNC")
|
||||||
|
put("propertiesValue", "${device.mcc},${device.mnc}")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
put("systemPropertiesList", JSONArray().apply {
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ro.product.manufacturer")
|
||||||
|
put("propertiesValue", device.manufactor)
|
||||||
|
})
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ro.product.brand")
|
||||||
|
put("propertiesValue", device.brand)
|
||||||
|
})
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ro.product.model")
|
||||||
|
put("propertiesValue", device.model)
|
||||||
|
})
|
||||||
|
// put(JSONObject().apply {
|
||||||
|
// put("propertiesName", "ro.build.id")
|
||||||
|
// put("propertiesValue", device.buildDisplayId)
|
||||||
|
// })
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ro.build.display.id")
|
||||||
|
put("propertiesValue", device.buildDisplayId)
|
||||||
|
})
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ro.product.name")
|
||||||
|
put("propertiesValue", device.product)
|
||||||
|
})
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ro.product.device")
|
||||||
|
put("propertiesValue", device.device)
|
||||||
|
})
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ro.product.board")
|
||||||
|
put("propertiesValue", device.expand.board)
|
||||||
|
})
|
||||||
|
// put(JSONObject().apply {
|
||||||
|
// put("propertiesName", "ro.build.tags")
|
||||||
|
// put("propertiesValue", device.expand)
|
||||||
|
// })
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ro.build.fingerprint")
|
||||||
|
put("propertiesValue", device.expand.fingerprint)
|
||||||
|
})
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ro.build.date.utc")
|
||||||
|
put("propertiesValue", device.expand.roBuildDateUtc)
|
||||||
|
})
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ro.build.user")
|
||||||
|
put("propertiesValue", device.expand.uname)
|
||||||
|
})
|
||||||
|
// put(JSONObject().apply {
|
||||||
|
// put("propertiesName", "ro.build.host")
|
||||||
|
// put("propertiesValue", device.expand.)
|
||||||
|
// })
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ro.build.description")
|
||||||
|
put("propertiesValue", device.expand.roBuildDescription)
|
||||||
|
})
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ro.build.version.incremental")
|
||||||
|
put("propertiesValue", device.expand.incremental)
|
||||||
|
})
|
||||||
|
// put(JSONObject().apply {
|
||||||
|
// put("propertiesName", "ro.build.version.codename")
|
||||||
|
// put("propertiesValue", device.cod)
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
put("settingPropertiesList", JSONArray().apply {
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "ssaid/${Util.recordPackageName}")
|
||||||
|
put("propertiesValue", device.androidId)
|
||||||
|
})
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "bt/mac")
|
||||||
|
put("propertiesValue", device.expand.lyMAC)
|
||||||
|
})
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "language")
|
||||||
|
put("propertiesValue", device.locale.lang)
|
||||||
|
})
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "timezone")
|
||||||
|
put("propertiesValue", device.tzDisplayName)
|
||||||
|
})
|
||||||
|
// put(JSONObject().apply {
|
||||||
|
// put("propertiesName", "systemvolume")
|
||||||
|
// put("propertiesValue", device.expand.)
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
put("oaidPropertiesList", JSONArray().apply {
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("propertiesName", "AAID")
|
||||||
|
put("propertiesValue", device.advertiserId)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}.toString()
|
||||||
|
val response = Api.updatePad(jsonString)
|
||||||
|
val dataList = response.data
|
||||||
|
if (response.isSuccess() && dataList!= null && dataList.isNotEmpty()){
|
||||||
|
val padTask = dataList[0]
|
||||||
|
scope.launch {
|
||||||
|
Log.d("TAG", "changeDevice: $padTask")
|
||||||
|
var loop = true
|
||||||
|
while (loop) {
|
||||||
|
delay(5000)
|
||||||
|
val result = Api.padTaskDetail(padTask.taskId)
|
||||||
|
if (result == 3) {
|
||||||
|
Log.d("ChangeDeviceInfoUtil", "changeDeviceInfo changeDeviceInfo success")
|
||||||
|
loop = false
|
||||||
|
callBack.changeSuccess()
|
||||||
|
} else if (result == -1) {
|
||||||
|
Log.d("ChangeDeviceInfoUtil", "changeDeviceInfo changeDeviceInfo fail")
|
||||||
|
loop = false
|
||||||
|
callBack.changeFailed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun changeDeviceInfo() {
|
fun changeDeviceInfo() {
|
||||||
try {
|
try {
|
||||||
|
MockTools.exec("pm grant com.android.grape android.permission.INTERACT_ACROSS_USERS")
|
||||||
|
MockTools.exec("pm grant com.android.grape android.permission.WRITE_SECURE_SETTINGS")
|
||||||
|
MockTools.exec("pm setenforce 0")
|
||||||
val deviceObject = paramsJson?.getJSONObject("device")
|
val deviceObject = paramsJson?.getJSONObject("device")
|
||||||
if (deviceObject == null) {
|
if (deviceObject == null) {
|
||||||
LogUtils.d("ERROR", "ChangeDeviceInfoUtil", "device is null")
|
LogUtils.d("ERROR", "ChangeDeviceInfoUtil", "device is null")
|
||||||
|
@ -51,7 +205,7 @@ object ChangeDeviceInfoUtil {
|
||||||
// **os_ver**
|
// **os_ver**
|
||||||
vcloudsettingsPut(currentPkgName + "_os_ver", device.sdkVer, context)
|
vcloudsettingsPut(currentPkgName + "_os_ver", device.sdkVer, context)
|
||||||
// **tz** (时区)
|
// **tz** (时区)
|
||||||
vcloudsettingsPut(currentPkgName + "_tz", device.tzOffTime.toString(), context)
|
vcloudsettingsPut(currentPkgName + "_tz", TimeZoneUtils.formatTimeZoneOffset(device.tzOffTime), context)
|
||||||
|
|
||||||
vcloudsettingsPut("$currentPkgName.advertiserId", device.advertiserId, context)
|
vcloudsettingsPut("$currentPkgName.advertiserId", device.advertiserId, context)
|
||||||
vcloudsettingsPut("$currentPkgName.brand", device.brand, context)
|
vcloudsettingsPut("$currentPkgName.brand", device.brand, context)
|
||||||
|
@ -121,6 +275,9 @@ object ChangeDeviceInfoUtil {
|
||||||
ShellUtils.execRootCmd("setprop persist.sys.cloud.battery.capacity ${device.battery}")
|
ShellUtils.execRootCmd("setprop persist.sys.cloud.battery.capacity ${device.battery}")
|
||||||
ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.gl_vendor ${device.expand.glVendor}")
|
ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.gl_vendor ${device.expand.glVendor}")
|
||||||
ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.gl_renderer ${device.expand.glRenderer}")
|
ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.gl_renderer ${device.expand.glRenderer}")
|
||||||
|
ShellUtils.execRootCmd("setprop persist.sys.timezone ${TimeZoneUtils.formatTimeZoneOffset(device.tzOffTime)}")
|
||||||
|
ShellUtils.execRootCmd("setprop persist.sys.country ${device.country}")
|
||||||
|
ShellUtils.execRootCmd("setprop persist.sys.language ${device.expand.displayLang}")
|
||||||
// 这个值不能随便改 必须是 OpenGL ES %d.%d 这个格式
|
// 这个值不能随便改 必须是 OpenGL ES %d.%d 这个格式
|
||||||
ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.gl_version ${device.expand.glVersion}")
|
ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.gl_version ${device.expand.glVersion}")
|
||||||
// ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.egl_vendor $persist_sys_cloud_gpu_egl_vendor")
|
// ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.egl_vendor $persist_sys_cloud_gpu_egl_vendor")
|
||||||
|
|
|
@ -12,25 +12,26 @@ object MockTools {
|
||||||
fun exec(cmd: String): String {
|
fun exec(cmd: String): String {
|
||||||
var retString = ""
|
var retString = ""
|
||||||
try {
|
try {
|
||||||
//创建socket
|
retString = ShellUtils.execRootCmdAndGetResult(cmd)
|
||||||
val myCmd = "SU|$cmd"
|
// //创建socket
|
||||||
|
// val myCmd = "SU|$cmd"
|
||||||
val mSocket = Socket()
|
//
|
||||||
val inetSocketAddress = InetSocketAddress("127.0.0.1", 12345)
|
// val mSocket = Socket()
|
||||||
mSocket.connect(inetSocketAddress)
|
// val inetSocketAddress = InetSocketAddress("127.0.0.1", 12345)
|
||||||
val bufferedWriter = BufferedWriter(OutputStreamWriter(mSocket.getOutputStream()))
|
// mSocket.connect(inetSocketAddress)
|
||||||
val bufferedReader = BufferedReader(InputStreamReader(mSocket.getInputStream()))
|
// val bufferedWriter = BufferedWriter(OutputStreamWriter(mSocket.getOutputStream()))
|
||||||
bufferedWriter.write(myCmd + "\r\n")
|
// val bufferedReader = BufferedReader(InputStreamReader(mSocket.getInputStream()))
|
||||||
bufferedWriter.flush()
|
// bufferedWriter.write(myCmd + "\r\n")
|
||||||
val stringBuilder = StringBuilder()
|
// bufferedWriter.flush()
|
||||||
var line: String? = null
|
// val stringBuilder = StringBuilder()
|
||||||
while ((bufferedReader.readLine().also { line = it }) != null) {
|
// var line: String? = null
|
||||||
stringBuilder.append(line + "\n")
|
// while ((bufferedReader.readLine().also { line = it }) != null) {
|
||||||
}
|
// stringBuilder.append(line + "\n")
|
||||||
//retString = bufferedReader.readLine();
|
// }
|
||||||
retString = stringBuilder.toString()
|
// //retString = bufferedReader.readLine();
|
||||||
bufferedReader.close()
|
// retString = stringBuilder.toString()
|
||||||
bufferedWriter.close()
|
// bufferedReader.close()
|
||||||
|
// bufferedWriter.close()
|
||||||
} catch (eeeee: Exception) {
|
} catch (eeeee: Exception) {
|
||||||
eeeee.printStackTrace()
|
eeeee.printStackTrace()
|
||||||
}
|
}
|
||||||
|
@ -40,25 +41,26 @@ object MockTools {
|
||||||
fun execRead(cmd: String): String {
|
fun execRead(cmd: String): String {
|
||||||
var retString = ""
|
var retString = ""
|
||||||
try {
|
try {
|
||||||
//创建socket
|
retString = ShellUtils.execRootCmdAndGetResult(cmd)
|
||||||
val myCmd = "SU_1|$cmd"
|
// //创建socket
|
||||||
|
// val myCmd = "SU_1|$cmd"
|
||||||
val mSocket = Socket()
|
//
|
||||||
val inetSocketAddress = InetSocketAddress("127.0.0.1", 12345)
|
// val mSocket = Socket()
|
||||||
mSocket.connect(inetSocketAddress)
|
// val inetSocketAddress = InetSocketAddress("127.0.0.1", 12345)
|
||||||
val bufferedWriter = BufferedWriter(OutputStreamWriter(mSocket.getOutputStream()))
|
// mSocket.connect(inetSocketAddress)
|
||||||
val bufferedReader = BufferedReader(InputStreamReader(mSocket.getInputStream()))
|
// val bufferedWriter = BufferedWriter(OutputStreamWriter(mSocket.getOutputStream()))
|
||||||
bufferedWriter.write(myCmd + "\r\n")
|
// val bufferedReader = BufferedReader(InputStreamReader(mSocket.getInputStream()))
|
||||||
bufferedWriter.flush()
|
// bufferedWriter.write(myCmd + "\r\n")
|
||||||
val stringBuilder = StringBuilder()
|
// bufferedWriter.flush()
|
||||||
var line: String? = null
|
// val stringBuilder = StringBuilder()
|
||||||
while ((bufferedReader.readLine().also { line = it }) != null) {
|
// var line: String? = null
|
||||||
stringBuilder.append(line + "\n")
|
// while ((bufferedReader.readLine().also { line = it }) != null) {
|
||||||
}
|
// stringBuilder.append(line + "\n")
|
||||||
retString = stringBuilder.toString()
|
// }
|
||||||
//retString = bufferedReader.readLine();
|
// retString = stringBuilder.toString()
|
||||||
bufferedReader.close()
|
// //retString = bufferedReader.readLine();
|
||||||
bufferedWriter.close()
|
// bufferedReader.close()
|
||||||
|
// bufferedWriter.close()
|
||||||
} catch (eeeee: Exception) {
|
} catch (eeeee: Exception) {
|
||||||
eeeee.printStackTrace()
|
eeeee.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import android.content.pm.PackageManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
|
import android.util.Log
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
@ -106,7 +107,7 @@ class NotificationPermissionHandler(
|
||||||
fun requestNotificationPermission() {
|
fun requestNotificationPermission() {
|
||||||
// 保存当前权限状态,用于比较设置后是否发生变化
|
// 保存当前权限状态,用于比较设置后是否发生变化
|
||||||
lastPermissionState = areNotificationsEnabled()
|
lastPermissionState = areNotificationsEnabled()
|
||||||
|
Log.d(TAG, "requestNotificationPermission: ")
|
||||||
when {
|
when {
|
||||||
// Android 13+ - 使用运行时权限请求
|
// Android 13+ - 使用运行时权限请求
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> {
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> {
|
||||||
|
@ -198,22 +199,23 @@ class NotificationPermissionHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
val activity = context as? AppCompatActivity ?: return
|
val activity = context as? AppCompatActivity ?: return
|
||||||
|
Log.d(TAG, "requestPermissionApi33: ")
|
||||||
when {
|
when {
|
||||||
// 已经拥有权限
|
// 已经拥有权限
|
||||||
areNotificationsEnabled() -> {
|
areNotificationsEnabled() -> {
|
||||||
callback(PermissionResult.GRANTED)
|
callback(PermissionResult.GRANTED)
|
||||||
}
|
}
|
||||||
// 需要显示权限解释
|
// 需要显示权限解释
|
||||||
ActivityCompat.shouldShowRequestPermissionRationale(
|
// ActivityCompat.shouldShowRequestPermissionRationale(
|
||||||
activity,
|
// activity,
|
||||||
Manifest.permission.POST_NOTIFICATIONS
|
// Manifest.permission.POST_NOTIFICATIONS
|
||||||
) -> {
|
// ) -> {
|
||||||
showPermissionRationaleDialog()
|
// showPermissionRationaleDialog()
|
||||||
}
|
// }
|
||||||
// 请求权限
|
// 请求权限
|
||||||
else -> {
|
else -> {
|
||||||
permissionRequestPending = true
|
permissionRequestPending = true
|
||||||
|
Log.d(TAG, "requestPermissionApi33: launch")
|
||||||
permissionLauncher?.launch(Manifest.permission.POST_NOTIFICATIONS)
|
permissionLauncher?.launch(Manifest.permission.POST_NOTIFICATIONS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,28 +278,36 @@ class NotificationPermissionHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private const val TAG = "NotificationPermissionH"
|
||||||
/**
|
/**
|
||||||
* 快速检查当前设备的通知权限状态
|
* 快速检查当前设备的通知权限状态
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun checkPermissionState(context: Context): PermissionResult {
|
fun checkPermissionState(context: Context): PermissionResult {
|
||||||
|
Log.d(TAG, "checkPermissionState: --------->")
|
||||||
return when {
|
return when {
|
||||||
// Android 13+ 需要运行时权限
|
// Android 13+ 需要运行时权限
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> {
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> {
|
||||||
|
Log.d(TAG, "checkPermissionState: Android 13+")
|
||||||
if (ContextCompat.checkSelfPermission(
|
if (ContextCompat.checkSelfPermission(
|
||||||
context,
|
context,
|
||||||
Manifest.permission.POST_NOTIFICATIONS
|
Manifest.permission.POST_NOTIFICATIONS
|
||||||
) == PackageManager.PERMISSION_GRANTED) {
|
) == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Log.d(TAG, "checkPermissionState: Granted")
|
||||||
PermissionResult.GRANTED
|
PermissionResult.GRANTED
|
||||||
} else {
|
} else {
|
||||||
|
Log.d(TAG, "checkPermissionState: Denied")
|
||||||
PermissionResult.DENIED
|
PermissionResult.DENIED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Android 8.0+ 检查通知设置
|
// Android 8.0+ 检查通知设置
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
|
||||||
|
Log.d(TAG, "checkPermissionState: Android 8.0+")
|
||||||
if (NotificationManagerCompat.from(context).areNotificationsEnabled()) {
|
if (NotificationManagerCompat.from(context).areNotificationsEnabled()) {
|
||||||
|
Log.d(TAG, "checkPermissionState: Granted")
|
||||||
PermissionResult.GRANTED
|
PermissionResult.GRANTED
|
||||||
} else {
|
} else {
|
||||||
|
Log.d(TAG, "checkPermissionState: Denied")
|
||||||
PermissionResult.NEEDS_SETTINGS
|
PermissionResult.NEEDS_SETTINGS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ public class ShellUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String execRootCmdAndGetResult(String cmd) {
|
public static String execRootCmdAndGetResult(String cmd) {
|
||||||
Log.d("ShellUtils", "execRootCmdAndGetResult - Started execution for command: " + cmd);
|
// Log.d("ShellUtils", "execRootCmdAndGetResult - Started execution for command: " + cmd);
|
||||||
if (cmd == null || cmd.trim().isEmpty()) {
|
if (cmd == null || cmd.trim().isEmpty()) {
|
||||||
LogUtils.e(Log.ERROR, "ShellUtils", "Unsafe or empty command. Aborting execution.", null);
|
LogUtils.e(Log.ERROR, "ShellUtils", "Unsafe or empty command. Aborting execution.", null);
|
||||||
throw new IllegalArgumentException("Unsafe or empty command.");
|
throw new IllegalArgumentException("Unsafe or empty command.");
|
||||||
|
@ -116,18 +116,18 @@ public class ShellUtils {
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(2);
|
ExecutorService executor = Executors.newFixedThreadPool(2);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Log.d("ShellUtils", "Determining appropriate shell for execution...");
|
// Log.d("ShellUtils", "Determining appropriate shell for execution...");
|
||||||
if (hasBin("su")) {
|
if (hasBin("su")) {
|
||||||
Log.d("ShellUtils", "'su' binary found, using 'su' shell.");
|
// Log.d("ShellUtils", "'su' binary found, using 'su' shell.");
|
||||||
process = Runtime.getRuntime().exec("su");
|
process = Runtime.getRuntime().exec("su");
|
||||||
} else if (hasBin("xu")) {
|
} else if (hasBin("xu")) {
|
||||||
Log.d("ShellUtils", "'xu' binary found, using 'xu' shell.");
|
// Log.d("ShellUtils", "'xu' binary found, using 'xu' shell.");
|
||||||
process = Runtime.getRuntime().exec("xu");
|
process = Runtime.getRuntime().exec("xu");
|
||||||
} else if (hasBin("vu")) {
|
} else if (hasBin("vu")) {
|
||||||
Log.d("ShellUtils", "'vu' binary found, using 'vu' shell.");
|
// Log.d("ShellUtils", "'vu' binary found, using 'vu' shell.");
|
||||||
process = Runtime.getRuntime().exec("vu");
|
process = Runtime.getRuntime().exec("vu");
|
||||||
} else {
|
} else {
|
||||||
Log.d("ShellUtils", "No specific binary found, using 'sh' shell.");
|
// Log.d("ShellUtils", "No specific binary found, using 'sh' shell.");
|
||||||
process = Runtime.getRuntime().exec("sh");
|
process = Runtime.getRuntime().exec("sh");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ public class ShellUtils {
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||||
BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream, StandardCharsets.UTF_8))) {
|
BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream, StandardCharsets.UTF_8))) {
|
||||||
|
|
||||||
Log.d("ShellUtils", "Starting separate thread to process error stream...");
|
// Log.d("ShellUtils", "Starting separate thread to process error stream...");
|
||||||
executor.submit(() -> {
|
executor.submit(() -> {
|
||||||
String line;
|
String line;
|
||||||
try {
|
try {
|
||||||
|
@ -149,28 +149,28 @@ public class ShellUtils {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Log.d("ShellUtils", "Writing the command to the shell...");
|
// Log.d("ShellUtils", "Writing the command to the shell...");
|
||||||
os.write((cmd + "\n").getBytes());
|
os.write((cmd + "\n").getBytes());
|
||||||
os.write("exit\n".getBytes());
|
os.write("exit\n".getBytes());
|
||||||
os.flush();
|
os.flush();
|
||||||
Log.d("ShellUtils", "Command written to shell. Waiting for process to complete.");
|
// Log.d("ShellUtils", "Command written to shell. Waiting for process to complete.");
|
||||||
|
|
||||||
StringBuilder output = new StringBuilder();
|
StringBuilder output = new StringBuilder();
|
||||||
String line;
|
String line;
|
||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
Log.d("ShellUtils", "Shell Output: " + line);
|
// Log.d("ShellUtils", "Shell Output: " + line);
|
||||||
output.append(line).append("\n");
|
output.append(line).append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d("ShellUtils", "Awaiting process termination...");
|
// Log.d("ShellUtils", "Awaiting process termination...");
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
if (!process.waitFor(10, TimeUnit.SECONDS)) {
|
if (!process.waitFor(10, TimeUnit.SECONDS)) {
|
||||||
LogUtils.e(Log.ERROR, "ShellUtils", "Process execution timed out. Destroying process.", null);
|
// LogUtils.e(Log.ERROR, "ShellUtils", "Process execution timed out. Destroying process.", null);
|
||||||
process.destroyForcibly();
|
process.destroyForcibly();
|
||||||
throw new RuntimeException("Shell command execution timeout.");
|
throw new RuntimeException("Shell command execution timeout.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d("ShellUtils", "Using manual time tracking method for process termination (API < 26).");
|
// Log.d("ShellUtils", "Using manual time tracking method for process termination (API < 26).");
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
|
@ -178,7 +178,7 @@ public class ShellUtils {
|
||||||
break;
|
break;
|
||||||
} catch (IllegalThreadStateException e) {
|
} catch (IllegalThreadStateException e) {
|
||||||
if (System.currentTimeMillis() - startTime > 10000) { // 10 seconds
|
if (System.currentTimeMillis() - startTime > 10000) { // 10 seconds
|
||||||
LogUtils.e(Log.ERROR, "ShellUtils", "Process execution timed out (manual tracking). Destroying process.", null);
|
// LogUtils.e(Log.ERROR, "ShellUtils", "Process execution timed out (manual tracking). Destroying process.", null);
|
||||||
process.destroy();
|
process.destroy();
|
||||||
throw new RuntimeException("Shell command execution timeout.");
|
throw new RuntimeException("Shell command execution timeout.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ object Util {
|
||||||
private const val sendRefer = true
|
private const val sendRefer = true
|
||||||
var isNeedRestored: Boolean = false
|
var isNeedRestored: Boolean = false
|
||||||
const val AUTO_PACKAGENAME: String = "com.play4u.luabox"
|
const val AUTO_PACKAGENAME: String = "com.play4u.luabox"
|
||||||
const val AUTO_JSPACKAGENAME: String = "org.autojs.autojs"
|
const val AUTO_JSPACKAGENAME: String = "org.autojs.autojs6"
|
||||||
const val proxy_packagename: String = "com.tunnelworkshop.postern"
|
const val proxy_packagename: String = "com.tunnelworkshop.postern"
|
||||||
const val AUTO_CLASSNAME: String = "com.cyjh.elfin.activity.SplashActivity"
|
const val AUTO_CLASSNAME: String = "com.cyjh.elfin.activity.SplashActivity"
|
||||||
private const val hookPackageName = "com.affsystem.androidhooker"
|
private const val hookPackageName = "com.affsystem.androidhooker"
|
||||||
|
@ -696,8 +696,8 @@ object Util {
|
||||||
val result: String? = MyPost.postData(" ".toByteArray(charset = Charsets.UTF_8),
|
val result: String? = MyPost.postData(" ".toByteArray(charset = Charsets.UTF_8),
|
||||||
"$url?$params"
|
"$url?$params"
|
||||||
)
|
)
|
||||||
|
LogUtils.e("IOSTQ:execReloginTask->result:$result")
|
||||||
if (result != null && result.length > 0) {
|
if (result != null && result.isNotEmpty()) {
|
||||||
taskJson = JSONObject(result).apply {
|
taskJson = JSONObject(result).apply {
|
||||||
val code = getInt("code")
|
val code = getInt("code")
|
||||||
if (code == 1) {
|
if (code == 1) {
|
||||||
|
@ -749,9 +749,9 @@ object Util {
|
||||||
"$url?$params"
|
"$url?$params"
|
||||||
)
|
)
|
||||||
|
|
||||||
printStr("request result : $result")
|
LogUtils.e("request result : $result")
|
||||||
|
|
||||||
if (result != null && result.length > 0) {
|
if (result != null && result.isNotEmpty()) {
|
||||||
taskJson = JSONObject(result)
|
taskJson = JSONObject(result)
|
||||||
|
|
||||||
val code = taskJson!!.getInt("code")
|
val code = taskJson!!.getInt("code")
|
||||||
|
@ -1045,7 +1045,7 @@ object Util {
|
||||||
val ret: String? = MyPost.postData("".toByteArray(), url)
|
val ret: String? = MyPost.postData("".toByteArray(), url)
|
||||||
Log.i(TAG, "ret:$ret")
|
Log.i(TAG, "ret:$ret")
|
||||||
|
|
||||||
val jo = JSONObject(ret)
|
val jo = JSONObject(ret?:"")
|
||||||
|
|
||||||
if (jo.getInt("code") == 1) {
|
if (jo.getInt("code") == 1) {
|
||||||
regEmailJson = jo.getJSONObject("emailInfo")
|
regEmailJson = jo.getJSONObject("emailInfo")
|
||||||
|
@ -1554,11 +1554,13 @@ object Util {
|
||||||
|
|
||||||
fun openRecordApp(context: Context) {
|
fun openRecordApp(context: Context) {
|
||||||
if (scriptOpenApp == 0) {
|
if (scriptOpenApp == 0) {
|
||||||
|
recordPackageName?.let {
|
||||||
execTargetApp(
|
execTargetApp(
|
||||||
context,
|
context,
|
||||||
recordPackageName!!
|
it
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!isCanAuto || canAutoLc.length <= 10) {
|
if (!isCanAuto || canAutoLc.length <= 10) {
|
||||||
Handler(Looper.getMainLooper()).postDelayed(Runnable {
|
Handler(Looper.getMainLooper()).postDelayed(Runnable {
|
||||||
|
@ -1618,10 +1620,12 @@ object Util {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
val parent = file.parentFile
|
val parent = file.parentFile
|
||||||
|
|
||||||
if (parent!!.exists()) {
|
if (parent?.exists() == true) {
|
||||||
file.mkdir()
|
file.mkdir()
|
||||||
} else {
|
} else {
|
||||||
|
if (parent != null) {
|
||||||
forceCreteDir(parent)
|
forceCreteDir(parent)
|
||||||
|
}
|
||||||
file.mkdir()
|
file.mkdir()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1631,7 +1635,8 @@ object Util {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
val parent = file.parentFile
|
val parent = file.parentFile
|
||||||
|
|
||||||
if (!parent!!.exists()) {
|
parent?.exists()?.let {
|
||||||
|
if (!it) {
|
||||||
MockTools.exec("mkdir $parent")
|
MockTools.exec("mkdir $parent")
|
||||||
forceMakeDir(parent)
|
forceMakeDir(parent)
|
||||||
// file.mkdirs();
|
// file.mkdirs();
|
||||||
|
@ -1640,6 +1645,7 @@ object Util {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun writeFile1(context: Context?, dirName: String, fileName: String, contents: String) {
|
fun writeFile1(context: Context?, dirName: String, fileName: String, contents: String) {
|
||||||
val fs = File("$dirName/$fileName")
|
val fs = File("$dirName/$fileName")
|
||||||
|
@ -1764,7 +1770,11 @@ object Util {
|
||||||
}
|
}
|
||||||
|
|
||||||
val create_dir = file.parentFile
|
val create_dir = file.parentFile
|
||||||
forceMakeDir(create_dir!!)
|
if (create_dir != null && !create_dir.exists()){
|
||||||
|
forceMakeDir(create_dir)
|
||||||
|
}else if (create_dir == null){
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
val fileLength = 0L
|
val fileLength = 0L
|
||||||
|
|
||||||
|
@ -1777,7 +1787,7 @@ object Util {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
conn = url.openConnection() as HttpURLConnection
|
conn = url.openConnection() as HttpURLConnection
|
||||||
`is` = conn!!.inputStream
|
`is` = conn.inputStream
|
||||||
fos = FileOutputStream(file)
|
fos = FileOutputStream(file)
|
||||||
val buf = ByteArray(256)
|
val buf = ByteArray(256)
|
||||||
conn.connect()
|
conn.connect()
|
||||||
|
@ -1806,15 +1816,15 @@ object Util {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
conn!!.disconnect()
|
conn?.disconnect()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
fos!!.close()
|
fos?.close()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
`is`!!.close()
|
`is`?.close()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2046,17 +2056,19 @@ object Util {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun installApks4Tmp(apkName: String?, context: Context?): Boolean {
|
fun installApks4Tmp(apkName: String?, context: Context): Boolean {
|
||||||
var result = MockTools.execRead("pm install-create")
|
var result = MockTools.execRead("pm install-create")
|
||||||
Log.d(TAG, "installApks4Tmp: successMsg $result")
|
Log.d(TAG, "installApks4Tmp: successMsg $result")
|
||||||
val session = result.substring(result.indexOf("[") + 1, result.indexOf("]"))
|
val session = result.substring(result.indexOf("[") + 1, result.indexOf("]"))
|
||||||
Log.d(TAG, "installApks4Tmp: session $session")
|
Log.d(TAG, "installApks4Tmp: session $session")
|
||||||
|
|
||||||
val file = File("/sdcard/apks/$apkName")
|
val file = File(getRecordDataDirName(context))
|
||||||
|
Log.d(TAG, "installApks4Tmp: ${file.absolutePath}")
|
||||||
val files = file.listFiles()
|
val files = file.listFiles()
|
||||||
var bool = true
|
var bool = true
|
||||||
var currentApkFile = 1
|
var currentApkFile = 1
|
||||||
for (f in files) {
|
files?.let {
|
||||||
|
for (f in it) {
|
||||||
val extraName = f.name.substring(f.name.lastIndexOf('.') + 1)
|
val extraName = f.name.substring(f.name.lastIndexOf('.') + 1)
|
||||||
Log.d(
|
Log.d(
|
||||||
TAG,
|
TAG,
|
||||||
|
@ -2075,6 +2087,8 @@ object Util {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bool) {
|
if (bool) {
|
||||||
result = MockTools.execRead("pm install-commit $session")
|
result = MockTools.execRead("pm install-commit $session")
|
||||||
if (!result.contains("Success")) {
|
if (!result.contains("Success")) {
|
||||||
|
@ -2083,9 +2097,11 @@ object Util {
|
||||||
} else {
|
} else {
|
||||||
result = MockTools.execRead("pm install-abandon $session")
|
result = MockTools.execRead("pm install-abandon $session")
|
||||||
}
|
}
|
||||||
for (f in files) {
|
files?.let {
|
||||||
|
for (f in it) {
|
||||||
MockTools.execRead("rm -rf $f")
|
MockTools.execRead("rm -rf $f")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
setInstallRet(bool)
|
setInstallRet(bool)
|
||||||
return bool
|
return bool
|
||||||
}
|
}
|
||||||
|
@ -2420,7 +2436,7 @@ object Util {
|
||||||
}
|
}
|
||||||
tags = filterStr(tags)
|
tags = filterStr(tags)
|
||||||
// Log.e(TAG, "getCid:*"+tags+"*");
|
// Log.e(TAG, "getCid:*"+tags+"*");
|
||||||
return tags!!
|
return tags?:""
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPropertiesFromAssets(context: Context, fileName: String): Properties {
|
fun getPropertiesFromAssets(context: Context, fileName: String): Properties {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import androidx.work.CoroutineWorker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import com.android.grape.service.MyAccessibilityService
|
import com.android.grape.service.MyAccessibilityService
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
|
import com.android.grape.job.MonitorService
|
||||||
|
|
||||||
class CheckAccessibilityWorker(
|
class CheckAccessibilityWorker(
|
||||||
context: Context,
|
context: Context,
|
||||||
|
|
Loading…
Reference in New Issue