In frameworks/base/services/java/com/android/server/am/ActivityManagerService.java :
private final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String requiredPermission, boolean ordered, boolean sticky, int callingPid, int callingUid) { intent = new Intent(intent); // By default broadcasts do not go to stopped apps. intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
... (略)
就是由於 Android 在 broadcast 的時候將 intent 加上了預設的 flag (Intent.FLAG_EXCLUDE_STOPPED_PACKAGES),因此,在 Stopped 階段的 packages 基本上收不到 intent,但是 3rd party app 可以自己加入 Intent.FLAG_INCLUDE_STOPPED_PACKAGES 這個 flag 讓 Stopped 階段的程式可以收到廣播內容!
因此,如果你不一想讓 App 收 System broadcast 的話,可以到管理選單上「Force Stop」,這樣就不會收到 broadcast 囉。同樣的,如果 App 沒有 Activity 的話,目前看起來就無法讓他自己跑起來了 ... ?
In frameworks/base/service/java/com/android/server/am/ActivityManagerService.java :
public void forceStopPackage(final String packageName) { if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) != PackageManager.PERMISSION_GRANTED) { String msg = "Permission Denial: forceStopPackage() from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES; Slog.w(TAG, msg); throw new SecurityException(msg); } long callingId = Binder.clearCallingIdentity(); try { IPackageManager pm = AppGlobals.getPackageManager(); int pkgUid = -1; synchronized(this) { try { pkgUid = pm.getPackageUid(packageName); } catch (RemoteException e) { } if (pkgUid == -1) { Slog.w(TAG, "Invalid packageName: " + packageName); return; } forceStopPackageLocked(packageName, pkgUid); try { pm.setPackageStoppedState(packageName, true); } catch (RemoteException e) { } catch (IllegalArgumentException e) { Slog.w(TAG, "Failed trying to unstop package " + packageName + ": " + e); } } } finally { Binder.restoreCallingIdentity(callingId); } }
在這邊有個 forceStopPackage() method,會呼叫 PackageManagerService.setPackageStoppedState,這個 method 會呼叫 Setting.setPackageManagerServiceLPw,然後把相對應 PackageName 的 PackageSetting 設定成 stopped ...
Android Developer 上有提到:http://developer.android.com/about/versions/android-3.1.html(但是我之前都沒注意到啊啊啊啊啊....)。
這個教訓告訴我們「要注意看 API Document」!
BTW,我這邊貼 code 是用 http://hilite.me/ 這個網站產生的。