版權聲明:本文為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。相信大家都可以實現這個小工具。