0

I am now writing battery widget for Android. But here's the problem, I registered two BroadcastReceivers in my service. I start my service on my AppWidgetProvider's onEnable() method, and stop it in onDisable(). The service is meant to listen for battery state updates and orientation changes and notify the widget to update itself by sending my custom Intent to my AppWidgetProvider. Because both broadcast (battery_state_changed and configuration_changed) can't be received by normal AppWidgetProvider and AppWidgetProvider can't register BroadcastReceivers in itself.

It all works properly for a day or two. But sometimes, the widget just didn't update itself when the battery state changed, it seems either the receiver in my service didn't work or the custom Intent stopped reaching my AppWidgetProvider successfully suddenly.

Any idea why this is happening?

package com.carllee.widgets.kittenbatterywidget;

import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;

public class BatteryStateMoniterService extends Service {
    private static final String TAG = "BatteryStateMoniterService";
    private BatteryStateReceiver batteryStateReceiver;
    private OrientationChangeReceiver orientationChangeReceiver;

    @Override
    public void onCreate() {
        super.onCreate();
        Logger.log(TAG, "onCreate");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (batteryStateReceiver == null) {
            this.unregisterReceiver(batteryStateReceiver);
        }
        if (orientationChangeReceiver == null) {
            this.unregisterReceiver(orientationChangeReceiver);
        }
        Logger.log(TAG, "onDestroy");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (batteryStateReceiver == null) {
            registerBatteryStateReceiver();
        }

        if (orientationChangeReceiver == null) {
            registerOrientationChangeReceiver();
        }
        Logger.log(TAG, "onStartCommand");
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void registerBatteryStateReceiver() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        filter.addAction(Intent.ACTION_BATTERY_LOW);
        filter.addAction(Intent.ACTION_BATTERY_OKAY);
        batteryStateReceiver = new BatteryStateReceiver();
        this.registerReceiver(batteryStateReceiver, filter);
    }

    private void registerOrientationChangeReceiver() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
        orientationChangeReceiver = new OrientationChangeReceiver();
        this.registerReceiver(orientationChangeReceiver, filter);
    }

}
CarlLee
  • 3,952
  • 5
  • 23
  • 33

1 Answers1

0

Well, for one, the statement:

    if (batteryStateReceiver == null) {
        this.unregisterReceiver(batteryStateReceiver);
    }
    if (orientationChangeReceiver == null) {
        this.unregisterReceiver(orientationChangeReceiver);
    }

doesn't make any sense. You'll get NullPointerException every time. Change == to != ;)

Also, see my post about keeping background services alive.

Example of a complex service that runs in the background for long periods (out of necessity) that calls startForeground(). It can still be killed by the system or user, however.

Community
  • 1
  • 1
Jon Willis
  • 6,993
  • 4
  • 43
  • 51
  • Yes, thank you, but startForeground() needs a Notification as parameter, this will make a notification in the status bar(if I remember correctly), it doesn't make sense for a app widget to give a notification every time it is added to the launcher. Is there any better solution to stop my service being killed? Or should I just pass null to startForeground()? Or is there any way to stop the Notification from showing in the status bar? – CarlLee Apr 22 '11 at 03:19
  • 1
    Hi, I have found a solution, seems to work, not sure if it works, I'm still testing. The solution is to call "setForeground(true) ;" , this set the service as foreground while not showing any message in the status bar. – CarlLee Apr 22 '11 at 05:41