This commit is contained in:
lisonge 2021-11-09 17:53:11 +08:00
parent a458ca2fdf
commit 64e6169321
6 changed files with 110 additions and 50 deletions

View File

@ -15,8 +15,9 @@ jobs:
- uses: actions/checkout@v2
- run: chmod 777 ./gradlew
- run: ./gradlew build
# - name: Archive production artifacts
# uses: actions/upload-artifact@v2
# with:
# name: dist
# path: test.js
- run: ./gradlew assembleDebug
- name: Archive artifacts
uses: actions/upload-artifact@v2
with:
name: build-outputs-apk
path: app/build/outputs/apk

View File

@ -1,3 +1,5 @@
# AdCloser
基于无障碍和自定义匹配规则的广告关闭app
记录递归调用的次数, 根据统计次数考虑是否添加规则长度, 可减少匹配时间

View File

@ -28,10 +28,10 @@ class MainActivity : ComponentActivity() {
LogUtils.d(this)
packageName
}
checkPermission(0)
Shizuku.addRequestPermissionResultListener { requestCode, grantResult ->
LogUtils.d(requestCode, grantResult)
}
// Shizuku.addRequestPermissionResultListener { requestCode, grantResult ->
// LogUtils.d(requestCode, grantResult)
// }
// checkPermission(0)
// Shizuku.bindUserService()
}

View File

@ -7,11 +7,11 @@ data class Rule(
) {
companion object {
val defaultRuleList = listOf<Rule>(
Rule(
"com.zhihu.android",
"com.zhihu.android.mix.activity.ContentMixProfileActivity",
"View[text=查看详情] + View[text=×]"
),
// Rule(
// "com.zhihu.android",
// "com.zhihu.android.mix.activity.ContentMixProfileActivity",
// "View[text=查看详情] + View[text=×]"
// ),
Rule(
"com.zhihu.android",
"com.zhihu.android.mix.activity.ContentMixProfileActivity",
@ -101,14 +101,57 @@ data class Rule(
"tv.danmaku.bili",
"tv.danmaku.bili.ui.video.VideoDetailsActivity",
"ImageView[id=tv.danmaku.bili:id/close]"
)
// TODO NAF node 的父亲节点属性无法查询
,
),
Rule(
"com.duokan.phone.remotecontroller",
"com.xiaomi.mitv.phone.remotecontroller.HoriWidgetMainActivityV2",
"ImageView[id=com.duokan.phone.remotecontroller:id/image_close_banner]"
),
Rule(
"com.tencent.mm",
"com.tencent.mm.plugin.sns.ui.SnsTimeLineUI",
"TextView[id=com.tencent.mm:id/hus][text=选择后将减少该类推荐] + TextView[id=com.tencent.mm:id/hui][text=确认]"
),
Rule(
"com.tencent.mm",
"com.tencent.mm.plugin.sns.ui.SnsTimeLineUI",
"TextView[id=com.tencent.mm:id/hus][text=选择后将减少该类推荐] + FrameLayout[id=com.tencent.mm:id/huj] > ViewGroup[id=com.tencent.mm:id/hul] > TextView[text=直接关闭]"
),
Rule(
"com.tencent.mm",
"com.tencent.mm.plugin.sns.ui.SnsTimeLineUI",
"TextView[id=com.tencent.mm:id/hus][text*=广告] + FrameLayout[id=com.tencent.mm:id/huj] > LinearLayout[id=com.tencent.mm:id/hum] > LinearLayout[id=com.tencent.mm:id/hue] + LinearLayout[id=com.tencent.mm:id/hup]"
),
Rule(
"com.tencent.mm",
"com.tencent.mm.plugin.sns.ui.SnsTimeLineUI",
"LinearLayout[childCount=2] > LinearLayout[id=com.tencent.mm:id/fzb] > TextView[id=com.tencent.mm:id/fzg] + LinearLayout[id=com.tencent.mm:id/fj][childCount=0]"
),
Rule(
"com.baidu.tieba",
"com.baidu.tieba.pb.pb.main.PbActivity",
"TextView[id=com.baidu.tieba:id/head_text] + View[id=com.baidu.tieba:id/uninterested_btn]"
),
Rule(
"com.baidu.tieba",
"com.baidu.tieba.pb.pb.main.PbActivity",
"ImageView[id=com.baidu.tieba:id/coverView] + TextView[id=com.baidu.tieba:id/alaStateView] + TextView[id=com.baidu.tieba:id/descView] + RelativeLayout + ImageView"
),
Rule(
"com.zhihu.android",
"com.zhihu.android.app.ui.activity.MainActivity",
"LinearLayout[id=com.zhihu.android:id/content] > RelativeLayout > TextView[id=com.zhihu.android:id/title][text=不感兴趣]"
),
Rule(
"com.zhihu.android",
"com.zhihu.android.app.ui.activity.MainActivity",
"FrameLayout[id=com.zhihu.android:id/ad_float] >> RecyclerView > FrameLayout > ViewGroup > ViewGroup > FrameLayout > ViewGroup[childCount=1] + ViewGroup[childCount=1] > ImageView"
),
// new rule
Rule(
"com.zhihu.android",
"com.zhihu.android.mix.activity.ContentMixProfileActivity",
"TextView[text*=赞同][text$=评论][text*=·] + TextView[text$=专题精选] + View[text=×]"
)
// Rule(
// "com.coolapk.market",

View File

@ -1,9 +1,6 @@
package li.songe.ad_closer.service
import android.accessibilityservice.AccessibilityService
import android.content.ComponentName
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager.NameNotFoundException
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
import com.blankj.utilcode.util.LogUtils
@ -18,24 +15,23 @@ import li.songe.ad_closer.util.findNodeInfo
*/
class AdCloserService : AccessibilityService() {
private fun getActivityInfo(componentName: ComponentName): ActivityInfo? {
return try {
packageManager.getActivityInfo(componentName, 0)
} catch (e: NameNotFoundException) {
null
}
}
// private fun getActivityInfo(componentName: ComponentName): ActivityInfo? {
// return try {
// packageManager.getActivityInfo(componentName, 0)
// } catch (e: NameNotFoundException) {
// null
// }
// }
private val scope = CoroutineScope(Dispatchers.Default + Job())
// override fun onDestroy() {
// super.onDestroy()
// }
private var currentPackageName: String? = null
// 考虑n种模式
// 默认情况 正常获取 activity class name
// 不使用 activity class name, 直接用 package class name, 会导致 匹配规则 变多
// 借助 shizuku 使用 adb 获取 activity class name
override fun onCreate() {
super.onCreate()
LogUtils.d("onCreate")
}
override fun onServiceConnected() {
super.onServiceConnected()
@ -54,14 +50,22 @@ class AdCloserService : AccessibilityService() {
if (window != null && ruleListMap.containsKey(currentActivityClassName)) {
run loop@{
ruleListMap[currentActivityClassName]!!.forEachIndexed { _, rule ->
val nodeInfo =
findNodeInfo(window, rule.matchUnit, listOf(0))
if (nodeInfo != null) {
LogUtils.dTag("click", rule.rawText)
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK)
nodeInfo.recycle()
return@loop
var nodeInfo = findNodeInfo(window, rule.matchUnit, listOf(0))
var level = 0
while (nodeInfo != null && !nodeInfo.isClickable) {
nodeInfo = nodeInfo.parent
level += 1
}
if (nodeInfo != null) {
nodeInfo.apply {
LogUtils.dTag("click", level, rule.rawText)
performAction(AccessibilityNodeInfo.ACTION_CLICK)
}
} else {
LogUtils.dTag("click", "not isClickable", rule.rawText)
}
return@loop
}
}
}
@ -105,7 +109,12 @@ class AdCloserService : AccessibilityService() {
// 在桌面和应用之间来回切换, 大概率导致识别失败
if (!className.startsWith("android.") && !className.startsWith("androidx.")) {
// className.startsWith(packageName)
currentActivityClassName = className
val rootPackageName = rootInActiveWindow?.packageName?.toString() ?: ""
if ((className == "com.miui.home.launcher.Launcher" && rootPackageName != "com.miui.home")) {
// 上滑手势, 导致 活动名 不属于包名
} else {
currentActivityClassName = className
}
}
}
else -> {
@ -141,7 +150,12 @@ class AdCloserService : AccessibilityService() {
set(value) {
if (field != value) {
field = value
LogUtils.dTag("updateClassName", field, rootInActiveWindow?.packageName)
val packageName = rootInActiveWindow?.packageName
LogUtils.dTag(
"updateClassName",
field,
packageName,
)
}
}

View File

@ -35,8 +35,8 @@ private fun match(
return false
}
val childCount = nodeInfo.childCount
val text:CharSequence? = nodeInfo.text
val id:String? = nodeInfo.viewIdResourceName
val text: CharSequence? = nodeInfo.text
val id: String? = nodeInfo.viewIdResourceName
// 在属性匹配列表不空的情况下, 列表所有项都匹配
if (matchUnit.attributeSelectorList.isNotEmpty()) {
@ -49,7 +49,7 @@ private fun match(
AttributeSelector.Operator.Less -> childCount < it.value.toInt()
AttributeSelector.Operator.More -> childCount > it.value.toInt()
AttributeSelector.Operator.Start -> false
else-> TODO()
else -> TODO()
}
AttributeSelector.Attribute.Id -> {
when (it.operator) {
@ -59,19 +59,19 @@ private fun match(
AttributeSelector.Operator.Less -> false
AttributeSelector.Operator.More -> false
AttributeSelector.Operator.Start -> false
else-> TODO()
else -> TODO()
}
}
AttributeSelector.Attribute.Text -> text!=null &&when (it.operator) {
AttributeSelector.Attribute.Text -> text != null && when (it.operator) {
AttributeSelector.Operator.End -> text.endsWith(it.value)
AttributeSelector.Operator.Equal -> text == it.value
AttributeSelector.Operator.Include -> text.contains(it.value)
AttributeSelector.Operator.Less -> false
AttributeSelector.Operator.More -> false
AttributeSelector.Operator.Start -> text.startsWith(it.value)
else-> TODO()
else -> TODO()
}
else-> TODO()
else -> TODO()
}
}
if (!condition2) {
@ -123,7 +123,7 @@ private fun match(
return false
}
fun findNodeInfo(
fun findNodeInfo(
nodeInfo: AccessibilityNodeInfo?,
matchUnit: MatchUnit,
pathIndexList: List<Int>,