未启动的应用无法监听到系统广播

先说下问题和解决方案:

Q:在 3.1 版本以后,新安装而从未启动过的app不能收到系统的广播(启动完成,网络状态变化之类的);

解决方案:

1. 将app做成系统应用,直接安装在 system/app 目录下

2.
通过第三方应用,发送带 FLAG_INCLUDE_STOPPED_PACKAGES 的广播给stop状态的自己

下文转载自 http://www.cnblogs.com/fanfeng/p/3236178.html ,很好的讲解了这个问题的原因

Android 开机自启动

首先实现开机自启动:

第一步创建一个广播接收者,如MyBootBroadcastReceiver.java

package com.example;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class MyBootBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent startServiceIntent = new Intent(context, MyService.class);
        context.startService(startServiceIntent);
        //启动应用
        //Intent intent = getPackageManager().getLaunchIntentForPackage(packageName);
        //context.startActivity(intent);
    }
}

第二步给receiver配置对应intent-filter

<receiver android:name="MyBootBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

第三步添加权限,缺少这步则无法在Android 3.0及其之前版本上自启动

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

上面的实现有以下【限制】:

1.由于Android系统在外置SD卡加载前广播ACTION_BOOT_COMPLETED,于是如果应用安装在外置SD卡上,它无法接收到此广播,原文见Broadcast
Receivers listening for "boot completed"

2.从Android 3.1(API level对应NDK版本)开始,系统的包管理器保持跟踪处于停止状态(stopped
state)的应用程序,提供了一种控制其从后台进程和其它应用程序启动的方式。这种停止状态的应用程序指那些安装了但从未启动过的apk,或被用户在程序管理中force stop的apk。Android系统为防止广播无意或不必要开启停止状态的组件,它给所有广播intent添加了FL??AG_EXCLUDE_STOPPED_PACKAGES标志(不设置和同FLAG_INCLUDE_STOPPED_PACKAGES一起设置结果都是此标志),

Intent.java

public boolean isExcludingStopped() {
        return (mFlags&(FLAG_EXCLUDE_STOPPED_PACKAGES|FLAG_INCLUDE_STOPPED_PACKAGES))
                == FLAG_EXCLUDE_STOPPED_PACKAGES;
    }

IntentResolver.java

/**
     * Returns whether the object associated with the given filter is
     * "stopped," that is whether it should not be included in the result
     * if the intent requests to excluded stopped objects.
     */
    protected boolean isFilterStopped(F filter, int userId) {
        return false;
    }

private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
            boolean debug, boolean defaultOnly,
            String resolvedType, String scheme, F[] src, List<R> dest, int userId) {
        ...

        final boolean excludingStopped = intent.isExcludingStopped();

        final int N = src != null ? src.length : 0;
        boolean hasNonDefaults = false;
        int i;
        F filter;
        for (i=0; i<N && (filter=src[i]) != null; i++) {
            int match;
            if (debug) Slog.v(TAG, "Matching against filter " + filter);

            if (excludingStopped && isFilterStopped(filter, userId)) {
                if (debug) {
                    Slog.v(TAG, "  Filter‘s target is stopped; skipping");
                }
                continue;
            }
        ...

此标志指广播intent排除停止状态的应用,原文见Launch controls on
stopped applications
。用户可以给自己的应用或者后台服务添加FLAG_INCLUDE_STOPPED_PACKAGES标志以唤醒停止状态的应用,但系统自带的广播intent,用户无法修改,只能接受;注意系统级应用都不是停止状态。

PackageManagerService.java中重写IntentResolver

final class ActivityIntentResolver
            extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
        ...
@Override
        protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
            if (!sUserManager.exists(userId)) return true;
            PackageParser.Package p = filter.activity.owner;
            if (p != null) {
                PackageSetting ps = (PackageSetting)p.mExtras;
                if (ps != null) {
                    // System apps are never considered stopped for purposes of
                    // filtering, because there may be no way for the user to
                    // actually re-launch them.
                    return (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
                            && ps.getStopped(userId);
                }
            }
            return false;
        }

private final class ServiceIntentResolver
            extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
        ...
@Override
        protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
            if (!sUserManager.exists(userId)) return true;
            PackageParser.Package p = filter.service.owner;
            if (p != null) {
                PackageSetting ps = (PackageSetting)p.mExtras;
                if (ps != null) {
                    // System apps are never considered stopped for purposes of
                    // filtering, because there may be no way for the user to
                    // actually re-launch them.
                    return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
                            && ps.getStopped(userId);
                }
            }
            return false;
        }
时间: 2024-10-08 01:16:45

未启动的应用无法监听到系统广播的相关文章

oracle 11g在安装过程中出现监听程序未启动或数据库服务未注册到该监听程序

15511477451 原文 oracle 11g在安装过程中出现监听程序未启动或数据库服务未注册到该监听程序? 环境:win7 64位系统.oracle11g数据库 问题描述:在win7 64位系统下安装oracle11g,在使用Database configuration Assistant创建数据库时,在创建到85%的时候报错.错误提示内容如下. 错误分析: 经过查看警告中给出的日志文件 F:\develop\oracle_data\app\Administrator\cfgtoollog

oninput事件(解决onkeyup无法监听到复制黏贴)

onkeyup无法监听到复制黏贴导致的内容变化,可以使用oninput事件 注:IE下 用 onpropertychange <textarea ng-keydown = "addReason(event)" oninput = "angular.element(this).scope().addReason(event)" onproperty = "angular.element(this).scope().addReason(event)&qu

orcle 11g rac crs状态正常,节点2数据库未启动

orcle 11g rac crs状态正常,节点2数据库未启动 安装完oracle11g R2 rac后,在节点1上查看数据库状态: [[email protected] ~]$ sqlplus / as sysdba SQL*Plus: Release 11.2.0.4.0 Production on Wed May 17 18:56:34 2017 Copyright (c) 1982, 2013, Oracle.  All rights reserved. Connected to: Or

ubuntu因IPV6未启动,导致snmpd无法启动

今对ubuntu的系统进行snmpd配置,完成后无法启动,经查看syslog日志,有如下报错: Mar  3 15:11:45 HK-EN-Prod-Web02 snmpd[10060]: error on subcontainer 'ia_addr' insert (-1)Mar  3 15:11:45 HK-EN-Prod-Web02 snmpd[10060]: /etc/snmp/snmpd.conf: line 146: Warning: Unknown token: defaultMo

监听短信(监听系统广播)

监听短信(监听系统广播)

SCCM2012软件更新点同步失败问题(0x80131505,WSUS服务未启动)

今天测试升级win7专业版到Win10,浏览微软官网发现免费升级一直未推送.查看官方说明要求操作系统SP1.IE升级到11.安装KB2952664补丁.发现这台PC没有打上KB2952664的补丁,怀疑WSUS补丁更新有问题,检查SCCM发现以下错误: 同步状态:失败,上一个同步错误代码:0x80131505 检查Windows日志,提示WSUS服务未启动,不是有效的Win32应用程序. 手动启动WSUS服务,提示错误193:0xc1 重启系统,在登录时有以下错误信息,C盘多了一个program

namenode未启动

1.问题:start-all.sh结果jps发现namenode没有启动,其它进程都启动 2.查看日志,没有namenode生产的日志 3.奇了,检查其它进程的日志,都在重新连接namenode Zzzzzzz..... 4.记得虚拟机是直接关机的,未执行stop-all.sh 5.删除tmp目录(metdata所在的目录) 6.重新格式化 hadoop namenode -format 7.启动,正常了. 8.具体原因还未知. namenode未启动

Docker未启动错误:Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

此问题是因为Docker安装后未启动所致,执行以下命令启动docker: systemctl start docker.service 具体日志如下: Connecting to 172.16.10.217:22... Connection established. To escape to local shell, press 'Ctrl+Alt+]'. Last login: Fri Aug 24 17:35:46 2018 [[email protected] ~]# docker ps

VS调试 启动vs报错--未启动IIS

VS调试 启动程序报错--未启动IIS Express Web服务 解决办法: 1.关闭VS. 2.删出项目文件下的".vs"文件. 3.重新启动解决方案. 4.编译,运行OK. 本人亲测有效,如有异常或更好的解决方法,欢迎一起沟通. 原文地址:https://www.cnblogs.com/pushYYL/p/10183635.html