BroadcastReceiver Priority issue - android

I am implementing SMSListener in my app and I have set it's possibly highest priority as android:priority="2147483647" so that I should get the call on new incoming sms.
In my second sample app I have set the same priority as above for SMSListener but when I get call for new incoming SMS I am using abortBroadcast();.
When I ran both these app and I found that 1 is getting the call before 2. Now I am seeking this behaviour will remain as it is or it is not constant and 2 can get call before 1.
I want to make sure that my app get's the call whenever sms comes even if there exists some other app which has the highest priority and it is aborting the sms.
I hope I have put my point and looking for some convincing answer.
Thanks for devoting your time to my problem.

The abortBroadcast only works when they get it first, usually based on installation order, but not always.) System level apps will execute, then Android will try to sort out non-system apps. If you look at the source code, the order of execution is based on priority level, but the calls to select the order of apps is not consistent for apps over 999 or for apps with the same priority level. It might be in order of installation, but system changes can result in other orders of execution (which I have seen many times with testing this).

Another thing, from what I understand, the priority for applications must be between -1000 and 1000, inclusive.
http://developer.android.com/reference/android/content/IntentFilter.html#setPriority%28int%29
http://developer.android.com/reference/android/content/IntentFilter.html#SYSTEM_HIGH_PRIORITY

Related

Android 8.1.0 API 27: how to register to receive broadcasts about your app's Notification Settings Changes?

Can anyone suggest an Action (intent) which an Android 8.1.0 system should broadcast to registered receivers when changing Notification Channel setting values? Some years back, we did the work to update our notifications system into the required channels and groups and specified a broadcast receiver for the settings changes in the manifest (later on we had to fix that when they took away implicit intents, so now it registers in code too - but that's fixed already). Our receiver sets internal "display" settings which correspond to the notification-channel setting chosen by the user into our sharedpreferences file. That's what controls the display of the content when a user actually opens the app.
I have notes that say we tested this on Android 8, but the actions/intents we registered for don't exist until API28. I'm unclear on how this ever passed on the 8.1 devices, but maybe we were focused on the notifications only and didn't notice the display. So right now, we're stuck with notification settings changes working, but if a user happens to go to the app for something else, they still see messages they expected to be hidden.
Android 9+ notification settings changes work fine all the way through because the broadcast receiver registers for the new-in-API-28 NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED, ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED and ACTION_APP_BLOCK_STATE_CHANGED and these get delivered fine when a user changes settings, since I can see the receiver runs and sets the preferences as we want.
Just to debug this, I registered our BroadcastListener for a few extra intents (basically everything that looked like it might have something to do with notifications!) - like this:
// Register to receive a broadcast whenever notification settings are changed (before API 26 this was done by specifying in AndroidManifest only,):
notificationSettingsReceiver = new NotificationSettingsBroadcastReceiver();
IntentFilter filter = new IntentFilter(NotificationManager.ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED);
filter.addAction(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
filter.addAction(NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED);
filter.addAction(NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED);
filter.addAction(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED);
this.registerReceiver(notificationSettingsReceiver,filter);
This proved that the code in my BroadcastReceiver is working fine in 8.1.0 if it would only get called; I can force it to run by changing a few Notification settings (disabling them, or changing the sounds, etc) and then switching the phone into do-not-disturb mode. The actual notification-settings-changes don't ever cause any intent to arrive at my receiver, but the DND change does, so this triggers the notification settings to get written into sharedpreferences (which is where our display code is expecting to find them).
Pre-android 8 notification settings still seem to work fine too and we write these changes into our sharedpreferences file directly. Something about compatibility must just handle this for us because it all still "just works" on API 23 devices.
If anyone could suggest a way for an API 27 device to listen for notification-channel settings changes, I would be most grateful! There has to be a way to to this in API 27, isn't there?
After a few days of looking around and trying things, I was unable to have the NotificationManager in API 27 send anything at all to our BroadcastReceiver.
I was able to come up with a solution, although at first it seemed a bit heavy-handed.
For Android O+ devices, I simply added the same "syncPreferences" block of code to our app's onCreate, onResume and onDestroy methods which calls the same function as our BroadcastReceiver (which works fine in API 28+) to write the values into our shared_prefs file at that time. I say "heavy-handed" since it does it every time, regardless of whether anything has changed, but it actually works very well. It's actually simpler than all the overhead of building a receiver and listening for notification changes... I could probably eliminate that whole process now!
As an amusing aside, as a trekker, I have to admit that I got quite a chuckle from whoever adds the android VERSION_CODES constants though! Check the comment I found while looking up API numbers-to-buildcode declarations:
/**
* Q.
* <p>
* <em>Why? Why, to give you a taste of your future, a preview of things
* to come. Con permiso, Capitan. The hall is rented, the orchestra
* engaged. It's now time to see if you can dance.</em>
*/
public static final int Q = 29;

Detect application is being uninstalled in lollipop devices

I would like to know which users have uninstalled my application so that I can ask them for a feedback to improve the app. Hence, I would like to detect when the user has initiated the uninstallation process on my app.
One of the older solutions on StackOverflow had the following steps:
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(MAX_PRIORITY);
String activityName = taskInfo.get(0).topActivity.getClassName();
if (activityName.equals("com.android.packageinstaller.UninstallerActivity")) {
// do whatever is needed
Since Lollipop, getRunningTasks has been deprecated. So how can com.android.packageinstaller.UninstallerActivity activity be detected without getRunningTask?
Alternatively is there any other method to detect uninstallation process has been started on my app? Using getAppTask probably?
Apparently you wont be able to do this, you will have to rely on something called silent notification.
What we did was we sent notification every 3 days or whatever frequency you want.
On the client side as soon as a notification is received we hit a network call which mark NotificationReceived for the client. Now since notification are not full proof we assumed a threshold of 2/3 missed notification as uninstall event. And for the client we have this counter above decided threshold we contacted them for feedback.
Also no one will be willing to fill your form at the time of uninstallation as user has already decided to uninstall your application.
Read these 2 questions and answers:
native solution
GCM solution
As I know you have to mix the two. Read the limitations of first solution. You have to confirm uninstallation event of the first solution with the second solution for a complete implementation.
Hopefully, this solution will work for you. It helps you understand the reasons for your app uninstalls, reduce the uninstall rate using a powerful predictive engine and also get app Re-installs through a unique actionable channel (Android version 4.0 and above).
Just set a variable named appLastPresent for every user in the server-side and update that variable every day by calling an API using WorkManager's PeriodicWorkRequest. Also set installedDate variable when the user installs the app.
Now set up a chron job on the server side to check if the difference between installedDate and appLastPresent is greater than 7 days. Then send the user an email or message enquiring for issues or feedback, if it is greater.
NB: User can be offline for 7 days. Therefore only send email enquiring like why you are not using the app, if uninstalled please let us know why

Why do we need a UserHandle in many API declarations

In Android Open Source Project, a lot of core API declarations have an integer parameter userId in the end. I traced back and figured out the integer comes from a class called "UserHandle.java". There is a simple comments saying this class represents a user on the device. It still confuses me. Why do we need such a class? What's the difference between different values of the class, such as "USER_OWNER", "USER_CURRENT", "USER_CURRENT_OR_SELF"?
Thanks in advance!!!
Ever since Jelly Bean, Android platform has supported multiple users. This means that multiple users may be able to use one device, yet not be able to access other user's files or communicate with another user's app.
The first user on the device is user 0. The rest start their numbering from 10,11,... (In JB the numbering was 1,2...).
USER_OWNER is user 0.
He has some extra privileges over the other users (mostly access certain settings that others can't or uninstall an app for all users).
Multiple users on one device requires that only one user can be active in a specific point in time, this user is referred to as USER_CURRENT (since Kitkat().
In general one user's application can't send a broadcast message or an Intent to other user's apps.
Only apps with system permissions can do that (for example when the battery is running low, an intent will be sent to all).
Whenever you send an Intent from your app, the system service verifies whether this is a valid Intent i.e. if its supposed to reach all users then it's not.
This means that even if you were to use a certain api with the wrong userId (for example you force userId=0 even though this is user 10), then your call will receive a SecurityException.
To avoid such exceptions, there is also the option to send an Intent with USER_CURRENT_OR_SELF.
This means you're trying to send to the current user, but if he's not allowed to receive the Intent, let the same user who sent the Intent receive it.

Can you manually fire ACTION_BATTERY_LOW?

I'm relatively new to android programming but I'm told most applications have a receiver that will cut down on battery expensive activities when android fires ACTION_BATTERY_LOW.
Android developing page says:
public static final String ACTION_BATTERY_LOW
Added in API level 1
Broadcast Action: Indicates low battery condition on the device. This broadcast corresponds to the "Low battery warning" system dialog.
This is a protected intent that can only be sent by the system.
Constant Value: "android.intent.action.BATTERY_LOW"
I was wondering if there was a way to send this intent manually, at any desired battery level. I have a rooted device if that makes a difference.
No. It's not possible. Check this post. Look into the answer given by Mark(commonsware).
Sure there is a way to change the level - just download the terabytes of complete source code and spend a week or two building your own custom ROM, and trying to flash it without bricking your phone. It will only work on your device.
But no, you cannot change it in an app, nor on anyone else's device, and you cannot fire it yourself - did you read the part you quoted, "This is a protected intent that can only be sent by the system."?

Samsung Chord as a Backgorund Process

I am going to enter the Samsung 2013 app contest, and one of the requirements is that you use their Chord API http://developer.samsung.com/chord.
I plan on allowing users to send messages to all phones that have my app installed. From what I gathered from the information in the previous link, this means that I will need to have a constantly running background process for users to receive the messages when they are not looking at the app at the time.
I want to know if this is true, and if so, is this viable? I am considering using the method detailed here: Android: keeping a background service alive (preventing process death) if I go ahead with this.
I'm trying to use Samsung Chord too. I thing you don't need to do this. Samsung's API Chord already provides this control.
According Chord's API:
"If a Chord node doesn’t receive a UDP signal within a specified amount of time, it considers the “missing”
node to no longer be part of the network."
And, the only thing you have to do is:
"A node cannot receive a UDP broadcast if it is in LCD-off status. Therefore, if developers want the node to discover other nodes while the application is running, the node’s status should be set to LCD-on. To do this, use Android’s PowerManager.WakeLock."
Best regards,
Adriano

Categories

Resources