I'm using some alarm functions to produce a notification every five seconds. In the functions there are variables which should change each time it is called. But nothing is happening , it just continues to display the first set of data in the notification.
This is from the MainActivity class:
public void setRepeatingAlarm(){
Intent intent = new Intent(this, TimeAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,intent, PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), (5 * 1000), pendingIntent);
}
This is from the TimeAlarm class:
public void onReceive(Context context, Intent intent) {
nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence from = "Homework";
CharSequence message = "test"+ MainActivity.arraytest[x2]+ x2;
x2 +=1;
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,new Intent(context,TimeAlarm.class), 0);
Notification notif = new Notification(R.drawable.ic_launcher,"Update", System.currentTimeMillis());
notif.setLatestEventInfo(context, from, message, contentIntent);
nm.notify(notify_id, notif);
}
The problem is that the x2 variable is not updating. it only updates when it is first called.
Thanks.
Making the x2 variable static seemed to solve the problem.
Maybe long shot but... I suspect that x2 may be accessed by more than one threads? In that case, it should be declared as volatile in order for compiler to skip any optimizations not suitable for variables accessed by multiple threads (which can be causing the wrong behaviour in this case).
Are you doing anything else with x2? Have a look at the lifecycle documentation for BroadcastReciever. Likely your instance of TimeAlarm is getting killed after each run of onReceive(); you'll need to do something to persist the value of x2 between runs.
Related
I am creating a research app that should prompt the user 4 times a day to enter their mood - by sending a notification, which when clicked launches the correct Activity. I am able to schedule these notifications using AlarmManager, however only the last scheduled notification ever shows. So although I schedule them for 9AM, 2PM, 5PM, and 8PM, it only ever sends a notification at 8PM.
How can I get all of the scheduled notifications to show?
Here is my code for setting (one of) the alarms (from a notification manager class). Note that al alarms are set using the same instance of AlarmManager:
cal.setTimeInMillis(System.currentTimeMillis());
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), createPendingIntent(9, this));
Here is the createPendingIntent method (in the same notification manager class):
public static PendingIntent createPendingIntent(int hour, Context c){
Intent notificationIntent = new Intent(c, AlarmBroadcastReceiver.class);
notificationIntent.putExtra("time", hour);
PendingIntent pendingIntent = PendingIntent.getBroadcast(c, 0 , notificationIntent , PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
Here is the BroadcastReceiver for the alarm:
public class AlarmBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationSender.createNotification(context);
}
}
And finally the createNotification method:
public static void createNotification(Context c){
Log.e("notif?", "creating");
Intent intent = new Intent(c, UpdateMoodActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
int notificationId = new Random().nextInt();
PendingIntent pendingIntent = PendingIntent.getActivity(c, 0, intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(c, "com.lizfltn.phdapp.notifChannelID")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("SoftMood")
.setContentText("Please record your mood")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(c);
notificationManager.notify(notificationId, builder.build());
}
Yes I know this isn't the best-practice way of doing things, or even the neatest, but unfortunately I need to get code working ahead of writing good code :P
I've tried various configurations of setting the alarm, e.g. using elapsed realtime instead of RTC, only setting the alarm, setting the exact alarm, etc, but there might be something fundamental I'm not understanding about how those work.
Any help appreciated!
Can you try with same id in pending intent and notify.?
Notification id in createNotification() method is random id.
int notificationId = new Random().nextInt();
and id used in createPendingIntent method is 0.
PendingIntent pendingIntent = PendingIntent.getBroadcast(c, 0 , notificationIntent , PendingIntent.FLAG_UPDATE_CURRENT);
Can you try with using same value for second parameter of getBroadcast?
I have an arraylist of objects, a member of which is a date/time.
The arraylist and object is used to populate the UI listview.
I would like to send a push notification when the time from the object/listview is approaching system/mobile time (whether its 5, 10 mins or modifiable, doesn't matter).
So i'm familiarizing myself with the Notification Builder, but i'm unsure where to put the logic and how the app will monitor the time and notify when its close.
Any ideas, suggestions on the right path much appreciated
You can trigger an alarm at a scheduled time and then use an IntentService to capture it once alarm goes off.
In the main activity (lets assume the name is MainActivity, you can create an alarm like this.
AlarmManager mgr = (AlarmManager) MainActivity.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(MainActivity, NotifService.class);
PendingIntent pi = PendingIntent.getService(MainActivity, 0, intent, 0);
mgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + PERIOD, pi);
where the PERIOD defines after how much milliseconds you want the alarm to go off.
To configure the AlarmManager differently, you can read more about it.
NotifService is what captures the alarm when it goes off. Create a class called NotifService it extends IntentService
public class NotifService extends IntentService {
public NotifService() {
super("My service");
}
#Override
protected void onHandleIntent(Intent intent) {
//write your code for sending Notification
Intent intent = new Intent();
intent.setAction("com.xxx.yyy.youractivitytobecalled");
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 1, intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder (getApplicationContext());
builder.setContentTitle("Your Application Title");
builder.setContentText("Notification Content");
builder.setContentIntent(pendingIntent);
builder.setTicker("Your content");
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setOngoing(false);
builder.setPriority(0);
Notification notification = builder.build();
NotificationManager notificationManger = (NotificationManager) getSystemService (Context.NOTIFICATION_SERVICE);
notificationManger.notify(1, notification);
}
}
Register NotifService in your AndroidManifest.xml
<application
fill content here />
<service android:name=".NotifService" >
</service>
</application>
Just for future reference, I created a class that extends BroardcastReceiver and used that to handle the alarms from AlarmManager - its all there in the docs but its kinda confusing how everything sits together at first.
I have a little question. I set my notifications in specific times using AlarmManager. The times I set notifications for are stored in SQLLite database. They all work perfect except the moment I reboot the phone. alarmManager looses their repeatings of course.
I would like to ask what is the best solution in this situation? I have my alarmManager set in MainActivity and I set my notification inside BroadcastReceiver as you can see in the code below:
Here is how I call it from MainActivity:
Intent intent = new Intent(context, MyReceiver.class);
intent.putExtra(EXTRA_TITLE, title);
intent.putExtra(EXTRA_COUNT, count);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, count, intent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), WEEK_LENGTH_MS, pendingIntent);
And here is Broadcast Receiver's method onReceive
public void onReceive(Context context, Intent intent)
{
nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence from = context.getString(R.string.app_name);
CharSequence message = intent.getStringExtra(DayActivity.EXTRA_TITLE);
Intent intentNotification = new Intent(context,DayActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, intent.getIntExtra(DayActivity.EXTRA_COUNT,0), intentNotification, 0);
Notification notif = new Notification(R.drawable.notification_logo,context.getString(R.string.app_name), System.currentTimeMillis());
notif.setLatestEventInfo(context, from, message, contentIntent);
notif.defaults |= Notification.DEFAULT_LIGHTS;
notif.flags |= Notification.FLAG_AUTO_CANCEL | Notification.FLAG_SHOW_LIGHTS;
nm.notify(intent.getIntExtra(DayActivity.EXTRA_COUNT,0), notif);
}
I am declaring BroadcastReceiver for BOOT_COMPLETED event, but it always calls just empty notification at the time i start the phone and never more.
I would like to ask what is the best solution in this situation?
Register a BOOT_COMPLETED BroadcastReceiver to call setRepeating() on AlarmManager to re-establish your schedules.
I am declaring BroadcastReceiver for BOOT_COMPLETED event, but it always calls just empty notification at the time i start the phone and never more.
The objective of the BOOT_COMPLETED BroadcastReceiver should be to reschedule your alarms. You might wish to consider using a separate BroadcastReceiver than the one you are using for the alarm events themselves.
I searched all similar questions/answers but I can't get it to work with my code! I can get the notification to appear instantly. However, I need it to appear 24 hrs after the user runs the app. I am stuck. I tried using Alarm Manager with no success. Here is my working code. Please guide me. Thanks.
public class NotifyNow {
static void noty(Context context, String message) {
int icon = R.drawable.ic_launcher;
long when = System.currentTimeMillis();
String appname = context.getResources().getString(R.string.app_name);
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification;
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(
context);
notification = builder.setContentIntent(contentIntent)
.setSmallIcon(icon).setTicker(appname).setWhen(0)
.setAutoCancel(true).setContentTitle(appname)
.setContentText(message).build();
//notification.defaults |= Notification.DEFAULT_SOUND;
notification.sound =
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
notificationManager.notify(0 , notification);
}
I call it from my MainActivity class as follows:
NotifyNow.noty(this,"Notification worked");
How do I implement the alarm. I would appreciate detailed answer as I am fairly new to java.
You can find Current DateTime using Date APIs, when your app runs by overcreate riding onStart() of Activity.
e.g.
currentTime = SystemClock.currentThreadTimeMillis();
Now, you can add an alarm using AlarmManager API.
AlarmManager Refernce
Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time,
even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier
and much more efficient to use Handler.
Sample Code for Creating an alarm is:
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
currentTime +
24 * 60 * 60 * 1000, alarmIntent);
Please Note: This code is not tested, but just a concept of requisite. Let me know if you face any issue.
I have tried this...
put uppercase notification service
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Notification notifyDetails=new Notification(
R.drawable.icon,contentTitle,System.currentTimeMillis());
notificationManager .notify(MY_SIMPLE_NOTFICATION_ID, notifyDetails);
You can achieve this by using this library also...
I am developing an android app which shows a notification every 12 hour if the time is saved in the database. So everytime a data is entered or edited in the database ,I cancel the current alarmmanager and start a fresh new one so that I dont miss one. Also on reboot I have called the alarmmanager. On the broadcast receiver, the database is checked for entry and if found a notification is set and the app is opened automatically.
So when I test the app by changing the date manually,the app works as expected.Also on reboot the app works.But if I keep the app idle for nearly 14 hours,the notification is not set ,but if I open the app and suspend it the notification is set after that.
This is how I call the alarmmanager.
Intent alarmintent = new Intent(context, package.Alarm_Manager.class);
alarmintent.putExtra("note","Notify");
sender = PendingIntent.getBroadcast(context , 0 , alarmintent , PendingIntent.FLAG_CANCEL_CURRENT | Intent.FILL_IN_DATA);
alarm_manger = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarm_manger.cancel(sender);
Calendar cal = Calendar.getInstance();
long now = cal.getTimeInMillis();
alarmintent = new Intent(context, package.Alarm_Manager.class);
alarmintent.putExtra("note","Notification");
sender = PendingIntent.getBroadcast(context , 0 , alarmintent , PendingIntent.FLAG_CANCEL_CURRENT | Intent.FILL_IN_DATA);
alarm_manger = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm_manger.setRepeating(AlarmManager.RTC_WAKEUP, now, AlarmManager.INTERVAL_HALF_DAY, sender);
This is the broadcast receiver
#Override
public void onReceive(Context context, Intent intent)
{
NotificationManager manger = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Calendar cal = Calendar.getInstance();
date = (int)(cal.getTimeInMillis()/1000);
Notification notification = new Notification(R.drawable.vlcsnap_396460 , "Notify" , System.currentTimeMillis());
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
notification.setLatestEventInfo(context, "App", "Notify" , contentIntent);
notification.flags = Notification.FLAG_INSISTENT;
manger.notify( 0 , notification);
}
You don't need to call alarm_manager.cancel(sender); if you set the PendingIntent.FLAG_CANCEL_CURRENT.
Your call to
alarm_manger.setRepeating(AlarmManager.RTC_WAKEUP, now, AlarmManager.INTERVAL_HALF_DAY, sender);
will trigger the alarm right away, since the now is already passed when you set the alarm.
I suggest you use
now + DateUtils.HOUR_IN_MILLIS / 2
for the triggerAtMillis parameter
Did you tried to schedule it for smaller interval? Does it get triggered ?
After having seen your Alarm_Manager code, I think it is illegal to do this in your BroadcastReceiver object directly. Quote:
If this BroadcastReceiver was launched through a tag, then the object is no longer alive after returning from this function.
I believe there is no other way than to create a Service which is informed by your BroadcastReceiver, and make sure that the Service calls setLatestEventInfo() with itself (this) as the Context.
The reason why your asynchronous Broadcast fails while it works when your app is running is probably that the Context provided to the BroadcastReceiver lives only for the duration of the call to the BroadcastReceiver when your app does not run. So the Notification service, which only runs after your BroadcastReceiver has died along with the temporary context, is missing a valid context.
When your app runs, the Broadcast probably comes with your Activity or Application object as Context, and this is still vaild when the Notification manager runs.
Hope this helps.
Update: An `IntentService`` will do. You don't want a full time Service for that.
Update 2: Some snippets.
<service android:name=".MyIntentService" android:label="#string/my_intent_service_name" />
public final class MyIntentService extends IntentService {
public MyIntentService() {
super("service name");
// set any properties you need
}
#Override
public void onCreate() {
super.onCreate();
// do init, e.g. get reference to notification service
}
#Override
protected void onHandleIntent(Intent intent) {
// handle the intent
// ...especially:
notification.setLatestEventInfo(this, "App", "Notify" , contentIntent);
// ...
}
}
public final class MyAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, MyIntentService.class));
}
}