zoukankan      html  css  js  c++  java
  • android开发之app在线时长统计sdk开发

    引言:

    很多app的在线时长统计都是通过在activity的生命周期中埋点来完成的。我这里既然是封装成sdk,当然就不能这样来了。封装sdk的规则,我想大家都清楚,入参尽量少,回调尽量全,权限尽量不要有。

    需求分析:

    作为sdk,最好是在Application中初始化,入参,当然是applicationcontext为好,为啥?生命周期长呀。我这sdk作为观察app的在线时长的,当然不能随便就被回收了。然后是权限问题,低调,才会有人用。不然,用户被你一堆权限吓跑了。

    既然不能再每个activity中埋点监听状态,那只好通过ApplicationContext找方法了。看看有没有能够监听全局的方法。一查api,还真有。那就开始造轮子。

    实践:

    给个API所在地址:http://www.android-doc.com/reference/android/app/Application.html

    找找方法呗:

    看到没,该方法很直接呀:activity生命周期回调。有了这个,大事可期!!!

    在点进去看看详情,确认一下:

    My god ,I love it !  简直是饿了送鸡腿,困了送枕头呀。

    1.分析生命周期的场景

            1.activity被后台后强杀,结束,上报时长日志。

            2.activity一层层的退出干净后,结束,上报时长日志。

    2.撸代码

    根据这两个场景,立马就开动了,使用一个map来记录activity的启动和结束,再用几个flag标记切换生命周期。但是,一通下来,发现,没这么简单呀。要考虑的东西真多。

    首先,要对启动模式进行考虑。standard模式,A-B-A,生命周期,这个大家应该很熟。但是singletask就在监听中有了变化。A-B-A过程中,A的onActivityStarted(Activity activity)方法中,activity并不是大家期待的b的实例,而是a的实例。当然还有很多其他问题。不一一赘述。代码是最好的老师。

    核心代码:

    package com.ailin.shoneworn.OnLineStatics;
    
    import android.app.Activity;
    import android.app.Application;
    import android.content.Context;
    import android.os.Bundle;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Created by admin on 2018/3/2.
     * @author  chenxiangxiang
     * shoneworn@163.com
     * 转载注明出处:http://www.cnblogs.com/shoneworn
     */
    
     class OnLineStatisticsClass {
        private String TAG = "OnlineStatics";
    
        private boolean isAppAlive = true;  //judge is app alive;
        private boolean isSwitchActivity = false;  // judge is switch activity from top to other in the stack of activity
        private boolean isAppExit = false;  //some times app have cleard the stack of activity but app is not exit . this boolean can help to static realive;
    
        private String topActivity ;
        private Map<String ,String> map = new HashMap<>();
        private long timeStart =0;   //start tag timestemp
    
        private OnLineImpl impl; //set a callback
    
        public void init(final Context context){
            Application application  = (Application)context.getApplicationContext();
            timeStart = System.currentTimeMillis()/1000;
    
            application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
                @Override
                public void onActivityCreated(Activity activity, Bundle bundle) {
                    topActivity = activity.getClass().getSimpleName();
                    map.put(topActivity,topActivity);
                    isAppAlive = true;
                    isSwitchActivity = false;
                }
    
                @Override
                public void onActivityStarted(Activity activity) {
                }
    
                @Override
                public void onActivityResumed(Activity activity) {
                    //do you know why this logic is used here? because of the launch mode ,when activity start with SingleTask mode ,the onActivityStarted callback a top activity .
                    if(!activity.getClass().getSimpleName().equals(topActivity)){
                        isSwitchActivity = true;
                    }else{
                        isSwitchActivity = false;
                    }
                    topActivity=activity.getClass().getSimpleName();
    
                   ..........................
                }
    
                @Override
                public void onActivityPaused(Activity activity) {
    
                }
    
                @Override
                public void onActivityStopped(Activity activity) {
                    if(activity.getClass().getSimpleName().equals(topActivity) ){
                        if(!isSwitchActivity||map.size()==1){
                         ...................
                        }
                    }
                }
    
                @Override
                public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
                }
    
                @Override
                public void onActivityDestroyed(Activity activity) {
                    map.remove(activity.getClass().getSimpleName());
                    if(map.size()==0&&isAppAlive){
                        long timeEnd = System.currentTimeMillis()/1000;
                        if(impl!=null){
                            long timegap = timeEnd-timeStart;
                            String onlineTime = String.valueOf(timegap);
                            impl.onReportDuration(onlineTime);
                            timeStart = System.currentTimeMillis()/1000;
                        }
                        isAppAlive = false;
                    }
                    if(map.size() ==0){
                        isAppExit = true;
                    }
                }
            });
        }
    
    
        public void setOnLineImpl(OnLineImpl impl){
            this.impl = impl;
        }
    
    }
    

    demo 下载地址:

    https://download.csdn.net/download/shoneworn/10405179

  • 相关阅读:
    20145210 20145226 《信息安全系统设计基础》实验五 简单嵌入式WEB服务器实验
    20145302张薇《网络对抗技术》PC平台逆向破解
    20145302张薇 《网络对抗技术》逆向及BOF基础实践
    小问题汇总
    20145302张薇 《信息安全系统设计基础》课程总结
    20145302张薇 《信息安全系统设计基础》第14周学习总结
    20145302张薇《信息安全系统设计基础》第13周学习总结
    20145302张薇 GDB调试汇编堆栈过程分析
    20145302张薇 《信息安全系统设计基础》第12周学习总结
    20145302张薇 20145308刘昊阳 《信息安全系统设计基础》实验五 网络通信
  • 原文地址:https://www.cnblogs.com/shoneworn/p/9029433.html
Copyright © 2011-2022 走看看