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

posted @ 2018-05-10 12:02  shoneworn  阅读(1879)  评论(0编辑  收藏  举报