Trouble sending Bundle with PendingIntent to a Broadcast Receiver, data lost - android

I am adding some basic alarm functionality to my program via the use of AlarmManager and a BroadcastReceiver class (named AReceiver.java). My problem is that the data I add to the bundle attached to the Intent creating the PendingIntent appears to be lost. The only bundle data I can access in the AReceiver class is a android.intent.extra.ALARM_COUNT=1.
Here is the basic code in the main activity class creating the Intent, PendingIntent and the AlarmManager:
[Code in main activity - Notepadv3]
Intent intent = new Intent(Notepadv3.this, AReceiver.class);
intent.putExtra("teststring","hello, passed string in Extra");
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, pendingPeriodIntentId, intent, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, timeOfNextPeriod.getTimeInMillis(), alarmIntent);
[Code in the BroadcastReceiver - AReceiver]
public void onReceive(Context con, Intent arg1) {
Bundle extrasBundle = arg1.getExtras();
Log.d("broadcast","contains teststring = " + extrasBundle.containsKey("teststring"));
Log.d("broadcast","is empty? = " + extrasBundle.isEmpty());
Log.d("broadcast","to string = " + extrasBundle.toString());
}
Debug messages say that contains teststring is FALSE, is empty is FALSE and when outputting the whole bundle, I get the android.intent.extra.ALARM_COUNT=1 value.
Any help would be greatly appreciated.
Cheers,
Tom

You have to change this line
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, pendingPeriodIntentId, intent, 0);
into this
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, pendingPeriodIntentId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
otherwise the data is lost

Related

Recurring alarm BroadcastReceiver Intent string extras not getting updated

I have the below class to check if my alarms are being triggered at the exact time which I scheduled or is it differing.
I will call SetAlarm method inside the BroadCast Reciever from MainActivity. The consecutive alarms will be set by the Receiver itself by setting current time as its new string extra.
Alarms are working fine except the issue Intent string extras are not getting updated. ScheduledTime will always hold the initial value regardless of what I have set it in the setAlarm method.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Date currentTime = new Date();
String ScheduledTime = "";
if (null != intent) { //Null Checking
ScheduledTime = intent.getStringExtra("ScheduledTime");
//intent.removeExtra("ScheduledTime");
}
String message = "Current Time" + currentTime + ", Scheduled Time was: " + ScheduledTime ;
//Show Notification
long alarmMillis =(10*60*1000) ; //Set Alarm after 10 minutes
Long newTimeInMillis = System.currentTimeMillis() + alarmMillis;
currentTime.setTime(newTimeInMillis );
setAlarm(context, newTimeInMillis , currentTime.toString());
}
public void setAlarm(Context context, Long timeMillis, String ScheduledTime)
{
AlarmManager am =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, AlarmReceiver.class);
i.putExtra("ScheduledTime", ScheduledTime);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setExact(AlarmManager.RTC_WAKEUP, timeMillis, pi);
}
}
From Android official site
public static final int FLAG_UPDATE_CURRENT
Flag indicating that if the described PendingIntent already exists,
then keep it but replace its extra data with what is in this new
Intent. For use with getActivity(Context, int, Intent, int),
getBroadcast(Context, int, Intent, int), and getService(Context, int,
Intent, int).
This can be used if you are creating intents where only the extras
change, and don't care that any entities that received your previous
PendingIntent will be able to launch it with your new extras even if
they are not explicitly given to it.
So change your code from
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
to
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);

Stop alarmManager from other activity

I am trying to stop the alarmManager in the MainActivity from the onBackPressed() method in the Map activity. I have tried the code below but the alarmManager is not being stoped and still firing. How can I fix it?
Code in the MainActivity:
Intent intent = new Intent(MainActivity.this, GetLLRD.class);
intent.putExtra("json_data", json);
PendingIntent pendingIntent = PendingIntent.getService(
getApplicationContext(), 123, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar cal = Calendar.getInstance();
alarm.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), 20 * 1000, pendingIntent);
startService(intent);
Code in the Map Activity:
#Override
public void onBackPressed() {
Intent intent = new Intent(Map.this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getService(
getApplicationContext(), 123, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pendingIntent);
}
u problem is u use two different classes for intent to create and stop alarm:
Intent intent = new Intent(context,
GetLLRD.class);
Intent intent = new Intent(context,
MainActivity.class);
/** as in source code - new intent constructor */
public Intent(Context packageContext, Class<?> cls) {
mComponent = new ComponentName(packageContext, cls);
}
if u want to check if u got the same pending intent as before you can try to use:
Intent.filterEquals(oherIntent);
to cancel alarm you have two options use flag or use the same intent on alarm:
PendingIntent.FLAG_CANCEL_CURRENT
& i advice to make pending intent as final - example:
/**
* create pending intent
*/
final PendingIntent pIntent(Intent alarmIntent) {
// Create a PendingIntent to be triggered when the alarm goes off
return PendingIntent.getBroadcast(getApplicationContext(), AlarmReceiver.REQUEST_CODE,
alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
/**
* cancel alarm
*/
public void cancelAlarm(Intent alarmIntent, Context context) {
try {
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
/** use flag cancel here */
PendingIntent pIntent = PendingIntent.getService(context, AlarmReceiver.REQUEST_CODE, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
/** cancel alarm */
alarm.cancel(pIntent);
} catch (Exception e) {
// handle exception here
}
}
why to make pending intent final ?
because to cancel alarm u need:
Create pending intent with the same id and appropriate intent FLAG.
(to get reference to current pending intent)
PendingIntent.getBroadcast(context, REQUEST_CODE, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Cancel that pending intent.
PendingIntent.cancel();
Cancel the alarm using alarm manager.
AlarmManager.cancel(PendingIntent);
A PendingIntent itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. This means that, even if its owning application's process is killed, the PendingIntent itself will remain usable from other processes that have been given it. If the creating application later re-retrieves the same kind of PendingIntent (same operation, same Intent action, data, categories, and components, and same flags), it will receive a PendingIntent representing the same token if that is still valid, and can thus call cancel() to remove it.
if you are using activity, use
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
12345, intent,0);

Cancel alarmmanager from broadcast receiver using Pending intent

I have created a BroadCastReceiver which schedules some events using alarm manager.
In the BroadcastReceiver I am using following code to schedule.
Intent localIntent = new Intent("com.test.sample");
PendingIntent pi = PendingIntent.getBroadcast(context, 0,
localIntent, 0);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + (5 * 60 * 1000),
pi);
Here context comes from the onReceive method of the receiver.
I want to cancel this alarm on receive of other broadcast.
I am aware that alarm can be cancelled by alarmManager.cancel(pi);
However if the alarmanager was set from any other activity that how to get hold of PendingIntent to cancel it?
Thanks
You need to create a new PendingIntent with the same id then pass it as argument in cancelAlarm() method like follows:
To create alarm
int alarmId = 0; /* Dynamically assign alarm ids for multiple alarms */
Intent intent = new Intent(context, AlarmReceiver.class); /* your Intent localIntent = new Intent("com.test.sample");*/
intent.putExtra("alarmId", alarmId); /* So we can catch the id on BroadcastReceiver */
PendingIntent alarmIntent;
alarmIntent = PendingIntent.getBroadcast(context,
alarmId, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
To cancel alarm (in BroadcastReceiverwhitin onReceive(Context context, Intent intent)method)
int alarmId = intent.getExtras().getInt("alarmId");
PendingIntent alarmIntent;
alarmIntent = PendingIntent.getBroadcast(this, alarmId,
new Intent(this, AlarmReceiver.class),
PendingIntent.FLAG_CANCEL_CURRENT);
cancelAlarm(alarmIntent);

intent.putExtra doesn´t deliver newest values of a string to intent

I use AlarmManager and try to give some values in putExtra to my BroadcastReceiver. The values I send go to the BroadcastReceiver, it works fine to transmit values.
But I send my variable "counter" and I always get the old values that existed on the first start of my setRepeating(). And I know that the counter values are ways more high that I see there. So when the values change nothing happens. How can I have an event every half hour with right values?!
I've searched now for 3 hours but can't find a solution to make an interaction of my AlarmManager and some values out of a Sensor...
public void startAlarm(View view) {
try {
AlarmManager alarms = (AlarmManager) this
.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getApplicationContext(),
MyAlarmReceiver.class);
intent.putExtra("startStepCounter", startStepCounter);
intent.putExtra("lastStepCounter", lastStepCounter);
final PendingIntent pIntent = PendingIntent.getBroadcast(this,
1234567, intent, PendingIntent.FLAG_CANCEL_CURRENT);
alarms.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), timeToAlarmMilli, pIntent);
} catch (Exception e) {
}
}
public class MyAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Alarm Receiver", "Entered");
//
Bundle bundle = intent.getExtras();
int local_start = bundle.getInt("startStepCounter");
int local_last = bundle.getInt("lastStepCounter");
Toast.makeText(context,
"ALARM " + local_start + " " + local_last,
Toast.LENGTH_SHORT).show();
}
}
look at this part of your code
final PendingIntent pIntent = PendingIntent.getBroadcast(this,
1234567, intent, PendingIntent.FLAG_CANCEL_CURRENT);
you need to provide uniuque id for secound part each time you use pending intent, so instead of 1234567, use a unique id.

How can I setup multiple alarms in Android?

So far and thanks to this website, I've been able to set up an alarm that will be set up and active, even if I turn of my phone.
Now, I set up a alarm to show a reminder for event A and I need the application to setup another alarm to show another reminder for event B.
I must be doing something wrong, because it only fires the reminder for event A. It seems that once set up, any other alarm is understood as the same one. :-(
Here is the detail of what I am doing in two steps:
1) From an activity I set an alarm that at certain time and date will call a receiver
Intent intent = new Intent(Activity_Reminder.this,
AlarmReceiver_SetOnService.class);
intent.putExtra("item_name", prescription
.getItemName());
intent
.putExtra(
"message",
Activity_Reminder.this
.getString(R.string.notif_text));
intent.putExtra("item_id", itemId);
intent.putExtra("activityToTrigg",
"com.companyName.appName.main.Activity_Reminder");
PendingIntent mAlarmSender;
mAlarmSender = PendingIntent.getBroadcast(
Activity_Reminder.this, 0, intent, 0);
long alarmTime = dateMgmt.getTimeForAlarm(pickedDate);
Calendar c = Calendar.getInstance();
c.setTimeInMillis(alarmTime);
// Schedule the alarm!
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, alarmTime + 15000,
mAlarmSender);
2) From the receiver I call a service
Bundle bundle = intent.getExtras();
String itemName = bundle.getString("item_name");
String reminderOrAlarmMessage = bundle.getString("message");
String activityToTrigg = bundle.getString("activityToTrigg");
int itemId = Integer.parseInt(bundle.getString("item_id"));
NotificationManager nm = (NotificationManager) context.getSystemService("notification");
CharSequence text = itemName + " "+reminderOrAlarmMessage;
Notification notification = new Notification(R.drawable.icon, text,
System.currentTimeMillis());
Intent newIntent = new Intent();
newIntent.setAction(activityToTrigg);
newIntent.putExtra("item_id", itemId);
CharSequence text1= itemName + " "+reminderOrAlarmMessage;
CharSequence text2= context.getString(R.string.notif_Go_To_Details);
PendingIntent pIntent = PendingIntent.getActivity(context,0, newIntent, 0);
notification.setLatestEventInfo(context, text1, text2, pIntent);
notification.flags = Notification.FLAG_AUTO_CANCEL;
notification.defaults = Notification.DEFAULT_ALL;
nm.notify(itemId, notification);
Thanks in Advance,
monn3t
Ok, when you set an PendingIntent, you're supposed to assign it a unique ID to it, incase you want to identify it later (for modifying/canceling it)
static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags)
//Retrieve a PendingIntent that will start a new activity, like calling Context.startActivity(Intent).
static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)
//Retrieve a PendingIntent that will perform a broadcast, like calling Context.sendBroadcast().
The Request code is that ID.
In your code, you keep resetting the SAME PendingIntent, instead use a different RequestCode each time.
PendingIntent pIntent = PendingIntent.getActivity(context,uniqueRQCODE, newIntent, 0);
It has to be an integer, i suppose you have a primaryid (itemId) that can identify Alarm A from Alarm B.
You can set up multiple alarms by supplying different request code in pendingIntent.getBroadcast(......)
The approach which I used to setup multiple alarm is that I created a single alarm. I initialized a static integer in alarm setting class which will be incremented each time from my main activity whenever I click on "add alarm" button in my main activity.
E.g.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void addAlarmClick(View v) {
AlarmActivity.broadcastCode++;
startActivity(new Intent(this, AlarmActivity.class));
}
}
AlarmActivity.java
public class AlarmActivity extends AppCompatActivity {`
//........
public static int broadcastCode=0;
//........
Intent myIntent = new Intent(AlarmActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(AlarmActivity.this,
broadcastCode, myIntent, 0);
For an easier way, if you are listing your Alarms by RecyclerView,
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), recyclerAdapterAlarm.getItemCount()+1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
It works for me.

Categories

Resources