Android 自动化埋点方案

特别声明:文章多为网络转载,资源使用一般不提供任何帮助,特殊资源除外,如有侵权请联系!

一、事件实现原理:
① View设置AccessibilityDelegate

②而当View 产生了click,long_click 等事件的时候.会在响应原有的Listener方法

③原有的Listener方法响应结束之后,然后在sendAccessibilityEvent方法中转发消息到AccessibilityDelegate

④在AccessibilityDelegate的sendAccessibilityEvent处理该事件

⑤不要调用call开头的方法如callOnClick,因为不能发送事件到sendAccessibilityEvent

如下方法可以使用

    public boolean performClick() {
        final boolean result;
        final ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            li.mOnClickListener.onClick(this);
            result = true;
        } else {
            result = false;
        }

        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

        notifyEnterOrExitForAutoFillIfNeeded(true);

        return result;
    }

⑥、sendAccessibilityEvent生成事件的key和value

 public void sendAccessibilityEvent(View host, int eventType) {
            host.sendAccessibilityEventInternal(eventType);
        }

二、Android组件生命周期埋点

①Activity生命周期

我们可以通过Application.ActivityLifecycleCallbacks来实现监听Activity的活动

②Service & BroadcastReciever生命周期

目前只能通过手动方式,至于实现方式可以修改如下代码

public class ActivityStatusManager implements Application.ActivityLifecycleCallbacks{

    public final Integer STATUS_CREATED = 0x0001;
    public final Integer STATUS_RESUMED = 0x0002;
    public final Integer STATUS_PAUSED = 0x0003;
    public final Integer STATUS_STARTED = 0x0004;
    public final Integer STATUS_STOPED = 0x0005;
    public final Integer STATUS_DESTROYED = -1;

    private Map<Activity,Integer> activityStack;

    public void registerActivityLifecycleCallbacks(Application application) {
            application.registerActivityLifecycleCallbacks(this);
    }

    public void unregisterActivityLifecycleCallbacks(Application application){
        application.unregisterActivityLifecycleCallbacks(this);
    }

    private static class Holder{
        public final static ActivityStatusManager instance = new ActivityStatusManager();
    }

    public static ActivityStatusManager shareInstance(){
        return Holder.instance;
    }

    private ActivityStatusManager(){
        activityStack = new ArrayMap<Activity,Integer>();
    }

    public Integer getActivityStatus(Activity activity) {
        final Integer status = activityStack.get(activity);
        if(status==null){
             return  STATUS_DESTROYED;
         }
        return status;
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        if(activity!=null){
            activityStack.put(activity,STATUS_CREATED);
        }
    }

    @Override
    public void onActivityStarted(Activity activity) {
        if(activity!=null){
            activityStack.put(activity,STATUS_STARTED);
        }
    }

    @Override
    public void onActivityResumed(Activity activity) {
        if(activity!=null){
            activityStack.put(activity,STATUS_RESUMED);
        }
    }

    @Override
    public void onActivityPaused(Activity activity) {
        if(activity!=null){
            activityStack.put(activity,STATUS_PAUSED);
        }
    }

    @Override
    public void onActivityStopped(Activity activity) {
        if(activity!=null){
            activityStack.put(activity,STATUS_STOPED);
        }
        synchronized (Holder.instance){
            int counter = 0;
            for (Map.Entry<Activity,Integer> entry : activityStack.entrySet()){
                if(entry.getValue()==STATUS_STOPED){
                    counter++;
                }
            }
            if(counter>0 && activityStack.size()==counter){
                BaseApplication.setInForeground(false);
            }else{
                BaseApplication.setInForeground(true);
            }
        }
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        Application application = activity.getApplication();
        activityStack.remove(activity);
        clearInvalidActivity();
        if(activityStack.isEmpty() && application!=null){
            unregisterActivityLifecycleCallbacks(application);
        }
    }

    public void clearInvalidActivity(){
        Iterator<Map.Entry<Activity,Integer>> iterator = activityStack.entrySet().iterator();
        do{
            if(!iterator.hasNext()) return;
            Map.Entry<Activity, Integer> entry = iterator.next();
            if(entry!=null && activityIsDestroyed(entry.getKey()) ){
                iterator.remove();
            }
        }while(iterator.hasNext());

    }

    public void finishAll(){
        if(activityStack.isEmpty()) return;
        Activity activity = null;
        Iterator<Map.Entry<Activity,Integer>> iterator = activityStack.entrySet().iterator();
        do{
            if(!iterator.hasNext()) return;
            Map.Entry<Activity, Integer> entry = iterator.next();
            if(entry!=null ){
                activity = entry.getKey();
                if(activity!=null && !activityIsDestroyed(activity))
                {
                    activity.finish();
                }
                iterator.remove();
            }
        }while(iterator.hasNext());

    }

    /**
     * 程序是否在前台运行
     *
     * @return
     */
    public  boolean isForegroundProcess(Context context) {
        // Returns a list of application processes that are running on the
        // device

        ActivityManager activityManager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
        String packageName = context.getApplicationContext().getPackageName();

        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager
                .getRunningAppProcesses();
        if (appProcesses == null)
            return false;

        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            // The name of the process that this object is associated with.
            if (appProcess.processName.equals(packageName)
                    && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                return true;
            }
        }
        return false;
    }

    private boolean activityIsDestroyed(Activity thatActivity){
        if(thatActivity==null) return  true;

        if(Build.VERSION.SDK_INT>=17){
            return thatActivity.isDestroyed() ||  thatActivity.isFinishing();
        }else{
            return  thatActivity.isFinishing();
        }
    }
}

 

三、配置环境埋点

在Application中注册 ComponentCallbacks2

未经允许不得转载:作者:SheaYang, 转载或复制请以 超链接形式 并注明出处 技术Dog|博客
原文地址:《Android 自动化埋点方案》 发布于2019-10-26

分享到:
赞(0)

评论 抢沙发

8 + 9 =


Android 自动化埋点方案

长按图片转发给朋友

Vieu4.0主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录