如何知道你的app进入了前台还是后台

众所周知android是个开放性系统,所以系统提供的api往往都不够用,如果遇到了某些需求系统api满足不了我们,就需要自己研究了。

本文就是实现一个利用Application.ActivityLifecycleCallbacks与监听ACTION_SCREEN_OFF广播实现的检测app进入了前台还是后台功能。

一 :Application.ActivityLifecycleCallbacks

长这个样子的:

    public interface ActivityLifecycleCallbacks {
        void onActivityCreated(Activity activity, Bundle savedInstanceState);
        void onActivityStarted(Activity activity);
        void onActivityResumed(Activity activity);
        void onActivityPaused(Activity activity);
        void onActivityStopped(Activity activity);
        void onActivitySaveInstanceState(Activity activity, Bundle outState);
        void onActivityDestroyed(Activity activity);
    }

二:息屏广播

长这个样子的:

/ ** 
  *广播操作:在设备进入睡眠状态并变为非交互状态时发送。 
  * <p> *由于历史原因,此广播操作的名称是指屏幕的电源状态,但实际上是根据设备总体交互状态的变化 而发送的。 
  *</p><p>
  *该广播是在设备变为非交互式时发送的,这可能与屏幕关闭无关。要确定屏幕的实际状态,请使用
  * {@link android.view.Display#getState}。 
  *</p><p>
  * 有关详细信息,请参见{@link android.os.PowerManager#isInteractive}。 
  * </p> 
  * 您<em>不能</em>通过清单中声明的​​组件接收此消息,只有通过使用
  * {@link Context#registerReceiver(BroadcastReceiver,IntentFilter)
  * Context.registerReceiver()}进行显式注册才能收到此消息。 
  *  <p class =“ note”>这是一个受保护的意图,只能由系统发送。 
  * /
    public static final String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";

三:结合一和二开始编写真正的帮助类AbsActivityLifecycle

长这个样子的:

import android.app.Activity;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;

import java.util.WeakHashMap;

/**
 * 有助于确定应用程序何时进入或离开前台。
 * 提供抽象方法来处理应用程序何时进入后台或前台。
 * 如果需要其他处理则可以覆盖任何活动生命周期回调。
 * 只需确保调用super方法,以使此类仍将按预期运行。
 */
public abstract class AbsActivityLifecycle implements Application.ActivityLifecycleCallbacks {
    private static final String TAG = "AbsActivityLifecycle";
    private boolean inForeground = false;
    /**
     * 跟踪尚未停止的活动(包括重新启动的活动)的生命周期。
     */
    private WeakHashMap<Activity, String> activityStringWeakHashMap = new WeakHashMap<>();

    /**
     * 构造函数。注册以接收活动生命周期事件。
     *
     * @param application The Android Application class.
     */
    public AbsActivityLifecycle(final Application application) {
        //注册ActivityLifecycleCallbacks
        application.registerActivityLifecycleCallbacks(this);
        //注册Intent.ACTION_SCREEN_OFF
        final ScreenOffReceiver screenOffReceiver = new ScreenOffReceiver();
        application.registerReceiver(screenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
    }

    @Override
    public void onActivityCreated(final Activity activity, final Bundle bundle) {
        Log.d(TAG, "onActivityCreated " + activity.getLocalClassName());
        handleOnCreateOrOnStartToHandleApplicationEnteredForeground();
        activityStringWeakHashMap.put(activity, "created");
    }

    @Override
    public void onActivityStarted(final Activity activity) {
        Log.d(TAG, "onActivityStarted " + activity.getLocalClassName());
        handleOnCreateOrOnStartToHandleApplicationEnteredForeground();
        activityStringWeakHashMap.put(activity, "started");
    }

    @Override
    public void onActivityResumed(final Activity activity) {
        Log.d(TAG, "onActivityResumed " + activity.getLocalClassName());
        activityStringWeakHashMap.put(activity, "resumed");
    }

    @Override
    public void onActivityPaused(final Activity activity) {
        Log.d(TAG, "onActivityPaused " + activity.getLocalClassName());
        activityStringWeakHashMap.put(activity, "paused");
    }

    @Override
    public void onActivityStopped(final Activity activity) {
        Log.d(TAG, "onActivityStopped " + activity.getLocalClassName());
        // 当活动停止时,我们将其从生命周期状态图中删除,因为不再考虑让会话保持活动状态。
        activityStringWeakHashMap.remove(activity);
    }

    @Override
    public void onActivitySaveInstanceState(final Activity activity, final Bundle outState) {
        Log.d(TAG, "onActivitySaveInstanceState " + activity.getLocalClassName());
    }

    @Override
    public void onActivityDestroyed(final Activity activity) {
        Log.d(TAG, "onActivityDestroyed " + activity.getLocalClassName());
        // 活动不应再位于activityLifecycleStateMap中。
        if (activityStringWeakHashMap.containsKey(activity)) {
            Log.e(TAG, "Destroyed activity present in activityLifecycleMap!?");
            activityStringWeakHashMap.remove(activity);
        }
    }

    //region 判断

    /**
     * Application.onTrimMemory()调用此方法。
     *
     * @param level 从Application.onTrimMemory()传递的级别
     */
    public void handleOnTrimMemory(final int level) {
        Log.d(TAG, "onTrimMemory " + level);
        // 如果没有任何活动在运行,并且该应用已进入后台。
        if (level >= Application.TRIM_MEMORY_UI_HIDDEN) {
            checkForApplicationEnteredBackground();
        }
    }

    /**
     * The BroadcastReceiver for Intent.ACTION_SCREEN_OFF
     */
    private class ScreenOffReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            checkForApplicationEnteredBackground();
        }
    }

    /**
     * 从onActivityCreated和onActivityStarted调用以在应用程序进入前台时进行处理。
     */
    private void handleOnCreateOrOnStartToHandleApplicationEnteredForeground() {
        //如果活动生命周期映射中没有任何内容指示我们可能在后台,并且标志表明我们确实在后台中。
        if (activityStringWeakHashMap.size() == 0 && !inForeground) {
            inForeground = true;
            // 由于在活动开始时会调用此方法,因此我们现在知道该应用程序已进入前台。
            applicationEnteredForeground();
        }
    }

    private void checkForApplicationEnteredBackground() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // 如果应用程序位于前台,并且不再有未停止的活动。
                if ((activityStringWeakHashMap.size() == 0) && inForeground) {
                    inForeground = false;
                    applicationEnteredBackground();
                }
            }
        });
    }

     /**
     * Run a runnable on the Main (UI) Thread.
     * @param runnable the runnable
     */
    private static void runOnUiThread(final Runnable runnable) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            new Handler(Looper.getMainLooper()).post(runnable);
        } else {
            runnable.run();
        }
    }
    //endregion

    //region 回调

    /**
     * 当应用程序进入前台时回调。
     */
    protected abstract void applicationEnteredForeground();

    /**
     * 应用程序进入后台时回调。
     */
    protected abstract void applicationEnteredBackground();
    //endregion
}

 

最后如何使用:

1.自定义MyApplication

import android.app.Application;
import android.util.Log;

/**
 * 自定义Application
 */
public class MyApplication extends Application {

    private AbsActivityLifecycle absActivityLifecycle;


    @Override
    public void onCreate() {
        super.onCreate();

        //帮助程序在构造时进行注册,以接收应用程序生命周期事件。
        // 这里保留了一个引用,以便通过
        // 应用程序类的onTrimMemory()调用来正确跟踪应用程序何时进入后台
        absActivityLifecycle = new AbsActivityLifecycle(this) {
            @Override
            protected void applicationEnteredForeground() {
                Log.d("AbsActivityLifecycle", "-->applicationEnteredForeground");
            }

            @Override
            protected void applicationEnteredBackground() {
                Log.d("AbsActivityLifecycle", "-->applicationEnteredBackground");
            }
        };
    }

    @Override
    public void onTrimMemory(final int level) {
        if (absActivityLifecycle != null) {
            absActivityLifecycle.handleOnTrimMemory(level);
        }
        super.onTrimMemory(level);
    }
}

2.清单文件中使用自己定义的MyApplication

  <application
        android:name=".application.MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/BaseAppTheme"
        tools:ignore="GoogleAppIndexingWarning">

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值