Cancel an AlarmManager - java

I´ve got a method that sets the time I want an alarm to fire.
In this method I also got a Stop button that cancels the alarm
if(alarmManager != null){
alarmManager.cancel(pi);
}
My problem is that when I set the alarm, go out of the app and in again to cancel the alarm I get a nullPointer. Im guessing it is because the PendingIntent also closes when I leave the app (get set to null).
How can I prevent this from happening, so that I can cancel the alarm?
Heres the whole method:
#SuppressWarnings("deprecation")
public void setTime(){
Calendar mcurrentTime = Calendar.getInstance();
int hour = mcurrentTime.get(Calendar.HOUR_OF_DAY);
int minute = mcurrentTime.get(Calendar.MINUTE);
TimePickerDialog mTimePicker;
mTimePicker = new TimePickerDialog(MainActivity.this, new TimePickerDialog.OnTimeSetListener()
{
int callCount = 0; //To track number of calls to onTimeSet()
#Override
public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute)
{
if(callCount == 1) // On second call
{
String timeString = "";
timeString = selectedHour + ":" + selectedMinute + ":00";
Log.d("TEST", "Chosen time : "+ timeString);
setAlarm(timePicker, selectedHour, selectedMinute);
}
callCount++; // Incrementing call count.
}
}, hour, minute, true);
mTimePicker.setButton(DialogInterface.BUTTON_POSITIVE, "Set", mTimePicker);
mTimePicker.setButton(DialogInterface.BUTTON_NEGATIVE, "Stop", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if(alarmManager != null){
alarmManager.cancel(pi);
}
}
});
mTimePicker.setTitle(R.string.time);
mTimePicker.show();
}

You can save the data that is used to construct your PendingIntent in a Bundle like shown here
So when you open up your app again, you will be able to reconstruct the PendingIntent and cancel the alarm if needed.
EDIT: First of all you have to override onSaveInstanceState and save the data that is used to create your PendingIntent object like shown below:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the pending intent id
savedInstanceState.putInt(PENDING_INTENT_ID, mPendingIntentId);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
After that, in your onCreate method you will check if the savedInstanceState is not null. If not null, restore the items from the savedInstanceState (Bundle) object like this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mPendingIntentId = savedInstanceState.getInt(PENDING_INTENT_ID);
} else {
// Probably initialize members with default values for a new instance
mPendingIntentId = YOUR_DEFAULT_INT_VALUE;
}
mPendingIntent = PendingIntent.getBroadcast(this, mPendingIntentId, YOUR_INTENT, PendindIntent.FLAG_UPDATE_CURRENT);
}
PendingIntent will be recreated every time you will enter your app, so you will be able to cancel the same alarm that has been triggered in a previous step.
EDIT 2 : Another approach in your case would be that since you have only one alarm, and it's id is always the same (which should be used for the PendingIntent's requestId), than you can simply recreate the PendingIntent whenever you want to add or cancel an alarm. A method like the one below would help you out.
private PendingIntent getPendingIntent(Context context){
return PendingIntent.getBroadcast(context, 0, new Intent(context, YourBroadcastReceiver.class), PendingIntent.FLAG_CANCEL_CURRENT);
}

Related

How to pass time value from timepicker to textView in another activity in Android studio(Java)?

I did everything when it comes to creating notification on selected time in timepicker but I cannot pass it to textview in another activity. Can someone help me with this?
I want to pass time value from SecondActivity to textView named textviewAlarm in HomeActivity when clicking button Done.
public class Second extends AppCompatActivity implements View.OnClickListener{
private int notificationId = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
// Set Onclick Listener.
findViewById(R.id.setBtn).setOnClickListener(this);
findViewById(R.id.cancelBtn).setOnClickListener(this);
}
#Override
public void onClick(View view) {
EditText editText = findViewById(R.id.editText);
TimePicker timePicker = findViewById(R.id.timePicker);
// Set notificationId & text.
Intent intent = new Intent(Second.this, AlarmReceiver.class);
intent.putExtra("notificationId", notificationId);
intent.putExtra("todo", editText.getText().toString());
// getBroadcast(context, requestCode, intent, flags)
PendingIntent alarmIntent = PendingIntent.getBroadcast(Second.this, 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE);
switch (view.getId()) {
case R.id.setBtn:
int hour = timePicker.getCurrentHour();
int minute = timePicker.getCurrentMinute();
// Create time.
Calendar startTime = Calendar.getInstance();
startTime.set(Calendar.HOUR_OF_DAY, hour);
startTime.set(Calendar.MINUTE, minute);
startTime.set(Calendar.SECOND, 0);
long alarmStartTime = startTime.getTimeInMillis();
// Set alarm.
// set(type, milliseconds, intent)
alarm.set(AlarmManager.RTC_WAKEUP, alarmStartTime, alarmIntent);
// Get TextView object which is used to show user pick date and time.
TextView textView = (TextView)findViewById(R.id.textViewAlarm);
StringBuffer strBuffer = new StringBuffer();
strBuffer.append("You selected date time : ");
strBuffer.append(this.notificationId);
textView.setText(strBuffer.toString());
break;
case R.id.cancelBtn:
alarm.cancel(alarmIntent);
Toast.makeText(this, "Canceled.", Toast.LENGTH_SHORT).show();
break;
}
}
}
I want my selected time to be shown in textViewAlarm in HomeActivity.
You can get the time from the time picker by adding a
timePicker.setOnTimeChangedListener( new TimePicker.onTimeChangedListener() {
#Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
time = String.valueOf(hourOfDay).toString() + ":" + String.valueOf(minute).toString();
}
}
When the user changes the time it will assign the time to a variable and pass that argument through intent as follow
Intent intent = new Intent(Second.this, AlarmReceiver.class);
intent.putExtra("notificationId", notificationId);
intent.putExtra("time", time);
Take that passed argument from the HomeActivity and set it to the TextView as follow
textviewAlarm.setText(time.toSring());

Android notification every 15 minutes crashes if app is closed

So i'm a complete newbie in Android Studio and I'm trying to make a simple app which does the following:
The app has a string array set on the /res/values folder called "frases".
The Main activity contains a button, when it's pressed, it increments a variable that represents the index of the array to be used (i've called it "iterador") and sets a textView to the value of frases[iterador].
Then on the onCreate method of the MainActivity, I have an alarnm with setRepeating that calls a class to receive a notification each 15 minutes. The purpose of this is to both have a textview in the MainActivity and a notification that can show the value of frases[iterador].
The problem here is whenever my app is closed (not stopped from the android settings menu, just closed) I get an error saying string array is null. And even worse, after the first notification, sometimes the second one won't appear even after 15 minutes if I don't open the app in my phone (even if it isn't closed).
I've tried to fix this by making both variables static so that I can access them from the notification class, but still doesn't work.
Is there a way to fix this and make the notificactions appear even whith the app closed?
My MainActivity vars and onCreate method:
public class MainActivity extends Activity implements View.OnClickListener {
//MY CODE
public static boolean primera; //APP OPENED FOR THE FIRST TIME
private Button b_corazon, b_carta;
private TextView t_frase;
public static final String PREFS_NAME = "MyPrefsFile";
//-------------------------STRING SHOW VARIABLES----------------------
public static String[] frases; //STRING ARRAY
public static int iterador; // INDEX FOR THE ARRAY
AlarmManager alarmManager; //ALARM MANAGER
#Override
protected void onCreate(Bundle savedInstanceState) {
Resources res=getResources(); //GET THE RESOURCES
frases=res.getStringArray(R.array.cartas); //ASIGN THE STRING ARRAY TO THE VARIABLE
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
//MI CODIGO
Intent intent = new Intent(getApplicationContext(), RecibeNotif.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(),0,intent,0);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar firing = Calendar.getInstance(); //SCHEDULED TIME
Calendar current = Calendar.getInstance(); //CURRENT TIME
firing.set(Calendar.HOUR_OF_DAY,14);
firing.set(Calendar.MINUTE,20);
firing.set(Calendar.SECOND,0);
long intendedTime=firing.getTimeInMillis(); //SCHEDULED TIME
long currentTime=current.getTimeInMillis(); //CURRENT TIME
if(intendedTime>=currentTime){ //IF IT ISN'T THE TIME YET
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, intendedTime,AlarmManager.INTERVAL_FIFTEEN_MINUTES,pendingIntent);
}
else{ //IF THE TIME HAS ALREADY PASSED
firing.add(Calendar.MINUTE,15); //ADD 15 MINUTES FOR THE NEXT ALARM
intendedTime=firing.getTimeInMillis();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, intendedTime,AlarmManager.INTERVAL_FIFTEEN_MINUTES,pendingIntent);
}
//SAVE THE VALUE OF ITERADOR IN THE APPLICATION DATA
SharedPreferences settings = getSharedPreferences(PREFS_NAME,0); //GUARDAR DATO DE ITERADOR
primera=getSharedPreferences("PREFERENCE",MODE_PRIVATE).getBoolean("primera", true);
iterador=settings.getInt("iterador",iterador);
init();
}
My BroadcastReceiver notification class:
public class RecibeNotif extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
String[] frasesaux;
int iteraux;
iteraux=MainActivity.iterador;
frasesaux=MainActivity.frases;
if(iteraux==frasesaux.length){
iteraux=0;
}
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent redir = new Intent(context,direct.class);
redir.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 100, redir, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.message) //ICONO DE LA NOTIFICACION
.setContentTitle(".////.")
.setContentText(frasesaux[iteraux])
.setAutoCancel(true);
notificationManager.notify(100,builder.build());
}
}
<-----------EDIT------------->
Okay, so it's fixed now, the notification works quite well. The only thing that still drives me crazy is how to update the value of iterador at the end of the notification class so it matches with iteraux.
So far, i've tried to edit the value of iterador using the SharedPreferences.editor but it doesn't seem to work.
Any ideas?
public void onReceive(Context context, Intent intent) {
String[] finale;
int iteraux;
SharedPreferences settings = context.getSharedPreferences(PREFS_NAME,0); //GUARDAR DATO DE ITERADOR
iteraux = settings.getInt("iterador",iterador);
Resources res= context.getResources(); //GET THE RESOURCES
finale=res.getStringArray(R.array.cartas); //ASIGN THE STRING ARRAY TO THE VARIABLE
//iteraux=MainActivity.iterador;
if(iteraux==finale.length){
iteraux=0;
}
else{
iteraux++;
}
//<-----------UPDATE ITERADOR VAR IN MAINACTIVITY
SharedPreferences.Editor editor2 = settings.edit();
editor2.putInt("iterador",iteraux);
editor2.commit();
// frasesaux=MainActivity.frases;
Your activity is not alive when you receive your notification so if you try to access the fields of Activity which is not alive , you get an exception
Solution
1.) use the context to get getStringArray(R.array.cartas)
2.) Use the same context to fetch data from SharedPreferences
public class RecibeNotif extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
String[] frasesaux;
int iteraux;
SharedPreferences settings = context.getSharedPreferences("MyPrefsFile",0);
iteraux = settings.getInt("iterador",0);
// ^^ your default value
//iteraux=MainActivity.iterador;
frasesaux=context.getResources().getStringArray(R.array.cartas);
// ^^ fetch the array
if(iteraux==frasesaux.length){
iteraux=0;
}
//...
}
}
Note : static won't make any difference because your array will only be initialized when onCreate will get called by the android OS so since this is not the case so hence your static fields will stay un-initialized mean null and 0.

Encapsulating alarm creation code in a different class than the Activity

I'm creating my first Android Notifications app, so I'm very much a beginner. I have a class, Notification.java, that asks the user for the time and date. Using these data, it creates an alarm that is triggered at the specified date and time.
Here is my code for Notification.java
public class Notification extends Activity {
private PendingIntent pendingIntent;
private SetAlarm alarm;
private Date date;
private Time time;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm);
findViewById(R.id.setTime).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setAlarmTime();
}
});
findViewById(R.id.setDate).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setAlarmDate();
}
});
findViewById(R.id.checkBox).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
createAlarm();
}
});
}
private void setAlarmTime() {
}
private void setAlarmDate() {
}
private void createAlarm() {
alarm = new SetAlarm();
}
}
The createAlarm() method is supposed to actually create the alarm using the information that the user has provided (i.e. time and date). However, I understand that I need the following code block to create the alarm?
private void setTheAlarm() {
Intent alarmIntent = new Intent(SetAlarm.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(SetAlarm.this, 0, alarmIntent, 0);
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
int interval;
/* Set the alarm to the date specified by user */
/* Repeating on every x minutes interval */
}
However, the Notification.java is where I am extending 'Activity'. It is also where I have the 'pendingIntent; code.
So essentially, how can I move the alarm creation code into a separate class when the code dealing with the Activity is in an entirely different class?
Thanks for the help. I hope my question is clear enough.
Not exactly clear if that is what you want, but if I understand you correct, you need the alarmManager inside an extra class to reach it from everywhere? You could make a static one like this:
public class MyAlarmManager{
private static AlarmManager mAlarmManager;
private static PendingIntent mPendingIntent;
//start alarm
public static void setAlarm(Context context, int alarmId, long alarmTime) {
if (mAlarmManager== null) {
mAlarmManager= (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
Intent startAlarmIntent = new Intent(context, YouReceiver.class);
if(mPendingIntent==null){
mPendingIntent = PendingIntent.getBroadcast(context, alarmId,
startAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
//check the version because of doze mode since MM
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
alarmTime, mPendingIntent);
} else {
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, mPendingIntent);
}
}
//stop alarm
public static void stopAlarm(Context context, int id) {
if (mAlarmManager == null) {
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
Intent stopAlarmIntent = new Intent(context, YourReceiver.class);
if(mPendingIntent==null){
mPendingIntent= PendingIntent.getBroadcast(context, id, stopAlarmIntent, 0);
}
mAlarmManager.cancel(mPendingIntent);
mPendingIntent.cancel();
}
}
Then you can call it like:
MyAlarmManager.setAlarm(this, id, interval);
and stop it:
MyAlarmManager.stopAlarm(this, id);
You can do this from every class by passing the context and the identical id . The alarm id must be the same as you passed by starting the alarm, otherwise it will not work. Notice that above MarshMallow, there are some changes for AlarmManager and it´s possible that it does not work in every case. If your app get´s killed or goes into idle mode, the alarm won´t be triggered in every circumstance. To handle doze mode, see this:https://developer.android.com/training/monitoring-device-state/doze-standby.html
And be aware of any third party app and battery managers, that could kill your app. Also, Huawei devices have their own battery management besides the doze mode.
If this is not what you wanted, come back. Can´t guarantee that there is no error because I have overseen something, it´s from scratch.

Anyway to send push notification to android without GCM?

Is there any other way to send push notifications to android device from server without using GCM? I don't want to share my device data or anything with 3rd party like Google? So any other way?
You may try this code for simple push notification without using GCM or FCM.
Update the changes in onCreateView method..
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* ed1=(EditText)findViewById(R.id.editText);
ed2=(EditText)findViewById(R.id.editText2);
ed3=(EditText)findViewById(R.id.editText3);*/
Button b1=(Button)findViewById(R.id.button);
b1.setOnClickListener(new View.OnClickListener() {
public int mNotificationId;
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onClick(View v) {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(getApplicationContext())
.setSmallIcon(R.drawable.msg)
.setContentTitle("My notification")
.setContentText("Hello Preetam! How are you");
Intent resultIntent = new Intent(getApplicationContext(), Result_Activity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(getApplicationContext());
stackBuilder.addParentStack(Result_Activity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(mNotificationId, mBuilder.build());
Toast.makeText(getApplicationContext(),"Check your notification",Toast.LENGTH_SHORT).show();
}
});
And Put a button to generate the notification.And make one more Activity to be displayed on clicking the notification.
I use a ftp library to connect to my server. in my notification service, I scan a directory where I keep plain text files. Each one represents a notification. If a new text file is added, the service gets the date the file was added to the server. If it was today, it reads the file, returns the contents, and I put it into a notification.
Here is an example of a service that looks for a text file with today's date as the title. If it exists, it will parse the data and put it into a notification
public class NotifyService extends Service {
private WakeLock mWakeLock;
/**
* Simply return null, since our Service will not be communicating with
* any other components. It just does its work silently.
*/
#Override
public IBinder onBind(Intent intent) {
return null;
}
#SuppressWarnings("deprecation")
private void handleIntent() {
// obtain the wake lock
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Partial");
mWakeLock.acquire();
// check the global background data setting
ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
if (!cm.getBackgroundDataSetting()) {
stopSelf();
return;
}
// do the actual work, in a separate thread
new PollTask().execute();
}
private class PollTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... args) {
// do stuff!
String title = null;
Calendar c = Calendar.getInstance();
int month = c.get(Calendar.MONTH) + 1;
int day = c.get(Calendar.DAY_OF_MONTH);
int year = c.get(Calendar.YEAR);
String Month = (String.valueOf(month));
String Day = (String.valueOf(day));
String Year = (String.valueOf(year));
String todaysDate = (Month + "-" + Day + "-" + Year);
try {
// Create a URL for the desired page
URL updateURL = new URL("URL to your notification directory" + todaysDate + ".txt");
// Read all the text returned by the server
BufferedReader in = new BufferedReader(new InputStreamReader(updateURL.openStream()));
StringBuilder total = new StringBuilder();
String line;
while ((line = in.readLine()) != null) {
total.append(line).append("\n");
}
title = total.toString();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
return title;
}
/**
* In here you should interpret whatever you fetched in doInBackground
* and push any notifications you need to the status bar, using the
* NotificationManager. I will not cover this here, go check the docs on
* NotificationManager.
*
* What you HAVE to do is call stopSelf() after you've pushed your
* notification(s). This will:
* 1) Kill the service so it doesn't waste precious resources
* 2) Call onDestroy() which will release the wake lock, so the device
* can go to sleep again and save precious battery.
*/
#Override
protected void onPostExecute(String title) {
int mId = 420;
if (title == null) {
stopSelf();
}else{
Intent notificationIntent = new Intent(getApplicationContext(), MapActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(NotifyService.this, 0, notificationIntent, 0);
//Set up the notification
Notification noti = new NotificationCompat.Builder(getApplicationContext()).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher))
.setSmallIcon(R.drawable.ic_launcher_small)
.setTicker("New Notification ...")
.setWhen(System.currentTimeMillis())
.setContentTitle("Your app name")
.setContentText(title)
.setContentIntent(contentIntent)
//At most three action buttons can be added
//.addAction(android.R.drawable.ic_menu_camera, "Action 1", contentIntent)
//.addAction(android.R.drawable.ic_menu_compass, "Action 2", contentIntent)
//.addAction(android.R.drawable.ic_menu_info_details, "Action 3", contentIntent)
.setAutoCancel(true).build();
//Show the notification
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(mId, noti);
// handle your data
stopSelf();
}
}
}
/**
* This is deprecated, but you have to implement it if you're planning on
* supporting devices with an API level lower than 5 (Android 2.0).
*/
#SuppressWarnings("deprecation")
#Override
public void onStart(Intent intent, int startId) {
handleIntent();
}
/**
* This is called on 2.0+ (API level 5 or higher). Returning
* START_NOT_STICKY tells the system to not restart the service if it is
* killed because of poor resource (memory/cpu) conditions.
*/
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handleIntent();
return START_NOT_STICKY;
}
/**
* In onDestroy() we release our wake lock. This ensures that whenever the
* Service stops (killed for resources, stopSelf() called, etc.), the wake
* lock will be released.
*/
public void onDestroy() {
super.onDestroy();
mWakeLock.release();
}
}
If you mean by targeting devices but without direct connection there is no really other way. If its just a text you can send a simple sms message but if you want a clickable notification GCMS is the only way for now.

Why do Android alarms fire at the same time?

Below is a pretty simple method that takes a Date and an id for an alarm to be fired which starts a countdown. For some reason I don't understand, if I call it once with one date and id 0 and call it again with another date and id 1 (i.e., two different countdowns), Android will fire both alarms at the same time (specifically the first date passed with id 0) so both countdowns start at the same time.
Can anyone tell me why and how to fix it? Thanks!
public void setCountdownAlarm(Date fireTime, int id)
{
// startCountdown will be called at fireTime
BroadcastReceiver startCountdown = new BroadcastReceiver() {
#Override public void onReceive( Context context, Intent theIntent )
{
countdownTimer = new Timer();
countdownTimer.schedule(new TimerTask() {
#Override
public void run() {
onSecondTick(showtime);
}
}, 0, 100); // call every 10th of a second
}
};
this.registerReceiver( startCountdown, new IntentFilter("com.counter.app.CountActivity.COUNT") );
Intent intent = new Intent("com.counter.app.CountActivity.COUNT");
PendingIntent pintent = PendingIntent.getBroadcast( this, id, intent, 0 );
AlarmManager manager = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
if (Build.VERSION.SDK_INT >= 19)
manager.setExact(AlarmManager.RTC_WAKEUP, fireTime.getTime(), pintent);
else
manager.set(AlarmManager.RTC_WAKEUP, fireTime.getTime(), pintent);
}
Editing to say that when I waited for the second alarm to fire, Android actually calls startCountdown twice -- once again for each alarm. Help!
I figured out what I did wrong. As explained in answers to similar questions, the second parameter of PendingIntent.getBroadcast (requestCode) must be unique if you want to get a unique pending intent. I took care of that by passing "id".
The second problem was that I registered the BroadcastReceiver each time I called setCountdownAlarm. The BroadcastReceiver should only be registered once, typically in the onCreate method of the activity.

Categories