In one activity I have three DatePickerDialog where the user can put three date for a reminder purpose. The app must notify each date and if the user enters two or three equal date they must be notified in sequence . My problem is that only the last date entered is notified. I use a random number for the notification_id. How do I fix? Thanks
Here the code:
ScheduleClient.java
public class ScheduleClient {
private ScheduleService mBoundService;
private Context mContext;
private boolean mIsBound;
public ScheduleClient(Context context) {
mContext = context;
}
public void doBindService() {
// Establish a connection with our service
mContext.bindService(new Intent(mContext, ScheduleService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with our service has been established,
// giving us the service object we can use to interact with our service.
mBoundService = ((ScheduleService.ServiceBinder) service).getService();
}
public void onServiceDisconnected(ComponentName className) {
mBoundService = null;
}
};
public void setAlarmForNotification(Calendar c){
mBoundService.setAlarm(c);
}
public void doUnbindService() {
if (mIsBound) {
// Detach our existing connection.
mContext.unbindService(mConnection);
mIsBound = false;
}
}
}
ScheduleService.java
public class ScheduleService extends Service {
public class ServiceBinder extends Binder {
ScheduleService getService() {
return ScheduleService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("ScheduleService", "Received start id " + startId + ": " + intent);
stopped, so return sticky.
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IBinder mBinder = new ServiceBinder();
public void setAlarm(Calendar c) {
// This starts a new thread to set the alarm
// You want to push off your tasks onto a new thread to free up the UI to carry on responding
new AlarmTask(this, c).run();
}
}
AlarmTask.java
public class AlarmTask implements Runnable {
private final Calendar date;
private final AlarmManager am;
private final Context context;
public AlarmTask(Context context, Calendar date) {
this.context = context;
this.am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
this.date = date;
}
#Override
public void run() {
// Request to start are service when the alarm date is upon us
// We don't start an activity as we just want to pop up a notification into the system bar not a full activity
Intent intent = new Intent(context, NotifyService.class);
intent.putExtra(NotifyService.INTENT_NOTIFY, true);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
// Sets an alarm - note this alarm will be lost if the phone is turned off and on again
am.set(AlarmManager.RTC, date.getTimeInMillis(), pendingIntent);
}
}
NotifyService.java
public class NotifyService extends Service {
public class ServiceBinder extends Binder {
NotifyService getService() {
return NotifyService.this;
}
}
Random random = new Random();
int randomID = random.nextInt(9999 - 1000) + 1000;
public static final String INTENT_NOTIFY = "com.try.myapp.INTENT_NOTIFY";
private NotificationManager mNM;
#Override
public void onCreate() {
Log.i("NotifyService", "onCreate()");
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// If this service was started by out AlarmTask intent then we want to show our notification
if(intent.getBooleanExtra(INTENT_NOTIFY, false))
showNotification(randomID);
// We don't care if this service is stopped as we have already delivered our notification
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IBinder mBinder = new ServiceBinder();
private void showNotification(int notificationID) {
// This is the 'title' of the notification
CharSequence title = "Notification!";
// This is the icon to use on the notification
int icon = R.drawable.ic_dialog_alert;
// This is the scrolling text of the notification
CharSequence text = "Sub text notification.";
// What time to show on the notification
long time = System.currentTimeMillis();
Notification notification = new Notification(icon, text, time);
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, notificationID, new Intent(this, SecondActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, title, text, contentIntent);
// Clear the notification when it is pressed
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_LIGHTS;
notification.defaults |= Notification.DEFAULT_VIBRATE;
// Send the notification to the system.
mNM.notify(notificationID, notification);
// Stop the service when we are finished
stopSelf();
}
}
InsertDateActivity.java
public class InsertCarActivity extends AppCompatActivity {
....
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
int id = item.getItemId();
if (id == R.id.saveButton) {
firstDate = fDate.getText().toString().trim();
secondDate = sDate.getText().toString().trim();
thirdDate = tDate.getText().toString().trim();
String[] arrFirstDate = firstDate.split("-");
int day = Integer.parseInt(arrFirstDate[0]);
int month = Integer.parseInt(arrFirstDate[1]);
month -= 1;
int year = Integer.parseInt(arrFirstDate[2]);
Calendar c = Calendar.getInstance();
c.set(year, month, day);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
scheduleClient.setAlarmForNotification(c);
String[] arrSecondDate = secondDate.split("-");
int day1 = Integer.parseInt(arrSecondDate[0]);
int month1 = Integer.parseInt(arrSecondDate[1]);
month1 -= 1;
int year1 = Integer.parseInt(arrSecondDate[2]);
Calendar c1 = Calendar.getInstance();
c1.set(year1, month1, day1);
c1.set(Calendar.HOUR_OF_DAY, 0);
c1.set(Calendar.MINUTE, 0);
c1.set(Calendar.SECOND, 0);
scheduleClient.setAlarmForNotification(c1);
String[] arrThirdDate = thirdDate.split("-");
int day2 = Integer.parseInt(arrThirdDate[0]);
int month2 = Integer.parseInt(arrThirdDate[1]);
month2 -= 1;
int year2 = Integer.parseInt(arrThirdDate[2]);
Calendar c2 = Calendar.getInstance();
c2.set(year2, month2, day2);
c2.set(Calendar.HOUR_OF_DAY, 0);
c2.set(Calendar.MINUTE, 0);
c2.set(Calendar.SECOND, 0);
scheduleClient.setAlarmForNotification(c2);
return true;
}
return false;
}
....
}
When you create your PendingIntent here:
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
you probably want to pass a different requestCode (the first 0 you're passing) every time or the PendingIntent will be the same as the last one you created and the following:
am.set(AlarmManager.RTC, date.getTimeInMillis(), pendingIntent);
will set a new alarm for the same PendingIntent as before, so only the last alarm you set will actually ever trigger.
From the official docs
If you truly need multiple distinct PendingIntent objects active at the same time (such as to use as two notifications that are both shown at the same time), then you will need to ensure there is something that is different about them to associate them with different PendingIntents. This may be any of the Intent attributes considered by Intent.filterEquals, or different request code integers supplied to getActivity(Context, int, Intent, int), getActivities(Context, int, Intent[], int), getBroadcast(Context, int, Intent, int), or getService(Context, int, Intent, int).
Related
I'm trying to start a service that adds an item to RecyclerView every 24 hours (every day). I used this code but it doesn't work:
BackgroundService.java
public class BackgroundService extends Service {
private boolean isRunning;
private Context context;
private Thread backgroundThread;
SharedPreferences pref;
String isMorningChecked;
String isEveningChecked;
String isNightChecked;
String isEchuraistChecked;
String isConfessChecked;
String isBibleChecked;
String Date;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
this.context = this;
this.isRunning = false;
this.backgroundThread = new Thread(addNewNote);
}
private Runnable addNewNote = new Runnable() {
#Override
public void run() {
Log.e("isRunning", "Yeeeeeeeeeees!");
pref = getApplicationContext().getSharedPreferences("checkStates", 0);
String checkMorningState = pref.getString("morning", "False");
String checkEveningState = pref.getString("evening", "False");
String checkNightState = pref.getString("night", "False");
String checkEchuraistState = pref.getString("echuraist", "False");
String checkConfessState = pref.getString("confess", "False");
String checkBibleState = pref.getString("bible", "False");
String writeYourNotes = pref.getString("writeNotes", "");
SimpleDateFormat sdf = new SimpleDateFormat("E", new Locale("ar"));
final SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy.MM.dd");
final Timestamp timestamp = new Timestamp(System.currentTimeMillis());
Date = sdf2.format(timestamp).toString();
if(checkMorningState.equals("True")){
isMorningChecked = "+";
}else{
isMorningChecked = "-";
}
if(checkEveningState.equals("True")){
isEveningChecked = "+";
}else{
isEveningChecked = "-";
}
if(checkNightState.equals("True")){
isNightChecked = "+";
}else{
isNightChecked = "-";
}
if(checkEchuraistState.equals("True")){
isEchuraistChecked = "+";
}else{
isEchuraistChecked = "-";
}
if(checkConfessState.equals("True")){
isConfessChecked = "+";
}else{
isConfessChecked = "-";
}
if(checkBibleState.equals("True")){
isBibleChecked = "+";
}else{
isBibleChecked = "-";
}
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "Note").allowMainThreadQueries().build();
db.userDao().insertAll(new Note(sdf.format(timestamp), sdf2.format(timestamp).toString(), isMorningChecked, isEveningChecked, isNightChecked, isEchuraistChecked, isConfessChecked, isBibleChecked, writeYourNotes));
stopSelf();
}
};
#Override
public void onDestroy() {
super.onDestroy();
this.isRunning = false;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(!this.isRunning){
this.isRunning = true;
this.backgroundThread.start();
}
return START_STICKY;
}
}
BoardCastReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, BackgroundService.class));
}
}
Home.java
Intent alarm = new Intent(this, AlarmReceiver.class);
boolean alarmRunning = ((PendingIntent.getBroadcast(this,0,alarm,PendingIntent.FLAG_NO_CREATE)) != null);
if(alarmRunning == false){
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,0,alarm,0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 1000, pendingIntent);
I have tried this but the Service works once or twice and then it stops and sometimes it gives me the following error:
java.lang.IllegalStateException: Not allowed to start service Intent
Background service can not be used for long running tasks on Android 8.0 onwards. Please use JobScheduler API or Workmanager to achieve the desired results. Consult the following link for details.
https://developer.android.com/topic/libraries/architecture/workmanager
I'm getting below mention error
Fatal Exception: android.app.RemoteServiceException
Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{c4f1a3e u0 com.sparkle.drinkwater/com.drinkwater.DemoNoti.SleepReminderService}
here is the SleepReminderService class
public class SleepReminderService extends Service {
private Alarmio alarmio;
private PowerManager powerManager;
private ScreenReceiver receiver;
#Override
public void onCreate() {
super.onCreate();
alarmio = (Alarmio) getApplicationContext();
powerManager = (PowerManager) getSystemService(POWER_SERVICE);
receiver = new ScreenReceiver(this);
refreshState();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(receiver, filter);
}
#Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
refreshState();
return super.onStartCommand(intent, flags, startId);
}
/**
* Refresh the state of the sleepy stuff. This will either show a notification if a notification
* should be shown, or stop the service if it shouldn't.
*/
public void refreshState() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? powerManager.isInteractive() : powerManager.isScreenOn()) {
AlarmData nextAlarm = getSleepyAlarm(alarmio);
if (nextAlarm != null) {
NotificationCompat.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (manager != null)
manager.createNotificationChannel(new NotificationChannel("sleepReminder", getString(R.string.title_sleep_reminder), NotificationManager.IMPORTANCE_DEFAULT));
builder = new NotificationCompat.Builder(this, "sleepReminder");
} else builder = new NotificationCompat.Builder(this);
startForeground(540, builder.setContentTitle(getString(R.string.title_sleep_reminder))
.setContentText(String.format(getString(R.string.msg_sleep_reminder),
FormatUtils.formatUnit(this, (int) TimeUnit.MILLISECONDS.toMinutes(nextAlarm.getNext().getTimeInMillis() - System.currentTimeMillis()))))
.setSmallIcon(R.drawable.ic_notification_sleep)
.setPriority(NotificationCompat.PRIORITY_LOW)
.build());
return;
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
stopSelf();
stopForeground(true);
}
/**
* Get a sleepy alarm. Well, get the next alarm that should trigger a sleep alert.
*
* #param alarmio The active Application instance.
* #return The next [AlarmData](../data/AlarmData) that should trigger a
* sleep alert, or null if there isn't one.
*/
#Nullable
public static AlarmData getSleepyAlarm(Alarmio alarmio) {
if (PreferenceData.SLEEP_REMINDER.getValue(alarmio)) {
AlarmData nextAlarm = getNextWakeAlarm(alarmio);
if (nextAlarm != null) {
Calendar nextTrigger = nextAlarm.getNext();
nextTrigger.set(Calendar.MINUTE, nextTrigger.get(Calendar.MINUTE) - (int) TimeUnit.MILLISECONDS.toMinutes((long) PreferenceData.SLEEP_REMINDER_TIME.getValue(alarmio)));
if (Calendar.getInstance().after(nextTrigger))
return nextAlarm;
}
}
return null;
}
/**
* Get the next scheduled [AlarmData](../data/AlarmData) that will ring.
*
* #param alarmio The active Application instance.
* #return The next AlarmData that will wake the user up.
*/
#Nullable
public static AlarmData getNextWakeAlarm(Alarmio alarmio) {
Calendar nextNoon = Calendar.getInstance();
nextNoon.set(Calendar.HOUR_OF_DAY, 12);
if (nextNoon.before(Calendar.getInstance()))
nextNoon.set(Calendar.DAY_OF_YEAR, nextNoon.get(Calendar.DAY_OF_YEAR) + 1);
else return null;
Calendar nextDay = Calendar.getInstance();
nextDay.set(Calendar.HOUR_OF_DAY, 0);
while (nextDay.before(Calendar.getInstance()))
nextDay.set(Calendar.DAY_OF_YEAR, nextDay.get(Calendar.DAY_OF_YEAR) + 1);
List<AlarmData> alarms = alarmio.getAlarms();
AlarmData nextAlarm = null;
for (AlarmData alarm : alarms) {
Calendar next = alarm.getNext();
if (alarm.isEnabled && next.before(nextNoon) && next.after(nextDay) && (nextAlarm == null || nextAlarm.getNext().after(next)))
nextAlarm = alarm;
}
return nextAlarm;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* To be called whenever an alarm is changed, might change, or when time might have
* unexpectedly leaped forwards. This will start the service if there is a
* [sleepy alarm](#getsleepyalarm) present.
*
* #param context An active context instance.
*/
public static void refreshSleepTime(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && ContextCompat.checkSelfPermission(context, Manifest.permission.FOREGROUND_SERVICE) != PackageManager.PERMISSION_GRANTED)
return;
Alarmio alarmio;
if (context instanceof Alarmio)
alarmio = (Alarmio) context;
else alarmio = (Alarmio) context.getApplicationContext();
if (getSleepyAlarm(alarmio) != null) {
Intent intent = new Intent(alarmio, SleepReminderService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
alarmio.startForegroundService(intent);
else alarmio.startService(intent);
}
}
private static class ScreenReceiver extends BroadcastReceiver {
private WeakReference<SleepReminderService> serviceReference;
public ScreenReceiver(SleepReminderService service) {
serviceReference = new WeakReference<>(service);
}
#Override
public void onReceive(Context context, Intent intent) {
SleepReminderService service = serviceReference.get();
if (service != null)
service.refreshState();
}
}
}
i am using service on my android application. I got this error on Fabric crashlytics also I was not able to reproduce this issue. Here is the AlarmData class
public class AlarmData implements Parcelable {
private int id;
public String name;
public Calendar time;
public boolean isEnabled = true;
public boolean[] isLast = new boolean[7];
public boolean[] days = new boolean[7];
public AlarmData(int id, Calendar time) {
this.id = id;
this.time = time;
}
public AlarmData(int id, Context context) {
this.id = id;
name = PreferenceData.ALARM_NAME.getSpecificOverriddenValue(context, getName(context), id);
time = Calendar.getInstance();
time.setTimeInMillis((long) PreferenceData.ALARM_TIME.getSpecificValue(context, id));
isEnabled = PreferenceData.ALARM_ENABLED.getSpecificValue(context, id);
for (int i = 0; i < 7; i++) {
days[i] = PreferenceData.ALARM_DAY_ENABLED.getSpecificValue(context, id, i);
isLast[i] = PreferenceData.ALARM_LAST_ENABLED.getSpecificValue(context, id, i);
}
}
public void setDays(Context context, boolean[] days,boolean[] isLast) {
this.days = days;
this.isLast = isLast;
for (int i = 0; i < 7; i++) {
PreferenceData.ALARM_DAY_ENABLED.setValue(context, days[i], id, i);
PreferenceData.ALARM_LAST_ENABLED.setValue(context, isLast[i], id, i);
}
}
/**
* Moves this AlarmData's preferences to another "id".
*
* #param id The new id to be assigned
* #param context An active context instance.
*/
public void onIdChanged(int id, Context context) {
PreferenceData.ALARM_NAME.setValue(context, getName(context), id);
PreferenceData.ALARM_TIME.setValue(context, time != null ? time.getTimeInMillis() : null, id);
PreferenceData.ALARM_ENABLED.setValue(context, isEnabled, id);
for (int i = 0; i < 7; i++) {
PreferenceData.ALARM_DAY_ENABLED.setValue(context, days[i], id, i);
}
onRemoved(context);
this.id = id;
if (isEnabled)
set(context, (AlarmManager) context.getSystemService(Context.ALARM_SERVICE));
}
public boolean isRepeat() {
for (boolean day : days) {
if (day)
return true;
}
return false;
}
public boolean isLastTrue() {
for (boolean day : isLast) {
if (day)
return true;
}
return false;
}
/**
* Removes this AlarmData's preferences.
*
* #param context An active context instance.
*/
public void onRemoved(Context context) {
cancel(context, (AlarmManager) context.getSystemService(Context.ALARM_SERVICE));
PreferenceData.ALARM_NAME.setValue(context, null, id);
PreferenceData.ALARM_TIME.setValue(context, null, id);
PreferenceData.ALARM_ENABLED.setValue(context, null, id);
}
/**
* Returns the user-defined "name" of the alarm, defaulting to
* "Alarm (1..)" if unset.
*
* #param context An active context instance.
* #return The alarm name, as a string.
*/
public String getName(Context context) {
if (name != null)
return name;
else return context.getString(R.string.title_alarm, id + 1);
}
/**
* Sets the user-defined "name" of the alarm.
*
* #param context An active context instance.
* #param name The new name to be set.
*/
public void setName(Context context, String name) {
this.name = name;
PreferenceData.ALARM_NAME.setValue(context, name, id);
}
/**
* Change the scheduled alarm time,
*
* #param context An active context instance.
* #param manager An AlarmManager to schedule the alarm on.
* #param timeMillis The UNIX time (in milliseconds) that the alarm should ring at.
* This is independent to days; if the time correlates to 9:30 on
* a Tuesday when the alarm should only repeat on Wednesdays and
* Thursdays, then the alarm will next ring at 9:30 on Wednesday.
*/
public void setTime(Context context, AlarmManager manager, long timeMillis) {
time.setTimeInMillis(timeMillis);
PreferenceData.ALARM_TIME.setValue(context, timeMillis, id);
if (isEnabled)
set(context, manager);
}
/**
* Set whether the alarm is enabled.
*
* #param context An active context instance.
* #param manager An AlarmManager to schedule the alarm on.
* #param isEnabled Whether the alarm is enabled.
*/
public void setEnabled(Context context, AlarmManager manager, boolean isEnabled) {
this.isEnabled = isEnabled;
PreferenceData.ALARM_ENABLED.setValue(context, isEnabled, id);
if (isEnabled)
set(context, manager);
else cancel(context, manager);
}
#Nullable
public Calendar getNext() {
if (isEnabled) {
Calendar now = Calendar.getInstance();
Calendar next = Calendar.getInstance();
next.set(Calendar.HOUR_OF_DAY, time.get(Calendar.HOUR_OF_DAY));
next.set(Calendar.MINUTE, time.get(Calendar.MINUTE));
next.set(Calendar.SECOND, 0);
while (now.after(next))
next.add(Calendar.DATE, 1);
if (isRepeat()) {
int nextDay = next.get(Calendar.DAY_OF_WEEK) - 1; // index on 0-6, rather than the 1-7 returned by Calendar
for (int i = 0; i < 7 && !days[nextDay]; i++) {
nextDay++;
nextDay %= 7;
}
next.set(Calendar.DAY_OF_WEEK, nextDay + 1); // + 1 = back to 1-7 range
while (now.after(next))
next.add(Calendar.DATE, 7);
}
return next;
}
return null;
}
/**
* Set the next time for the alarm to ring.
*
* #param context An active context instance.
* #param manager The AlarmManager to schedule the alarm on.
* #return The next [Date](https://developer.android.com/reference/java/util/Date)
* at which the alarm will ring.
*/
public Date set(Context context, AlarmManager manager) {
Calendar nextTime = getNext();
setAlarm(context, manager, nextTime.getTimeInMillis());
return nextTime.getTime();
}
/**
* Schedule a time for the alarm to ring at.
*
* #param context An active context instance.
* #param manager The AlarmManager to schedule the alarm on.
* #param timeMillis A UNIX timestamp specifying the next time for the alarm to ring.
*/
private void setAlarm(Context context, AlarmManager manager, long timeMillis) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
manager.setAlarmClock(
new AlarmManager.AlarmClockInfo(
timeMillis,
PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0)
),
getIntent(context)
);
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
manager.setExact(AlarmManager.RTC_WAKEUP, timeMillis, getIntent(context));
else
manager.set(AlarmManager.RTC_WAKEUP, timeMillis, getIntent(context));
Intent intent = new Intent("android.intent.action.ALARM_CHANGED");
intent.putExtra("alarmSet", true);
context.sendBroadcast(intent);
}
manager.set(AlarmManager.RTC_WAKEUP,
timeMillis - (long) PreferenceData.SLEEP_REMINDER_TIME.getValue(context),
PendingIntent.getService(context, 0, new Intent(context, SleepReminderService.class), 0));
SleepReminderService.refreshSleepTime(context);
}
/**
* Cancel the next time for the alarm to ring.
*
* #param context An active context instance.
* #param manager The AlarmManager that the alarm was scheduled on.
*/
public void cancel(Context context, AlarmManager manager) {
manager.cancel(getIntent(context));
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Intent intent = new Intent("android.intent.action.ALARM_CHANGED");
intent.putExtra("alarmSet", false);
context.sendBroadcast(intent);
}
}
/**
* The intent to fire when the alarm should ring.
*
* #param context An active context instance.
* #return A PendingIntent that will open the alert screen.
*/
private PendingIntent getIntent(Context context) {
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra(AlarmReceiver.EXTRA_ALARM_ID, id);
return PendingIntent.getBroadcast(context, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
protected AlarmData(Parcel in) {
id = in.readInt();
name = in.readString();
time = Calendar.getInstance();
time.setTimeInMillis(in.readLong());
isEnabled = in.readByte() != 0;
isLast = in.createBooleanArray();
days = in.createBooleanArray();
}
#Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(id);
parcel.writeString(name);
parcel.writeLong(time.getTimeInMillis());
parcel.writeBooleanArray(days);
parcel.writeBooleanArray(isLast);
parcel.writeByte((byte) (isEnabled ? 1 : 0));
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<AlarmData> CREATOR = new Creator<AlarmData>() {
#Override
public AlarmData createFromParcel(Parcel in) {
return new AlarmData(in);
}
#Override
public AlarmData[] newArray(int size) {
return new AlarmData[size];
}
};
}
Any one help me how can i solve this ?
I want to use alarm based on some database time value . Currently my alarm is working for one alarm Like : I have 3 alarm set at 8:30am , 10:20am and 12:20Pm
my alarm is working only for one value .This is reminder class there i am creating the alarm
public class OwnGoalReminder extends EventReminder {
GoalOwn goalOwn;
int interValTime;
int goalId;
int hour;
int minute;
int requestCode;
String type;
public void setInterValTime(int interValTime) {
this.interValTime = interValTime;
}
public int getHour() {
return hour;
}
public void setHour(int hour) {
this.hour = hour;
}
public void setRequestCode(int requestCode) {
this.requestCode = requestCode;
}
public void setType(String type) {
this.type = type;
}
public int getMinute() {
return minute;
}
#Override
protected int getGoalId(){return this.goalId;}
public void setMinute(int minute) {
this.minute = minute;
}
public OwnGoalReminder(Context context , int goalId, int interValTime){
super(context);
this.interValTime = interValTime;
this.goalId = goalId;
}
#Override
protected String getType() {
return this.type;
}
#Override
protected String getMessage() {
return "Reminder!!! You should check your goals!";
}
#Override
protected int getRequestCode() {
return requestCode;
}
#Override
protected EventTime getEventTime() {
int h = hour;
int m = minute;
return new EventTime(hour,minute,interValTime);
}
#Override
protected Class getBroadcastReceiver() {
return MyBroadcastReceiver.class;
}
}
This is base class of OwnGOalReminder
public abstract class EventReminder{
protected Context context;
protected Alarm alarm;
PushNotificationsManager notificationsManager;
public void remind() {
Bundle bundle = new Bundle();
bundle.putString("type", getType());
bundle.putString("msg", getMessage());
notificationsManager.sendNotification(bundle);
}
protected abstract String getType();
protected abstract String getMessage();
protected abstract int getRequestCode();
protected abstract int getGoalId();
protected abstract EventTime getEventTime();
protected abstract Class getBroadcastReceiver();
protected EventReminder(Context context){
this.context = context;
alarm = new Alarm(context, getBroadcastReceiver());
notificationsManager = new PushNotificationsManager(context);
}
public void startReminder(){
alarm.startAlert(getRequestCode(), getGoalId(), getEventTime().hour, getEventTime().minute, getEventTime().intervalInMinute);
//alarm.setAlarm(context, getEventTime().hour, getEventTime().minute);
}
protected class EventTime{
int hour, minute, intervalInMinute;
public EventTime(int hour, int minute, int intervalInMinute){
this.hour = hour;
this.minute = minute;
this.intervalInMinute = intervalInMinute;
}
}
}
this is alarm class there i am creating the alarmmanager
public class Alarm{
private final Context context;
private Class broadcastReceiver;
public Alarm(Context context, Class broadcastReceiver){
this.context = context;
this.broadcastReceiver = broadcastReceiver;
}
public void startAlert(int requestCode, int gid, int hour, int minute, int intervalMinute) {
Log.d(this.getClass().getName(), "starting alert");
int i = 10;
Long timeToMilliSeconds = timeToMilliSeconds(hour, minute);
Intent intent = new Intent(context, MyBroadcastReceiver.class);
intent.putExtra("reqcode", requestCode);
intent.putExtra("time", timeToMilliSeconds);
intent.putExtra("gid" , gid);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, timeToMilliSeconds+
+ (i * 1000), 1000*60*intervalMinute, pendingIntent);
//Toast.makeText(context, "Alarm set in " + i + " seconds",Toast.LENGTH_LONG).show();
}
#NonNull
public static long timeToMilliSeconds(int hour, int minute) {
Date dat = new Date();//initializes to now
Calendar cal_alarm = Calendar.getInstance();
Calendar cal_now = Calendar.getInstance();
cal_now.setTime(dat);
cal_alarm.setTime(dat);
cal_alarm.set(Calendar.HOUR_OF_DAY,hour);//set the alarm time
cal_alarm.set(Calendar.MINUTE, minute);
cal_alarm.set(Calendar.SECOND,0);
if(cal_alarm.getTimeInMillis() < System.currentTimeMillis()){
cal_alarm.add(Calendar.DAY_OF_YEAR,1);
}
return cal_alarm.getTimeInMillis();
}
}
This is the method here i am creating the multiple alarm object based on database value
public static void registerAlarm(Context context){
if(!UserPreferences.isAlarmRegistered(context)) {
GoalReminder goalReminder = new GoalReminder(context);
AppraisalReminder appraisalReminder = new AppraisalReminder(context);
goalReminder.startReminder();
appraisalReminder.startReminder();
// ownGoalReminder.startReminder();
//UserPreferences.setIsAlarmRegistered(context,true);
ArrayList<Goal> LIST_OF_OWN_GOALS = new ArrayList<>();
LIST_OF_OWN_GOALS = (ArrayList<Goal>) Goal.getGoalFromOwnGoals();
for (Goal g : LIST_OF_OWN_GOALS) {
OwnGoalReminder ownGoalReminder = new OwnGoalReminder(context , g.getgId(),3 );
int h = Integer.parseInt(g.getrTime())/60;
int min = Integer.parseInt(g.getrTime())%60;
ownGoalReminder.setHour(h);
ownGoalReminder.setMinute(min);
ownGoalReminder.setRequestCode(16);
ownGoalReminder.setType("16");
ownGoalReminder.startReminder();
LIST_OF_OWN_REMINDERS.add(ownGoalReminder);
}
}
}
This is my Broadcast receiver class :
public class MyBroadcastReceiver extends BroadcastReceiver {
private static final String[] goalMessagesArray = ApraiseApplication.getContext().getResources().getStringArray(R.array.goals_messages);
private static Queue<String> goalMessagesQueue = new ArrayDeque<>(Arrays.asList(goalMessagesArray));
private static final String[] appraisalsMessagesArray = ApraiseApplication.getContext().getResources().getStringArray(R.array.appraisals_messages);
private static Queue<String> appraisalsMessagesQueue = new ArrayDeque<>(Arrays.asList(appraisalsMessagesArray));
#Override
public void onReceive(Context context, Intent intent) {
Log.d(this.getClass().getName(), "notify");
PushNotificationsManager notificationsManager = new PushNotificationsManager(context);
PowerManager.WakeLock wl = acquireWakeLock(context);
int requestCode = intent.getIntExtra("reqcode",1);
int gId = intent.getIntExtra("gid",1);
long time = intent.getLongExtra("time",0);
String message = "";
// it will create the instance of Random class
Random randomGenerator = new Random();
// it will generate a random number based on goal message arrayList length
int indexForGoalMessage = randomGenerator.nextInt(goalMessagesArray.length);
// it will generate a random number based on appraisalsMessagesArray length
int indexForAppraisalsMessage = randomGenerator.nextInt(goalMessagesArray.length);
String gid = "";
if(isNotifyTimePassed(time)){
//return;
}
if(requestCode == 123){
// if(goalMessagesQueue.isEmpty()){
// goalMessagesQueue = new ArrayDeque<>(Arrays.asList(goalMessagesArray));
// }
// message = goalMessagesQueue.poll();
message = goalMessagesArray[indexForGoalMessage];
}else if(requestCode == 124){
// if(appraisalsMessagesQueue.isEmpty()){
// appraisalsMessagesQueue = new ArrayDeque<>(Arrays.asList(appraisalsMessagesArray));
// }
// message = appraisalsMessagesQueue.poll();
message = appraisalsMessagesArray[indexForAppraisalsMessage];
}
Bundle bundle = new Bundle();
bundle.putString("type", Integer.toString(requestCode));
bundle.putString("msg", message);
bundle.putString("gid" , String.valueOf(gId));
notificationsManager.sendNotification(bundle);
wl.release();
}
#NonNull
private PowerManager.WakeLock acquireWakeLock(Context context) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
return wl;
}
private boolean isNotifyTimePassed(long time) {
return (System.currentTimeMillis()-time) > 1000L*60L*5L;
}
}
[I have found this solution from searching google ]
I have solved that problem by passing unique id which is depend on current time:-
final int intent_id= (int) System.currentTimeMillis();
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, intent_id , intent, PendingIntent.FLAG_UPDATE_CURRENT);
It is good to set your event id (unique id) as the request code of PendingIntent.getBroadcast() method. So the advantage here is when you update/edit the event then alarm wont duplicate.
I have a togglebutton in the main activity which enables alarm. aid is a unique key.
I need to have an alarm notification when the togglebutton is enabled so on that particular date the alarm will go. When the toggle button is offed the alarm should be canceled.
When the togglebutton is on the toast is not coming. which means the BroadcastReceiver is not called.
But when the toggle is offed the toast comes.
btnToggle.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (btnToggle.isChecked()) {
AddReminder reminder = new AddReminder(year,
month, day, hour,
min, body, context, aid);
reminder.setNotification();
} else {
AddReminder reminder = new AddReminder(context, mtchid);
reminder.offNotification();
}
}
});
This is the AddReminder Class I coded
public class AddReminder {
private String formattedYear;
private String formattedMonth;
private String formattedDay;
private String formattedHour;
private String formattedMin;
private String body;
private Context context;
private String aid;
private int mYear;
private int mMonth;
private int mDay;
private int mHour;
private int mMin;
private int alrmId = 0;
int aID;
public AddReminder(Context c, String aid){
this.context = c;
this.aid = aid;
aID = Integer.parseInt(aid);
}
public AddReminder(String year, String month, String day, String hour, String min, String body, Context c, String aid){
this.formattedYear = year;
this.formattedMonth = month;
this.formattedDay = day;
this.formattedHour = hour;
this.formattedMin = min;
this.body = body;
this.context = c;
this.aid = aid;
aID = Integer.parseInt(aid);
}
public void setNotification(){
Calendar c = Calendar.getInstance();
mYear = Integer.parseInt(formattedYear);
mMonth = Integer.parseInt(formattedMonth);
mDay = Integer.parseInt(formattedDay) - 1;
mHour = Integer.parseInt(formattedHour);
mMin = Integer.parseInt(formattedMin);
//set Reminder time and date into calendar object
c.set(Calendar.YEAR,mYear);
c.set(Calendar.MONTH, mMonth);
c.set(Calendar.DATE, mDay);// 1 days before
c.set(Calendar.HOUR_OF_DAY, mHour);
c.set(Calendar.MINUTE, mMin);
c.set(Calendar.SECOND, 0);
alrmId = Integer.parseInt(mMonth + "" + mDay + "" + mHour + ""
+ mMin);
Intent in = new Intent(context, ReminderReceiver.class);
in.putExtra("body", body);
in.putExtra("AlrmId", alrmId);
in.putExtra("aid",aid);
PendingIntent sender = PendingIntent.getBroadcast(context, aID, in, PendingIntent.FLAG_CANCEL_CURRENT);
// Get the AlarmManager service
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), sender);
}
public void offNotification(){
Intent intent = new Intent(context, ReminderReceiver.class);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getBroadcast(context, aID, intent,0);
am.cancel(pi);
}
}
This is the broadcast Receiver class
public class ReminderReceiver extends BroadcastReceiver {
String body;
String AlrmId;
String id;
String aid;
#Override
public void onReceive(Context context, Intent intent) {
body = intent.getStringExtra("body");
AlrmId = intent.getStringExtra("AlrmId");
aid = intent.getStringExtra("aid");
Toast.makeText(context, body+"/"+AlrmId+"/"+id+"/"+aid, Toast.LENGTH_SHORT).show();
}
}
The Toast is not shown because it´s not the time for it. The BroadcastReceiver is reached when the alarmManager fires the message at the given time. So to make the simple message when the alarm is turned on, do it inside the setNotification() event:
public void setNotification(){
//Your code
.
.
.
Toast.makeText(context,"ALARM IS ON", Toast.LENGTH_SHORT().show();
}
I'm trying to use pressure sensor.
After every 6 sec read sensor value and show.
But it always shows "0.0"
First time I tried static variable...but not working.
Now using singleton, still it is not working.
I don't know where I am wrong.
Help me. Please.
/* broadcastReceiver */
public class Alarm extends BroadcastReceiver {
static int count = 0;
#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, "");
wl.acquire();
SensorValue sv = SensorValue.getInstance();
Toast.makeText(context, "Barometer : " + String.valueOf( sv.getBaroVal() ) + " count : " + String.valueOf( count ), Toast.LENGTH_SHORT ).show(); // For example
count++;
wl.release();
}
public void SetAlarm(Context context){
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10 * 60 * 10, pi); // Millisec * Second * Minute
}
public void CancelAlarm(Context context) {
Intent intent = new Intent(context, Alarm.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
}
/* singleton */
public class SensorValue {
private static SensorValue singleton = new SensorValue();
private double baroVal = 0.0;
private SensorValue(){
}
public static SensorValue getInstance(){
return singleton;
}
public void setBaroVal( double val ) {
baroVal = val;
}
public double getBaroVal() {
return baroVal;
}
}
/* MainActivity */
#Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_PRESSURE:
sv.setBaroVal( event.values[0] );
break;
}
}
Thank You!
Change your SensorValue class to below.
public class SensorValue {
private static SensorValue singleton;
private double baroVal = 0.0;
private SensorValue(){
singleton = new SensorValue();
}
public static SensorValue getInstance(){
if(singleton == null)
{
singleton = new SensorValue();
}
return singleton
}
public void setBaroVal( double val ) {
baroVal = val;
}
public double getBaroVal() {
return baroVal;
}
}
I don,t know whether it will work or not though test it with once.
Finally, I found a reason.
in manifest file. i set receiver option like this
android:process=":remote"
it worked another process.
have a good day.