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.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"
|
||||||
|
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" />
|
||||||
|
@ -41,6 +43,7 @@
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
|
@ -117,8 +120,6 @@
|
||||||
android:name="android.accessibilityservice"
|
android:name="android.accessibilityservice"
|
||||||
android:resource="@xml/accessibility_service_config" />
|
android:resource="@xml/accessibility_service_config" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<receiver android:name="com.android.grape.receiver.ScriptReceiver" />
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -13,18 +13,24 @@ import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
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 androidx.lifecycle.lifecycleScope
|
||||||
import com.android.grape.databinding.ActivityMainBinding
|
import com.android.grape.databinding.ActivityMainBinding
|
||||||
import com.android.grape.job.MonitorService
|
import com.android.grape.job.MonitorService
|
||||||
import com.android.grape.receiver.ScriptReceiver
|
import com.android.grape.receiver.ScriptReceiver
|
||||||
import com.android.grape.util.ClashUtil
|
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.android.grape.util.StoragePermissionHelper
|
||||||
import com.blankj.utilcode.util.LogUtils
|
import com.blankj.utilcode.util.LogUtils
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
private val viewModel by viewModels<MainViewModel>()
|
private val viewModel by viewModels<MainViewModel>()
|
||||||
private lateinit var viewBinding: ActivityMainBinding
|
private lateinit var viewBinding: ActivityMainBinding
|
||||||
private var intentFilter: IntentFilter? = null
|
private var intentFilter: IntentFilter? = null
|
||||||
private var scriptReceiver: ScriptReceiver? = null
|
private var scriptReceiver: ScriptReceiver? = null
|
||||||
|
private lateinit var permissionHandler: NotificationPermissionHandler
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
|
@ -39,15 +45,14 @@ class MainActivity : AppCompatActivity() {
|
||||||
registerReceiver()
|
registerReceiver()
|
||||||
viewBinding.start.setOnClickListener {
|
viewBinding.start.setOnClickListener {
|
||||||
try {
|
try {
|
||||||
ClashUtil.startProxy(this) // 在主线程中调用
|
ClashUtil.startProxy(this)
|
||||||
ClashUtil.switchProxyGroup("GLOBAL", "us", "http://127.0.0.1:6170")
|
ClashUtil.switchProxyGroup(
|
||||||
} catch (e: Exception) {
|
"GLOBAL",
|
||||||
LogUtils.log(
|
ClashUtil.getRandomLocale(),
|
||||||
Log.ERROR,
|
"http://127.0.0.1:6170"
|
||||||
"MainActivity",
|
|
||||||
"startProxyVpn: Failed to start VPN",
|
|
||||||
e
|
|
||||||
)
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
LogUtils.e("startProxyVpn: Failed to start VPN", e)
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this,
|
this,
|
||||||
"Failed to start VPN: " + (if (e.message != null) e.message else "Unknown error"),
|
"Failed to start VPN: " + (if (e.message != null) e.message else "Unknown error"),
|
||||||
|
@ -77,7 +82,11 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPermission() {
|
private fun checkPermission() {
|
||||||
viewModel.checkAccessibilityService()
|
permissionHandler = NotificationPermissionHandler(this) { result ->
|
||||||
|
handlePermissionResult(result)
|
||||||
|
}
|
||||||
|
checkNotificationPermission()
|
||||||
|
|
||||||
StoragePermissionHelper.requestFullStoragePermission(
|
StoragePermissionHelper.requestFullStoragePermission(
|
||||||
activity = this,
|
activity = this,
|
||||||
onGranted = { performFileOperation() },
|
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() {
|
private fun performFileOperation() {
|
||||||
// 执行文件读写操作
|
// 执行文件读写操作
|
||||||
// Toast.makeText(this, "文件访问权限已授予", Toast.LENGTH_SHORT).show()
|
// Toast.makeText(this, "文件访问权限已授予", Toast.LENGTH_SHORT).show()
|
||||||
MonitorService.onEvent(this)
|
// MonitorService.onEvent(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showPermissionDeniedDialog() {
|
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.content.Intent
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.app.JobIntentService
|
import androidx.core.app.JobIntentService
|
||||||
|
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
|
||||||
import com.android.grape.util.Util
|
import com.android.grape.util.Util
|
||||||
|
@ -28,13 +29,15 @@ class OpenAppService : JobIntentService() {
|
||||||
Util.doScript(this, Util.AUTO_JSPACKAGENAME) //autojs
|
Util.doScript(this, Util.AUTO_JSPACKAGENAME) //autojs
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (Util.isNeedRestored) {
|
//todo fix 改机流程
|
||||||
Log.d("IOSTQ:", "执行留存任务")
|
// if (Util.isNeedRestored) {
|
||||||
Util.setRrInfo(this)
|
// Log.d("IOSTQ:", "执行留存任务")
|
||||||
} else {
|
// Util.setRrInfo(this)
|
||||||
Log.d("IOSTQ:", "执行新装任务")
|
// } else {
|
||||||
Util.setInfo(this)
|
// Log.d("IOSTQ:", "执行新装任务")
|
||||||
}
|
// Util.setInfo(this)
|
||||||
|
// }
|
||||||
|
ChangeDeviceInfoUtil.changeDeviceInfo()
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,329 +3,150 @@ package com.android.grape.util
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.android.grape.data.AfInfo
|
import com.android.grape.MainApplication
|
||||||
import com.android.grape.data.BigoInfo
|
import com.android.grape.data.Device
|
||||||
import com.android.grape.data.DeviceInfo
|
import com.android.grape.util.Util.paramsJson
|
||||||
import com.blankj.utilcode.util.LogUtils
|
import com.blankj.utilcode.util.LogUtils
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.lang.reflect.InvocationTargetException
|
import java.lang.reflect.InvocationTargetException
|
||||||
|
|
||||||
object ChangeDeviceInfoUtil {
|
object ChangeDeviceInfoUtil {
|
||||||
fun changeDeviceInfo(
|
fun changeDeviceInfo(
|
||||||
current_pkg_name: String,
|
|
||||||
context: Context?,
|
|
||||||
bigoDeviceObject: JSONObject?,
|
|
||||||
afDeviceObject: JSONObject?
|
|
||||||
) {
|
) {
|
||||||
var bigoDeviceObject = bigoDeviceObject
|
|
||||||
var afDeviceObject = afDeviceObject
|
|
||||||
try {
|
try {
|
||||||
val bigoDevice: BigoInfo
|
val deviceObject = paramsJson?.getJSONObject("device")
|
||||||
if (bigoDeviceObject != null) {
|
if (deviceObject == null) {
|
||||||
// BIGO
|
LogUtils.d("ERROR", "ChangeDeviceInfoUtil", "device is null")
|
||||||
val cpuClockSpeed = bigoDeviceObject.optString("cpu_clock_speed")
|
return
|
||||||
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 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
|
vcloudsettingsPut("$currentPkgName.advertiserId", device.advertiserId, context)
|
||||||
val afDevice: AfInfo
|
vcloudsettingsPut("$currentPkgName.brand", device.brand, context)
|
||||||
if (afDeviceObject != null) {
|
vcloudsettingsPut("$currentPkgName.android_id", device.androidId, context)
|
||||||
val advertiserId = afDeviceObject.optString(".advertiserId")
|
vcloudsettingsPut("$currentPkgName.lang", device.lang, context)
|
||||||
val model = afDeviceObject.optString(".model")
|
vcloudsettingsPut("$currentPkgName.country", device.country, context)
|
||||||
val brand = afDeviceObject.optString(".brand")
|
vcloudsettingsPut(
|
||||||
val androidId = afDeviceObject.optString(".android_id")
|
"$currentPkgName.batteryLevel",
|
||||||
val xPixels = afDeviceObject.optInt(".deviceData.dim.x_px")
|
device.batteryLevel.toString(), context
|
||||||
val yPixels = afDeviceObject.optInt(".deviceData.dim.y_px")
|
)
|
||||||
val densityDpi = afDeviceObject.optInt(".deviceData.dim.d_dpi")
|
// callVCloudSettings_put(
|
||||||
val country = afDeviceObject.optString(".country")
|
// currentPkgName + "_screen.optMetrics.stack",
|
||||||
val batteryLevel = afDeviceObject.optString(".batteryLevel")
|
// stackInfo,
|
||||||
val stackInfo = Thread.currentThread().stackTrace[2].toString()
|
// context
|
||||||
val product = afDeviceObject.optString(".product")
|
// )
|
||||||
val network = afDeviceObject.optString(".network")
|
vcloudsettingsPut("$currentPkgName.product", device.product, context)
|
||||||
val langCode = afDeviceObject.optString(".lang_code")
|
vcloudsettingsPut("$currentPkgName.network", device.network, context)
|
||||||
val cpuAbi = afDeviceObject.optString(".deviceData.cpu_abi")
|
vcloudsettingsPut("$currentPkgName.cpu_abi", device.cpuAbi, context)
|
||||||
val yDp = afDeviceObject.optLong(".deviceData.dim.ydp")
|
vcloudsettingsPut("$currentPkgName.lang_code", device.langCode, context)
|
||||||
|
// **广告标识符 (advertiserId)** 及 **启用状态**
|
||||||
|
val isAdIdEnabled = true // 默认启用广告 ID
|
||||||
|
vcloudsettingsPut(
|
||||||
|
"$currentPkgName.advertiserIdEnabled",
|
||||||
|
isAdIdEnabled.toString(),
|
||||||
|
context
|
||||||
|
)
|
||||||
|
|
||||||
afDevice = AfInfo()
|
val displayMetrics = JSONObject()
|
||||||
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 lang = afDeviceObject.optString(".lang")
|
displayMetrics.put("widthPixels", device.expand.width)
|
||||||
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", "")
|
|
||||||
|
|
||||||
deviceInfo = DeviceInfo()
|
displayMetrics.put("heightPixels", device.expand.height)
|
||||||
deviceInfo.lang = lang
|
displayMetrics.put("densityDpi", device.expand.dPI)
|
||||||
deviceInfo.roProductBrand = ro_product_brand
|
displayMetrics.put("yDp", device.dim.ydp)
|
||||||
deviceInfo.roProductModel = ro_product_model
|
vcloudsettingsPut(
|
||||||
deviceInfo.roProductManufacturer = ro_product_manufacturer
|
"screen.device.displayMetrics",
|
||||||
deviceInfo.roProductDevice = ro_product_device
|
displayMetrics.toString(),
|
||||||
deviceInfo.roProductName = ro_product_name
|
context
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
val displayMetrics = JSONObject()
|
if (!ShellUtils.hasRootAccess()) {
|
||||||
|
LogUtils.d(
|
||||||
displayMetrics.put("widthPixels", xPixels)
|
"ERROR",
|
||||||
|
"ChangeDeviceInfoUtil",
|
||||||
displayMetrics.put("heightPixels", yPixels)
|
"Root access is required to execute system property changes"
|
||||||
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
|
|
||||||
}
|
}
|
||||||
} 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?) {
|
private fun vcloudsettingsPut(key: String?, value: String?, context: Context) {
|
||||||
if (context == null) {
|
if (key.isNullOrEmpty()) {
|
||||||
LogUtils.e(Log.ERROR, "ChangeDeviceInfoUtil", "Context cannot be null", null)
|
|
||||||
throw IllegalArgumentException("Context cannot be null")
|
|
||||||
}
|
|
||||||
if (key == null || key.isEmpty()) {
|
|
||||||
LogUtils.e(Log.ERROR, "ChangeDeviceInfoUtil", "Key cannot be null or empty", null)
|
LogUtils.e(Log.ERROR, "ChangeDeviceInfoUtil", "Key cannot be null or empty", null)
|
||||||
throw IllegalArgumentException("Key cannot be null or empty")
|
throw IllegalArgumentException("Key cannot be null or empty")
|
||||||
}
|
}
|
||||||
|
@ -350,15 +171,11 @@ object ChangeDeviceInfoUtil {
|
||||||
Log.d("Debug", "putString executed successfully.")
|
Log.d("Debug", "putString executed successfully.")
|
||||||
} catch (e: ClassNotFoundException) {
|
} catch (e: ClassNotFoundException) {
|
||||||
LogUtils.e(
|
LogUtils.e(
|
||||||
Log.WARN,
|
|
||||||
"ChangeDeviceInfoUtil",
|
|
||||||
"Class not found: android.provider.VCloudSettings\$Global. This may not be supported on this device.",
|
"Class not found: android.provider.VCloudSettings\$Global. This may not be supported on this device.",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
} catch (e: NoSuchMethodException) {
|
} catch (e: NoSuchMethodException) {
|
||||||
LogUtils.e(
|
LogUtils.e(
|
||||||
Log.WARN,
|
|
||||||
"ChangeDeviceInfoUtil",
|
|
||||||
"Method not found: android.provider.VCloudSettings\$Global.putString. This may not be supported on this",
|
"Method not found: android.provider.VCloudSettings\$Global.putString. This may not be supported on this",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
|
@ -366,23 +183,17 @@ object ChangeDeviceInfoUtil {
|
||||||
val cause = e.targetException
|
val cause = e.targetException
|
||||||
if (cause is SecurityException) {
|
if (cause is SecurityException) {
|
||||||
LogUtils.e(
|
LogUtils.e(
|
||||||
Log.ERROR,
|
|
||||||
"ChangeDeviceInfoUtil",
|
|
||||||
"Error occurred in changeDeviceInfo",
|
"Error occurred in changeDeviceInfo",
|
||||||
cause
|
cause
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
LogUtils.e(
|
LogUtils.e(
|
||||||
Log.ERROR,
|
|
||||||
"ChangeDeviceInfoUtil",
|
|
||||||
"Error occurred in changeDeviceInfo",
|
"Error occurred in changeDeviceInfo",
|
||||||
cause
|
cause
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
LogUtils.e(
|
LogUtils.e(
|
||||||
Log.ERROR,
|
|
||||||
"ChangeDeviceInfoUtil",
|
|
||||||
"Unexpected error during putString invocation",
|
"Unexpected error during putString invocation",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
|
|
|
@ -77,9 +77,19 @@ object ClashUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unregisterReceiver(context: Context) {
|
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) {
|
fun switchProxyGroup(groupName: String?, proxyName: String?, controllerUrl: String) {
|
||||||
if (groupName == null || groupName.trim { it <= ' ' }
|
if (groupName == null || groupName.trim { it <= ' ' }
|
||||||
.isEmpty() || proxyName == null || proxyName.trim { it <= ' ' }.isEmpty()) {
|
.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
|
val valid = false
|
||||||
println("IOSTQ:execReloginTask->url:$url?$params")
|
println("IOSTQ:execReloginTask->url:$url?$params")
|
||||||
try {
|
try {
|
||||||
val result: String? = MyPost.postData(" ".toByteArray(charset("utf-8")),
|
val result: String? = MyPost.postData(" ".toByteArray(charset = Charsets.UTF_8),
|
||||||
"$url?$params"
|
"$url?$params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -748,7 +748,7 @@ object Util {
|
||||||
// boolean valid = false;
|
// boolean valid = false;
|
||||||
printStr("IOSTQ:request result : $url?$params")
|
printStr("IOSTQ:request result : $url?$params")
|
||||||
try {
|
try {
|
||||||
val result: String? = MyPost.postData(" ".toByteArray(charset("utf-8")),
|
val result: String? = MyPost.postData(" ".toByteArray(charset = Charsets.UTF_8),
|
||||||
"$url?$params"
|
"$url?$params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2394,7 +2394,7 @@ object Util {
|
||||||
// Log.i(TAG, "setFinish");
|
// Log.i(TAG, "setFinish");
|
||||||
|
|
||||||
MonitorService.setRunning(false)
|
MonitorService.setRunning(false)
|
||||||
killRecordProcess(context, "com.tunnelworkshop.postern")
|
// killRecordProcess(context, "com.tunnelworkshop.postern")
|
||||||
killRecordProcess(context, AUTO_JSPACKAGENAME)
|
killRecordProcess(context, AUTO_JSPACKAGENAME)
|
||||||
Handler(Looper.getMainLooper()).postDelayed(Runnable {
|
Handler(Looper.getMainLooper()).postDelayed(Runnable {
|
||||||
MonitorService.onEvent(
|
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