android 判断应用是否处于前台

判断 app 是否处于前台

方法1

使用 RunningAppProcessInfo 类提供的信息来判断,主要是依据进程等级来判断。

进程等级分5级:

  • IMPORTANCE_FOREGROUND 正处于activity resume状态,正处于bound服务交互的状态,正处于服务在前台运行的状态(StartForeGround()被调用),Service生命周期正在被执行nCreate(),onStart(),onDestroy()),BroadcastReceiver正在执行onReceive()方法, 杀死foreground需要用户响应,因为这个安全优先级是最高的
  • IMPORTANCE_VISIBLE activity不在前端显示,但也没有完全隐藏,能够看得见,比如弹出一个对话框,没有前台组件,但仍可被用户在屏幕上所见。
  • IMPORTANCE_SERVICE 正在运行的,不在上述两种状态的service,是由 startService() 方法启动的服务,它不会变成上述两类。
  • IMPORTANCE_BACKGROUND 不可见状态的activity进程,onstop被调用
  • IMPORTANCE_EMPTY 没有运行任何component的进程,保留这个进程主要是为了缓存的需要

实现方法如下:

/**
     * 应用是否处于前台
     * @return
     */
    private boolean isAppForeground(){
        ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcessInfos = manager.getRunningAppProcesses();
        if(appProcessInfos == null || appProcessInfos.isEmpty()){
            return false;
        }
        for(ActivityManager.RunningAppProcessInfo info : appProcessInfos){
            //当前应用处于运行中,并且在前台
            if(info.processName.equals(getPackageName()) && info.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
                return true;
            }
        }
        return false;
    }

方法2

主要是实现 ActivityLifecycleCallbacks 接口,原理就是根据 activity 的生命周期的变化,会回调相应的函数,这样我们就可以通过记录前台 activity 的数量来达到判断应用是否处于前台的目的。

实现方法如下:

package com.meizu.rxjava.example;

import android.app.Activity;
import android.app.Application;
import android.os.Bundle;

/**
 * Created by ngudream on 2017/2/26.
 */
public class MyApplication extends Application {

    private MyActivitiesLife myActivitiesLife;

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(myActivitiesLife);
    }

    private static class MyActivitiesLife implements ActivityLifecycleCallbacks{

        private static int resumed;
        private static int paused;

        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        }

        @Override
        public void onActivityStarted(Activity activity) {
        }

        @Override
        public void onActivityResumed(Activity activity) {
            ++resumed;
        }

        @Override
        public void onActivityPaused(Activity activity) {
            ++paused;
        }

        @Override
        public void onActivityStopped(Activity activity) {
        }

        @Override
        public void onActivityDestroyed(Activity activity) {
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        }

        /**
         * 判断应用是否在前台
         * @return
         */
        public static boolean isAppForeground() {
            return resumed > paused;
        }
    }
}

当 resumed 状态的 activity,即可见状态的 activity 的数量大于不可见状态的 activity 的数量的时候,我们就可以认为应用处于前台。

创建前台 service

前台服务是那些被认为用户知道且在系统内存不足的时候不允许系统杀死的服务。前台服务必须给状态栏提供一个通知,即依赖通知栏的存在来保证服务不被杀死,直到通知被关掉。

首先我们创建一个service:

package com.meizu.rxjava.example;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;

/**
 * Created by ngudream on 2017/2/26.
 */

public class MyForegroundService extends Service {

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

然后创建一个通知栏消息:

/**
     * 构建通知栏消息
     * @return
     */
    private Notification createNotification() {
        Notification.Builder builder = new Notification.Builder(this.getApplicationContext()); //获取一个Notification构造器
        Intent newIntent = new Intent(this, MainActivity.class);
        builder.setContentIntent(PendingIntent.getActivity(this, 0, newIntent, 0))
                .setContentTitle("前台 service 标题")
                .setContentText("前台 service 内容")
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                .setSmallIcon(R.mipmap.ic_launcher);
        
        return builder.build();
    }

那在什么时机调用(启动前台服务)这个通知栏消息呢?我们可以在 onStartCommand 方法中调用。service 提供了 startForeground 方法。

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startForeground(FOREGROUND_SERVICE_ID, createNotification());
        return super.onStartCommand(intent, flags, startId);
    }

如何想停止前台服务,即删除通知栏消息,我们可以通过在 service 的 onDestroy 方法中调用 stopForeground 来完成:

@Override
    public void onDestroy() {
        super.onDestroy();
        stopForeground(true);
    }

stopForeground 方法的原型如下,参数表示是否移除通知栏消息:

/**
     * Synonym for {@link #stopForeground(int)}.
     * @param removeNotification If true, the {@link #STOP_FOREGROUND_REMOVE} flag
     * will be supplied.
     * @see #stopForeground(int)
     * @see #startForeground(int, Notification)
     */
    public final void stopForeground(boolean removeNotification) {
        stopForeground(removeNotification ? STOP_FOREGROUND_REMOVE : 0);
    }

整个 service 的完整代码如下:

package com.meizu.rxjava.example;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.IBinder;
import android.support.annotation.Nullable;

/**
 * Created by ngudream on 2017/2/26.
 * 前台服务优先级比较高,在系统内存不足的情况下,不会被系统杀死
 */

public class MyForegroundService extends Service {

    private final static int FOREGROUND_SERVICE_ID = 100;

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startForeground(FOREGROUND_SERVICE_ID, createNotification());//启动前台服务,在通知栏显示一个消息
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopForeground(true);//停止前台服务并且移除通知栏
    }

    /**
     * 构建通知栏消息
     * @return
     */
    private Notification createNotification() {
        Notification.Builder builder = new Notification.Builder(this.getApplicationContext()); //获取一个Notification构造器
        Intent newIntent = new Intent(this, MainActivity.class);
        builder.setContentIntent(PendingIntent.getActivity(this, 0, newIntent, 0))
                .setContentTitle("前台 service 标题")
                .setContentText("前台 service 内容")
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                .setSmallIcon(R.mipmap.ic_launcher);

        return builder.build();
    }
}

文章目录
  1. 1. 判断 app 是否处于前台
    1. 1.1. 方法1
    2. 1.2. 方法2
  2. 2. 创建前台 service
|