让你监控Android手机的通知栏

2016.6.12更新

最最主要的源码其实就只有下面我提到的这些了,最核心的功能都在上面了,以及可能碰到的坑。

代码已经开源到github,地址:

https://github.com/zhuohui/AndMonitor


原文:


有段时间没写博了,想着还是要写点东西,免得生疏了,正好前段时间做了一个抓取通知栏的功能,期间也走了一些弯路,

通过网上查资料,看Android源码,最终总算解决了监控通知栏的功能。实现的效果如下:

让你监控Android手机的通知栏_第1张图片


不过在使用通知栏监控之前,首先要进行设置,要让手机允许你监控通知栏,毕竟这是很隐私的操作,不然如果没有这个允许动作,那么Android手机也太危险了,

包括聊天信息,短消息都有可能被监控。设置如下:

让你监控Android手机的通知栏_第2张图片

在辅助功能这里,开启NotificationMonitor服务。

接下来来讲一下实现方法:

首先写一个类继承AccessibilityService,AccessibilityService辅助服务,可以看官方介绍:

http://developer.android.com/reference/android/accessibilityservice/AccessibilityService.html

这个服务运行在后台,当有定义的的AccessibilityEvent被触发时,则会进行相应的回调函数,通知栏需要使用到的事件是:

AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED
也就是通知栏状态变化事件。

代码如下:

public class NeNotificationService extends AccessibilityService {

	
	@Override
	public void onAccessibilityEvent(AccessibilityEvent event) {
		
		//判断辅助服务触发的事件是否是通知栏改变事件
	    if (event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) 
	    {
	    	
	    		//获取Parcelable对象
	    		Parcelable data = event.getParcelableData();
	    		
	    		//判断是否是Notification对象
				if (data instanceof Notification) {
				
					Notification notification = (Notification) data;
					
					Intent intent = new Intent();
					intent.putExtra("NotifyData", notification);
					intent.putExtra("packageName", event.getPackageName());
					
					intent.setAction(".NeNotificationService");
				
					//进行处理解析通知栏内容的函数
					MainActivity.notifyReceive((String)event.getPackageName(), notification);
				
	    }else
	    {
	    	
	    }
	    
	}
	
	
	/**
	*Service被启动的时候会调用这个API
	*/
	@Override
	protected void onServiceConnected() {

		//设置关心的事件类型
	    AccessibilityServiceInfo info = new AccessibilityServiceInfo();
	    info.eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED |
				AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | 
				AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
	    info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
	    info.notificationTimeout = 100;//两个相同事件的超时时间间隔
	    setServiceInfo(info);
	}
}

这个服务类在使用之前肯定是要先被启动的,启动可以放在MainActivity的某个按钮点击时:

//在MainActivity.onCreate里初始化
Intent upservice = new Intent(this, NeNotificationService.class); 

//按钮按下时更新或启动服务
accesscStartNo.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				updateServiceStatus(true);
			}
		});

//这里防止多次启动服务,所以先判断服务是否在运行中
private void updateServiceStatus(boolean start)
	{
		boolean bRunning = util.isServiceRunning(this, "com.nis.bcreceiver.NeNotificationService");
		
		//没有Running则启动
		if (start && !bRunning) {
			this.startService(upservice);
		} else if(!start && bRunning) {
			this.stopService(upservice);
		}		
		
	}

//另外需要在AndroidManifest.xml文件中配置

        
            
        
         
    


这样我们基本完成了Notification的监控和抓取,至于如果你想解析出什么数据,就可以处理这个
notification变量。通过多个程序的测试,发现notification里比较有用的就是contentView,这是一个直接显示在

界面上的View,我们只要解析它就可以获取展示的View的标题及文本内容,处理代码如下:

  private void AnalyzeView(RemoteViews remoteView, String packName) {

		try {
			//把RemoteView apply后变成当前可以处理的View
			View v1 = remoteView.apply(this, rootLayout);
		
			//然后就是枚举处理这个View的内容
			EnumGroupViews(v1);
			
			//展示出来
			rootLayout.addView(v1);
			
			
		} catch (Exception e) {
			AppLog.e("addToUi excep",e);
		}
		
	}

	private void EnumGroupViews(View v1)
	{
		if(v1 instanceof ViewGroup)
		{
			
			ViewGroup lav = (ViewGroup)v1;
			int lcCnt = lav.getChildCount();
			for(int i = 0; i < lcCnt; i++)
			{
				View c1 = lav.getChildAt(i);
				if(c1 instanceof ViewGroup)
					EnumGroupViews(c1);//递归处理GroupView
				else if(c1 instanceof TextView)
				{
					//TestView则解析里面文本内容
					TextView txt = (TextView)c1;
					String str = txt.getText().toString().trim();
					if(str.length() > 0)
					{
						//这里打印文本内容
					}
					
					AppLog.i( "TextView id:"+ txt.getId() + ".text:" + str);
				}else
				{
					AppLog.w("2 other layout:" + c1.toString());
					
				}
			}
		}
		else {
			AppLog.w("1 other layout:" + v1.toString());
		}
	}

通过这个解析,我们基本上完成了从监控、抓取、解析内容的过程。网上也还有其它一些解析处理的方法,大家也可以参考,以上解析remoteView是本人

在查看其相应源码情况下自己琢磨出来的,而且测试了十几款有推送消息的应用,都可以正常解析其所有内容。



你可能感兴趣的:(Android)