Cancel Android Alarms without knowing the requestCodes - android

I have a MainActivity that starts a class HintergrundDienst extending Service by pressing a button btnStartStop on the MainGUI of MainActivity with
Intent inte = new Intent(getApplicationContext(), HintergrundDienst.class);
Bundle ints = new Bundle();
ints.putInt....
inte.putExtras(ints);
startService(inte);
MainActivity and HintergrundDienst both have a
PlayerClass pcObject = new PlayerClass();
Now
public class PlayerClass extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
///
}
public void abbrechen(Context context, long requestCode)
{
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent myIntent = new Intent(context.getApplicationContext(), PlayerClass.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context.getApplicationContext(), (int)requestCode, myIntent, 0);
alarmManager.cancel(pendingIntent);
}
public void alarmieren(Context context, long requestCode, int ResID)
{
AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
...
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, (int)requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
alarmMgr.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, requestCode, pendingIntent);
}
}
I set alarms in HintergrundDienst with audioAbspielen.alarmieren(this,time.getTimeInMillis(),R.raw.test);.
My goal is to press btnStartStop once for it to start and btnStartStop again for it to stop all alarms. My issue is that to stop an alarm, I need requestCode. I'd have to put all requestCodes into a List in PlayerClass. But I cannot access this List from MainActivity where btnStartStop is directly. But I could expose it via method in PlayerClass. But how I see it, the pcObject in MainActivity is not the one as in HintergrundDienst. So the list being filled in HintergrundDienst might be null or empty in MainActivity.
In short: how do I cancel all alarms in this context?

You can use SharedPreferences to save the value of requestCode when calling alarmieren, and retrieve it back to cancel.

Related

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);

Starting IntentService periodically with AlarmManager - Losing Data at certain point

In my app, I want to send sensor data every ten seconds via POST to a webserver.
I am doing this with an activity who starts/stopps a AlarmMananger who is calling an IntentService.
Problem is: the target URL is generated in the Activity and doesn't arrive at the IntentService.
Activity:
public class MyActivity extends AppCompatActivity {
...
#Override
protected void onResume() {
super.onResume();
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
AlarmManager alarmManager=(AlarmManager) getSystemService(ALARM_SERVICE);
String targetURL = "www.google.de";
alarmIntent.putExtra("targetURL", targetURL);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10000, pendingIntent);
}
...
}
Broadcast-Receiver:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String targetURL = intent.getStringExtra("targetURL");
Intent newintent = new Intent(context, SendPostRequest_Service.class);
newintent.putExtra("targetURL", targetURL);
context.startService(newintent);
}
}
Intent Service:
public class SendPostRequest_Service extends IntentService implements SensorEventListener{
...
public SendPostRequest_Service() {
super(SendPostRequest_Service.class.getName());
}
#Override
protected void onHandleIntent(Intent intent) {
String targetURL = intent.getStringExtra("targetURL");
// Problem: targetURL = null
//read sensors, send POST-Request via okhttp <- working
}
...
}
Do you have any suggestions?
Put your code into a test project. Only way I was able to get it working was to change the order of when the extra is added to the intent. Update MyActivty with the below. It would appear to G. Blake Meike point that there's a copy of the intent being done.
#Override
protected void onResume() {
super.onResume();
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
String targetURL = "www.google.de";
alarmIntent.putExtra("targetURL", targetURL);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
AlarmManager alarmManager=(AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10000, pendingIntent);
}
You'll need to take a wake lock in your BroadcastReceiver and release it in your Service. Otherwise, the system may return to a sleep state before your Service gets a chance to run. The WakefulReceiver is particularly useful for this. If you'd like some more details, this article will help: http://hiqes.com/android-alarm-ins-outs/

Cancel an AlarmManager pendingIntent in another pendingintent

I want cancel AlarmManager which define a service,in this service might start a new AlarmManger or cancel alarm that defined before.And I know the params pendingintent in alarmManager.cancel(PendingIntent),must be the same.compare with filterEquals(Intent other)
but It still not work.cancel failed.
here is my code
public class GetRoundStroe {
private Store[] stores;
private Context mContext;
public GetRoundStroe(Context mContext) {
this.mContext = mContext;
}
public Store[] getStores() {
if (ComCommand.haveInternet(mContext)) {
start_am_normal();
} else {
start_am_silence();
}
return stores;
}
public Store[] start_am_silence() {
long firstTime = SystemClock.elapsedRealtime();
AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
if (AlarmHolder.mAlarmNormal != null) {
am.cancel(AlarmHolder.mAlarmNormal);
}
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime, TestSwitch.getInstance().getSilence_time(), AlarmHolder.mAlarmSilence);
return null;
}
public Store[] start_am_normal() {
long firstTime = SystemClock.elapsedRealtime();
AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
if (AlarmHolder.mAlarmSilence != null) {
MyLog.e(GetRoundStroe.class,"AlarmHolder.mAlarmSilence"+AlarmHolder.mAlarmSilence+"");
am.cancel(AlarmHolder.mAlarmSilence);
}
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime, TestSwitch.getInstance().getNormal_time(), AlarmHolder.mAlarmNormal);
return null;
}
private static final class AlarmHolder {
static final PendingIntent mAlarmSilence = PendingIntent.getService(ApplicationContext.getInstance(),
0,
new Intent(ApplicationContext.getInstance(), GetRoundSilenceService.class),
0);
static final PendingIntent mAlarmNormal = PendingIntent.getService(ApplicationContext.getInstance(),
0, new
Intent(ApplicationContext.getInstance(), GetRoundNormalService.class),
0);
}
}
GetRoundSilenceService and GerRoundNormalService invoke start_am_normal() or start_am_silence; Anyone could help me? thanks
myIntent = new Intent(SetActivity.this, AlarmActivity.class);
pendingIntent = PendingIntent.getActivity(CellManageAddShowActivity.this,
id, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
pendingIntent.cancel();
alarmManager.cancel(pendingIntent);
These lines of code surely can help you remove/cancel the pending intent and alarm.
The main thing that you will need is:
Create pending intent with the same id and appropriate intent FLAG.
Cancel that pending intent.
Cancel the alarm using alarm manager.
#MKJParekh answer is correct, however I would like to add more information so that we all know what will work and what will not.
Lets say on activityA you create and set the AlarmManager to open activityC in 30 seconds, then on some other activity which can be any, we want to cancel that AlarmManager. Thus, we would do the following;
in activityA we create and set the AlarmManager;
//activityA
Intent myIntentA = new Intent(actvityA.this, activityB.class)
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent myPendingIntent = PendingIntent.getActivity(activityA.this, 0, myIntentA, PendingIntent.FLAG_ONE_SHOT);
//Calendar with the time we want to fire the Alarm
Calendar calendar = Calendar.getInstance(); // Get Current Time
calendar.add(Calendar.SECOND,30); //Fire Alarm in 30 seconds from Now.
((AlarmManager)getSystemService(ALARM_SERVICE)).setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), myPendingIntent);
in Another Activity some time later we want to cancel such AlarmManager created in activityA which we have no access to. Lets call this current activity activityZ;
//activityZ
Intent myIntentZ = new Intent(activityZ.this, activityB.class);
PendingIntent pendingIntentZ = PendingIntent.getActivity(activityZ.this, 0, myIntentZ, PendingIntent.FLAG_ONE_SHOT);
((AlarmManager)getSystemService(ALARM_SERVICE)).cancel(pendingIntentZ);
Some important points,
The context we provide in activityA in new Intent(context) and getActivity(context) are the same, however they do not have to match the activity from where we are canceling the AlarmManager, in this case activityZ has another context.
The class we want to open with the AlarmManager has to be the same in both activities new Intent (context, activityB.class), the requestCode which is an int must be the same, I used 0 for this example. Finally the flag has to be the same in both activities PendingIntent.FLAG_ONE_SHOT.
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); was used because PendingIntent.getActivity requires it if we are starting an activity outside of a context of an existing activity.

Android : AlarmManager not start

I must create an AlarmManager that repeating every seconds, I use this code
Intent in = new Intent(context,Tempo_Indietro.class);
in.putExtra("id_widget", appWidgetIds[i]);
PendingIntent pi = PendingIntent.getActivity(context, 0, in, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000, pi);
but it don't start...why ??
To start a Scheduled Activity: you can use like:
Step1: Setting for AlarmManager
Intent intent =new Intent(context,AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, in, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManger.RTC_WAKEUP,System.currentTimeMillis(), 1000, pi);
Step2: creating a BroadcastReceiver
public class AlarmReceiver extends BroadcastReceiver {
//override onReceive(Context, Intent) method
#Override public void onReceive(Context context, Intent intent)
{
//.........
Intent i = new Intent(context,Tempo_Indietro.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
//..........
}
}
Note: Don’t forget to include the newly created activity, receiver in the AndroidManifest.xml file.

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