安卓游戏推广联盟(安卓游戏推广)

时间:2023-11-14 07:41:13 来源:互联网 编辑:孤僻成性

如何在Android开发中实现跳过开屏广告功能

一个没联网也没盈利的应用开屏广告跳过APP的开发者,收到了 "南山必胜客" 发的律师函,说他的APP可用于屏蔽、过滤XX浏览器的广告服务,构成不正当竞争,并最终导致 "用户福祉的减损"。

2333,原来看广告是用户福祉...

除李跳跳外,其它几款比较有名的同类型APP也不约而同也收到律师函,如:叮小跳、大圣净化、轻启动等。

了解李跳跳的应该都知道,它被搞不是一天两天了,之前就经历过酷安下架和国产手机系统安装报毒:

从酷安小编的一席话不难看出被搞的本质原因:

断人财路,毕竟开屏广告已经成为许多App的主要变现手段,据央视财经频道报道,某些手机App通过开屏弹窗广告获得的收益,占其总广告收入高达80%。影响力大,阅读量10w+,8.2w+点赞,用户量不得有个几十万?

所以,被搞是情理之中,即便南山必胜客不站出来,也会有其它利益受损方站出来,只是迟早的问题~

还记得不久前的多多提权坚强用户事件吗?Google Play 以 "恶意软件" 为由将其下架,并向已下载该APP的用户发出警告,提醒卸载。反观国内,屁事没有,很多人甚至不知道这件事。

所以,这种大环境下的为众人报薪者,必冻毙于风雪。综上,李跳跳停更是无奈之举,感谢开发者一直用爱发电默默更新。

虽然停更,但是还是能搜索下载到APP的,鱼龙混杂,各位读者下载安装时注意甄别!!!比如这种恶心盗版:

当然,也可以尝试其它平替,如果觉得代码闭源不放心,可在Github搜下关键字 "广告跳过" 。

也可以在了解完跳过原理后,自己动手写一个,不过还请切记 "闷声发大财"~

/ 跳过广告原理 /

Android中的广告跳过原理有两派:

利用手机系统提供的威屁恩接口实现本地代理,接管应用的网络请求,配合对应的拦截规则(DNS、主机域名) 来实现广告拦截。利用Android AccessibilityService无障碍服务来识别广告跳过按钮,然后模拟点击,一般针对App开屏广告,国内绝大部分广告跳过APP都是这种。

/ 简单七步实现开屏广告跳过 /

第一种方案自己实现的成本比较高,直接介绍下有哪些软件支持,按需安装即可:

AdGuard:支持APP中的广告拦截、自定义规则和过滤器,完整功能要钱,3台设备一年40+。Adblock:支持浏览器浏览网页时的广告屏蔽。不过很多浏览器都内置了广告屏蔽功能,而且能直接订阅第三方规则,如Via、X浏览器等。甚至笔者用的IDM+自带浏览器都有这个功能:

如果确实有兴趣想自己折腾,可以参考下这两个开源库:

AdAwayNetBare-Android

第二种方案就非常简单了,完全可以自己写一个耍耍。

实现跳过开屏广告的核心点就三步:关注Event → 查找结点 → 点击结点,创建一个新的Android项目后,直接开整~

自定义AccessibilityService

class ADGunService : AccessibilityService() { companion object { var instance: ADGunService? = null // 单例 val isServiceEnable: Boolean get() = instance != null // 判断无障碍服务是否可用 } override fun onAccessibilityEvent(event: AccessibilityEvent?) { event?.let { // 在这里写跳过广告的逻辑 log.d(TAG, "$it") } } override fun onInterrupt() {} override fun onServiceConnected() { super.onServiceConnected() instance = this } override fun onDestroy() { super.onDestroy() instance = null }}

在res/xml目录下新建服务配置文件

ad_gun_service_config.xml

<?xml version="1.0" encoding="utf-8"?><accessibility-service xmlns:android="http://schemas.android/apk/res/android" android:description="@string/accessibility_description" android:accessibilityEventTypes="typeAllMask" android:canPerformGestures="true" android:accessibilityFeedbackType="feedbackSpoken" android:canRetrieveWindowContent="true" android:accessibilityFlags="flagRetrieveInteractiveWindows" android:notificationTimeout="1000"/>

AndroidManifest.xml中对服务进行声明

<service android:name=".ADGunService" android:exported="false" android:label="AD 滚犊子!!!" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/ad_gun_service_config" /></service>

写个简单的页面xml

显示服务开启状态的文本和一个去开启的按钮(activity_main.xml)。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <androidxcompat.widget.AppCompatTextView android:id="@+id/tv_service_status" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="跳过广告服务状态:" /> <androidxcompat.widget.AppCompatButton android:id="@+id/bt_open_service" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="去开启" /></LinearLayout>

控件绑定并设置UI和点击事件

加个设置无障碍服务的状态UI的方法,一个点击跳转无障碍服务设置页(MainActivity.kt)

class MainActivity : AppCompatActivity() { private lateinit var mServiceStatusTv: TextView private lateinit var mToOpenBt: Button override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(Ryout.activity_main) mServiceStatusTv = findViewById(R.id_service_status) mToOpenBt = findViewById<Button>(R.id.bt_open_service)ly { setOnClickListener { jumpAccessibilityServiceSettings() } } } override fun onResume() { super.onResume() refreshServiceStatusUI() } /** * 刷新无障碍服务状态的UI * */ private fun refreshServiceStatusUI() { if (ADGunService.isServiceEnable) { mServiceStatusTv.text = "跳过广告服务状态:已开启" mToOpenBt.visibility = View.GONE } else { mServiceStatusTv.text = "跳过广告服务状态:未开启" mToOpenBt.visibility = View.VISIBLE } }}

运行后,点击去开启按钮,如下图依次开启无障碍服务

此时打开其它APP,可以看到Logcat输出的Event信息:

查找跳过广告结点

得益于市场监管总局修订发布的《互联网广告管理办法》。

查找跳过广告结点变得容易多了,想当年,假按钮,极小点击区域等骗点击的伎俩层出不穷。这里只需要遍历页面结点,查找包含"跳过"的结点即可~

/** * 获得当前视图根节点 * */private fun getCurrentRootNode() = try { rootInActiveWindow} catch (e: Exception) { essage?.let { Log.e(TAG, it) } null}override fun onAccessibilityEvent(event: AccessibilityEvent?) { event?.let { // 如果查找包含跳过按钮的结点列表不为空,取第一个,然后输出 getCurrentRootNode()?.findAccessibilityNodeInfosByText("跳过").takeUnless { it.isNullOrEmpty() }?.get(0)?.let { logD("检测到跳过广告结点:$it") } }}

运行后随便打开一个有开屏广告的APP,可以看到控制台输出的结点信息:

点击跳过广告结点

有《互联网广告管理办法》这份文件在,大部分APP应该不会知法犯法,结点一般是支持直接点击的:

所以直接performAction()触发结点点击:

运行看看跳过效果:

牛批,有些广告还没看清直接就跳过了,我们通过简单七步就快速实现了一个广告跳过APP。

当然,要投入真正使用还得完善一些细节,比如前台服务保活,引入线程池/协程解析结点避免堵塞主线程,监听特定Event提高结点查找效率等 , 本文只是抛砖引玉,对Android自动化感兴趣的童鞋,可以移步至《杰哥带你玩转Android自动化》自行学习~

补充:自定义规则过滤

除了开屏广告外,还有一种很烦人的弹窗:

跳过广告类APP里的自定义规则过滤就是针对这种,这种规则只能靠人力来堆,众人拾柴火焰高,找到一个比较全的:LiTiaotiao-Custom-Rules,直接复制全部规则的json保存到res/raw文件夹下,截取其中一段:

{ "-1606001344": "{"popup_rules":[{"id":"playing_tv_redeem_title","action":"playing_ic_close"}]}"},

不难发现结构规则,id → 匹配结点的id或文本,action → 点击结点的id或文本,key值是随机变化的字符串,直接使用Java自带抠脚Json来解析,先定义两个实体类存数据:

data class RuleEntity( val popupRules: ArrayList<RuleDetail>)data class RuleDetail( val id: String, val action: String)

接着整个线程池用来读取解析Json文件,以及解析结点,耗时操作避免堵塞主线程~

var executor: ExecutorService = Executors.newFixedThreadPool(4) // 执行任务的线程池

接着编写解析json文件的方法,返回规则列表:

/** * 读取json文件生成规则实体列表 * */private fun readJsonToRuleList(): List<RuleEntity>? { try { val inputStream = resources.openRawResource(R.raw.custom_rules) val reader = BufferedReader(InputStreamReader(inputStream)) val sb = StringBuilder() readere { var line: String? = it.readLine() while (line != null) { sbend(line) line = it.readLine() } } val ruleEntityList = arrayListOf<RuleEntity>() val jsonArray = JSONArray(sb.toString()) for (i in 0 until jsonArray.length()) { val jsonObject = jsonArray.getJSONObject(i) val keys = jsonObject.keys() while (keys.hasNext()) { val key = keys.next() val value = jsonObject.getString(key) val ruleEntityJson = JSONObject(value) val popupRules = ruleEntityJson.getJSONArray("popup_rules") val ruleEntity = RuleEntity(arrayListOf()) for (j in 0 until popupRules.length()) { val ruleObject = popupRules.getJSONObject(j) val ruleDetail = RuleDetail(ruleObject.getString("id"), ruleObject.getString("action")) ruleEntity.popupRules.add(ruleDetail) } ruleEntityList.add(ruleEntity) } } return ruleEntityList } catch (e: IOException) { e.printStackTrace() } catch (e: JSONException) { e.printStackTrace() } return null}

接着在onServiceConnected()时调用此方法,即无障碍服务启动时读取初始化:

override fun onServiceConnected() { super.onServiceConnected() executor.execute { ruleList = readJsonToRuleList() ruleList?.forEach { logD("$it") } logD("自定义规则列表已加载...") } instance = this}

运行后可以看到规则列表已加载:

接着编写匹配文字和id结点的方法:

/** * 递归遍历查找匹配文本或id结点 * 结点id的构造规则:包名:id/具体id * */private fun searchNode(filter: String): AccessibilityNodeInfo? { val rootNode = getCurrentRootNode() if (rootNode != null) { rootNode.findAccessibilityNodeInfosByText(filter).takeUnless { it.isNullOrEmpty() }?.let { return it[0] } if (!rootNode.packageName.isNullOrBlank()) { rootNode.findAccessibilityNodeInfosByViewId("${rootNode.packageName}:id/$filter") .takeUnless { it.isNullOrEmpty() }?.let { return it[0] } } } return null}

接着在onAccessibilityEvent()遍历自定义规则列表,批量调用。

override fun onAccessibilityEvent(event: AccessibilityEvent?) { event?.let { executor.execute { searchNode("跳过")?.performAction(AccessibilityNodeInfo.ACTION_CLICK) ruleList?.forEach { it.popupRules.forEach { rule -> // 如果定位到匹配结点,查找要点击的结点并点击 if (searchNode(rule.id) != null) searchNode(rule.action)?.performAction(AccessibilityNodeInfo.ACTION_CLICK) } } } }}

接着可以找 LiTiaotiao-Custom-Rules 提到APP去验证,反正笔者试了下网易云的更新弹窗能够自动点击关闭~

手游代理的一些赚钱门道,以及它们的靠谱程度

手游代理是一种非常有前景的赚钱项目,但是要想赚到钱,靠自己摸索有点云里雾里,以下是手游代理的一些赚钱门道,以及它们的靠谱程度:

1. 游戏销售收入

游戏销售收入是手游代理最主要的赚钱方式之一。代理商可以通过与游戏联运平台或发行商签订协议,获得游戏的独家代理权,负责在指定地区或市场推广和运营游戏,并从中获取销售收入。

2. 广告收入

广告收入是手游代理的另一种赚钱方式。代理商可以通过在游戏中投放广告,获得广告收入。

3. 虚拟物品销售

虚拟物品销售是手游代理的另一种赚钱方式。代理商可以通过在游戏中销售虚拟物品,如游戏道具、装备等,获得销售收入。

4. 代理游戏直播

代理游戏直播是手游代理的一种新型赚钱方式。代理商可以与游戏直播平台合作,招募适合的主播,进行游戏直播,并从中获取广告收入和礼物收入。

总的来说,手游代理有很多赚钱门道,但是要想赚到钱,需要代理商具备一定的市场分析和推广能力,以及与游戏开发商或发行商、广告商、游戏直播平台和主播等建立良好的合作关系。只有在这些条件都具备的情况下,手游代理才是一种比较靠谱的赚钱方式。

声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送至邮件举报,一经查实,本站将立刻删除。转载务必注明出处:http://www.hixs.net/article/20231114/169625420082476.html