2

I have a very simple IntentReceiver to receive event when time changes. Here's the code:

public class IntentRec extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("IntentRec", intent.getAction());
    }
}

<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
    <receiver android:name=".IntentRec">
        <intent-filter>
            <action android:name="android.intent.action.TIME_SET"/>
        </intent-filter>
    </receiver>
    <activity android:name="MyActivity"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
</application>

However, I receive the intent while the application is running. But if I shutdown (using Force Close) the app, onReceive is not called. So my question is, do I receive intents only when listener app is running? I thought that intents was designed to run target listener class when the app was not running.

Thanks

Davita
  • 8,928
  • 14
  • 67
  • 119
  • possible duplicate of [How to use Intents from a Service or Broadcast Receiver?](http://stackoverflow.com/questions/1909812/how-to-use-intents-from-a-service-or-broadcast-receiver) – Ken White Jun 10 '12 at 23:34
  • 1
    "But if I shutdown the app, onReceive is not called." -- how precisely did you "shutdown the app"? – CommonsWare Jun 10 '12 at 23:35
  • When you say "shutdown the app" do you mean simply exiting the `Activity` or are you going to Settings -> Applications -> Manage Applications and using 'Force Close'? – Squonk Jun 10 '12 at 23:36
  • 1
    @Davita : Don't Force Close an app unless you have a specific reason to do so. Why do you think you have to go through so many steps (as I mention above) to actually do it? The Android OS manages resources very well, all you need to do is allow the user to exit your Activities and make sure your code cleans up things like Services when they're not needed. If you do that correctly, your app basically becomes dormant and the OS will clean it up if the few resources it still maintains are needed for other purposes. – Squonk Jun 10 '12 at 23:55
  • @Squonk, thanks for the info, but in this case, when the phone is booted, I won't receive intents until I start the app manually? – Davita Jun 10 '12 at 23:56
  • @Davita: Once the user has run some activity of yours, your manifest-registered `BroadcastReceivers` will work just fine, until the user presses Force Stop. This includes working again after a reboot. – CommonsWare Jun 11 '12 at 00:01
  • Hi CommonsWare, do you know if there's a way to detect that your app was previously force-closed by the user? – Reuben Scratton Dec 07 '12 at 23:49

2 Answers2

6

The solution is simple: stop clicking Force Close.

On Android 3.1+, Force Close will prevent anything in your app from running again, until the user runs an activity of yours manually, or something else (e.g., third-party app) starts up your app.


UPDATE

I suspect that you are being confused by multiple meanings of the word "stopped". Let's walk through the process, avoiding the word "stopped", to see if it helps.

When your app is first installed on an Android device, is in a state known to some as "snicklefritzed". While the app is in this "snicklefritzed" state, no manifest-registered BroadcastReceiver will work. To move an app out of the "snicklefritzed" state, some third-party app (like the home screen launcher) must explicitly request to run something in your app (like an activity). So, the normal course of events is that the user downloads your app, clicks on the launcher icon for it, and your app is moved into the "normal" state and away from the "snickelfritzed" state. While in the "normal" state, your BroadcastReceiver will work fine.

Let's suppose that your BroadcastReceiver is for the ACTION_BOOT_COMPLETED broadcast. The "snicklefritzed" state has nothing to do with whether your app is presently running or not -- it is dependent only upon if your app has ever run or not. Hence, if the user installs your app, but reboots their phone before doing anything with your app, your ACTION_BOOT_COMPLETED receiver will not get control at boot time. If, however, the user runs something in your app, then reboots the phone, your receiver will receive the ACTION_BOOT_COMPLETED broadcast as normal.

Normally, apps move out of the "snicklefritzed" state and never return to that state. One thing that will cause an app to be "snicklefritzed" again is if the user clicks on Force Close for this app in Settings. Here, the user is expressly telling Android that your app is misbehaving and should not run again until the user says otherwise. If, of course, the user launches your activity again, you move back to "normal" state.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • but how can I close an application otherwise? – Davita Jun 10 '12 at 23:47
  • @Davita: For testing purposes, you can terminate any process on an emulator, or debuggable processes on production hardware, from DDMS. – CommonsWare Jun 11 '12 at 00:00
  • Thank you very much again. So you say that at least one of my activities should be run manually in order to BroadcastReceivers to work. In this case, I don't understand how ACTION_BOOT_COMPLETED action works. I know that it is used to auto start apps at startup, and at startup none of activities are launched by users. I'm really confused here. Thanks again – Davita Jun 11 '12 at 00:08
  • Impressive, you was very helpful, thank you very much for clearing things up :-) – Davita Jun 11 '12 at 00:23
0

You have to add android:process=":remote" in order for the BroadcastReceiver to receive independent of your Activity.

<receiver android:name=".IntentRec"
    android:process=":remote"> //We declare that this is in a remote process
    <intent-filter>
        <action android:name="android.intent.action.TIME_SET"/>
    </intent-filter>
</receiver>

Cheers, Zed

Zaid Daghestani
  • 8,555
  • 3
  • 34
  • 44
  • Who the f**** troll downvoted this answer. You helped me a lot Zed, thanks :-). +1 – Davita Jun 10 '12 at 23:41
  • This is incorrect. Moreover, it is wasteful of RAM and may cause problems depending on what the `BroadcastReceiver` is trying to do (coordinating with the other process, if running). – CommonsWare Jun 10 '12 at 23:41
  • Tell that to Google's sample projects. ^_^ How else are you supposed to start a background service in the case of an intent, without having your activity pop up? This is exactly the point of android:process=":remote". It's up to the Dev to use it responsibly. – Zaid Daghestani Jun 10 '12 at 23:43
  • @Zed, could you please point me an article where I can shed light on it's drawbacks? – Davita Jun 10 '12 at 23:46
  • 2
    @Zed: ""Tell that to Google's sample projects" -- name any that use `android:process=:remote`. " How else are you supposed to start a background service in the case of an intent, without having your activity pop up? " -- your activity doesn't "pop up" because a manifest-registered `BroadcastReceiver` calls `startService()`. `android:process=:remote` has no effect on this behavior. "This is exactly the point of android:process=":remote"" -- no, it is not. – CommonsWare Jun 11 '12 at 00:03