应用前后台切换,Application registerActivityLifecycleCallbacks(API 14)-Android

Android将后台应用唤起到前台的方法- https://blog.csdn.net/ShareUs/article/details/72902947

registerActivityLifecycleCallbacks与ActivityLifecycleCallbacks?

-- 需求:

1.统计App的停留时间registerActivityLifecycleCallbacks();

2.统计App中某个Activity停留时间:onResume()->onPause()的时间差。。。

3.App应用由前台到后台再切前台超过1小时,展示广告

-- 在微信中,对于4.0以上的机型也是采用通过注册ActivityLifecycleCallbacks接口,对于4.0以下的机型我们会尝试反射ActivityThread中的mInstrumentation对象。

Android中Hook Instrumentation 的实现- https://blog.csdn.net/u012341052/article/details/71191409
Android插件化开发之Hook StartActivity方法- https://blog.csdn.net/u011068702/article/details/53208825
public class Hooker {
    private static final String TAG = "Hooker";
    public static void hookInstrumentation() throws Exception {
        Class<?> activityThread = Class.forName("android.app.ActivityThread");
        Method sCurrentActivityThread = activityThread.getDeclaredMethod("currentActivityThread");
        sCurrentActivityThread.setAccessible(true);
        //获取ActivityThread 对象
        Object activityThreadObject = sCurrentActivityThread.invoke(activityThread);

        //获取 Instrumentation 对象
        Field mInstrumentation = activityThread.getDeclaredField("mInstrumentation");
        mInstrumentation.setAccessible(true);
        Instrumentation instrumentation = (Instrumentation) mInstrumentation.get(activityThreadObject);
        CustomInstrumentation customInstrumentation = new CustomInstrumentation(instrumentation);
        //将我们的 customInstrumentation 设置进去
        mInstrumentation.set(activityThreadObject, customInstrumentation);
    }

}

-- APP前后台切换
 getRunningTasks和getRunningAppProcesses失效- https://blog.csdn.net/axi295309066/article/details/56123954
 Android 5.0以上的getRunningTasks失效,该方法可以获得在前台运行的系统进程。可以用getRunningAppProcesses方法暂时替代。android6.0以上的getRunningAppProcesses也失效,系统关闭了三方软件对系统进程的访问,出于安全考虑。
 -- 在5.0以下可以使用,即在4.0以下可以使用
/**
     * APP是否处于前台唤醒状态
     *
     * @return
     */
    public boolean isAppOnForeground() {
        ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
        String packageName = 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;
    }

在5.1.+后获取运行中进程呢
Example code for "How-To SU" - https://github.com/Chainfire/libsuperuser

-- registerActivityLifecycleCallbacks 在 API 14-Android 4.0才出现的。Android在API 14之后,在Application类中,提供了一个应用生命周期回调的注册方法,用来对应用的生命周期进行集中管理,这个接口叫registerActivityLifecycleCallbacks,可以通过它注册自己的ActivityLifeCycleCallback,每一个Activity的生命周期都会回调到这里的对应方法。其实这个注册方法的本质和我们实现BaseActivity是一样的,只是将生命周期的管理移到了Activity本身的实现中。

Android API- https://developer.android.com/reference/android/app/Application.ActivityLifecycleCallbacks.html

> 需求3代码实现如下(>= APi 14):

public int count = 0;
private long standardCompareTime = 10000;//比较时间是否会超过30分钟 30 * 60 * 1000 TODO
//Log.e("1", "run:--------->当前类名: "+ getClass().getSimpleName());
private void monitorAppFrontBackstage() {//监听App前后台状态
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {//API 14:Android 4.0
            @Override
            public void onActivityStopped(Activity activity) {
                LogUtil.e("desaco", activity + "onActivityStopped");
                count--;
                if (count == 0) {
                    LogUtil.e("desaco", ">>>>>>>>>>>>>>>>>>>切到后台  lifecycle");
                    PreferencesManager.getInstance().put("time_is_show_ads", System.currentTimeMillis());
                }
            }

            @Override
            public void onActivityStarted(Activity activity) {
                LogUtil.e("desaco", activity + "onActivityStarted");
                long oldTime = PreferencesManager.getInstance().get("time_is_show_ads", 0l);
                long newTime = System.currentTimeMillis();
                long interval = newTime - oldTime;
                LogUtil.e("desaco", "切到前台 oldTime="+oldTime+",,,newTime="+newTime+",,interval="+interval);
                if (count == 0) {
                    LogUtil.e("desaco", ">>>>>>>>>>>>>>>>>>>切到前台  lifecycle");
                    if (oldTime > 0 && interval > standardCompareTime) {
//                        LogUtil.e("desaco", "activity name=" + activity.getClass().getSimpleName());
                        LogUtil.e("desaco", "需要展示广告!!!");
                        Intent intent = new Intent(activity, LoadingActivity.class);
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        intent.putExtra(ConstantAttr.SHOW_ADS_PAGE, true);
                        startActivity(intent);
                    }
                    PreferencesManager.getInstance().put("time_is_show_ads", 0l);
                }
                count++;
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
//                LogUtil.e("desaco", activity + "onActivitySaveInstanceState");
            }

            @Override
            public void onActivityResumed(Activity activity) {
                LogUtil.e("desaco", activity + "onActivityResumed");
            }

            @Override
            public void onActivityPaused(Activity activity) {
                LogUtil.e("desaco", activity + "onActivityPaused");
            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                LogUtil.e("desaco", activity + "onActivityDestroyed");
            }

            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                LogUtil.e("desaco", activity + "onActivityCreated");
            }
        });

    }

> 需求3,API14之前可以考虑这个(< APi 14):在App的Activity基类中开始和结束计时

/**
 * Created by desaco on 2018/1/16.
 * 应用处于非激活状态超过30min后,再进入激活状态,展示LoadingActivity页(主要是用来展示广告),
 */
public class StatAppInactiveTimeUtils {
    private StatAppInactiveTimeUtils() {
    }
    private static StatAppInactiveTimeUtils singleton = null;
    public static StatAppInactiveTimeUtils getInstance() {
        if (singleton == null) {
            synchronized (StatAppInactiveTimeUtils.class) {
                if (singleton == null) {
                    singleton = new StatAppInactiveTimeUtils();
                }
            }
        }
        return singleton;
    }

    /**
     * onStop()生命周期中开始计时,onReStart()计时结束
     */
    private static long startTime;//开始计时时间;

    //开启计时 关闭计时 重新计时(计时器)
    public void startStatTime() {
        startTime = System.currentTimeMillis();
    }

    //关闭计时,并清空
    public void endAndClearStatTime() {
        startTime = 0;
    }

    //获取开始计时时间
    public long getStartTime() {
        return startTime;
    }

    //--------------------------------
    /**
     * 计算一个页面从onResume()到onPause()花了多少时间,即页面停留了多长时间
     * 当页面停留时间大于30min,则不跳广告
     */
    private static long onResumeStartTime;//记录执行onResume()方法时的当前时间
    private static long onPauseEndTime;//记录执行onPause()方法时的当前时间
//    private static long onStopCurrentTime;

    public void statOnResumeStartTime() {
        onResumeStartTime = System.currentTimeMillis();
    }

    public void statOnPauseEndTime() {
        onPauseEndTime = System.currentTimeMillis();
    }

    public long getOnResumeStartTime() {
        return onResumeStartTime;
    }

    public long getOnPauseEndTime() {
        return onPauseEndTime;
    }

//    public long getOnStopCurrentTime() {
//        onStopCurrentTime = System.currentTimeMillis();
//        return onStopCurrentTime;
//    }

    public void resetAfterKeyPress() {//按HOME、电源键后重新计时
        StatAppInactiveTimeUtils.getInstance().statOnResumeStartTime();
        StatAppInactiveTimeUtils.getInstance().statOnPauseEndTime();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值