版权声明:本文为xing_star原创文章,转载请注明出处!
本文同步自http://javaexception.com/archives/113
Android开发利器之ActivityTracker
今天在群里面划水,有个小伙伴问到一个问题,”刚进公司 清单文件的activity 较多 不便于查找和定位,有什么办法解决”。这个问题我自认为还是很有经验的,向对方推荐了一个ActivityTracker软件,这个软件的作用嘛,就是开启了一个悬浮窗,会显示当前页面的Activity的名称,无论是系统App,还是新接手的公司App,通过展示的Activity类名,能够很容易的找到这块业务逻辑的代码所在。这个小工具真的很可以提高开发效率,所以准备记录下来,这个东西也是用了好几年了,不是今天有人问到,也不会有想法特意写篇文章记录下ActivityTracker。
源码分析
这个小工具在Github上是开源的,地址是https://github.com/fashare2015/ActivityTracker,也有幸提过pr,代码量上就四五个类,很容易看懂的。本质上采用的是Android的AccessibilityService这个辅助服务机制,时刻检测屏幕对应的Activity,同时在Service中用WindowManager显示悬浮view。
具体到代码层面,当用户开启辅助服务后,TrackerService被激活,onAccessibilityEvent方法就会不断的被执行
@Override public void onAccessibilityEvent(AccessibilityEvent event) { Log.d(TAG, "onAccessibilityEvent: " + event.getPackageName()); if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { CharSequence packageName = event.getPackageName(); CharSequence className = event.getClassName(); if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(className)) { EventBus.getDefault().post(new ActivityChangedEvent( event.getPackageName().toString(), event.getClassName().toString() )); } } }
当onAcessibilityEvent被触发后,满足TYPE_WINDOW_STATE_CHANGED(用来表示Window窗口发生了变化)条件后,通过EventBus将当前页面的包名,Activity类名传递到FloatingView中,接着就在FloatingView中刷新对应的包名,类名值。
public void onEventMainThread(TrackerService.ActivityChangedEvent event){ Log.d(TAG, "event:" + event.getPackageName() + ": " + event.getClassName()); String packageName = event.getPackageName(), className = event.getClassName(); mTvPackageName.setText(packageName); mTvClassName.setText( className.startsWith(packageName)? className.substring(packageName.length()): className ); Log.d(TAG, "event:" + event.getPackageName() + ": " + event.getClassName() + ", end invoked!"); }
这块是核心逻辑。
FloatingView是如何在Service中显示隐藏的呢,可以看到TrackerService里面有个成员变量mTrackerWindowManager,他用来控制显示隐藏FloatingView。
TrackerWindowManager的静态代码块设置了悬浮view的默认显示位置,以及可以接受手势触摸
static { WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.x = 0; params.y = 0; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.gravity = Gravity.LEFT | Gravity.TOP; params.type = WindowManager.LayoutParams.TYPE_PHONE; params.format = PixelFormat.RGBA_8888; params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; LAYOUT_PARAMS = params; }
public void addView() { if(mFloatingView == null){ mFloatingView = new FloatingView(mContext); mFloatingView.setLayoutParams(LAYOUT_PARAMS); mWindowManager.addView(mFloatingView, LAYOUT_PARAMS); } }
addView方法就是将FloatingView添加到Service的WindowManager中,并显示出来,这块需要对WindowManager有所理解,了解其用法。
在我们真正使用的过程中会发现,ActivityTracker明明Activity页面已经finish了,但是悬浮view依旧显示在当前的屏幕上,控制悬浮view显示的是WindowManager,而这个windowManager在Service中存活着。所以基本上就会一直显示着,很少会被系统杀死。
分析完后发现,这个小工具并不难,主要用到的就是AccessibilityService,WindowManager添加FloatingView,以及EventBus。相信大家都可以实现这个小工具。