众所周知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">