salezica
salezica

Reputation: 77039

Android: receive ACTION_POWER_CONNECTED with application closed

A few years ago, I wrote a tiny application to apply some settings changes to my phone when the charging state changed.

To do this at the time, I registered a receiver in the manifest:

<receiver android:name=".services.PowerStateReceiver">
    <intent-filter>
        <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
        <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
    </intent-filter>
</receiver>

This receiver ran a few lines of code, and that was it. It worked perfectly.

Since API 26, this no longer works. I have to register the receiver at runtime, and it only seems to work while the app is open and for a while after it leaves foreground. I tried to switch methods, then tried using a Service to register the receiver with START_STICKY, to no avail.

How can I achieve the same effect with the current API restrictions?

Upvotes: 1

Views: 284

Answers (1)

user496854
user496854

Reputation: 6830

It is my understanding that Google clamped down on anything that allows the app to run in the background over the past few API versions, and there are only a few things that are exempt, and they're all pretty hacky. With any of these, you'll probably want to do the following 2 things:

  1. You'll need to make sure that your app is exempt from battery optimizations. You can either do it manually, or have your app launch an intent that'll let the user do it easily.
  2. You should also set your app Manifest with android:persistent="true", and extend your Appication class to keep it running in the background

And then, here are a few ways that you can have your app "wake up" or stay running:

  • Set up your app to have Notification Access with a NotificationListenerService, and then launch your BroadcastReceiver inside onListenerConnected(). That will keep the service running in the background, and because your receiver was registered inside it, it'll keep that running as well
  • Set up AlarmManager to periodically send your app an intent to wake it up, and then re-launch your BroadcastReceiver
  • Set up Firebase push notifications to periodically wake up your app, and it can then spin up the BroadcastReceiver

I think you can also set up your app as an AccessibilityService, but I don't remember if that will run continuously in the background

Edit: I forgot that you can also use WorkManager to schedule periodic wake-ups, and check if the power is plugged in. Here's how to do it

Upvotes: 1

Related Questions