最新动态
Android爬取第三方app推送消息
2024-12-21 18:09

该篇文章是在公司的一个特别奇葩的需求之下产生的,我们公司的产品需要监听一些新闻app的推送消息,从而进行自己的消息推送。作为一个Android Coder第一反应就是直接用NotificationListenerService进行推送监听不就完了嘛,So Easy。说干就干,百度示例代码,ctrl c+ctrl v一气呵成,run!这不就拿到了吗。然后屁颠的去找产品经理了。产品经理看完头都不抬的说我要的是推送携带的详细参数,不是简单的title 和content这种文字信息。我的天,这个时候我在开始细细琢磨这个需求,这个需求的本质就是获取第三方app通知栏通知中写的详细参数——再直白点就是获取第三方App的通知栏通知携带的Intent。有点方啊,坦白说这种需求不用动脑子都知道Android肯定不会给你这个权限的,要是谁都能随便拿到那那行啊。但是说归说还是要尝试一下。我们都知道Notification所携带的参数都是由Intent封装的所以找到这个Intent就行,而在生成Notification时Intent有封装进了PendingIntent里面,而这个PendingIntent是我们通过NotificationListenerService可以获取道的。所以基本思路就出来了通过PendingIntent获取Intent进而获取Intent携带的参数。
好了,废话不多说,下面进入正文,文章主要会讲到以下几个问题

  • 利用NotificationListenerService监听获取第三App的Notification

  • 获取Notification中的Intent

  • 获取第三方App Intent携带的信息

  • 解析第三方App的Serializable对象

  • 解析第三方App的Parcelable对象


这个知识点其实网上有很多教程的无非就是自己写一个Service继承NotificationListenerService,之后就可以重写NotificationListenerService的相关方法然后从中获取到第三方App的通知,这个点是比较简单的稍微贴一下代码就好不再详细说了,如果有什么问题请出门google

Android爬取第三方app推送消息


这是一个service,只要startService一下,然后在系统中给与相应权限就可以了,这里不再细
表。其中sbn.getNotification().extras这个api获取的只是通知携带的参数,如title,textContent等,和咱们要获取的不是一回事,这里说明一下。

从这开始就是比较重要的点了,通过常规的方法肯定是获取不到PendingIntent里边携带的Intent的,第一个思路就是从源码入手看看Android是如何在从通知跳转到activity时利用PendingIntent获取到Intent的。然后照葫芦画瓢做。好吧说干就干。由于涉及到Intent以及打开activity那么肯定会涉及到AMS。Android studio看AMS的源码有点力不从心啊,在这推荐一个Android在线源码地址
好吧,现在就开始看源码,从PendingIntent和Intent产生关联的地方开始看吧。


跟着方法找下去,发现其实是AMS处理的。


我们接着看AMS的源码
懒得翻源码了,经过我用百度一番google之后,发现答案其实就在PendingIntent里边,PendingIntent有个API getIntent()


获取的就是PendingIntent携带的Intent,简单不,就是这么Easy。
由于打了hide的注解,是不能直接调用的,但是反射处理一下就可以了。处理完之后run起来发现这个api需要系统级的权限。想想也是只有系统才能这么随便的去窥探别人家App的数据。怎么给应用加系统级的权限有两种办法

  • 自己做个ROM把自己的应用打包进去成为系统App
  • 把手机root,然后把自己的App放在系统App的目录下

难易程度上来讲当然是第二个比较简单,而且有专门的工具,条件只是手机root。这里不再展开细说,因为这篇文章不是主要来讲这个问题的。
好了,现在按着以上说的

  1. 利用NotificationListenerService获取到想要劫持的通知的PenddingIntent
  2. 利用反射调用隐藏API获取Intent对象
  3. 将自己的应用打包,通过相应方式刷成系统App
  4. 运行,当你监听的App推送一条通知时,在你的代码里应该就能获取这个通知的Intent了。

OK,现在可能有的童靴会说了 Intent都拿到了,还有啥难得。
naiveヽ(ー_ー)ノ下面才正式开始本篇文章干货。

回想一下,大家平时获取Intent携带的信息都是怎么做的


看起来平平无奇,其实这其中是有个隐藏条件的,你要获取一个intent携带的信息,一个必要条件就是你得知道存储这个信息的key值,就是对于第三方App的Intent来说,咱们对他内部的数据信息是一无所知的,所以这就带来了第一问题:如何在不知道key的情况下获取intent内部的数据。
遇到这种问题,第一个思路就是考虑intent数据结构。根据API可以知道intent里边的数据是以键值对的形式进行存储的,方式类似HashMap。HashMap的数据其实存放在内部的哈希表中的,本质就是一个元素为链表的数组,即使咱们不知道key值,直接对这个链表数组进行遍历也是可以拿到HashMap里边所有信息的。Intent同理,我虽然不知道key,但是只要找到内部存储的数据,然后遍历一遍也可以拿到我想要的所有信息。
查看Intent 获取数据的源码


接着看Bundle的getString


其实跟我们想的差不多,Intent的所有数据都是放在Intent内部的mExtras(Bundle)字段的mMap(ArrayMap<String, Object>)字段中。我们只要拿到mMap,遍历然后就可以了。unparcel方法是用来从native层读取数据用来填充mMap用的。
看到这大致的思路其实就有了,先获取Intent的mExtras对象,然后调用mExtras的 unparcel()方法,填充值后,直接遍历mMap,就可以拿到Intent携带的所有信息了。
这两个字段都没办法直接拿到,只能用反射,代码还是比较简单的


到这写个demo赶紧跑一下:起一个应用发一个通知然后用上边的代码,自己监听自己。一气呵成,赶紧run起来。
App A发出一个通知,App B果真正确解析了A的通知中携带的参数。









你以为这就完了?
too young!
当年我也是这么想的,当时我们业务上需要检测二十来个App。App装上之后需要等待被检测App发出通知,所以不能实时观测结果。结果第二天来查看收集结果的日志,发现一堆报错

    以上就是本篇文章【Android爬取第三方app推送消息】的全部内容了,欢迎阅览 ! 文章地址:https://sicmodule.kub2b.com/quote/10124.html 
     栏目首页      相关文章      动态      同类文章      热门文章      网站地图      返回首页 企库往资讯移动站https://sicmodule.kub2b.com/mobile/,查看更多   
发表评论
0评