Android: AlarmManager on firing correct alarms - android

ALREADY ANSWERED, FOR THOSE WHO HAVE THE SAME PROBLEM PLEASE REFERE TO THE BOTTOM OF THIS POST
I have this part on my app which schedules an alarm, all was working well, it scheduled the alarm correctly but there is a erratic behavior wherein sometimes, when the alarm scheduled is fired, instead of firing once, it fired several times, i know this cuz everytime an alarm fires i displayed "ALARM FIRED" on logcat, there are several ALARM FIRED on my logcat, sometimes up to 10, what im confused about is that i only scheudled that alarm once, and it fired many times. Here is Codes:
THIS IS FOR SCHEDULING MY ALARM THIS IS ON THE Helper class accessed in static way
public final static String ACTION = "com.medical.organizer.utilities.NotifyReciever";
private static NotifyReciever RECIEVER = new NotifyReciever();
public static void scheduleAlarm(Context context,String message,int rCode, long triggerTime)
{
RECIEVER = new NotifyReciever();
NotifyAlarm.TRIGGER_TIME = triggerTime;
NotifyAlarm.CONTEXT = context;
IntentFilter inFil = new IntentFilter(ACTION);
NotifyAlarm.CONTEXT.registerReceiver(RECIEVER, inFil);
Intent intent = new Intent(ACTION);
intent.putExtra("message", message);
NotifyAlarm.INTENT = intent;
NotifyAlarm.startAlarm(rCode);
}
public static void cancelAlarm(Context context, int requestCode)
{
RECIEVER = new NotifyReciever();
NotifyAlarm.CONTEXT = context;
IntentFilter inFil = new IntentFilter(ACTION);
NotifyAlarm.CONTEXT.registerReceiver(RECIEVER, inFil);
Intent intent = new Intent(ACTION);
NotifyAlarm.INTENT = intent;
//context.unregisterReceiver(RECIEVER);
NotifyAlarm.stopAlarm(requestCode);
}
THIS IS FOR THE ALARM ITSELF
public class NotifyAlarm {
public static Context CONTEXT;
public static Intent INTENT;
public static long TRIGGER_TIME;
public static void startAlarm(int requestCode)
{
AlarmManager am = (AlarmManager) CONTEXT.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(CONTEXT, requestCode, INTENT, 0);
am.set(AlarmManager.RTC_WAKEUP, TRIGGER_TIME, pendingIntent);
Log.d("AlarmCheck", "Alarm Started for the First Time, set() was called");
}
public static void stopAlarm(int requestCode)
{
AlarmManager am = (AlarmManager) CONTEXT.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(CONTEXT, requestCode, INTENT, 0);
am.cancel(pendingIntent);
Log.d("ALARMSTOP","========ALARM WAS STOPPED AT THIS POINT==========");
}
}
THIS IS FOR MY ALARM RECIEVER (BROADCAST RECIEVER)
public class NotifyReciever extends BroadcastReceiver {
private Context context;
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
Log.d("AlarmCheck","ALARM FIRED!");
AlertDialog.Builder build = new AlertDialog.Builder(context);
String message = intent.getStringExtra("message");
build.setMessage(message);
build.setCancelable(false);
build.setPositiveButton("Snooze", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//Rechedules the alarm after 25 secs time of interval is for
//testing purposes only
NotifyReciever.this.context.unregisterReceiver(NotifyReciever.this);
Helper.scheduleAlarm(NotifyReciever.this.context, s,
s.getRequestCode(),System.currentTimeMillis()+Helper.TWENTY_FIVE_SEC);
}
});
build.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//CANCELS THE ALARM
Helper.cancelAlarm(NotifyReciever.this.context, s.getRequestCode());
}
});
AlertDialog alert = build.create();
alert.show();
}
}
Note that the receivers aren't declared through XML, they are registered programatically so to support dialogs.
Consider this situation, this is where i notice that behavior always occurs, Say, i've added a schedule and scheduled the alarm # 5:00am (Current time is 4:59), so at first it fired completely fine, then i decided to rescheduled that alarm to 5:01 (Current time 5:00) then this occurs, the alarm is fired for several times. the alear dialog appears several times, have to fast click them all to cancel the dialogs, sometimes my app crashes due to too many dialogs showing up.
anyone knows how to go about this problem please do share and anybody knows how to properly schedule and fire an alarm please do share, as well as scheduling and firing multiple alarms as well as canceling them would be much appreciated. Explanation and some examples would be better.
EDIT
Legend: a colored dot on the side means that it is fired a at specific time and that was what logged on logcat, say an alarm fired # 4:00 display the one with several blue dots
EDIT THIS IS THE ANSWER
So this is what i've discovered , mine is that you have to register your reciever only once, so to avoid multiple returns from the intentFilter, which matches all intents using ur ACTION, in my case i've registered my reciever over and over again so there are already many instances of intents with the same ACTIOn thus returning multiple recievers and yeah firing multiple alarms at a specified time instead of firing only one receiver, so yeah REGISTER OONLY ONCE YOUR RECEIVER MAYBE AT A GLOBAL CLASS IF YOU DECIDE NOT TO DECLARE YOUR RECEIVER IN XML

Related

Android alarm triggers repeatedly

I am trying to set an alarm to call a method in MainActivity. I have used the method described here; the alarm fires but once it does it repeats about once a second.
I am using setExactAndAllowWhileIdle since the alarm is needed only every hour or so (actually it doesn't need to be exact, I could use setAndAllowWhileIdle instead but that gives the same problem).
My Alarm class is pretty simple:
public class Alarm extends BroadcastReceiver
{
static MainActivity main = null;
public Alarm()
{
}
public Alarm(MainActivity ctx)
{
main = ctx;
}
#Override
public void onReceive(Context context, Intent intent)
{
if (main != null)
main.alarmAction();
}
}
In OnCreate() for MainActivity I have
alarmReceiver = new Alarm(this);
IntentFilter alarmFilter = new IntentFilter("Alarm");
registerReceiver(alarmReceiver,alarmFilter);
and then I have methods:
public void SetAlarm() {
alarmStarted = true;
Intent i = new Intent(this, Alarm.class);
i.setAction("Alarm");
PendingIntent pi = PendingIntent.getBroadcast(this, 1001, i, 0);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.cancel(pi); // tried this to solve the problem but probably not needed
am.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, 1000 * 60 * 10, pi);
}
public void alarmAction() {
if (!alarmStarted)
return;
SetAlarm();
// will be more stuff here but this is minimum required to show problem
}
The flag alarmStarted is set from a button press.
Android Studio is giving me a memory-leak warning about the use of static in static MainActivity main = null, but without this main is always null in onReceive. I don't know if the repeating alarm issue is connected with this or not.

How to display an alert box using Alarm Manager and BroadcastReceiver

I want my android app to pop-up an alert dialog box at specific time of each day. Of what I have understood is that we need to use Alarm manager to set the time of the day on repeating, and then send a broadcast to display the alert dialog box. The alert box should be displayed at the specified time even if the app is closed. I have tried the following code but it does not do anything at the specified time. Please suggest what needs to be done. I am new to android development and this is my very first implementation.
Main_Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR,Calendar.MONTH,Calendar.DAY_OF_MONTH,6, 10);
setAlarm(calendar.getTimeInMillis());
}
private void setAlarm(long timeInMillis) {
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlertBox.class);
PendingIntent penIntent = PendingIntent.getBroadcast(this,0,intent,0);
am.setRepeating(AlarmManager.RTC_WAKEUP,timeInMillis,AlarmManager.INTERVAL_DAY,penIntent);
//Toast.makeText(this,"Alarm is set",Toast.LENGTH_SHORT).show();
}
AlertBox
#Override
public void onReceive(Context context, Intent intent) {
DisplayAlertBox(context, "Tip of the Day");
}
private void DisplayAlertBox(Context context, String msg) {
Toast.makeText(context, "Dialog Box should display Now", Toast.LENGTH_LONG).show();
PendingIntent alertBox = PendingIntent.getActivity(context,0, new Intent(context,MainActivity.class),0);
AlertDialog.Builder aBuilder = new AlertDialog.Builder(context);
aBuilder.setTitle("Message");
aBuilder.setMessage(msg);
aBuilder.setPositiveButton("Accept",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int whichButton)
{
}});
aBuilder.create();
aBuilder.show();
}
The reason why nothing is happening is because you don't have a clear understanding of BroadcastReceiver.
BroadcastReceivers, once registered, will sit there waiting for a broadcast that it can receive. Registering a BroadcastReceiver can be done in both your Manifest file or through your code. The broadcast that it can wait to receive can be either an implicit or explicit broadcast. But in your case, it's an explicit broadcast. So you would declare it in your Manifest like so:
<receiver android:name="com.package.AlertBox">
<intent-filter>
<action android:name="can.be.any.name.like.tip.of.the.day"
</intent-filter>
</receiver>
You may also register the BroadcastReceiver through code if you don't want to do so through the Manifest.
Your problem is that the intent that you're sending to your AlarmManager is Intent intent = new Intent(this, AlertBox.class). What this does is that it's only going to start your BroadcastReceiver, which isn't necessary once it's already registered. It's onReceive() is never called this way.
Your AlertBox will only show the AlertDialog when onReceive() is called, but onReceive is never called because a BroadcastReceiver's onReceive is only called when it receives the broadcast it's registered to receive.
So your setAlarm() method should be written like this:
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent("can.be.any.name.like.tip.of.the.day");
PendingIntent penIntent = PendingIntent.getBroadcast(this,0,intent,0);
am.setRepeating(AlarmManager.RTC_WAKEUP, timeInMillis, AlarmManager.INTERVAL_DAY, penIntent);
Keep in mind that the String that's used as the action of the Intent must match the String that your Broadcast Receiver is listening to. This way, the onReceive() method will be able to trigger.
However, I should also mention that the BroadcastReceiver should not be where you run your AlertDialog. BroadcastReceivers are meant for short execution of codes and are not meant to persist for a lengthy amount of time. For that, an Activity or Service would be a better option.
You should consider having the AlarmManager launch a transparent Activity that hosts a DialogFragment instead.

Enable button for a limited time period in a day in Adndroid

I have a button it should work according to time from 09.00 Am to 04.00 pm and rest of time it should not work.
I am developing an app. I am new in android. I have three buttons namely register, events, gallery.
When I click register button it should work according to time mentioned above.
if the user click register on that time it should pass on to the next activity and rest of times the button click action should not work.
check for class AlarmManager
on app start create AlarmManage class service with
time gap current to desable/enable time in milisecond.
public class MyReceiver extends BroadcastReceiver {
private static final int PERIOD = 1200000;//20*60*1000; 20 minutes
#Override
public void onReceive(Context ctxt, Intent i) {
scheduleAlarms(ctxt);
}
public static void scheduleAlarms(Context ctxt) {
AlarmManager mgr =
(AlarmManager) ctxt.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(ctxt, AuthenticateService.class);
PendingIntent pi = PendingIntent.getService(ctxt, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + PERIOD, PERIOD, pi);
}

my alarm service run several times and not in actual time

i have an alarm service that works with alarm manager. it's works correctly when you set alarm for later. but when you set it for past ( you want to alert you tomorrow) it gone crazy and alert several times instead of once and finally wont work tomorrow.
some one plz help me on this.
i do like this: I have a alarm class. when i create it, so it make an pending intent that run a service with alarm manger. and the service will open my activity.
is it the wrong way?
here is my alarm class:
public class MyAlarm {
private Context myContext;
private NotificationManager mNM;
private int NOTIFICATION = 10002; //Any unique number for this notification
MyAlarm(Context myAct){
myContext = myAct;
showNotification();
}
// this constractor is for cancelling alarm
MyAlarm(Context myAct, String str) {
myContext = myAct;
cancelPendigIntent();
}
private void cancelPendigIntent() {
//Intent myIntent = new Intent(myContext, MyAlarmService.class);
//G.pendingIntent = PendingIntent.getService(myContext, 0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);
//G.pendingIntent.cancel();
//G.alarmManager.cancel(G.pendingIntent);
}
private void showNotification() {
Intent myIntent = new Intent(myContext, MyAlarmService.class);
G.pendingIntent = PendingIntent.getService(myContext, 0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);
G.alarmManager = (AlarmManager)myContext.getSystemService(Context.ALARM_SERVICE);
G.calendar = Calendar.getInstance();
int to_day= G.calendar.get(Calendar.DATE);
int to_mounth= G.calendar.get(Calendar.MONTH);
int to_year= G.calendar.get(Calendar.YEAR);
G.calendar.set(to_year, to_mounth, to_day, Integer.parseInt(G.myPref.loadString("alert_time_houre")), Integer.parseInt(G.myPref.loadString("alert_time_mins")), 0);
Log.i("LOG", "alert_time_houre="+G.myPref.loadString("alert_time_houre")+" alert_time_mins="+G.myPref.loadString("alert_time_mins"));
G.alarmManager.setRepeating(AlarmManager.RTC, G.calendar.getTimeInMillis(),AlarmManager.INTERVAL_DAY, G.pendingIntent);
}
i finally find the answer.
my problem is not about alarm manager.
i set the pendig intent to a service that opens a activity. the problem was while the service is run in background it opened my activity again and again and my app go crazy. maybe i should destroy the service after her job done once.
i change it from service to broadcastreceiver and it's works correctly.
thanks for guides :)

Android-Broadcast Receiver

I am new to android. I what to know the difference between Intent and BroadcastReceiver. I am more confused with BroadcastReceiver than Intent.
Please help me out. Simple code will be helpful.
Ok, I will explain it with an example.
Let's suppose I want to create an app to check subway status from it's webpage. I also want a system notification if the subway is not working ok.
I will have:
An Activity to show results.
A Service to check if the subway is working and show a notification if it's not working.
A Broadcast Receiver called Alarm Receiver to call the service every 15 minutes.
Let me show you some code:
/* AlarmReceiver.java */
public class AlarmReceiver extends BroadcastReceiver {
public static final String ACTION_REFRESH_SUBWAY_ALARM =
"com.x.ACTION_REFRESH_SUBWAY_ALARM";
#Override
public void onReceive(Context context, Intent intent) {
Intent startIntent = new Intent(context, StatusService.class);
context.startService(startIntent);
}
}
Explanation:
As you can see you can set an alarm. and when the alarm is received we use an intent to start the service. Basically the intent is a msg which can have actions, an serialized stuff.
public class StatusService extends Service {
#Override
public void onCreate() {
super.onCreate();
mAlarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intentToFire = new Intent(AlarmReceiver.ACTION_REFRESH_ALARM);
mAlarmIntent = PendingIntent.getBroadcast(this, 0, intentToFire, 0);
}
#Override
public void onStart(Intent intent, int arg1) {
super.onStart(intent, arg1);
Log.d(TAG, "SERVICE STARTED");
setAlarm();
Log.d(TAG, "Performing update!");
new SubwayAsyncTask().execute();
stopSelf();
}
private void setAlarm() {
int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
mAlarms.setInexactRepeating(alarmType, SystemClock.elapsedRealtime() + timeToRefresh(),
AlarmManager.INTERVAL_HALF_DAY, mAlarmIntent);
}
}
Explanation:
The service starts and:
Set the alarm for the next call. (Check the intent it's used. Just a msg)
Calls an AsyncTask which takes care of updating an notifying the Activity
It doesn't make sense to paste the AsyncTask but when it finished it calls:
private void sendSubwayUpdates(LinkedList<Subway> subways) {
Intent intent = new Intent(NEW_SUBWAYS_STATUS);
intent.putExtra("subways", subways);
sendBroadcast(intent);
}
This creates a new Intent with a certain NEW_SUBWAYS_STATUS action, put inside the intent the subways and sendBroadcast. If someone is interested in getting that info, it will have a receiver.
I hope I made myself clear.
PS: Some days ago someone explained broadcast and intents in a very cool way.
Someone wants to share his beer, so he sends a broadcast
with an intent having action:"FREE_BEER" and with an extra: "A glass of beer".
The API states:
A BroadcastReceiver is a base class for code that will receive intents sent by sendBroadcast().
An intent is an abstract description of an operation to be performed.
So, a BroadcastReceiver is just an Activity that responds to Intents. You can send your own broadcasts or even the Android Device can send these system wide broadcasts including things like the battery is low, or the device just booted-up.

Categories

Resources