Android应用在未启动的情况下接受指定广播

最近项目中遇到一个这样的需求,如何使App在接收到指定广播的时候,做特定的事情(启动APP或者做某些数据收集操作)
思考:如果APP已经启动,只需注册相应的广播就可以实现这个需求,但是如果APP从未启动过呢?

问题原因

Android在3.1以后将新安装的应用置为“STOPPED”状态,只有当应用启动过一次之后这个状态才会改变,同时,从Android 3.1开始,系统的包管理器保持跟踪处于停止状态(stopped state)的应用程序,提供了一种控制其从后台进程和其它应用程序启动的方式。这种停止状态的应用程序指那些安装了但从未启动过的apk,或被用户在程序管理中force stop的apk。Android系统为防止广播无意或不必要开启停止状态的组件,它给所有广播intent添加了FL​​AG_EXCLUDE_STOPPED_PACKAGES标志(不设置和同FLAG_INCLUDE_STOPPED_PACKAGES一起设置结果都是此标志)

简言之就是:从Android 3.1开始,系统给intent定义了两个新的Flag,分别为FLAG_INCLUDE_STOPPED_PACKAGES(表示包含未启动的App)和FLAG_EXCLUDE_STOPPED_PACKAGES(表示不包含未启动的App),用来控制Intent是否要对处于停止状态的App起作用,而默认所有广播intent flag都是FLAG_EXCLUDE_STOPPED_PACKAGES。

解决方案

在发送intent的地方加上FLAG_INCLUDE_STOPPED_PACKAGES

Intent intent = new Intent();
intent.setAction("ITBIRD.TEST.ACTION");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
sendBroadcast(intent);

在您的App中注册广播并创建广播器接收指定广播即可。
注册指定广播

 <receiver android:name=".MyReceiver">
            <intent-filter>
                <action android:name="ITBIRD.TEST.ACTION"/>
            </intent-filter>
</receiver>

自定义广播接收器

package itbird.com.myapplication33;

import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import java.util.List;

/**
 * 自定义广播接收器
 * Created by xfkang on 2018/5/7.
 */

public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent == null) {
            return;
        }

        Log.d("MyReceiver", intent.getAction());
        if (!isRun(context, "itbird.com.myapplication33")) {
            intent.setClass(context, MainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        }
    }

    /**
     * 判断应用是否在运行
     *
     * @param context
     * @return
     */
    public boolean isRun(Context context, String packagename) {
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> list = am.getRunningTasks(100);
        boolean isAppRunning = false;
        //100表示取的最大的任务数,info.topActivity表示当前正在运行的Activity,info.baseActivity表系统后台有此进程在运行
        for (ActivityManager.RunningTaskInfo info : list) {
            if (info.topActivity.getPackageName().equals(packagename) || info.baseActivity.getPackageName().equals(packagename)) {
                isAppRunning = true;
                Log.d("ActivityService isRun()", info.topActivity.getPackageName() + " info.baseActivity.getPackageName()=" + info.baseActivity.getPackageName());
                break;
            }
        }
        Log.d("ActivityService isRun()", "com.ad 程序  ...isAppRunning......" + isAppRunning);
        return isAppRunning;
    }
}
    原文作者:itbird01
    原文地址: https://www.jianshu.com/p/ac1ed1782adf
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞