均均有礼 發表於 2019-6-2 14:39:00

Android开发利器之ActivityTracker

<p>版权声明:本文为xing_star原创文章,转载请注明出处!</p>
<p>本文同步自http://javaexception.com/archives/113</p>
<h2 id="title-0">Android开发利器之ActivityTracker</h2>
<p>今天在群里面划水,有个小伙伴问到一个问题,”刚进公司 清单文件的activity 较多 不便于查找和定位,有什么办法解决”。这个问题我自认为还是很有经验的,向对方推荐了一个ActivityTracker软件,这个软件的作用嘛,就是开启了一个悬浮窗,会显示当前页面的Activity的名称,无论是系统App,还是新接手的公司App,通过展示的Activity类名,能够很容易的找到这块业务逻辑的代码所在。这个小工具真的很可以提高开发效率,所以准备记录下来,这个东西也是用了好几年了,不是今天有人问到,也不会有想法特意写篇文章记录下ActivityTracker。</p>
<h2 id="title-1">源码分析</h2>
<p>这个小工具在Github上是开源的,地址是https://github.com/fashare2015/ActivityTracker,也有幸提过pr,代码量上就四五个类,很容易看懂的。本质上采用的是Android的AccessibilityService这个辅助服务机制,时刻检测屏幕对应的Activity,同时在Service中用WindowManager显示悬浮view。</p>
<p>具体到代码层面,当用户开启辅助服务后,TrackerService被激活,onAccessibilityEvent方法就会不断的被执行</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onAccessibilityEvent(AccessibilityEvent event) {
    Log.d(TAG, </span>"onAccessibilityEvent: " +<span style="color: rgba(0, 0, 0, 1)"> event.getPackageName());
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (event.getEventType() ==<span style="color: rgba(0, 0, 0, 1)"> AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {

      CharSequence packageName </span>=<span style="color: rgba(0, 0, 0, 1)"> event.getPackageName();
      CharSequence className </span>=<span style="color: rgba(0, 0, 0, 1)"> event.getClassName();
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!TextUtils.isEmpty(packageName) &amp;&amp; !<span style="color: rgba(0, 0, 0, 1)">TextUtils.isEmpty(className)) {
            EventBus.getDefault().post(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ActivityChangedEvent(
                  event.getPackageName().toString(),
                  event.getClassName().toString()
            ));
      }
    }
}</span></pre>
</div>
<p>当onAcessibilityEvent被触发后,满足TYPE_WINDOW_STATE_CHANGED(用来表示Window窗口发生了变化)条件后,通过EventBus将当前页面的包名,Activity类名传递到FloatingView中,接着就在FloatingView中刷新对应的包名,类名值。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onEventMainThread(TrackerService.ActivityChangedEvent event){
    Log.d(TAG, </span>"event:" + event.getPackageName() + ": " +<span style="color: rgba(0, 0, 0, 1)"> event.getClassName());
    String packageName </span>=<span style="color: rgba(0, 0, 0, 1)"> event.getPackageName(),
            className </span>=<span style="color: rgba(0, 0, 0, 1)"> event.getClassName();

    mTvPackageName.setText(packageName);
    mTvClassName.setText(
            className.startsWith(packageName)</span>?<span style="color: rgba(0, 0, 0, 1)">
            className.substring(packageName.length()):
            className
    );
    Log.d(TAG, </span>"event:" + event.getPackageName() + ": " + event.getClassName() + ", end invoked!"<span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<p>这块是核心逻辑。</p>
<p>FloatingView是如何在Service中显示隐藏的呢,可以看到TrackerService里面有个成员变量mTrackerWindowManager,他用来控制显示隐藏FloatingView。</p>
<p>TrackerWindowManager的静态代码块设置了悬浮view的默认显示位置,以及可以接受手势触摸</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> {
    WindowManager.LayoutParams params </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> WindowManager.LayoutParams();
    params.x </span>= 0<span style="color: rgba(0, 0, 0, 1)">;
    params.y </span>= 0<span style="color: rgba(0, 0, 0, 1)">;
    params.width </span>=<span style="color: rgba(0, 0, 0, 1)"> WindowManager.LayoutParams.WRAP_CONTENT;
    params.height </span>=<span style="color: rgba(0, 0, 0, 1)"> WindowManager.LayoutParams.WRAP_CONTENT;
    params.gravity </span>= Gravity.LEFT |<span style="color: rgba(0, 0, 0, 1)"> Gravity.TOP;
    params.type </span>=<span style="color: rgba(0, 0, 0, 1)"> WindowManager.LayoutParams.TYPE_PHONE;
    params.format </span>=<span style="color: rgba(0, 0, 0, 1)"> PixelFormat.RGBA_8888;
    params.flags </span>=<span style="color: rgba(0, 0, 0, 1)"> WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
            </span>|<span style="color: rgba(0, 0, 0, 1)"> WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

    LAYOUT_PARAMS </span>=<span style="color: rgba(0, 0, 0, 1)"> params;
}</span></pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> addView() {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(mFloatingView == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">){
      mFloatingView </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> FloatingView(mContext);
      mFloatingView.setLayoutParams(LAYOUT_PARAMS);

      mWindowManager.addView(mFloatingView, LAYOUT_PARAMS);
    }
}</span></pre>
</div>
<p>addView方法就是将FloatingView添加到Service的WindowManager中,并显示出来,这块需要对WindowManager有所理解,了解其用法。</p>
<p>在我们真正使用的过程中会发现,ActivityTracker明明Activity页面已经finish了,但是悬浮view依旧显示在当前的屏幕上,控制悬浮view显示的是WindowManager,而这个windowManager在Service中存活着。所以基本上就会一直显示着,很少会被系统杀死。</p>
<p>分析完后发现,这个小工具并不难,主要用到的就是AccessibilityService,WindowManager添加FloatingView,以及EventBus。相信大家都可以实现这个小工具。</p>
<h2 id="title-2">项目地址</h2>
<p>https://github.com/fashare2015/ActivityTracker</p><br><br>
来源:https://www.cnblogs.com/xing-star/p/10962004.html
頁: [1]
查看完整版本: Android开发利器之ActivityTracker