Search code examples
androidbroadcastreceiverbattery

Receiver class doesn't recognize ACTION_BATTERY_CHANGED


I want to play a sound as a notification when battery charge is full.

in my receiver class I wrote 2 more notifications for "power connected" and "power disconnected" and they works ok!

but my receiver doesn't recognize the ACTION_BATTERY_CHANGED. I've searched a lot and I found out that I must register it programmatically.

The problem is that I need to register it without any Activity. Because I want to notify "Battery_Fully_charged" even when my program doesn't run.

how can I register something like this within my receiver ("MyReceiver.class")?

here is the sample code that I found and it workes. But I want to do it without an Activity.

public class Main extends Activity {
  private TextView batteryTxt;
  private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver(){
    @Override
    public void onReceive(Context ctxt, Intent intent) {
      int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
      batteryTxt.setText(String.valueOf(level) + "%");
    }
  };

  @Override
  public void onCreate(Bundle b) {
    super.onCreate(b);
    setContentView(R.layout.main);
    batteryTxt = (TextView) this.findViewById(R.id.batteryTxt);
    this.registerReceiver(this.mBatInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
  }
}

Edit: what is the difference between Service and Broadcase Receiver? I tried the Service but still didn't get any result


Solution

  • From documentation:

    You cannot receive this through components declared in manifests, only by explicitly registering for it with Context.registerReceiver(). [...]

    This means:

    1) Only a BroadcastReceiver can receive these intents.

    2) Only a dynamically registered receiver can receive these intents.

    You already understand how to do it inside an activity let's look at the service:

    public class MyService extends Service {
    
        private final IntentFilter batteryIntentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        private final BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context ctxt, Intent intent) {
                // React.
            }
        };
    
        public void onCreate() {
            super.onCreate();
            registerReceiver(batteryReceiver, batteryIntentFilter);
        }
    
        public void onDestroy() {
            unregisterReceiver(batteryReceiver);
            super.onDestroy();
        }
    
        public int onStartCommand (Intent intent, int flags, int startId) {
            return START_STICKY;
        }
    }
    

    You can decrease the chance of the service getting killed by putting it to foreground (google "foreground service").

    As mentioned in http://developer.android.com/preview/behavior-changes.html#bg-opt some implicit intents are going away so be prepared ACTION_BATTERY_CHANGED is going to be among them.