欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android开发利器之ActivityTracker

程序员文章站 2022-03-22 11:37:24
版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/113 Android开发利器之ActivityTracker 今天在群里面划水,有个小伙伴问到一个问题,”刚进公司 清单文件的activity 较多 不便于查 ......

版权声明:本文为xing_star原创文章,转载请注明出处!

本文同步自

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。相信大家都可以实现这个小工具。

项目地址

https://github.com/fashare2015/activitytracker