Notification shows when it's not supposed to - java

I'm currently working on a notification that has to show at a specific time chosen by the user.
BUT when I run it, notifications show but not at the selected time, only when I ask the time in a timepickerdialog appear, before even choosing a time.
Does anyone know how to change the code so that notifications only appear at the time selected?
showDialog(DIALOG_ID); //this is the dialog that asks for an hour and minute.
alarmMethod1();
private void alarmMethod1(){
Calendar calendari1 = Calendar.getInstance();
calendari1.set(Calendar.HOUR_OF_DAY, hour_x);
calendari1.set(Calendar.MINUTE, minute_x);
calendari1.set(Calendar.SECOND, 00);
Intent myIntent1 = new Intent(Main2Activity.this, NotifyService1.class);
AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);
pendingIntent1 = PendingIntent.getService(Main2Activity.this, 0, myIntent1, 0);
alarmManager1.setRepeating(AlarmManager.RTC_WAKEUP, calendari1.getTimeInMillis(), 24 * 60 * 60 * 1000, pendingIntent1);
}
Then here is the class where the intent goes:
public class NotifyService1 extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onCreate(){
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager nNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Intent intent1 = new Intent(this.getApplicationContext(),Main3Activity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent1, 0);
Notification mNotify = new Notification.Builder(this)
.setContentTitle("Hora d'entrenar!")
.setContentText("Clica per començar entrenament de pit i braços")
.setSmallIcon(R.drawable.logofinal)
.setContentIntent(pIntent)
.setSound(sound)
.build();
nNM.notify(1,mNotify);
}
}

Since Android API 19, all alarms are inexact in order to reduce battery consumption, that means that your alarms will not be triggered exactly when you want, but if you really need to do it, you need to use setExact and then write the repeat alarm handler by yourself, there's no longer a "set exact and repeat". Please, see:
http://developer.android.com/reference/android/app/AlarmManager.html#setRepeating(int, long, long, android.app.PendingIntent)
http://developer.android.com/reference/android/app/AlarmManager.html#setExact(int, long, android.app.PendingIntent)

Related

Setting multiple alarms in Android Studio with an alarmmanager causes problems

I currently have a small project running in Android Studio that I need help with. I want to include a reminder function with notifications.
I have a total of 4 time pickers for each of which I want to set an alarm at the corresponding selected time.
With my current code the planned feature works only halfway, with the following problem:
If I select one time, then I sometimes get a notification at this time as desired. However, not always on time. Most of the time the alert doesn't appear and if it does, then half a minute to a minute later. And if I set all 4 alarms, in the best case I get a notification at the last selected time. In the worst case nothing happens.
But all I want is to get daily notifications at the selected 4 times.
About my code, I use an alarm manager which I call 4 times for the 4 alarms. I also use a broadcast receiver in which the notification is triggered. And I use a different RequestCode for each PendingIntent.
I really searched all relevant posts on SO, but not one of them worked for me. Maybe I have included it in the wrong way. I hope someone can help me. Here are my methods:
Alarm method from Activity.class
(UhrzeitInMillis describes the chosen time by timepicker, for example 16.03):
public void SetAlarm(Context context, long UhrzeitInMillis) {
Intent intent = new Intent(context, Optionen_Alarm.class);
final int id = (int) System.currentTimeMillis();
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this.getApplicationContext(), id, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, UhrzeitInMillis, AlarmManager.INTERVAL_DAY, pendingIntent);
}
BroadcastReceiver (Optionen_Alarm.java):
public class Optionen_Alarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "myapp:mywakelocktag");
wl.acquire();
createNotificationChannel(context);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "1");
builder.setContentTitle("titel");
builder.setContentText("text!");
builder.setSmallIcon(R.drawable.picture);
builder.setColor(context.getResources().getColor(R.color.red));
builder.setVibrate(new long[]{0, 300, 300, 300});
builder.setLights(Color.WHITE, 1000, 5000);
builder.setAutoCancel(true);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setStyle(new NotificationCompat.BigTextStyle().bigText("text!"));
Intent notifyIntent = new Intent(context, Activity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 2, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
Notification notificationCompat = builder.build();
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(context);
managerCompat.notify(15, notificationCompat);
wl.release();
private void createNotificationChannel(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "name";
String description = "description";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel("1", name, importance);
channel.setDescription(description);
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
}
```java
For battery reason, from android 6.0 the time you set on the alarm manager will not be guaranteed to trigger at the exact same time you have set. You could use the method '''setExactAndAllowWhileIdle()''' to make the alarm behave like you want.
You can read more about this here https://developer.android.com/training/scheduling/alarms

Why is onReceive() called twice in this Alarm setup?

I'm building an Android pedometer app that sends data to a SQLite database at 30 minute intervals using AlarmManager; if the phone is off when the transfer is supposed to occur, it will do the transfer immediately when the phone is switched back on.
(30 minutes is for testing - the actual interval will be 1 week).
I was told alarms wouldn't persist unless I used "intent.action.BOOT_COMPLETED" in the manifest, so I put that as a filter for my Alarm.java class.
My code to set the alarm (in MainActivity.java) is as follows:
public void insertData(View view) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
long time= System.currentTimeMillis();
Date d = new Date(time);
editor.putLong("alarmtime", time); //the next ring time for the alarm is put in SharedPreferences
editor.apply();
Intent intent = new Intent(this, Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC, time, AlarmManager.INTERVAL_DAY, pendingIntent);
Toast.makeText(MainActivity.this, "Alarm Set", Toast.LENGTH_LONG).show();
}
The code in the Alarm.java class (which extends BroadcastReceiver) is as follows:
Context context; //plus other declared variables
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
preferences = context.getSharedPreferences("MyPreferences", context.MODE_PRIVATE);
editor = preferences.edit();
long startedtime = preferences.getLong("alarmtime", 0); //get the next ring time
Date nextRingTime = new Date(startedtime);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
String action = intent.getAction();
//sometimes the onReceive() is called by the phone turning on
if (action != null && action.equals(Intent.ACTION_BOOT_COMPLETED)) {
//if phone turned on again before the alarm, just re-create the alarm for the same time, don't transfer data
Date currenttime = new Date(System.currentTimeMillis());
if ((currenttime.compareTo(nextRingTime) < 0)) {
Intent newintent = new Intent(context, Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
0,
newintent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC, startedtime, AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
return;
}
else if ((currenttime.compareTo(nextRingTime) > 0)) {
//if the phone was off when the alarm was supposed to make the transfer, set the alarm to the next intended ring time and insert data to db immediately
Calendar d = Calendar.getInstance();
d.setTime(nextRingTime);
d.add(Calendar.MINUTE, 30);
long newtime = d.getTimeInMillis();
Intent newintent = new Intent(context, Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
0,
newintent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC, newtime, AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
}
}
myDb = new DatabaseHelper(context);
// code for inserting data into database
//finally, update next intended ring time in SharedPreferences now that this particular transfer is done:
Calendar c = Calendar.getInstance();
c.setTime(nextRingTime);
c.add(Calendar.MINUTE, 30);
Log.v("insertdone, alarrm now", c.getTime().toString());
long nexttime = c.getTimeInMillis();
editor.putLong("alarmtime", nextime);
editor.apply();
}
Unfortunately, if the phone is off at the time of a scheduled alarm, when I turn it on afterwards, it calls onReceive() TWICE, meaning it inserts data twice.
How can this be stopped?
A solution would maybe be to use RTC_WAKEUP, but I really don't want to do that unless as an absolute last resort.
N.B. I have a separate bootBroadcastReceiver class that uses "intent.action.BOOT_COMPLETED" to restart a pedometer service, and am wondering whether having 2 different things started by the boot is causing problems...

Android notification repeats several times at event instead of one time

I want the code to execute a notification once every day at 07 am. I created a debug apk and installed it to see how it performs and noticed, that it actually sends a notification at about 07 am, but if you click on the notification and get into the app and close it afterwars, it sends a notification again. Does someone see a mistake in the code?
this is the code in the MainActivity.java (the notification part):
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent_anmeldeActivity = new Intent(this, anmeldeActivity.class);
intent_WebViewActivity = new Intent(this, WebViewActivity.class);
prefs = getSharedPreferences("prefs", Context.MODE_PRIVATE);
prefsEditor = prefs.edit();
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 07);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 00);
intent_notification = new Intent(this, NotificationClass.class);
Intent intent1 = new Intent(MainActivity.this, NotificationClass.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(MainActivity.this.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
Also it sends notifications kind of randomly.
Thanks in advance!
EDIT:
public class NotificationClass extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
loadText loadText = new loadText();
loadText.startAsyncTask(context);
} }
In AsyncTask class loadText, the class NotificationBuilding is executed in onPostExecute:
public class NotificationBuilding {
Context mContext = null;
int ID = 1;
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
long when = System.currentTimeMillis();
public void startNotificationBuilding(Context con, String title, String text) {
this.mContext = con;
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(mContext, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mNotifyBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(
mContext)
.setSmallIcon(R.drawable.ic_stat_name)
.setColor(Color.argb(255, 234, 146, 21))
.setContentTitle(title)
.setContentText(text)
.setSound(alarmSound)
.setAutoCancel(true)
.setWhen(when)
.setContentIntent(pendingIntent)
.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000})
.setLights(Color.argb(255, 234, 146, 21), 1000, 10000)
.setStyle(new NotificationCompat.BigTextStyle().bigText(text));
notificationManager.notify(ID, mNotifyBuilder.build());
ID++;
} }
// Set the alarm to start at approximately 7:00 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 07);
// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr.**setInexactRepeating**(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
Decide how precise your alarm needs to be
As described above, choosing the alarm type is often the first step in creating an alarm. A further distinction is how precise you need your alarm to be. For most apps, setInexactRepeating() is the right choice. When you use this method, Android synchronizes multiple inexact repeating alarms and fires them at the same time. This reduces the drain on the battery.
For the rare app that has rigid time requirements—for example, the alarm needs to fire precisely at 8:30 a.m., and every hour on the hour thereafter—use setRepeating(). But you should avoid using exact alarms if possible.
With setInexactRepeating(), you can't specify a custom interval the way you can with setRepeating(). You have to use one of the interval constants, such as INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY, and so on. See AlarmManager for the complete list.

Android : Schedule notification message at specific date

I'm looking to create a function for an Android app in which I get a notification every 25th day of the month indicating I have to do a certain task.
I've been able to display the notification using the following code :
public class NotificationPublisher extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
long[] pattern = {0, 300, 0};
PendingIntent pi = PendingIntent.getActivity(context, 01234, intent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.small_logo_ico)
.setContentTitle(context.getResources().getString(R.string.notification_title))
.setContentText(context.getResources().getString(R.string.notification_content))
.setVibrate(pattern)
.setAutoCancel(true);
mBuilder.setContentIntent(pi);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(01234, mBuilder.build());
}
}
Now this system only works when I have my app open and doesn't allow me to display this when the app is closed. I've searched around and came to this:
Android notification at specific date
After trying this out (the schedule part) I noticed that it doesn't work when I close the app, as I get an error about unregistering the Receiver, doing this (unregistering) results in the receiver being canceled, and the notification can not be showed.
code used for the schedule:
NotificationPublisher receiver = new NotificationPublisher();
this.receiver = receiver;
IntentFilter filter = new IntentFilter("ALARM_ACTION");
registerReceiver(receiver, filter);
Intent intent = new Intent("ALARM_ACTION");
intent.putExtra("param", "My scheduled action");
PendingIntent operation = PendingIntent.getBroadcast(this, 0, intent, 0);
// I choose 15s after the launch of my application
alarms.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+15000, operation) ;
Is there anything I'm missing, or am I using the wrong methods to schedule a notification on a certain date? ( The current notification is set to be scheduled 15 seconds in the future, this is just for testing, I've got a function ready to display this at a certain date)
This is used to notify on middle of the month. Maybe You can get from below code.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_MONTH, 15);
calendar.set(Calendar.HOUR_OF_DAY, 12);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
if (calendar.getTimeInMillis() < System.currentTimeMillis()) {
calendar.add(Calendar.DAY_OF_YEAR, 30);
}
Intent myIntent = new Intent(getApplicationContext(), MyReceiver.class);
myIntent.putExtra("NOTI_MSG",getString(R.string.notification_sidas));
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), NOTI_REQ_CODE_SIDAS, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY * 30, pendingIntent);
}

Alarm Manager does not execute broadcaster class

I'm trying out alarms and have hit a wall. I don't think my alarm is setting up properly because I never get a confirmation after the alarm is supposed to go off. Here's how I call on the alarm manager:
long alarmtime=new GregorianCalendar().getTimeInMillis()+10*1000;//run after 10 seconds
Intent i = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
AlarmManager alarmman = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmman.cancel(pi); // cancel any existing alarms
alarmman.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
alarmtime, 10 * 1000, pi);//run every 10 seconds
And here's my AlarmReceiver.java:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "TEST", Toast.LENGTH_LONG).show();
}
}
However, the TEST text does not appear, and I can't figure out why.
Since you are using the AlarmManager.ELAPSED_REALTIME_WAKEUP argument, your initial alarm-time should be base on the elapsed real time of the device:
long alarmtime = SystemClock.elapsedRealtime() + 10 * 1000;
alarmman.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmtime, 10 * 1000, pi);
(see this link).
For a BroadcastReceiver it's probably PendingIntent.getBroadcast() instead of PendingIntent.getService(). You are also cancelling the alarm, just update your PendingIntent like this and try not cancelling before:
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Read the documentation thoroughly for further information.
Make sure that the BroadcastReceiver is being called by doing a System.out.println("TEST"); instead of Toast. If you are able to see that in your logcat, then the problem probably is that you need to run the Toast in UI thread.

Categories