5

I want a Broadcastreceiver to be called every time Intent.ACTION_BATTERY_CHANGED gets broacasted so I can track some data.

What I have now:

public class ReceiverApplication extends Application {

    @Override
    public void onCreate() {
        // Register Receiver
    }
    public static BroadcastReceiver myReceiver = new BroadcastReceiver()  {

        @Override
        public void onReceive(Context context, Intent intent) {
            // Start Service to progress data
        }       
    };  
}

This works fine UNTIL I use the Recent Apps "Taskmanager" to swipe away one of my preference Screens or my main activity. Then the BroadcastReceiver doesnt get called anymore. If I start one of my activities, onCreate() of ReceiverApplication gets called and it starts working again.

I could work around that by having a empty service running all the time. The service doesn't seem to get killed by swiping an activity away and onCreate() gets called after some time and restarts the BroadcastReceiver without doing anything. The problem here is that I don't want a service to run all the time.

So, how can I get a Broadcastreceiver outside of any Acitivity or Service which can receive Broadcasts as long as the user wants?

user1566228
  • 119
  • 1
  • 7
  • See this useful answer on SO: http://stackoverflow.com/questions/7257378/android-how-to-force-restart-service-os-killing-on-low-memory-behavior as well as this one: http://stackoverflow.com/a/7877466/490961 – Vincent Mimoun-Prat Sep 17 '12 at 19:50
  • @MarvinLabs Thanks, what exactly are you refering to? Because if possible I dont want to use a Service. – user1566228 Sep 17 '12 at 20:11

3 Answers3

2

I want a Broadcastreceiver to be called every time Intent.ACTION_BATTERY_CHANGED gets broacasted so I can track some data.

This broadcast may be sent a lot. Hence, Android only allows running applications to receive this broadcast, so it does not have to fork a bunch of processes just to tell a bunch of apps "hey, the battery level changed".

This works fine UNTIL I use the Recent Apps "Taskmanager" to swipe away one of my preference Screens or my main activity. Then the BroadcastReceiver doesnt get called anymore.

That act terminates your process.

So, how can I get a Broadcastreceiver outside of any Acitivity or Service which can receive Broadcasts as long as the user wants?

Normally, you would register for the broadcast in the manifest. For ACTION_BATTERY_CHANGED, this is not possible.

Bear in mind that you can poll ACTION_BATTERY_CHANGED -- instead of calling registerReceiver() with an actual BroadcastReceiver, pass in null. The return value of registerReceiver() will be the last ACTION_BATTERY_CHANGED Intent. So, if you can get away with finding the battery level every few minutes, use AlarmManager to wake up every so often and check the current battery level.

CommonsWare
  • 910,778
  • 176
  • 2,215
  • 2,253
0

Instead of nesting a broadcast receiver and registering it dynamically, declare one in your Android manifest According to the documentation, BATTERY_CHANGED cannot be declared in the manifest:

You can not receive this through components declared in manifests, only by explicitly registering for it with Context.registerReceiver(). See ACTION_BATTERY_LOW, ACTION_BATTERY_OKAY, ACTION_POWER_CONNECTED, and ACTION_POWER_DISCONNECTED for distinct battery-related broadcasts that are sent and can be received through manifest receivers.

I would register a broadcast receiver to recieve all these events:

    <receiver
        android:name="MyBroadcastReceiver">
        <intent-filter>
            <action
                android:name="android.intent.action.BATTERY_LOW" />
            <category
                android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <intent-filter>
            <action
                android:name="android.intent.action.BATTERY_OKAY" />
            <category
                android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <intent-filter>
            <action
                android:name="android.intent.action.ACTION_POWER_CONNECTED" />
            <category
                android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <intent-filter>
            <action
                android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
            <category
                android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

The broadcast receiver will be notified regardless of whether your app is running or not.

Samuel
  • 15,583
  • 5
  • 54
  • 70
  • 2
    Sadly I dont think BATTERY_CHANGED can be registred via manifest – user1566228 Sep 17 '12 at 19:58
  • @user1566228 You're right. The docs say you can listen to individual battery events, however. Will that work for you? See my updated answer. – Samuel Sep 17 '12 at 20:03
  • Thank you, but no sorry I especially need to get a Broadcast when batterylevel changes so I guess that wont work. – user1566228 Sep 17 '12 at 20:07
  • Then you'll really need a service to register it for you. I don't think there is any other way. I'm pretty sure they don't let you declare it in the manifest because an instance of the receiver would have to be created every time the intent is broadcast which is very frequently. With a dynamic registration, one instance can be used over and over. See @MarvinLab's comment addressing issues with onCreate and services. – Samuel Sep 17 '12 at 20:09
  • Well I guess. I just think its stupid to have a service running all the time that basically doesnt do anything :/ Thanks for your help Samuel :) – user1566228 Sep 17 '12 at 20:13
  • @user1566228 Yeah it's pretty annoying. – Samuel Sep 17 '12 at 20:18
0

In addition to the answer already made, it's normal that your app stops to work correctly when you "swipe it away" with a Task Manager. A taskmanager will stop it because the user asks it.

If you don't want to stop the life cycle of your activity, just don't do it... Your application will call the onPause() method, and other ones if needed, and your broacast will still available even if the user don't actually use your application. The task manager will kill the app and all "related" threads.

If you want some details about Activity's life cycle, please take a look to the official documentation : http://developer.android.com/reference/android/app/Activity.html

mithrop
  • 3,123
  • 2
  • 19
  • 39