Android O : PHONE_STATE broadcast limitation - android

I have been trying to do something similar to truecaller app, where my app is supposed to show a screen after a call gets hung up. Was achieving this by registering android.intent.action.PHONE_STATE implicit broadcast in the manifest file.
But it is not working if I change the app to target Android O, because of the Android O broadcast limitation, and I'm trying to figure out an alternative solution to this use case.
Alternative solutions suggested in android docs: Job scheduler or register a service with context.
Job scheduler: Because of the Job scheduler optimizations there will be some delay to receive the callback. So it will affect the user experience if our app screen is shown a few min after the phone call and polling to check for new call logs every few seconds causes battery drain issue.
Register service with context in Java: I want the behavior to work even if the app is not active or alive. This will not work if the system kills the Service.
Register a Foreground Service: This requires a notification to be shown to the user all the time, which would be spam the user, and running a service 24/7 consumes lots of resources which defeats the whole purpose of broadcast limitation.
Please suggest an alternate solution so that the user experience remains the same.
Thanks in advance

Eventually, the action was added to the "Implicit Broadcast Exceptions" list so you can add ACTION_PHONE_STATE_CHANGED to your manifest and it will work:
https://developer.android.com/guide/components/broadcast-exceptions
ACTION_CARRIER_CONFIG_CHANGED,
TelephonyIntents.ACTION_*_SUBSCRIPTION_CHANGED,
"TelephonyIntents.SECRET_CODE_ACTION", ACTION_PHONE_STATE_CHANGED,
ACTION_PHONE_ACCOUNT_REGISTERED, ACTION_PHONE_ACCOUNT_UNREGISTERED
OEM
telephony apps may need to receive these broadcasts.

You have only one solution, use a foreground service and register the broadcast receiver in the service.

As there is NO proper solution to read the PHONE_STATE from Android O. The best alternative we can go for is to trigger a job on new call log entry from the content provider. By this, the behaviour is maintained of showing a screen(with a few sec of delay) after the call ends.
NOTE : The disadvantage is we cannot get the state of the phone call(Ringing or off_the_hook etc.,). The call back will only be received after the new call log has been added to the System DB.

For me, and my production app, the solution would be to avoid targeting api 25 and above, until a better workaround/api comes up.
If your app targets level 24 or below, you're not affected by the new Implicit Broadcast Limitations and your app can still listen to PHONE_STATE broadcasts even when your app is not running.
An app targeting lower APIs can still be downloaded and installed normally on new Android versions, the only reason to update your sdkTarget value is if your app requires usage of new APIs.

There seems to be an broadcast exception for ACTION_NEW_OUTGOING_CALL but not one for incoming call (or when call ends). It seems like a bug to have one for outgoing but not one for incoming. There's been a bug report filed in google issue tracker. Hopefully their answer will clarify what we should be doing.
I'll update this answer if/when the bug tracker gets updated.

As mentioned here: https://issuetracker.google.com/37273064#comment4, ACTION_PHONE_STATE_CHANGED (android.intent.action.PHONE_STATE) will be whitelisted for the Android O release. Though they may be replaced with a different mechanism in a future release.

Related

Receiving Incoming SMS post Android 8

Since android 8 the OS has placed may restrictions on how and when can the apps use Broadcast Receivers and Services.
Background Service Limitations
Broadcast Limitations
TL;DR: Starting Android 8 the OS will stop your Services and Broadcast Receivers except in some situations mentioned in above documents.
What is then a proper way to detect incoming sms? We can use WorkManager to manually query the SMS to check for new entries every 15 minutes. But what would be a way to get it instantly?
Also the official docs list the SMS_RECEIVE intent in the list of broadcasts that are exceptions to the above rules, but many have found that the receivers and services still get terminated and I have confirmed that by testing it myself.
There are some spend tracking apps out there that still do track the incoming sms regardless of the situation.
Would appreciate any inputs on the situation.
Thanks.

FirebaseMessagingService does not persist in memory after app is closed [duplicate]

I have read a similar question on SO, however, I was not able to get the correct answer from it.
I have a system wherein we send notification to around 500 devices.
Unfortunately, many of these devices are not receiving the notification. I have found that OPPO F1 series phones are particularly not getting the notification.
I have observed that this occurs if the app is stopped from multi-task tray. How do I resolve this?
Update: I have observed that when I close the app from task-tray, my app is forced stop in application manager. While when I close Whatsapp from task-tray, it is still not forced stop. How is that being handled by Whatsapp?
Update 03/2017 - Including a part of my answer here.
For the topic with regards to swipe closed/killed/force stopped, this topic has been discussed for quite some time and there doesn't seem to be a definite answer. During one of my testings, I am able to still receive a message (tested with a data-only message payload) if I Swipe close my app. But when I force closed it from the Settings menu, I wasn't able to receive any messages. Do note that this is not always the behavior.
There are some devices that were designed that when you swipe close the app, it will be the same as force stopping them (see my answer here).
There are also devices where even if the app is still just simply swiped away, even though it's not force closed, the device itself is preventing it from receiving messages. Others say that this can't be the case because apps like WhatsApp were able to do it. The reason I've learned so far for that is because the device manufacturers have whitelisted most of the well-known apps for it to be possible.
This is not documented anywhere because (IMO), this is a topic that depends also on the device and that FCM has no total control over.
Original Answer:
Since it's device specific (as you mentioned in your post: OPPO F1 series phones), it may very well be possible that when an app is stopped from multi-task tray in that device, it is actually killing the app, causing the services and other background processes associated with it to also be destroyed. See this answer for a little more idea of what I'm trying to say.
If you search around the community, what is commonly suggested here is to make use of the START_STICKY flag. However, I've seen that it was previously mentioned before for FirebaseMessagingService (see this post, comment by #ArthurThompson):
These services will be started by Google Play services, which is always running on the device. You don't have to and should not start/stop these services yourself.
With that said, there is also the possibility of (again from the comments):
There may be a setting on the device that allows/disallows this.
I suggest doing further testing if the services are being killed by the device itself or see if there are settings that are blocking the notifications.
Have you tried to use stopWithTask attribute on your service class?
<service
android:name="com.yourapp.YourPushService"
android:stopWithTask="false" />
If set to true, this service with be automatically stopped when the
user remove a task rooted in an activity owned by the application. The
default is false.
If the flag is false, there is an onTaskRemoved callback in your Service class.
In the case you can detect the "swipe" event, and you can implement a workaround.
I've been through the same but in my case, it was Xiaomi phones instead of Oppo phones. What actually happens is that when you close the app from system tray, the system kills the app entirely. What that means is your app won't be able to receive notifications via GCM/FCM. WAKE_LOCK permission doesn't help either.
That does NOT mean that phone is not receiving the notification. It is. It just won't let the apps show it. You can verify this by sending a broadcast from adb and looking at your logcat.
One possible solution to this problem is to use SyncAdapter. Although it is NOT advised, I've seen some apps using it. Other possible solutions are to use some kind of background service which is always running. Some people also use AlarmManager as it almost never gets killed. My point is - you cannot rely on GCM/FCM for your notifications.
Let's talk about WhatsApp now -
In Xiaomi phones, they whitelist or blacklist an app based on certain criteria. If you download an app and if it is in their whitelist, they'll permit the app to show notifications. If not, you already know what happens. But the good thing is that you can change these settings. Look for an app named Security. If you revoke the right permissions, even WhatsApp will stop showing notifications.
I was also facing the same issue, But then I realized after lots of debugging that, i was stopping the services that receive the Firebase notifications in on stop method of one of the activities.
Please check whether you are stopping these services anywhere in the app.
Make sure you are using service and not intent-service.
Swiping the app will never stop services. So try to debug the app for first two point.
Answer was found here
There are no way to send data message from notification console.
But there are other way to send notification to devices and them will be catch inside onMessageReceived!
You need can use terminal (Mac or Linux) or some service like Postman to send Post request on this link: https://fcm.googleapis.com/fcm/send
with the next body:
{
"to": "/topics/your_topic_here",
"data": {
"text":"text",
"text1":"text1",
...
}
}
also you need to add 2 headers:
Authorization - key=your_server_key_here
Content-Type - application/json
To get your server key, you can find it in the firebase console: Your project -> settings -> Project settings -> Cloud messaging -> Server Key
I am using MoEngage Push notification service to send push notifications.
The solution is to initialise the PushNotification object/service in Application class of Android , instead of MainActivity.
Then notifications will be received in killed state as well.
How to call from Application class
Declare the class name which will be the Application class inside application tag in your androidManifest.xml file
<application
android:name="App" //class name that will be an Application class
android:label="#string/app_name"
android:fullBackupContent="#xml/backup_descriptor"
android:usesCleartextTraffic="true"
android:icon="#mipmap/ic_launcher">
This will be the App.kt class
class App: FlutterApplication() {
override fun onCreate() {
super.onCreate()
//initialize your notification service here
}
}

How can I use a Broadcast Reciever and BOOT_COMPLETED to send a large list of notifications for a signed-in user

In my Xamarin Forms application, I have a reminder feature built in that uses the cross platform plugin LocalNotificationsPlugin. On the Github page, the author states for Android that:
Currently, if the phone is re-booted then the pending notifications are not sent, you should save them out to settings and re-send on re-boot.
I have looked into how to doing this and it looks like I will need a broadcast reciever, triggered with a startup RECEIVE_BOOT_COMPLETED in my manifest file. This works well when I test, calling the show notification code when I reboot my device. However, it gets a little more complicated when I try implementing what I need.
I have to dependency inject my setting service to retrieve the currently active user. I then have to use an injected todo service to get all of their reminders. Both of these are normally done as tasks when the app is running. But to do this from a broadcast reciever, it appears I either need to uses GoAsync() (for operations lasting no more than 10 seconds), or start an IntentService. I'm not sure which of these would be more suited, but my guess is an IntentService as the user might have a lot of stored reminders.
I'm also trying to work out if our Security API will be able to return the currently logged in user if the app is not running.
Debugging is also a headache with this. Most guides online tell you how to reattach to a process when Android Studio or Eclipse is involved, but Visual Studio and Xamarin don't seem to have any way to do this.
So I suppose my main questions are: Am I right in using a Broadcast Receiver and possibly an intentservice?
Can a stored user be accessed even if the app is not running?
Are there ways to effectively debug when using Broadcast receivers after rebooting? I've tried reattaching the debugger and logging to the DDMS but haven't had much success in seeing what's going on.
A sample project trying to do exactly what I'm doing would be very helpful to me, but I'm struggling to find one that's comparable to my problem.

Android receiver cannot always get broadcast correctly

I have a package added receiver in my Android application, and has been distributed for a couple months.
Recently I found that not all the PACKAGE_ADDED broadcasts can be received by my receiver.
looked up a while, someone said that if your app had been killed by users or system, then you will no longer get broadcasts.
My questions are:
Is that true?
confirmed, if you terminate your app from Settings->Applications --> force stop
then your application wont receive any broadcast.
How can I prevent this happening, or is there a work around?
1.Yes that is true.
2.Take a look at WakefulBroadcastReceiver that will wake up when it receives an Intent. Then make sure you spawn eg. an IntentService so it will process your work in the background.
Take a look at CommonsWare's WakefulIntentService for implementation example.

how implement broadcastrecevier for uninstall particular application in device?

I want to receive Broad Cast receiver for "when will i remove or uninstall my application in device,How to implement,
Thanks
there is no such broadcast. you are not notified when your application is removed
See my answer to [Android] Hook some regular tasks ?.
You can be notified when an app is removed (including your own), but you cannot prevent it or alter the outcome, so depending on what you want to do with the notification, it may not be of any practical use for you.
Also, since your app is being removed asynchronously, your window of opportunity to receive the notification may be too small to do anything practical or respond in any way.
You can use "android.intent.action.PACKAGE_REMOVED" to broadcast the application package that has been removed.

Categories

Resources