android開發之app在線時長統計sdk開發

引言:

不少app的在線時長統計都是經過在activity的生命週期中埋點來完成的。我這裏既然是封裝成sdk,固然就不能這樣來了。封裝sdk的規則,我想你們都清楚,入參儘可能少,回調儘可能全,權限盡可能不要有。css

需求分析:

做爲sdk,最好是在Application中初始化,入參,固然是applicationcontext爲好,爲啥?生命週期長呀。我這sdk做爲觀察app的在線時長的,固然不能隨便就被回收了。而後是權限問題,低調,纔會有人用。否則,用戶被你一堆權限嚇跑了。html

既然不能再每一個activity中埋點監聽狀態,那隻好經過ApplicationContext找方法了。看看有沒有可以監聽全局的方法。一查api,還真有。那就開始造輪子。java

實踐:

給個API所在地址:http://www.android-doc.com/reference/android/app/Application.htmlandroid

找找方法唄:
api

看到沒,該方法很直接呀:activity生命週期回調。有了這個,大事可期!!!markdown

在點進去看看詳情,確認一下:app

My god ,I love it !  簡直是餓了送雞腿,困了送枕頭呀。ide

1.分析生命週期的場景

        1.activity被後臺後強殺,結束,上報時長日誌。this

        2.activity一層層的退出乾淨後,結束,上報時長日誌。.net

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

相關文章
相關標籤/搜索