init
This commit is contained in:
parent
890539cbc0
commit
1e7ceae4ed
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -9,6 +9,8 @@
|
|||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.BIND_VPN_SERVICE"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
<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.INTERNET" />
|
||||
<uses-permission android:name="android.permission.VPN_SERVICE" />
|
||||
|
@ -41,6 +43,7 @@
|
|||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
|
@ -117,8 +120,6 @@
|
|||
android:name="android.accessibilityservice"
|
||||
android:resource="@xml/accessibility_service_config" />
|
||||
</service>
|
||||
|
||||
<receiver android:name="com.android.grape.receiver.ScriptReceiver" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -13,18 +13,24 @@ import androidx.appcompat.app.AlertDialog
|
|||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.android.grape.databinding.ActivityMainBinding
|
||||
import com.android.grape.job.MonitorService
|
||||
import com.android.grape.receiver.ScriptReceiver
|
||||
import com.android.grape.util.ClashUtil
|
||||
import com.android.grape.util.HttpUtil
|
||||
import com.android.grape.util.NotificationPermissionHandler
|
||||
import com.android.grape.util.StoragePermissionHelper
|
||||
import com.blankj.utilcode.util.LogUtils
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private val viewModel by viewModels<MainViewModel>()
|
||||
private lateinit var viewBinding: ActivityMainBinding
|
||||
private var intentFilter: IntentFilter? = null
|
||||
private var scriptReceiver: ScriptReceiver? = null
|
||||
private lateinit var permissionHandler: NotificationPermissionHandler
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
|
@ -39,15 +45,14 @@ class MainActivity : AppCompatActivity() {
|
|||
registerReceiver()
|
||||
viewBinding.start.setOnClickListener {
|
||||
try {
|
||||
ClashUtil.startProxy(this) // 在主线程中调用
|
||||
ClashUtil.switchProxyGroup("GLOBAL", "us", "http://127.0.0.1:6170")
|
||||
} catch (e: Exception) {
|
||||
LogUtils.log(
|
||||
Log.ERROR,
|
||||
"MainActivity",
|
||||
"startProxyVpn: Failed to start VPN",
|
||||
e
|
||||
ClashUtil.startProxy(this)
|
||||
ClashUtil.switchProxyGroup(
|
||||
"GLOBAL",
|
||||
ClashUtil.getRandomLocale(),
|
||||
"http://127.0.0.1:6170"
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
LogUtils.e("startProxyVpn: Failed to start VPN", e)
|
||||
Toast.makeText(
|
||||
this,
|
||||
"Failed to start VPN: " + (if (e.message != null) e.message else "Unknown error"),
|
||||
|
@ -77,7 +82,11 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun checkPermission() {
|
||||
viewModel.checkAccessibilityService()
|
||||
permissionHandler = NotificationPermissionHandler(this) { result ->
|
||||
handlePermissionResult(result)
|
||||
}
|
||||
checkNotificationPermission()
|
||||
|
||||
StoragePermissionHelper.requestFullStoragePermission(
|
||||
activity = this,
|
||||
onGranted = { performFileOperation() },
|
||||
|
@ -85,10 +94,56 @@ class MainActivity : AppCompatActivity() {
|
|||
)
|
||||
}
|
||||
|
||||
private fun checkNotificationPermission() {
|
||||
when (val result = NotificationPermissionHandler.checkPermissionState(this)) {
|
||||
NotificationPermissionHandler.PermissionResult.GRANTED,
|
||||
NotificationPermissionHandler.PermissionResult.NOT_NEEDED -> {
|
||||
showNotification()
|
||||
}
|
||||
|
||||
NotificationPermissionHandler.PermissionResult.DENIED,
|
||||
NotificationPermissionHandler.PermissionResult.NEEDS_SETTINGS -> {
|
||||
// 请求权限
|
||||
permissionHandler.requestNotificationPermission()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理权限结果回调
|
||||
*/
|
||||
private fun handlePermissionResult(result: NotificationPermissionHandler.PermissionResult) {
|
||||
when (result) {
|
||||
NotificationPermissionHandler.PermissionResult.GRANTED -> {
|
||||
// 权限已授予,显示通知
|
||||
showNotification()
|
||||
Toast.makeText(this, "通知权限已开启", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
NotificationPermissionHandler.PermissionResult.DENIED -> {
|
||||
// 权限被拒绝
|
||||
Toast.makeText(this, "通知权限被拒绝", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
NotificationPermissionHandler.PermissionResult.NEEDS_SETTINGS -> {
|
||||
Toast.makeText(this, "通知权限被拒绝", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
NotificationPermissionHandler.PermissionResult.NOT_NEEDED -> {
|
||||
// 不需要特殊权限(旧设备)
|
||||
showNotification()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showNotification() {
|
||||
viewModel.checkAccessibilityService()
|
||||
}
|
||||
|
||||
private fun performFileOperation() {
|
||||
// 执行文件读写操作
|
||||
// Toast.makeText(this, "文件访问权限已授予", Toast.LENGTH_SHORT).show()
|
||||
MonitorService.onEvent(this)
|
||||
// MonitorService.onEvent(this)
|
||||
}
|
||||
|
||||
private fun showPermissionDeniedDialog() {
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package com.android.grape.data
|
||||
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class As(
|
||||
var nameValuePairs: NameValuePairs = NameValuePairs()
|
||||
)
|
|
@ -0,0 +1,11 @@
|
|||
package com.android.grape.data
|
||||
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class DdlInfo(
|
||||
var fromfg: Int = 0,
|
||||
var net0: Int = 0,
|
||||
var rfrwait: Int = 0,
|
||||
var status: String = ""
|
||||
)
|
|
@ -0,0 +1,113 @@
|
|||
package com.android.grape.data
|
||||
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class Device(
|
||||
var advertiserId: String = "",
|
||||
@SerializedName("af_preinstalled")
|
||||
var afPreinstalled: Boolean = false,
|
||||
var androidId: String = "",
|
||||
var arch: String = "",
|
||||
@SerializedName("as")
|
||||
var asX: As = As(),
|
||||
var battery: Int = 0,
|
||||
var battery1: Int = 0,
|
||||
var batteryLevel: Int = 0,
|
||||
var batteryType: Int = 0,
|
||||
var bn: String = "",
|
||||
var brand: String = "",
|
||||
var btch: String = "",
|
||||
@SerializedName("build_display_id")
|
||||
var buildDisplayId: String = "",
|
||||
var carrier: String = "",
|
||||
@SerializedName("click_ts")
|
||||
var clickTs: Int = 0,
|
||||
var clk: String = "",
|
||||
var country: String = "",
|
||||
@SerializedName("cpu_abi")
|
||||
var cpuAbi: String = "",
|
||||
@SerializedName("cpu_abi2")
|
||||
var cpuAbi2: String = "",
|
||||
var ddlInfo: DdlInfo = DdlInfo(),
|
||||
var debug: Boolean = false,
|
||||
var device: String = "",
|
||||
var deviceCity: String = "",
|
||||
var deviceType: String = "",
|
||||
var dim: Dim = Dim(),
|
||||
var dimId: Int = 0,
|
||||
var dimReset: Int = 0,
|
||||
var dimType: Int = 0,
|
||||
var disk: String = "",
|
||||
var diskRate: Double = 0.0,
|
||||
var expand: Expand = Expand(),
|
||||
var fetchAdIdLatency: Int = 0,
|
||||
@SerializedName("from_fg")
|
||||
var fromFg: Int = 0,
|
||||
@SerializedName("google_custom")
|
||||
var googleCustom: GoogleCustom = GoogleCustom(),
|
||||
var hook: String = "",
|
||||
@SerializedName("init_to_fg")
|
||||
var initToFg: Int = 0,
|
||||
var install: String = "",
|
||||
@SerializedName("install_begin_ts")
|
||||
var installBeginTs: Int = 0,
|
||||
@SerializedName("installer_package")
|
||||
var installerPackage: String = "",
|
||||
var instant: Boolean = false,
|
||||
var ip: String = "",
|
||||
var ivc: Boolean = false,
|
||||
var lang: String = "",
|
||||
@SerializedName("lang_code")
|
||||
var langCode: String = "",
|
||||
@SerializedName("last_boot_time")
|
||||
var lastBootTime: Long = 0,
|
||||
var lastBootTimeOff: Int = 0,
|
||||
var latency: Int = 0,
|
||||
var locale: Locale = Locale(),
|
||||
var manufactor: String = "",
|
||||
var mcc: Int = 0,
|
||||
var mnc: Int = 0,
|
||||
var model: String = "",
|
||||
@SerializedName("native_dir")
|
||||
var nativeDir: Boolean = false,
|
||||
var network: String = "",
|
||||
var noRcLatency: Boolean = false,
|
||||
@SerializedName("open_referrer")
|
||||
var openReferrer: String = "",
|
||||
@SerializedName("open_referrerReset")
|
||||
var openReferrerReset: Int = 0,
|
||||
var opener: String = "",
|
||||
var `operator`: String = "",
|
||||
var platformextension: String = "",
|
||||
var pr: Pr = Pr(),
|
||||
var product: String = "",
|
||||
var rawDevice: String = "",
|
||||
var rawProduct: String = "",
|
||||
@SerializedName("rc.delay")
|
||||
var rcDelay: Int = 0,
|
||||
@SerializedName("rc.latency")
|
||||
var rcLatency: Int = 0,
|
||||
var referrer: String = "",
|
||||
@SerializedName("sc_o")
|
||||
var scO: String = "",
|
||||
var sdk: String = "",
|
||||
var sdkVer: String = "",
|
||||
var sensor: List<Sensor> = listOf(),
|
||||
var sensorReset: Int = 0,
|
||||
@SerializedName("sensor_size")
|
||||
var sensorSize: Int = 0,
|
||||
@SerializedName("sig_n")
|
||||
var sigN: String = "",
|
||||
@SerializedName("sys_ua")
|
||||
var sysUa: String = "",
|
||||
var timepassedsincelastlaunch: Int = 0,
|
||||
var tzDisplayName: String = "",
|
||||
var tzOffTime: Int = 0,
|
||||
@SerializedName("val")
|
||||
var valX: String = "",
|
||||
var vendingVersionCode: String = "",
|
||||
var vendingVersionName: String = "",
|
||||
@SerializedName("web_ua")
|
||||
var webUa: String = ""
|
||||
)
|
|
@ -0,0 +1,16 @@
|
|||
package com.android.grape.data
|
||||
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class Dim(
|
||||
@SerializedName("d_dpi")
|
||||
var dDpi: String = "",
|
||||
var size: String = "",
|
||||
@SerializedName("x_px")
|
||||
var xPx: String = "",
|
||||
var xdp: String = "",
|
||||
@SerializedName("y_px")
|
||||
var yPx: String = "",
|
||||
var ydp: String = ""
|
||||
)
|
|
@ -0,0 +1,87 @@
|
|||
package com.android.grape.data
|
||||
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class Expand(
|
||||
@SerializedName("ABI")
|
||||
var aBI: String = "",
|
||||
@SerializedName("API")
|
||||
var aPI: String = "",
|
||||
var amGetConfig: String = "",
|
||||
@SerializedName("AndroidID")
|
||||
var androidID: String = "",
|
||||
@SerializedName("AndroidVer")
|
||||
var androidVer: String = "",
|
||||
@SerializedName("BSSID")
|
||||
var bSSID: String = "",
|
||||
var baseband: String = "",
|
||||
var batteryLevel: Int = 0,
|
||||
var board: String = "",
|
||||
var bootLoader: String = "",
|
||||
var brand: String = "",
|
||||
var country: String = "",
|
||||
@SerializedName("CountryCode")
|
||||
var countryCode: String = "",
|
||||
var cpuinfobuf: String = "",
|
||||
var cpuinfostr: String = "",
|
||||
@SerializedName("DPI")
|
||||
var dPI: Int = 0,
|
||||
var dataStatfs: Long = 0,
|
||||
var device: String = "",
|
||||
var display: String = "",
|
||||
var displayLang: String = "",
|
||||
var downloadCacheStatfs: Long = 0,
|
||||
var fingerprint: String = "",
|
||||
var firstInstallTime: Int = 0,
|
||||
var gaid: String = "",
|
||||
var glExtensions: String = "",
|
||||
var glRenderer: String = "",
|
||||
var glVendor: String = "",
|
||||
var glVersion: String = "",
|
||||
var height: Int = 0,
|
||||
@SerializedName("ID")
|
||||
var iD: String = "",
|
||||
var incremental: String = "",
|
||||
var lang: String = "",
|
||||
var lastUpdateTime: Int = 0,
|
||||
var latitude: Double = 0.0,
|
||||
var localip: String = "",
|
||||
var longtitude: Double = 0.0,
|
||||
var lyMAC: String = "",
|
||||
@SerializedName("Manufacture")
|
||||
var manufacture: String = "",
|
||||
var model: String = "",
|
||||
var network: String = "",
|
||||
var phoneBootTime: Int = 0,
|
||||
var phoneUsedTime: Int = 0,
|
||||
var pmfea: String = "",
|
||||
var pmlib: String = "",
|
||||
var procStat: String = "",
|
||||
var procVersion: String = "",
|
||||
var ratioVersion: String = "",
|
||||
var referrerClickTime: Long = 0,
|
||||
var referrerFromGP: String = "",
|
||||
var regionid: String = "",
|
||||
var roBoardPlatform: String = "",
|
||||
var roBootimageBuildFingerprint: String = "",
|
||||
var roBuildDateUtc: Int = 0,
|
||||
var roBuildDescription: String = "",
|
||||
var roHardware: String = "",
|
||||
var roProductCpuAbilist: String = "",
|
||||
var roProductName: String = "",
|
||||
var rootStatfs: Int = 0,
|
||||
var screenBrightness: Int = 0,
|
||||
var sdStatfs: Long = 0,
|
||||
var sdcardCreateTime: Int = 0,
|
||||
var soRomRam: String = "",
|
||||
var timerawoff: Int = 0,
|
||||
var tmdisplayname: String = "",
|
||||
var uname: String = "",
|
||||
var width: Int = 0,
|
||||
@SerializedName("WifiMAC")
|
||||
var wifiMAC: String = "",
|
||||
@SerializedName("WifiName")
|
||||
var wifiName: String = "",
|
||||
var wvua: String = ""
|
||||
)
|
|
@ -0,0 +1,14 @@
|
|||
package com.android.grape.data
|
||||
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class GoogleCustom(
|
||||
@SerializedName("click_server_ts")
|
||||
var clickServerTs: Int = 0,
|
||||
@SerializedName("install_begin_server_ts")
|
||||
var installBeginServerTs: Int = 0,
|
||||
@SerializedName("install_version")
|
||||
var installVersion: String = "",
|
||||
var instant: Boolean = false
|
||||
)
|
|
@ -0,0 +1,10 @@
|
|||
package com.android.grape.data
|
||||
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class Locale(
|
||||
var country: String = "",
|
||||
var displayLang: String = "",
|
||||
var lang: String = ""
|
||||
)
|
|
@ -0,0 +1,11 @@
|
|||
package com.android.grape.data
|
||||
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class NameValuePairs(
|
||||
var cav: Int = 0,
|
||||
@SerializedName("null")
|
||||
var nullX: Int = 0,
|
||||
var other: Int = 0
|
||||
)
|
|
@ -0,0 +1,22 @@
|
|||
package com.android.grape.data
|
||||
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class NameValuePairsX(
|
||||
var ac: String = "",
|
||||
var ah: String = "",
|
||||
var ai: String = "",
|
||||
var ak: String = "",
|
||||
var al: String = "",
|
||||
var am: String = "",
|
||||
var an: String = "",
|
||||
var ap: String = "",
|
||||
var aq: String = "",
|
||||
var ar: String = "",
|
||||
@SerializedName("as")
|
||||
var asX: String = "",
|
||||
var at: String = "",
|
||||
var au: String = "",
|
||||
var av: String = ""
|
||||
)
|
|
@ -0,0 +1,8 @@
|
|||
package com.android.grape.data
|
||||
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class Pr(
|
||||
var nameValuePairs: NameValuePairsX = NameValuePairsX()
|
||||
)
|
|
@ -0,0 +1,12 @@
|
|||
package com.android.grape.data
|
||||
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class Sensor(
|
||||
var sN: String = "",
|
||||
var sT: Int = 0,
|
||||
var sV: String = "",
|
||||
var sVE: List<Double> = listOf(),
|
||||
var sVS: List<Double> = listOf()
|
||||
)
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import androidx.core.app.JobIntentService
|
||||
import com.android.grape.util.ChangeDeviceInfoUtil
|
||||
import com.android.grape.util.MockTools
|
||||
import com.android.grape.util.ServiceUtils
|
||||
import com.android.grape.util.Util
|
||||
|
@ -28,13 +29,15 @@ class OpenAppService : JobIntentService() {
|
|||
Util.doScript(this, Util.AUTO_JSPACKAGENAME) //autojs
|
||||
}
|
||||
try {
|
||||
if (Util.isNeedRestored) {
|
||||
Log.d("IOSTQ:", "执行留存任务")
|
||||
Util.setRrInfo(this)
|
||||
} else {
|
||||
Log.d("IOSTQ:", "执行新装任务")
|
||||
Util.setInfo(this)
|
||||
}
|
||||
//todo fix 改机流程
|
||||
// if (Util.isNeedRestored) {
|
||||
// Log.d("IOSTQ:", "执行留存任务")
|
||||
// Util.setRrInfo(this)
|
||||
// } else {
|
||||
// Log.d("IOSTQ:", "执行新装任务")
|
||||
// Util.setInfo(this)
|
||||
// }
|
||||
ChangeDeviceInfoUtil.changeDeviceInfo()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
|
|
@ -3,329 +3,150 @@ package com.android.grape.util
|
|||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.android.grape.data.AfInfo
|
||||
import com.android.grape.data.BigoInfo
|
||||
import com.android.grape.data.DeviceInfo
|
||||
import com.android.grape.MainApplication
|
||||
import com.android.grape.data.Device
|
||||
import com.android.grape.util.Util.paramsJson
|
||||
import com.blankj.utilcode.util.LogUtils
|
||||
import org.json.JSONObject
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
|
||||
object ChangeDeviceInfoUtil {
|
||||
fun changeDeviceInfo(
|
||||
current_pkg_name: String,
|
||||
context: Context?,
|
||||
bigoDeviceObject: JSONObject?,
|
||||
afDeviceObject: JSONObject?
|
||||
) {
|
||||
var bigoDeviceObject = bigoDeviceObject
|
||||
var afDeviceObject = afDeviceObject
|
||||
try {
|
||||
val bigoDevice: BigoInfo
|
||||
if (bigoDeviceObject != null) {
|
||||
// BIGO
|
||||
val cpuClockSpeed = bigoDeviceObject.optString("cpu_clock_speed")
|
||||
val gaid = bigoDeviceObject.optString("gaid")
|
||||
val userAgent = bigoDeviceObject.optString("User-Agent")
|
||||
val osLang = bigoDeviceObject.optString("os_lang")
|
||||
val osVer = bigoDeviceObject.optString("os_ver")
|
||||
val tz = bigoDeviceObject.optString("tz")
|
||||
val systemCountry = bigoDeviceObject.optString("system_country")
|
||||
val simCountry = bigoDeviceObject.optString("sim_country")
|
||||
val romFreeIn = bigoDeviceObject.optLong("rom_free_in")
|
||||
val resolution = bigoDeviceObject.optString("resolution")
|
||||
val vendor = bigoDeviceObject.optString("vendor")
|
||||
val batteryScale = bigoDeviceObject.optInt("bat_scale")
|
||||
// String model = deviceObject.optString("model");
|
||||
val net = bigoDeviceObject.optString("net")
|
||||
val dpi = bigoDeviceObject.optLong("dpi")
|
||||
val romFreeExt = bigoDeviceObject.optLong("rom_free_ext")
|
||||
val dpiF = bigoDeviceObject.optString("dpi_f")
|
||||
val cpuCoreNum = bigoDeviceObject.optLong("cpu_core_num")
|
||||
|
||||
bigoDevice = BigoInfo()
|
||||
bigoDevice.cpuClockSpeed = cpuClockSpeed
|
||||
bigoDevice.gaid = gaid
|
||||
bigoDevice.userAgent = userAgent
|
||||
bigoDevice.osLang = osLang
|
||||
bigoDevice.osVer = osVer
|
||||
bigoDevice.tz = tz
|
||||
bigoDevice.systemCountry = systemCountry
|
||||
bigoDevice.simCountry = simCountry
|
||||
bigoDevice.romFreeIn = romFreeIn
|
||||
bigoDevice.resolution = resolution
|
||||
bigoDevice.vendor = vendor
|
||||
bigoDevice.batteryScale = batteryScale
|
||||
bigoDevice.net = net
|
||||
bigoDevice.dpi = dpi
|
||||
bigoDevice.romFreeExt = romFreeExt
|
||||
bigoDevice.dpiF = dpiF
|
||||
bigoDevice.cpuCoreNum = cpuCoreNum
|
||||
// TaskUtil.setBigoDevice(bigoDevice)
|
||||
try {
|
||||
callVCloudSettings_put(
|
||||
"$current_pkg_name.system_country",
|
||||
systemCountry,
|
||||
context
|
||||
)
|
||||
callVCloudSettings_put("$current_pkg_name.sim_country", simCountry, context)
|
||||
callVCloudSettings_put(
|
||||
"$current_pkg_name.rom_free_in",
|
||||
romFreeIn.toString(),
|
||||
context
|
||||
)
|
||||
callVCloudSettings_put("$current_pkg_name.resolution", resolution, context)
|
||||
callVCloudSettings_put("$current_pkg_name.vendor", vendor, context)
|
||||
callVCloudSettings_put(
|
||||
"$current_pkg_name.battery_scale",
|
||||
batteryScale.toString(),
|
||||
context
|
||||
)
|
||||
callVCloudSettings_put("$current_pkg_name.os_lang", osLang, context)
|
||||
// callVCloudSettings_put(current_pkg_name + ".model", model, context);
|
||||
callVCloudSettings_put("$current_pkg_name.net", net, context)
|
||||
callVCloudSettings_put("$current_pkg_name.dpi", dpi.toString(), context)
|
||||
callVCloudSettings_put(
|
||||
"$current_pkg_name.rom_free_ext",
|
||||
romFreeExt.toString(),
|
||||
context
|
||||
)
|
||||
callVCloudSettings_put("$current_pkg_name.dpi_f", dpiF, context)
|
||||
callVCloudSettings_put(
|
||||
"$current_pkg_name.cpu_core_num",
|
||||
cpuCoreNum.toString(),
|
||||
context
|
||||
)
|
||||
callVCloudSettings_put(
|
||||
"$current_pkg_name.cpu_clock_speed",
|
||||
cpuClockSpeed,
|
||||
context
|
||||
)
|
||||
callVCloudSettings_put(current_pkg_name + "_gaid", gaid, context)
|
||||
// **User-Agent**
|
||||
callVCloudSettings_put(current_pkg_name + "_user_agent", userAgent, context)
|
||||
// **os_lang**系统语言
|
||||
callVCloudSettings_put(current_pkg_name + "_os_lang", osLang, context)
|
||||
// **os_ver**
|
||||
callVCloudSettings_put(current_pkg_name + "_os_ver", osVer, context)
|
||||
// **tz** (时区)
|
||||
callVCloudSettings_put(current_pkg_name + "_tz", tz, context)
|
||||
} catch (e: Throwable) {
|
||||
LogUtils.e(
|
||||
Log.ERROR,
|
||||
"ChangeDeviceInfoUtil",
|
||||
"Error occurred while changing device info",
|
||||
e
|
||||
)
|
||||
throw RuntimeException("Error occurred in changeDeviceInfo", e)
|
||||
}
|
||||
bigoDeviceObject = null
|
||||
val deviceObject = paramsJson?.getJSONObject("device")
|
||||
if (deviceObject == null) {
|
||||
LogUtils.d("ERROR", "ChangeDeviceInfoUtil", "device is null")
|
||||
return
|
||||
}
|
||||
val context = MainApplication.instance
|
||||
val device = GsonUtils.fromJsonObject(deviceObject.toString(), Device::class.java)
|
||||
val currentPkgName = MainApplication.instance.packageName
|
||||
vcloudsettingsPut(
|
||||
"$currentPkgName.system_country",
|
||||
device.country,
|
||||
context
|
||||
)
|
||||
vcloudsettingsPut("$currentPkgName.sim_country", device.country, context)
|
||||
// callVCloudSettings_put(
|
||||
// "$currentPkgName.rom_free_in",
|
||||
// romFreeIn.toString(),
|
||||
// context
|
||||
// )
|
||||
vcloudsettingsPut(
|
||||
"$currentPkgName.resolution",
|
||||
"${device.expand.width}x${device.expand.height}}",
|
||||
context
|
||||
)
|
||||
vcloudsettingsPut("$currentPkgName.vendor", device.expand.glVendor, context)
|
||||
// callVCloudSettings_put("$currentPkgName.battery_scale", batteryScale.toString(), context)
|
||||
vcloudsettingsPut("$currentPkgName.os_lang", device.lang, context)
|
||||
vcloudsettingsPut("$currentPkgName.model", device.model, context);
|
||||
vcloudsettingsPut("$currentPkgName.net", device.network, context)
|
||||
vcloudsettingsPut("$currentPkgName.dpi", device.expand.dPI.toString(), context)
|
||||
// callVCloudSettings_put(
|
||||
// "$currentPkgName.rom_free_ext",
|
||||
// romFreeExt.toString(),
|
||||
// context
|
||||
// )
|
||||
// callVCloudSettings_put("$currentPkgName.dpi_f", dpiF, context)
|
||||
// callVCloudSettings_put("$currentPkgName.cpu_core_num", cpuCoreNum.toString(), context)
|
||||
// callVCloudSettings_put("$currentPkgName.cpu_clock_speed", cpuClockSpeed, context)
|
||||
vcloudsettingsPut(currentPkgName + "_gaid", device.expand.gaid, context)
|
||||
// **User-Agent**
|
||||
// callVCloudSettings_put(currentPkgName + "_user_agent", userAgent, context)
|
||||
// **os_lang**系统语言
|
||||
vcloudsettingsPut(currentPkgName + "_os_lang", device.lang, context)
|
||||
// **os_ver**
|
||||
vcloudsettingsPut(currentPkgName + "_os_ver", device.sdkVer, context)
|
||||
// **tz** (时区)
|
||||
vcloudsettingsPut(currentPkgName + "_tz", device.tzOffTime.toString(), context)
|
||||
|
||||
val deviceInfo: DeviceInfo
|
||||
val afDevice: AfInfo
|
||||
if (afDeviceObject != null) {
|
||||
val advertiserId = afDeviceObject.optString(".advertiserId")
|
||||
val model = afDeviceObject.optString(".model")
|
||||
val brand = afDeviceObject.optString(".brand")
|
||||
val androidId = afDeviceObject.optString(".android_id")
|
||||
val xPixels = afDeviceObject.optInt(".deviceData.dim.x_px")
|
||||
val yPixels = afDeviceObject.optInt(".deviceData.dim.y_px")
|
||||
val densityDpi = afDeviceObject.optInt(".deviceData.dim.d_dpi")
|
||||
val country = afDeviceObject.optString(".country")
|
||||
val batteryLevel = afDeviceObject.optString(".batteryLevel")
|
||||
val stackInfo = Thread.currentThread().stackTrace[2].toString()
|
||||
val product = afDeviceObject.optString(".product")
|
||||
val network = afDeviceObject.optString(".network")
|
||||
val langCode = afDeviceObject.optString(".lang_code")
|
||||
val cpuAbi = afDeviceObject.optString(".deviceData.cpu_abi")
|
||||
val yDp = afDeviceObject.optLong(".deviceData.dim.ydp")
|
||||
vcloudsettingsPut("$currentPkgName.advertiserId", device.advertiserId, context)
|
||||
vcloudsettingsPut("$currentPkgName.brand", device.brand, context)
|
||||
vcloudsettingsPut("$currentPkgName.android_id", device.androidId, context)
|
||||
vcloudsettingsPut("$currentPkgName.lang", device.lang, context)
|
||||
vcloudsettingsPut("$currentPkgName.country", device.country, context)
|
||||
vcloudsettingsPut(
|
||||
"$currentPkgName.batteryLevel",
|
||||
device.batteryLevel.toString(), context
|
||||
)
|
||||
// callVCloudSettings_put(
|
||||
// currentPkgName + "_screen.optMetrics.stack",
|
||||
// stackInfo,
|
||||
// context
|
||||
// )
|
||||
vcloudsettingsPut("$currentPkgName.product", device.product, context)
|
||||
vcloudsettingsPut("$currentPkgName.network", device.network, context)
|
||||
vcloudsettingsPut("$currentPkgName.cpu_abi", device.cpuAbi, context)
|
||||
vcloudsettingsPut("$currentPkgName.lang_code", device.langCode, context)
|
||||
// **广告标识符 (advertiserId)** 及 **启用状态**
|
||||
val isAdIdEnabled = true // 默认启用广告 ID
|
||||
vcloudsettingsPut(
|
||||
"$currentPkgName.advertiserIdEnabled",
|
||||
isAdIdEnabled.toString(),
|
||||
context
|
||||
)
|
||||
|
||||
afDevice = AfInfo()
|
||||
afDevice.advertiserId = advertiserId
|
||||
afDevice.model = model
|
||||
afDevice.brand = brand
|
||||
afDevice.androidId = androidId
|
||||
afDevice.xPixels = xPixels
|
||||
afDevice.yPixels = yPixels
|
||||
afDevice.densityDpi = densityDpi
|
||||
afDevice.country = country
|
||||
afDevice.batteryLevel = batteryLevel
|
||||
afDevice.stackInfo = stackInfo
|
||||
afDevice.product = product
|
||||
afDevice.network = network
|
||||
afDevice.langCode = langCode
|
||||
afDevice.cpuAbi = cpuAbi
|
||||
afDevice.yDp = yDp
|
||||
// TaskUtil.setAfDevice(afDevice)
|
||||
val displayMetrics = JSONObject()
|
||||
|
||||
val lang = afDeviceObject.optString(".lang")
|
||||
val ro_product_brand = afDeviceObject.optString("ro.product.brand", "")
|
||||
val ro_product_model = afDeviceObject.optString("ro.product.model", "")
|
||||
val ro_product_manufacturer =
|
||||
afDeviceObject.optString("ro.product.manufacturer", "")
|
||||
val ro_product_device = afDeviceObject.optString("ro.product.device", "")
|
||||
val ro_product_name = afDeviceObject.optString("ro.product.name", "")
|
||||
val ro_build_version_incremental =
|
||||
afDeviceObject.optString("ro.build.version.incremental", "")
|
||||
val ro_build_fingerprint = afDeviceObject.optString("ro.build.fingerprint", "")
|
||||
val ro_odm_build_fingerprint =
|
||||
afDeviceObject.optString("ro.odm.build.fingerprint", "")
|
||||
val ro_product_build_fingerprint =
|
||||
afDeviceObject.optString("ro.product.build.fingerprint", "")
|
||||
val ro_system_build_fingerprint =
|
||||
afDeviceObject.optString("ro.system.build.fingerprint", "")
|
||||
val ro_system_ext_build_fingerprint =
|
||||
afDeviceObject.optString("ro.system_ext.build.fingerprint", "")
|
||||
val ro_vendor_build_fingerprint =
|
||||
afDeviceObject.optString("ro.vendor.build.fingerprint", "")
|
||||
val ro_build_platform = afDeviceObject.optString("ro.board.platform", "")
|
||||
val persist_sys_cloud_drm_id =
|
||||
afDeviceObject.optString("persist.sys.cloud.drm.id", "")
|
||||
val persist_sys_cloud_battery_capacity =
|
||||
afDeviceObject.optInt("persist.sys.cloud.battery.capacity", -1)
|
||||
val persist_sys_cloud_gpu_gl_vendor =
|
||||
afDeviceObject.optString("persist.sys.cloud.gpu.gl_vendor", "")
|
||||
val persist_sys_cloud_gpu_gl_renderer =
|
||||
afDeviceObject.optString("persist.sys.cloud.gpu.gl_renderer", "")
|
||||
val persist_sys_cloud_gpu_gl_version =
|
||||
afDeviceObject.optString("persist.sys.cloud.gpu.gl_version", "")
|
||||
val persist_sys_cloud_gpu_egl_vendor =
|
||||
afDeviceObject.optString("persist.sys.cloud.gpu.egl_vendor", "")
|
||||
val persist_sys_cloud_gpu_egl_version =
|
||||
afDeviceObject.optString("persist.sys.cloud.gpu.egl_version", "")
|
||||
val global_android_id = afDeviceObject.optString(".android_id", "")
|
||||
val anticheck_pkgs = afDeviceObject.optString(".anticheck_pkgs", "")
|
||||
val pm_list_features = afDeviceObject.optString(".pm_list_features", "")
|
||||
val pm_list_libraries = afDeviceObject.optString(".pm_list_libraries", "")
|
||||
val system_http_agent = afDeviceObject.optString("system.http.agent", "")
|
||||
val webkit_http_agent = afDeviceObject.optString("webkit.http.agent", "")
|
||||
val com_fk_tools_pkgInfo = afDeviceObject.optString(".pkg_info", "")
|
||||
val appsflyerKey = afDeviceObject.optString(".appsflyerKey", "")
|
||||
val appUserId = afDeviceObject.optString(".appUserId", "")
|
||||
val disk = afDeviceObject.optString(".disk", "")
|
||||
val operator = afDeviceObject.optString(".operator", "")
|
||||
val cell_mcc = afDeviceObject.optString(".cell.mcc", "")
|
||||
val cell_mnc = afDeviceObject.optString(".cell.mnc", "")
|
||||
val date1 = afDeviceObject.optString(".date1", "")
|
||||
val date2 = afDeviceObject.optString(".date2", "")
|
||||
val bootId = afDeviceObject.optString("BootId", "")
|
||||
displayMetrics.put("widthPixels", device.expand.width)
|
||||
|
||||
deviceInfo = DeviceInfo()
|
||||
deviceInfo.lang = lang
|
||||
deviceInfo.roProductBrand = ro_product_brand
|
||||
deviceInfo.roProductModel = ro_product_model
|
||||
deviceInfo.roProductManufacturer = ro_product_manufacturer
|
||||
deviceInfo.roProductDevice = ro_product_device
|
||||
deviceInfo.roProductName = ro_product_name
|
||||
deviceInfo.roBuildVersionIncremental = ro_build_version_incremental
|
||||
deviceInfo.roBuildFingerprint = ro_build_fingerprint
|
||||
deviceInfo.roOdmBuildFingerprint = ro_odm_build_fingerprint
|
||||
deviceInfo.roProductBuildFingerprint = ro_product_build_fingerprint
|
||||
deviceInfo.roSystemBuildFingerprint = ro_system_build_fingerprint
|
||||
deviceInfo.roSystemExtBuildFingerprint = ro_system_ext_build_fingerprint
|
||||
deviceInfo.roVendorBuildFingerprint = ro_vendor_build_fingerprint
|
||||
deviceInfo.roBuildPlatform = ro_build_platform
|
||||
deviceInfo.persistSysCloudDrmId = persist_sys_cloud_drm_id
|
||||
deviceInfo.persistSysCloudBatteryCapacity = persist_sys_cloud_battery_capacity
|
||||
deviceInfo.persistSysCloudGpuGlVendor = persist_sys_cloud_gpu_gl_vendor
|
||||
deviceInfo.persistSysCloudGpuGlRenderer = persist_sys_cloud_gpu_gl_renderer
|
||||
deviceInfo.persistSysCloudGpuGlVersion = persist_sys_cloud_gpu_gl_version
|
||||
deviceInfo.persistSysCloudGpuEglVendor = persist_sys_cloud_gpu_egl_vendor
|
||||
deviceInfo.persistSysCloudGpuEglVersion = persist_sys_cloud_gpu_egl_version
|
||||
// TaskUtil.setDeviceInfo(deviceInfo)
|
||||
try {
|
||||
callVCloudSettings_put("$current_pkg_name.advertiserId", advertiserId, context)
|
||||
callVCloudSettings_put("$current_pkg_name.model", model, context)
|
||||
callVCloudSettings_put("$current_pkg_name.brand", brand, context)
|
||||
callVCloudSettings_put("$current_pkg_name.android_id", androidId, context)
|
||||
callVCloudSettings_put("$current_pkg_name.lang", lang, context)
|
||||
callVCloudSettings_put("$current_pkg_name.country", country, context)
|
||||
callVCloudSettings_put("$current_pkg_name.batteryLevel", batteryLevel, context)
|
||||
callVCloudSettings_put(
|
||||
current_pkg_name + "_screen.optMetrics.stack",
|
||||
stackInfo,
|
||||
context
|
||||
)
|
||||
callVCloudSettings_put("$current_pkg_name.product", product, context)
|
||||
callVCloudSettings_put("$current_pkg_name.network", network, context)
|
||||
callVCloudSettings_put("$current_pkg_name.cpu_abi", cpuAbi, context)
|
||||
callVCloudSettings_put("$current_pkg_name.lang_code", langCode, context)
|
||||
// **广告标识符 (advertiserId)** 及 **启用状态**
|
||||
val isAdIdEnabled = true // 默认启用广告 ID
|
||||
callVCloudSettings_put(
|
||||
"$current_pkg_name.advertiserIdEnabled",
|
||||
isAdIdEnabled.toString(),
|
||||
context
|
||||
)
|
||||
displayMetrics.put("heightPixels", device.expand.height)
|
||||
displayMetrics.put("densityDpi", device.expand.dPI)
|
||||
displayMetrics.put("yDp", device.dim.ydp)
|
||||
vcloudsettingsPut(
|
||||
"screen.device.displayMetrics",
|
||||
displayMetrics.toString(),
|
||||
context
|
||||
)
|
||||
|
||||
val displayMetrics = JSONObject()
|
||||
|
||||
displayMetrics.put("widthPixels", xPixels)
|
||||
|
||||
displayMetrics.put("heightPixels", yPixels)
|
||||
displayMetrics.put("densityDpi", densityDpi)
|
||||
displayMetrics.put("yDp", yDp)
|
||||
callVCloudSettings_put(
|
||||
"screen.device.displayMetrics",
|
||||
displayMetrics.toString(),
|
||||
context
|
||||
)
|
||||
|
||||
if (!ShellUtils.hasRootAccess()) {
|
||||
LogUtils.d(
|
||||
"ERROR",
|
||||
"ChangeDeviceInfoUtil",
|
||||
"Root access is required to execute system property changes"
|
||||
)
|
||||
}
|
||||
// 设置机型, 直接设置属性
|
||||
ShellUtils.execRootCmd("setprop ro.product.brand $ro_product_brand")
|
||||
ShellUtils.execRootCmd("setprop ro.product.model $ro_product_model")
|
||||
ShellUtils.execRootCmd("setprop ro.product.manufacturer $ro_product_manufacturer")
|
||||
ShellUtils.execRootCmd("setprop ro.product.device $ro_product_device")
|
||||
ShellUtils.execRootCmd("setprop ro.product.name $ro_product_name")
|
||||
ShellUtils.execRootCmd("setprop ro.build.version.incremental $ro_build_version_incremental")
|
||||
ShellUtils.execRootCmd("setprop ro.build.fingerprint $ro_build_fingerprint")
|
||||
ShellUtils.execRootCmd("setprop ro.odm.build.fingerprint $ro_odm_build_fingerprint")
|
||||
ShellUtils.execRootCmd("setprop ro.product.build.fingerprint $ro_product_build_fingerprint")
|
||||
ShellUtils.execRootCmd("setprop ro.system.build.fingerprint $ro_system_build_fingerprint")
|
||||
ShellUtils.execRootCmd("setprop ro.system_ext.build.fingerprint $ro_system_ext_build_fingerprint")
|
||||
ShellUtils.execRootCmd("setprop ro.vendor.build.fingerprint $ro_vendor_build_fingerprint")
|
||||
ShellUtils.execRootCmd("setprop ro.board.platform $ro_build_platform")
|
||||
|
||||
// Native.setBootId(bootId);
|
||||
// 修改drm id
|
||||
ShellUtils.execRootCmd("setprop persist.sys.cloud.drm.id $persist_sys_cloud_drm_id")
|
||||
// 电量模拟需要大于1000
|
||||
ShellUtils.execRootCmd("setprop persist.sys.cloud.battery.capacity $persist_sys_cloud_battery_capacity")
|
||||
ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.gl_vendor $persist_sys_cloud_gpu_gl_vendor")
|
||||
ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.gl_renderer $persist_sys_cloud_gpu_gl_renderer")
|
||||
// 这个值不能随便改 必须是 OpenGL ES %d.%d 这个格式
|
||||
ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.gl_version $persist_sys_cloud_gpu_gl_version")
|
||||
ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.egl_vendor $persist_sys_cloud_gpu_egl_vendor")
|
||||
ShellUtils.execRootCmd("setprop persist.sys.cloud.gpu.egl_version $persist_sys_cloud_gpu_egl_version")
|
||||
} catch (e: Throwable) {
|
||||
LogUtils.e(
|
||||
Log.ERROR,
|
||||
"ChangeDeviceInfoUtil",
|
||||
"Error occurred in changeDeviceInfo",
|
||||
e
|
||||
)
|
||||
throw RuntimeException("Error occurred in changeDeviceInfo", e)
|
||||
}
|
||||
afDeviceObject = null
|
||||
if (!ShellUtils.hasRootAccess()) {
|
||||
LogUtils.d(
|
||||
"ERROR",
|
||||
"ChangeDeviceInfoUtil",
|
||||
"Root access is required to execute system property changes"
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
// 设置机型, 直接设置属性
|
||||
ShellUtils.execRootCmd("setprop ro.product.brand ${device.brand}")
|
||||
ShellUtils.execRootCmd("setprop ro.product.model ${device.model}")
|
||||
ShellUtils.execRootCmd("setprop ro.product.manufacturer ${device.manufactor}")
|
||||
ShellUtils.execRootCmd("setprop ro.product.device ${device.device}")
|
||||
ShellUtils.execRootCmd("setprop ro.product.name ${device.expand.roProductName}")
|
||||
ShellUtils.execRootCmd("setprop ro.build.version.incremental ${device.expand.incremental}")
|
||||
ShellUtils.execRootCmd("setprop ro.build.fingerprint ${device.expand.roBootimageBuildFingerprint}")
|
||||
ShellUtils.execRootCmd("setprop ro.odm.build.fingerprint ${device.expand.roBootimageBuildFingerprint}")
|
||||
ShellUtils.execRootCmd("setprop ro.product.build.fingerprint ${device.expand.roBootimageBuildFingerprint}")
|
||||
ShellUtils.execRootCmd("setprop ro.system.build.fingerprint ${device.expand.roBootimageBuildFingerprint}")
|
||||
ShellUtils.execRootCmd("setprop ro.system_ext.build.fingerprint ${device.expand.roBootimageBuildFingerprint}")
|
||||
ShellUtils.execRootCmd("setprop ro.vendor.build.fingerprint ${device.expand.roBootimageBuildFingerprint}")
|
||||
ShellUtils.execRootCmd("setprop ro.board.platform ${device.expand.roBoardPlatform}")
|
||||
|
||||
// 修改drm id
|
||||
// ShellUtils.execRootCmd("setprop persist.sys.cloud.drm.id $persist_sys_cloud_drm_id")
|
||||
// 电量模拟需要大于1000
|
||||
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_renderer ${device.expand.glRenderer}")
|
||||
// 这个值不能随便改 必须是 OpenGL ES %d.%d 这个格式
|
||||
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_version $persist_sys_cloud_gpu_egl_version")
|
||||
} catch (e: Throwable) {
|
||||
LogUtils.e(
|
||||
Log.ERROR,
|
||||
"ChangeDeviceInfoUtil",
|
||||
"Error occurred while changing device info",
|
||||
e
|
||||
)
|
||||
throw RuntimeException("Error occurred in changeDeviceInfo", e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun callVCloudSettings_put(key: String?, value: String?, context: Context?) {
|
||||
if (context == null) {
|
||||
LogUtils.e(Log.ERROR, "ChangeDeviceInfoUtil", "Context cannot be null", null)
|
||||
throw IllegalArgumentException("Context cannot be null")
|
||||
}
|
||||
if (key == null || key.isEmpty()) {
|
||||
private fun vcloudsettingsPut(key: String?, value: String?, context: Context) {
|
||||
if (key.isNullOrEmpty()) {
|
||||
LogUtils.e(Log.ERROR, "ChangeDeviceInfoUtil", "Key cannot be null or empty", null)
|
||||
throw IllegalArgumentException("Key cannot be null or empty")
|
||||
}
|
||||
|
@ -350,15 +171,11 @@ object ChangeDeviceInfoUtil {
|
|||
Log.d("Debug", "putString executed successfully.")
|
||||
} catch (e: ClassNotFoundException) {
|
||||
LogUtils.e(
|
||||
Log.WARN,
|
||||
"ChangeDeviceInfoUtil",
|
||||
"Class not found: android.provider.VCloudSettings\$Global. This may not be supported on this device.",
|
||||
e
|
||||
)
|
||||
} catch (e: NoSuchMethodException) {
|
||||
LogUtils.e(
|
||||
Log.WARN,
|
||||
"ChangeDeviceInfoUtil",
|
||||
"Method not found: android.provider.VCloudSettings\$Global.putString. This may not be supported on this",
|
||||
e
|
||||
)
|
||||
|
@ -366,23 +183,17 @@ object ChangeDeviceInfoUtil {
|
|||
val cause = e.targetException
|
||||
if (cause is SecurityException) {
|
||||
LogUtils.e(
|
||||
Log.ERROR,
|
||||
"ChangeDeviceInfoUtil",
|
||||
"Error occurred in changeDeviceInfo",
|
||||
cause
|
||||
)
|
||||
} else {
|
||||
LogUtils.e(
|
||||
Log.ERROR,
|
||||
"ChangeDeviceInfoUtil",
|
||||
"Error occurred in changeDeviceInfo",
|
||||
cause
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
LogUtils.e(
|
||||
Log.ERROR,
|
||||
"ChangeDeviceInfoUtil",
|
||||
"Unexpected error during putString invocation",
|
||||
e
|
||||
)
|
||||
|
|
|
@ -77,9 +77,19 @@ object ClashUtil {
|
|||
}
|
||||
|
||||
fun unregisterReceiver(context: Context) {
|
||||
context.unregisterReceiver(clashStatusReceiver)
|
||||
try {
|
||||
context.unregisterReceiver(clashStatusReceiver)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun getRandomLocale(): String {
|
||||
val locales = listOf("ru", "us")
|
||||
return locales.random()
|
||||
}
|
||||
|
||||
|
||||
fun switchProxyGroup(groupName: String?, proxyName: String?, controllerUrl: String) {
|
||||
if (groupName == null || groupName.trim { it <= ' ' }
|
||||
.isEmpty() || proxyName == null || proxyName.trim { it <= ' ' }.isEmpty()) {
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package com.android.grape.util
|
||||
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import java.lang.reflect.Type
|
||||
import java.util.*
|
||||
|
||||
object GsonUtils {
|
||||
// 可配置的Gson实例
|
||||
private val gson: Gson by lazy {
|
||||
GsonBuilder()
|
||||
// .setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
|
||||
.create()
|
||||
}
|
||||
|
||||
// 自定义Gson实例
|
||||
private val customGson = mutableMapOf<String, Gson>()
|
||||
|
||||
/**
|
||||
* 通用转换函数
|
||||
* @param json JsonObject
|
||||
* @param clazz 目标类型
|
||||
*/
|
||||
fun <T> fromJsonObject(json: String, clazz: Class<T>): T {
|
||||
return gson.fromJson(json, clazz)
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用转换函数(带泛型)
|
||||
* @param json JsonObject
|
||||
* @param typeToken 类型Token
|
||||
*/
|
||||
fun <T> fromJsonObject(json: JsonObject, typeToken: TypeToken<T>): T {
|
||||
return gson.fromJson(json, typeToken.type)
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用自定义适配器转换
|
||||
* @param json JsonObject
|
||||
* @param clazz 目标类型
|
||||
* @param adapters 适配器列表
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.P)
|
||||
fun <T> fromJsonObject(
|
||||
json: JsonObject,
|
||||
clazz: Class<T>,
|
||||
vararg adapters: Pair<Type, Any>
|
||||
): T {
|
||||
val gsonKey = clazz.name + adapters.joinToString { it.first.typeName }
|
||||
val customGsonInstance = customGson[gsonKey] ?: buildCustomGson(adapters).also {
|
||||
customGson[gsonKey] = it
|
||||
}
|
||||
|
||||
return customGsonInstance.fromJson(json, clazz)
|
||||
}
|
||||
|
||||
private fun buildCustomGson(adapters: Array<out Pair<Type, Any>>): Gson {
|
||||
val builder = GsonBuilder()
|
||||
adapters.forEach { (type, adapter) ->
|
||||
when (adapter) {
|
||||
is JsonDeserializer<*> -> builder.registerTypeAdapter(type, adapter)
|
||||
else -> throw IllegalArgumentException("Unsupported adapter type")
|
||||
}
|
||||
}
|
||||
return builder.create()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.android.grape.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import com.blankj.utilcode.util.LogUtils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class HttpUtil {
|
||||
|
||||
public static void execReloginTask(Context context) {
|
||||
String url = "http://39.103.73.250/tt/ddj/preRequest!requestRelogin.do";
|
||||
String ANDROID_ID = Settings.System.getString(context.getContentResolver(), Settings.System.ANDROID_ID);
|
||||
String params = "platform=Android&tag=" + "119" + "&uuid=" + ANDROID_ID;
|
||||
System.out.println("IOSTQ:execReloginTask->url:" + url + "?" + params);
|
||||
try {
|
||||
|
||||
String result = new MyPost().PostData(context, " ".getBytes(StandardCharsets.UTF_8), url + "?" + params);
|
||||
|
||||
LogUtils.e("request result : " + result);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.i("TAG", "execTask error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void execInstallTask(Context context) {
|
||||
String url = "http://39.103.73.250/tt/ddj/preRequest!requestInstall.do";
|
||||
|
||||
String ANDROID_ID = Settings.System.getString(context.getContentResolver(), Settings.System.ANDROID_ID);
|
||||
|
||||
String params = "platform=Android&tag=" + "119" + "&uuid=" + ANDROID_ID;
|
||||
LogUtils.e("IOSTQ:request result : " + url + "?" + params);
|
||||
try {
|
||||
|
||||
String result = new MyPost().PostData(context, " ".getBytes("utf-8"), url + "?" + params);
|
||||
|
||||
LogUtils.e("request result : " + result);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
LogUtils.i("TAG", "execTask error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
package com.android.grape.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
public class MyPost {
|
||||
|
||||
private static final String TAG = "MyPost";
|
||||
// private static final String TAG = TT.dd("4B7HyaIsVcs=");
|
||||
|
||||
private static okhttp3.OkHttpClient oklient = new okhttp3.OkHttpClient();
|
||||
|
||||
public String PostData(Context context, byte[] byt, String url_) {
|
||||
|
||||
byte[] bytes = postDataBytes(context, byt, url_);
|
||||
|
||||
if (bytes != null && bytes.length > 0) {
|
||||
|
||||
try {
|
||||
return new String(bytes, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String PostDataCommon(Context context, byte[] byt, String url_) {
|
||||
byte[] bytes = postDataBytes(context, byt, url_);
|
||||
|
||||
if (bytes != null && bytes.length >= 0) {
|
||||
if (bytes.length == 0) {
|
||||
return "";
|
||||
} else {
|
||||
try {
|
||||
return new String(bytes, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public String httpGet(String url) throws Exception {
|
||||
|
||||
URL obj = new URL(url);
|
||||
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
||||
|
||||
//默认值我GET
|
||||
con.setRequestMethod("GET");
|
||||
|
||||
int responseCode = con.getResponseCode();
|
||||
System.out.println("\nSending 'GET' request to URL : " + url);
|
||||
System.out.println("Response Code : " + responseCode);
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(con.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuffer response = new StringBuffer();
|
||||
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
|
||||
//打印结果
|
||||
System.out.println(response.toString());
|
||||
return response.toString();
|
||||
|
||||
}
|
||||
|
||||
public byte[] postDataBytes(Context context, byte[] byt, String url_) {
|
||||
String result = null;
|
||||
HttpURLConnection httpUrlConnection = null;
|
||||
InputStream inStrm = null;
|
||||
ByteArrayOutputStream baos = null;
|
||||
BufferedInputStream bis = null;
|
||||
|
||||
try {
|
||||
httpUrlConnection = NetWorkUtils.getHttpURLConnection(context, url_);
|
||||
|
||||
httpUrlConnection.setAllowUserInteraction(true);
|
||||
httpUrlConnection.setDoOutput(true);
|
||||
httpUrlConnection.setDoInput(true);
|
||||
httpUrlConnection.setUseCaches(false);
|
||||
httpUrlConnection.setRequestProperty("Connection", "close");//add 20200428
|
||||
httpUrlConnection.setRequestProperty("Content-type", "application/x-java-serialized-object");
|
||||
// httpUrlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
httpUrlConnection.setRequestMethod("POST");
|
||||
httpUrlConnection.setConnectTimeout(20000);
|
||||
OutputStream outStrm = null;
|
||||
|
||||
|
||||
outStrm = httpUrlConnection.getOutputStream();
|
||||
|
||||
|
||||
outStrm.write(byt);
|
||||
outStrm.flush();
|
||||
outStrm.close();
|
||||
|
||||
inStrm = httpUrlConnection.getInputStream();
|
||||
|
||||
baos = new ByteArrayOutputStream();
|
||||
|
||||
bis = new BufferedInputStream(inStrm);
|
||||
byte[] buf = new byte[1024];
|
||||
int readSize = -1;
|
||||
|
||||
while ((readSize = bis.read(buf)) != -1) {
|
||||
baos.write(buf, 0, readSize);
|
||||
}
|
||||
|
||||
byte[] data = baos.toByteArray();
|
||||
|
||||
return data;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
result = null;
|
||||
} finally {
|
||||
|
||||
if (baos != null) {
|
||||
try {
|
||||
baos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (bis != null) {
|
||||
try {
|
||||
bis.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (inStrm != null) {
|
||||
try {
|
||||
inStrm.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (httpUrlConnection != null) {
|
||||
httpUrlConnection.disconnect();
|
||||
httpUrlConnection = null;
|
||||
}
|
||||
|
||||
System.gc();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.android.grape.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
public class NetWorkUtils {
|
||||
|
||||
public static HttpURLConnection getHttpURLConnection(Context context,
|
||||
String _url) throws IOException {
|
||||
return getHttpURLConnection(context, _url, false);
|
||||
}
|
||||
|
||||
private static int dynamicPort0 = 20380;
|
||||
|
||||
public static HttpURLConnection getHttpURLConnection(Context context, String _url, boolean isProxy) throws IOException {
|
||||
URL url = new URL(_url);
|
||||
|
||||
HttpURLConnection httpUrlConnection = null;
|
||||
|
||||
httpUrlConnection = (HttpURLConnection)url.openConnection();
|
||||
return httpUrlConnection;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,309 @@
|
|||
package com.android.grape.util
|
||||
|
||||
import android.Manifest
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
|
||||
/**
|
||||
* 通知权限管理工具
|
||||
*
|
||||
* 使用示例:
|
||||
*
|
||||
* class MainActivity : AppCompatActivity() {
|
||||
* private lateinit var permissionHandler: NotificationPermissionHandler
|
||||
*
|
||||
* override fun onCreate(savedInstanceState: Bundle?) {
|
||||
* super.onCreate(savedInstanceState)
|
||||
*
|
||||
* // 初始化权限处理器
|
||||
* permissionHandler = NotificationPermissionHandler(this, ::onPermissionResult)
|
||||
*
|
||||
* // 检查通知权限
|
||||
* if (permissionHandler.shouldRequestNotificationPermission()) {
|
||||
* permissionHandler.requestNotificationPermission()
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* override fun onResume() {
|
||||
* super.onResume()
|
||||
* // 处理从设置返回的情况
|
||||
* permissionHandler.handleReturnFromSettings()
|
||||
* }
|
||||
*
|
||||
* // 权限回调处理
|
||||
* private fun onPermissionResult(result: PermissionResult) {
|
||||
* when(result) {
|
||||
* PermissionResult.GRANTED -> showNotification()
|
||||
* PermissionResult.DENIED -> showRationale()
|
||||
* PermissionResult.NEEDS_SETTINGS -> showSettingsGuide()
|
||||
* PermissionResult.NOT_NEEDED -> showNotification()
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
class NotificationPermissionHandler(
|
||||
private val context: Context,
|
||||
private val callback: (PermissionResult) -> Unit
|
||||
) {
|
||||
// Android 13+ 通知权限请求启动器
|
||||
private var permissionLauncher: ActivityResultLauncher<String>? = null
|
||||
|
||||
// 请求状态跟踪
|
||||
private var permissionRequestPending = false
|
||||
private var lastPermissionState = false
|
||||
|
||||
// 用于跟踪从设置页面返回的状态
|
||||
private var returnFromSettings = false
|
||||
|
||||
init {
|
||||
registerPermissionLauncherIfNeeded()
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否需要请求通知权限
|
||||
*/
|
||||
fun shouldRequestNotificationPermission(): Boolean {
|
||||
return !areNotificationsEnabled()
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查通知权限是否已授予
|
||||
*/
|
||||
fun areNotificationsEnabled(): Boolean {
|
||||
return when {
|
||||
// Android 13+ (TIRAMISU) 需要运行时权限
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> {
|
||||
ContextCompat.checkSelfPermission(
|
||||
context,
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
// Android 8.0+ (Oreo) 检查通知设置
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
|
||||
NotificationManagerCompat.from(context).areNotificationsEnabled()
|
||||
}
|
||||
// Android 7.1 及以下不需要特别权限
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求通知权限
|
||||
*/
|
||||
fun requestNotificationPermission() {
|
||||
// 保存当前权限状态,用于比较设置后是否发生变化
|
||||
lastPermissionState = areNotificationsEnabled()
|
||||
|
||||
when {
|
||||
// Android 13+ - 使用运行时权限请求
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> {
|
||||
requestPermissionApi33()
|
||||
}
|
||||
// Android 8.0-12 - 跳转到应用通知设置
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
|
||||
openNotificationSettings()
|
||||
permissionRequestPending = true
|
||||
}
|
||||
// Android 7.1 及以下 - 默认启用
|
||||
else -> {
|
||||
callback(PermissionResult.NOT_NEEDED)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理从设置页面返回的情况
|
||||
* 应在Activity的onResume中调用
|
||||
*/
|
||||
fun handleReturnFromSettings() {
|
||||
if (returnFromSettings) {
|
||||
returnFromSettings = false
|
||||
checkSettingsChanged()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开应用的通知设置页面
|
||||
*/
|
||||
fun openNotificationSettings() {
|
||||
val intent = when {
|
||||
// Android 8.0及以上
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
|
||||
Intent().apply {
|
||||
action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
|
||||
putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
|
||||
|
||||
// 处理特定设备需要额外设置的情况
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||
putExtra(Settings.EXTRA_CHANNEL_ID, context.applicationInfo.uid)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Android 7.1及以下
|
||||
else -> {
|
||||
Intent().apply {
|
||||
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||
addCategory(Intent.CATEGORY_DEFAULT)
|
||||
data = Uri.parse("package:${context.packageName}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (context is AppCompatActivity) {
|
||||
returnFromSettings = true
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示权限解释对话框
|
||||
*/
|
||||
fun showPermissionRationaleDialog() {
|
||||
if (context !is AppCompatActivity) return
|
||||
|
||||
val activity = context as AppCompatActivity
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle("需要通知权限")
|
||||
.setMessage("我们需要通知权限来向你发送重要信息、更新提醒等内容。请允许通知权限以使用完整功能。")
|
||||
.setPositiveButton("确定") { _, _ ->
|
||||
requestNotificationPermission()
|
||||
}
|
||||
.setNegativeButton("取消", null)
|
||||
.show()
|
||||
}
|
||||
|
||||
// 私有方法 --------------------------------------------
|
||||
|
||||
/**
|
||||
* Android 13+ 权限请求处理
|
||||
*/
|
||||
@RequiresApi(33)
|
||||
private fun requestPermissionApi33() {
|
||||
if (permissionLauncher == null) {
|
||||
throw IllegalStateException("Permission launcher not registered. Call registerPermissionLauncherIfNeeded() first.")
|
||||
}
|
||||
|
||||
val activity = context as? AppCompatActivity ?: return
|
||||
|
||||
when {
|
||||
// 已经拥有权限
|
||||
areNotificationsEnabled() -> {
|
||||
callback(PermissionResult.GRANTED)
|
||||
}
|
||||
// 需要显示权限解释
|
||||
ActivityCompat.shouldShowRequestPermissionRationale(
|
||||
activity,
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
) -> {
|
||||
showPermissionRationaleDialog()
|
||||
}
|
||||
// 请求权限
|
||||
else -> {
|
||||
permissionRequestPending = true
|
||||
permissionLauncher?.launch(Manifest.permission.POST_NOTIFICATIONS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册权限启动器(仅Android 13+需要)
|
||||
*/
|
||||
private fun registerPermissionLauncherIfNeeded() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return
|
||||
if (context !is AppCompatActivity) return
|
||||
|
||||
val activity = context as AppCompatActivity
|
||||
|
||||
permissionLauncher = activity.registerForActivityResult(
|
||||
ActivityResultContracts.RequestPermission()
|
||||
) { isGranted ->
|
||||
if (isGranted) {
|
||||
callback(PermissionResult.GRANTED)
|
||||
} else {
|
||||
// 如果用户勾选了"不再询问"
|
||||
if (!ActivityCompat.shouldShowRequestPermissionRationale(
|
||||
activity,
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
)) {
|
||||
callback(PermissionResult.NEEDS_SETTINGS)
|
||||
} else {
|
||||
callback(PermissionResult.DENIED)
|
||||
}
|
||||
}
|
||||
permissionRequestPending = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查设置页面返回后的权限变化
|
||||
*/
|
||||
private fun checkSettingsChanged() {
|
||||
if (!permissionRequestPending) return
|
||||
|
||||
permissionRequestPending = false
|
||||
|
||||
val currentState = areNotificationsEnabled()
|
||||
when {
|
||||
currentState -> callback(PermissionResult.GRANTED)
|
||||
currentState != lastPermissionState -> callback(PermissionResult.DENIED)
|
||||
// 状态未改变
|
||||
else -> Unit // 无操作
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限请求结果枚举
|
||||
*/
|
||||
enum class PermissionResult {
|
||||
GRANTED, // 权限已授予
|
||||
DENIED, // 权限被拒绝
|
||||
NEEDS_SETTINGS, // 需要跳转到设置
|
||||
NOT_NEEDED // 不需要权限(Android 7.1及以下)
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* 快速检查当前设备的通知权限状态
|
||||
*/
|
||||
@JvmStatic
|
||||
fun checkPermissionState(context: Context): PermissionResult {
|
||||
return when {
|
||||
// Android 13+ 需要运行时权限
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> {
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
context,
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
) == PackageManager.PERMISSION_GRANTED) {
|
||||
PermissionResult.GRANTED
|
||||
} else {
|
||||
PermissionResult.DENIED
|
||||
}
|
||||
}
|
||||
// Android 8.0+ 检查通知设置
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
|
||||
if (NotificationManagerCompat.from(context).areNotificationsEnabled()) {
|
||||
PermissionResult.GRANTED
|
||||
} else {
|
||||
PermissionResult.NEEDS_SETTINGS
|
||||
}
|
||||
}
|
||||
// Android 7.1 及以下默认启用通知
|
||||
else -> PermissionResult.NOT_NEEDED
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -696,7 +696,7 @@ object Util {
|
|||
val valid = false
|
||||
println("IOSTQ:execReloginTask->url:$url?$params")
|
||||
try {
|
||||
val result: String? = MyPost.postData(" ".toByteArray(charset("utf-8")),
|
||||
val result: String? = MyPost.postData(" ".toByteArray(charset = Charsets.UTF_8),
|
||||
"$url?$params"
|
||||
)
|
||||
|
||||
|
@ -748,7 +748,7 @@ object Util {
|
|||
// boolean valid = false;
|
||||
printStr("IOSTQ:request result : $url?$params")
|
||||
try {
|
||||
val result: String? = MyPost.postData(" ".toByteArray(charset("utf-8")),
|
||||
val result: String? = MyPost.postData(" ".toByteArray(charset = Charsets.UTF_8),
|
||||
"$url?$params"
|
||||
)
|
||||
|
||||
|
@ -2394,7 +2394,7 @@ object Util {
|
|||
// Log.i(TAG, "setFinish");
|
||||
|
||||
MonitorService.setRunning(false)
|
||||
killRecordProcess(context, "com.tunnelworkshop.postern")
|
||||
// killRecordProcess(context, "com.tunnelworkshop.postern")
|
||||
killRecordProcess(context, AUTO_JSPACKAGENAME)
|
||||
Handler(Looper.getMainLooper()).postDelayed(Runnable {
|
||||
MonitorService.onEvent(
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<certificates src="user" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">127.0.0.1</domain>
|
||||
</domain-config>
|
||||
</network-security-config>
|
Loading…
Reference in New Issue