I am trying to call from my BroadcastReceiver(ReceiverSchedule) to call a method (CancelSchedules) in my Activity(ViewScheduleActivity). The main problem I have is that it the Activity becomes null on the onReceive. I think I'm simply passing it into the intent wrong. I have tried the following link: Call an activity method from a BroadcastReceiver class.
First there is an alarmanager that will get called at the correct time then in the Receiver I want to cancel all alarms. Here is the code in the Activity to set the alarm (this part will work fine).
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent myIntent = new Intent(this, RecieverSchedule.class);
myIntent.setClass(this, recieverSchedule.getClass());
myIntent.putExtra("scheduleJson", gs.toJson(schedule));
myIntent.putExtra("LoginUserAsString", gs.toJson(loginUser));
myIntent.putExtra("PatientAsString", gs.toJson(patientResult));
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, myIntent, i);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Toast.makeText(ViewScheduleActivity.this, "Set One Time Alarm at: "+ hour +":" + min, Toast.LENGTH_LONG).show();
Now to pass the Activity over in my BroadCastReceiver I have:
public void setMainActivityHandler(ViewScheduleActivity main) {
viewScheduleActivity = main;
}
with the declaration on top:
ViewScheduleActivity viewScheduleActivity = null;
Now on create I would like to call the method CancelSchedules which is in my ViewScheduleActivity:
public void CancelSchedules()
{
for (int i =0; i< 10; ++i)
{
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent myIntent = new Intent(this, RecieverSchedule.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, myIntent, i);
alarmManager.cancel(pendingIntent);
}
}
In my onReceive in RecieverSchedule I have:
public void onReceive(Context context, Intent intent) {
viewScheduleActivity.CancelSchedules();
}
The problem is that viewScheduleActivity is null causing me to be unable to call it.
I have the following code to pass over the Activity with ReciverSchedule created as a member in the Activity:
recieverSchedule = new RecieverSchedule();
recieverSchedule.setMainActivityHandler(this);
IntentFilter callInterceptorIntentFilter = new IntentFilter("android.intent.action.ANY_ACTION");
registerReceiver(recieverSchedule, callInterceptorIntentFilter);
The setMainActivityHandler will get called and created, but I suspect that I am passing a new RecevierSchedule rather than the set receiverSchdule. If I am correct, how do I pass receiverSchedule into the Alarmmanager? I thought registerReceiver would fix this issue but maybe the placement is wrong.
Your Activity will likely be long killed and dead by the time the AlarmManager triggers your BroadcastReceiver. When that happens, Android will create a new process for your application, instantiate your BroadcastReceiver and call onReceive(). This is why the variable viewScheduleActivity is null.
As #Athena suggested, you don't need to call back into your Activity in order to cancel alarms.
Related
I've seen several examples on how to make some event to be repeated even when the app isnt running, but still I'm not sure if I got it.
With AlarmManager you can make your app to wake up to do something in some fixed interval without it consuming system resources between the periods, right?
But can it be to show up a toast over your current activity instead of having an Activity with a layout for it?
AlarmReceiver class:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// this is where to start activity or service to launch toast message
}
}
In activity or boot receiver:
private static final int PERIOD = 60000; //or whatever you need for repeating alarm
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent alIntent = new Intent(context, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, alIntent, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 60000, PERIOD, pi);
In AndroidManifest, add:
<receiver android:name=".AlarmReceiver"></receiver>
I am using Android AlarmManger to schedule an IntentService to run after small intervals.
Here is my AlarmManger:
static void setNextSchedule(Context ctx, long interval){
AlarmManager manager = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
Intent nIntent = new Intent(ctx, DService.class);
PendingIntent pIntent = PendingIntent.getActivity(ctx, 1, nIntent, PendingIntent.FLAG_UPDATE_CURRENT);
manager.setRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + interval, interval, pIntent);
Log.i(ScheduleAlarm.class.getSimpleName(), "Next alarm set");
}
And my IntentService:
#Override
protected void onHandleIntent(Intent intent) {
Log.i(DService.class.getSimpleName(), "Service starting");
ScheduleAlarm.setNextSchedule(getApplicationContext(), 15000);
}
Currently it just holds code for testing. Now this code will run successfully with no problems once the app starts but after 15 seconds it will state that the service is starting in the logcat but the code won't execute.
How to get the intenet service the execute the code inside the onHandleIntent each time it runs?
Thanks
When using a PendingIntent, the factory method needs to match the type of component that your Intent is for:
If your Intent points to an activity, use getActivity()
If your Intent points to a service, use getService()
If your Intent points to a BroadcastReceiver, use getBroadcast()
If your Intent points to none of the above, go directly to jail, do not pass Go!, do not collect $200 :-)
I have used the following code to start a broadcastreceiver which calls a new intent after its designted time, but the problem is the intent is not being called.
The alarm is called by a button on screen, when the button is clicked after designated time the new intent is expected to start.
private void alarm(){
br = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent i) {
Toast.makeText(c, "Rise and Shine!", Toast.LENGTH_LONG).show();
}
};
Log.v("ranjith","Inside setup");
registerReceiver(br, new IntentFilter("com.example.ads.test"));
pendingIntent = PendingIntent.getBroadcast( this, 0, new Intent(getApplicationContext(),test.class),0);
alarmManager = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
}
First, you are not calling set(), setRepeating(), or setInexactRepeating() on the AlarmManager, to schedule an event to occur that will send your broadcast.
Second, your PendingIntent is incorrect. Use the following to line up with your IntentFilter:
pendingIntent = PendingIntent.getBroadcast( this, 0, new Intent("com.example.ads.test"), 0);
Third, using a dynamically-registered receiver with AlarmManager is rather unusual, as it means that your alarm will only be valid while your application is running.
I set an AlarmManager object to start a service.
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); //context = getApplicationContext();
Intent alarmServiceIntent = new Intent(context, AlarmHandlingService.class);
alarmServiceIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
alarmServiceIntent.putExtra("alarmId", _id); //_id is a "long" value
PendingIntent pi = PendingIntent.getService(context, (int)_id, alarmServiceIntent, 0);
am.set(AlarmManager.RTC_WAKEUP, time, pi);
The onStartCommand(..., ..., ...) of AlarmHandlingService works as it has to work and when it has to work. There isn't any problem:
public int onStartCommand(Intent intent, int flags, int startId)
{
long alarmId = intent.getLongExtra("alarmId", -1);
Intent someActivityIntent = new Intent(this, SomeActivity.class);
someActivityIntent.putExtra("alarmId", alarmId);
someActivityIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(someActivityIntent);
return START_NOT_STICKY;
}
But then, when a new activity is opened (SomeActivity) and I call stopService(...), the service is not stopped:
stopService(new Intent(context, AlarmHandlingService.class)); //context = getApplicationContext();
This is the declaration of my service class in the manifest:
<service android:name="***myPackageName***.AlarmHandlingService"></service>
I tried to debug and noticed only that the registerReceiver (BroadcastReceiver receiver, IntentFilter filter) function of android.content.ContextWrapper class is called when I call the stopService.
From you comments you are not doing anything when your stopService is being called.
When you call stopService it will actually give a call to the function stopService().(which is being done in your application).
You must use onDestroy Method.
public void onDestroy ()
Added in API level 1
Called by the system to notify a Service that it is no longer used and is being removed. The service should clean up any resources it holds (threads, registered receivers, etc) at this point. Upon return, there will be no more calls in to this Service object and it is effectively dead.
(Do not call this method directly).
and the other problem is you are not calling anything to stop your alarm manager.
you must have called cancel method for AlarmManager.
please try with new activity.
stopService(new Intent(this, AlarmHandlingService.class));
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.