Notification buttons don't work for just one user - android

I have a notification for controlling media. I used to use my own custom views but now I've switched to MediaStyle. This is used for playing media tens of thousands of times per day by a lot of users. I have one single user that has ever complained that the buttons on the notification don't work. I got logs from him and my BroadCastReceiver is never getting called when he presses the buttons. What is also strange is that when I didn't use MediaStyle, he had the same exact issue.
This is how I set the intents:
Intent intent = new Intent(getApplicationContext(), PlayingBroadcastReceiver.class);
intent.setAction(action);
PendingIntent pending PendingIntent.getBroadcast(getApplicationContext(), id, intent, 0);
notifBuilder.addAction(R.drawable.icon, context.getString(R.string.label), pending);
What am I doing wrong? I've tested this on tons of phones and never had the issue, I have also never heard from a single other user with this issue after millions of uses of this notification.
This issue is on a Samsung Galaxy S6.
Edit: Got more info from the user today. I have an pending intent that opens an activity, it is set on setContentIntent. That one apparently works. The only difference is that that one uses PendingIntent.getActivity() vs the other that uses PendingIntent.getBroadcast() and of course the class the intent calls is different.

Turns out the user had manually disabled the BroadcastReceiver of my app. After months of complaints it is finally fixed.

Related

Android: Why use PendingIntent instead of Intent to start an activity?

I'm developing a news app, it gets the contents from the news website. I'm making a push notification service by using the new GoogleCloudMessaging technique, so i follow Google's official tutorial and i noticed that they used a PendingIntent, so here are my questions:
What is a pending intent exactly ?
And how does it differ from the normal intent ?
Can i replace it with a normal intent and still can pass my data (extras) to my desired activity ?
Is there any differences in usage and implementation between the two of them ?
Thanks in advance.
A pending intent has a special purpose- it can be passed to other apps to allow them to call into you with the same permissions of your app that other app might not have. PendingIntent should only be used when you're passing it off to another application, such as when setting a Notification (the Notification app can launch your activity via the pending intent). There's no reason to use it internally within your app.

Is there an equivalent solution like iOS's localNotification on Android platform?

My app needs to show notifications to users at certain specified time in the future (maybe months away). In iOS, all I need to do is this:
UILocalNotification* localNotification = [[UILocalNotificationalloc] init];
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:60];
localNotification.alertBody = #"Your alert message";
localNotification.timeZone = [NSTimeZone defaultTimeZone];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
However, in Android, it is much more complicated than I originally expected:
I have to install alarms with Alarm Manager, to start a service at each specified time in future.
These services, in turn, create a notification, and use Notification Manager to push the notification to status bar, etc.
But this solution has problems:
If the device is restarted before the alarm fires, the alarm is lost. I can register for boot-up broadcast like this and re-install the services. However, I really want to avoid installing duplicate alarms for the same event, but it seems there is no way to get currently installed alarms from the Alarm Manager?
The notification is composed at the scheduled time in future (say a month later), not when I set the notification(now). At that time, the required data for the notification may no longer be available. I don't see any way around this, except to store the relevant data, and wait for the alarm to fire.
Is there a pain-free solution to the local notification problem on Android?
If the device is restarted before the alarm fires, the alarm is lost.
I can register for boot-up broadcast like this and re-install the
services. However, I really want to avoid installing duplicate alarms
for the same event, but it seems there is no way to get currently
installed alarms from the Alarm Manager?
How are you going to get duplicated alarms when the device is restarted? When the device is restarted all alarms are canceled so you would do like you said where you start it again in the BroadcastReceiver when the device boots
The notification is composed at the scheduled time in future (say a
month later), not when I set the notification(now). At that time, the
required data for the notification may no longer be available. I don't
see any way around this, except to store the relevant data, and wait
for the alarm to fire.
that is correct you need to store the data that you want to show in the notification, SharedPreferences will probably be the easiest
EDIT:
You do not need to keep a reference to the pending intent all you have to do is create the intent the same way example
when you first created the alarm you used this intent
Intent intent = new Intent(context,MyClass.class);
//any flags or extras
PendingIntent.getBroadcast(context, 0, intent, 0);
Now you want to cancel that alarm so just create the same intent again, it must be a 1 for 1 of the origional
Intent intent = new Intent(context,MyClass.class);
//any flags or extras that you previously had
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmMgr.cancel(pi);

Broadcasting an EVENT_REMINDER

I am trying to broadcast an EVENT_REMINDER in order to cause the system to popup a notification. Is it possible or do I have to hit the route of implementing a Sync Adapter? That seems too much for such a simple task. I know some broadcasts are protected (CALL, SMS) but this should not be the case.
Intent intent = new Intent();
intent.setAction("android.intent.action.EVENT_REMINDER");
sendBroadcast(intent);
Thanks in advance!
I don't want to pop a Notification I want to simulate an event reminder programmatically
I have no idea what you think an "event reminder" is that isn't a Notification -- every device on which I use the Calendar app, event reminders are Notifications. Also, please note that what you claim in your comment runs counter to your first sentence of your question, where you specifically state that you want to "popup a notification":
I am trying to broadcast an EVENT_REMINDER in order to cause the system to popup a notification.
Regardless, the AOSP calendar app will not respond to your broadcast. From the manifest, you need to have a content:// Uri in the Intent, and presumably that will need to point to an actual calendar entry. And I would not be surprised if devices that replace the AOSP calendar app with their own do not support the broadcast at all.

AlarmManager stops working in Android 4.4.2 (using SetExact())

I'm setting in my code an alarm to go off in specific time.
The alarm mechanism works great on SDK < 19, but on 19 the alarms aren't fired.
Here is the code where I set the alarm :
public void SetAlarm(Context context, Long executionTime)
{
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReciever.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Only one alarm can live, so cancel previous.
am.cancel(pi);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
am.set(AlarmManager.RTC_WAKEUP, executionTime, pi);
} else {
setAlarmFromKitkat(am, executionTime, pi);
}
}
Since I'm setting the alarm using a Service I use GetApplicationContext() as the context.
The onReceive() code :
#Override
public void onReceive(Context context, Intent intent) {
for (SchedulerListener listener : listeners) {
listener.fetchAndRebuildNotification();
}
}
Here is the declaration of the BroadcastReceiver :
<receiver
android:name="com.SagiL.myAppName.BroadCastReceivers.AlarmReciever" />
The callback runs a method in a service (which is still alive when the alarm supposed to fire, notice it doesn't starts one).
This whole thing is a library which is used in my app, and there I declare the receiver the same way.
Sometimes the alarm do fires once, but mostly it doesn't fire at all.
Has anyone experienced such a thing ?
I can't believe it's common to SDK 19 since a lot of apps are using AlarmManager and they will break too if it is common.
I had a similar problem with my application. I found out that using 0 ad the id in getBroadcast(...); didn't work very well and caused numerous problems.
Try changing the id from 0 to the alarm's real id.
From:
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
To:
PendingIntent pi = PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
It´s a late answer, but may help. In Android KitKat 4.4.xx a battery manager is integrated (my device: Huawei Ascend Mate 7). There is an option to kill background process and services of an app in the battery manager. Don´t know if the options are named similar to the german options, so just try:
go to settings
select save energy
select detailed power consumption
select Screen off: perform further
enable Your app
It sounds simple, but that exactly was my problem. On Samsung Galaxy S3 with ICS everything worked like a charm. But bought a new device, the huawei, with Android 4.4.2, and suddenly my apps alarms didn´t work. After checking the system, I detected that option, enabled my app and now everything is fine. Not everything is a programming answer :) .
UPDATE
Since this answer was made, a lot happened in Android. For everybody with a similar problem: Since update to Marshmallow, there are two problems: first one is like described above, the second one is the doze mode:
Optimitzing Doze
Some devices, like my Huawei Ascend Mate 7, using both energy saving methods. So it isn´t enough to do what is described above. Also, you have to whitelist the app and use the new alarmManager methods setAllowWhileIdle(), setExactAndAllowWhileIdle() and setAlarmClock() .
Possible Problems
By whitelisting your app, you have to tell this the user. You can do it with a simple information at starting your app, for example a AlertDialog and/or you can use ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS intent to start the whitelisting screen. But be aware of this Action, because like reported from some developers, Google can suspend an app from playstore that is calling this action.
setAlarmClockshould also work, but if you do this, an alarm clock icon is on the top.
Testing
I have made some tests with that new documented doze mode and found out, that it usually works. But without whitelisting, the app falling to standby and ´alarmManager´ does not fire anymore, also not with that new methods. I tested it over night and the app is send to standby within about one hour. At a normal situation at day, where the user is active and often moves his device, it works without whitelisting.

Notifications combined with BroadcastIntents are stale , how to freshen them?

I am sending notifications out from a BroadcastIntentReceiver, however, when I click on the notification, it is from a few broadcasts ago.
I'm using this pattern, however, I do not believe that cancelAll() works. If it did, then wouldn't the fresh Broadcasts be getting their information into these notifs??
mNotificationManager.cancelAll();
mNotificationManager.notify(3, intent);
There is no concept in Android of a Notification being "stale".
I am going to take the educated guess that what you really meant to say was:
I created a Notification with a PendingIntent wrapped around an Intent that contained some extras. Later on, I updated or re-raised that same Notification on a PendingIntent for the same basic Intent but with new extras. Now, however, when I tap on the Notification, I see the original extras, not the current ones.
If so, you need to use FLAG_UPDATE_CURRENT when creating the PendingIntent (e.g., getActivity()).

Categories

Resources