未啟動的應用無法監聽到系統廣播,啟動監聽系統廣播

來源:互聯網
上載者:User

未啟動的應用無法監聽到系統廣播,啟動監聽系統廣播
先說下問題和解決方案: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添加了FLAG_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;        }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.