Alternative to ACTION_SHUTDOWN on Android API 28 - android

I am writing an Android app and need to performe some code before phone switches off. Previously, this was possible by defining a BroadcastReceiver and registering it in AndroidManifest.xml with:
<receiver android:name="MyBroadcastReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
In this case, before phone is switched off, an intent with action ACTION_SHUTDOWN is sent to MyBroadcastReceiver and the code in the methode onReceive is executed.
But this is not working anymore in API 28 because ACTION_SHUTDOWN cannot be registered in the manifest anymore.
I tried to register a BroadcastReceiver with ACTION_BOOT_COMPLETED (because it is still allowed) that triggers on boot a service whose task is to monitor and detect when the phone is shut down, but it didn't work.

Related

After device restart, my app receiving BOOT_COMPLETED broadcast slower/later than other apps?

When I restart my device, I am receiving BOOT_COMPLETED broadcast much slower (around 10-15 seconds later) than other apps.
I have seen this. But I do not think this is completely true. How (I think) I proved it wrong:
(Let's define X as an application that receives BOOT_COMPLETED broadcast faster than mine).
Installed X
Installed my application.
Restarted device.
RESULT: X received BOOT_COMPLETED broadcast very fast. My applicated received the broadcast slow.
Uninstalled both applications.
Installed my application once again.
Restarted device.
RESULT: My app received BOOT_COMPLETED broadcast slow again.
Uninstalled my application.
Installed X.
Restarted device.
RESULT: X received BOOT_COMPLETED broadcast very fast once again.
CONCLUSION: My app receives BOOT_COMPLETED broadcast slow whether X is installed or not. X always receives BOOT_COMPLETED broadcast very fast. How X is being able to receive the boot completed broadcast much faster than my application even though X is installed after my application?
That is why I do not think this is completely true answer. There is something X is doing that causing it to receive BOOT_COMPLETED at a higher priority than my app.
Maybe there are some other broadcasts other than BOOT_COMPLETED which are much faster?
Any suggestions are appreciated.
Manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
...
<receiver
android:name=".receivers.BootCompletedIntentReceived">
<intent-filter android:priority="2147483647">
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<!--For HTC devices-->
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
BootCompletedIntentReceived.kt
class BootCompletedIntentReceived: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
//DO SOMETHING HERE
}
}
The value of priority of intent-filter must be between -1000 and 1000.
Try this:
<intent-filter android:priority="999">
I suspect that the app X is a priveledged application.
From the documentation for android:priority attribute:
In certain circumstances the requested priority is ignored and the
value is capped to 0. This occurs when: A non-privileged application
requests any priority >0
So if X is a priveledged app and it requests a high priority, it will be granted, and your app, being non-priveledged, will always get the broadcast later.
Experiment
I created 2 sample apps - app1 and app2, each of which registered its own BroadcastReceiver for receiving an android.intent.action.BOOT_COMPLETED. So, BroadcastReceiver for app1 had a priority of 10 and the other - 20.
app1
...
<receiver
android:name="com.example.app1.BootCompletedIntentReceiver">
<intent-filter android:priority="10">
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
...
app2
...
<receiver
android:name="com.example.app2.BootCompletedIntentReceiver">
<intent-filter android:priority="20">
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
...
Result
2021-03-30 18:14:07.337 3453-3453/com.example.app1 E/Anatolii: BootCompletedIntentReceiver called
2021-03-30 18:14:07.509
3498-3498/com.example.app2 E/Anatolii: BootCompletedIntentReceiver
called
As it can be seen from the output, app1 received the intent earlier, event though it had a higher priority.
Answer
Your android:priority doesn't matter because android.intent.action.BOOT_COMPLETED is probably not sent in the synchronous way, and so priority is ignored as stated in the documentation:
android:priority
...
It controls the order in which broadcast receivers are executed to
receive broadcast messages. Those with higher priority values are
called before those with lower values. (The order applies only to
synchronous messages; it's ignored for asynchronous messages.)...

Receivers not receiving intents after boot on Galaxy S5 (on battery only!)

I am trying to get a BOOT_COMPLETED receiver to work on a Galays S5 Neo device (running 5.1.1) to start a service right after the device is fully booted.
So in the manifest i defined
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
and also added a receiver for the BOOT_COMPLETED intent
<receiver android:name="com.xyzMyApp.BootCompleteReceiver" >
<intent-filter android:priority="999" >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
This works fine on nearly all devices no matter if used on battery or not. On the Galaxy S5 Neo this is only working when the device is connected to power on boot. If i use the device on battery and do a reboot, it can take up to 5 minutes until the intent is received.
I also tried to receive other broadcasts like android.net.wifi.RSSI_CHANGED or android.intent.action.USER_PRESENT or android.intent.action.TIME_TICK to maybe use them as a replacement for the boot completed event. The idea was that those events happen pretty often and so after a reboot it won't take very long until one of the receivers is triggered. Turns out that the behavior is the same, on battery it can take up to some minutes until ANY of the receivers receives ANY intent.
I also disabled all kinds of battery optimization for apps i found in the system settings but that did not solve the issue.
Thanks for every hint or idea.
Try to add QUICKBOOT_POWERON as some devices have issues in receiving BOOT_COMPLETED broadcast:
<receiver android:name="com.xyzMyApp.BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
Also make sure your app is not installed on external storage(SD card) as suggested on this answer

Get PHONE_STATE event only when app is already running

I have an app for which I've added some functionality for when a call is coming in (phone ringing or answered). I did so by creating a BroadcastReceiver like this:
<receiver android:name="mypackage.PhoneReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" >
</action>
</intent-filter>
</receiver>
It is all working well but the problem is that it gets called even when my app isn't running, which makes sense but this triggers all sorts of other things on my app.
So the question is, can I have that BroadcastReceiver triggered only if my app (or a service I have) is running? or have my Application.onCreate() somehow know it is being created for the BroadcastReceiver and skip everything else it usually does?
Thanks.
You can take the receiver Off of the manifest, and register it programmatically in your code. Doing so, you can register/unregister whenever you want.

Broacast receiver not receiving intent if another app registered for same intent before (PHONE_STATE)?

My app registers in the manifest a broadcastreceiver for PHONE_STATE intent.
<receiver android:name=".receiver.PhoneStateReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
<action android:name="android.intent.action.PHONE_STATE"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Everything worked fine until i installed another app which handles phone calls (in specific it records audio of phone calls). From that moment my registered receiver does not fire every time. If i remote the second app all returns to be ok.
I assume that this app (as mine) registers a broadcastreceiver for PHONE_STATE intent. Is it possible that this app "consumes" the broadcastreceiver and so it will not fire mine?
i assume that the other broadcast consumer has called the abortBroadcast() method, that ... will prevent any other broadcast receivers from receiving the broadcast.

handling phone shutdown event in android

Could you post a simple code to handle shutdown event.
I need manifest and receiver.
I need the following:
I have a service running in background and I want to detect phone shutting down in order to make it in silent mode so that the terrible operator music doesn't play.
After restarting the phone (I already have on boot receiver) the service will enable phone sound.
You need to listen for the following intent action in your receiver:
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
To make it compatible with some HTC (or other) devices which offer quick power-off feature, you need to include the following action too with in the same intent-filter:
<action android:name="android.intent.action.QUICKBOOT_POWEROFF" />
For more info, read this
<receiver android:name=".ShutdownReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
<action android:name="android.intent.action.QUICKBOOT_POWEROFF" />
</intent-filter>
</receiver>
public static final String ACTION_SHUTDOWN
Broadcast Action: Device is shutting down. This is broadcast when the device is being shut down (completely turned off, not sleeping). Once the broadcast is complete, the final shutdown will proceed and all unsaved data lost. Apps will not normally need to handle this, since the foreground activity will be paused as well.
This is a protected intent that can only be sent by the system.
Constant Value: "android.intent.action.ACTION_SHUTDOWN"
And this ACTION_SHUTDOWN may differ from device to device
Like HTC its android.intent.action.QUICKBOOT_POWEROFF

Categories

Resources