Alarm Manager & Broadcast receiver not stopping - android

I want to create notifications on multiple specific dates & time, which are stored in database. I can get Notifications on correct date and time, but what i noticed later is, that i also got notifications randomly on the next day. They keep cropping up whenever i restart the emulator.
So, it seems that i can't stop the Alarm manager or Broadcast receiver. I've tried with providing pendingIntent to alarmmanager's cancel method to no avail. I also use toggle button to enable/disable notification, but it has no effect
Below is my code.
MainActivity.java
PendingIntent pendingIntent;
AlarmManager alarmManager;
Button set, cancel;
MTPAdapter db;
ArrayList<TourPlan> arrDates;
ToggleButton toggle;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
toggle = (ToggleButton) findViewById(R.id.toggleButton1);
// This function fetched data from DB
fetchDates();
set = (Button) findViewById(R.id.the_button);
cancel = (Button) findViewById(R.id.the_button_cancel);
cancel.setEnabled(false);
toggle.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked) {
Toast.makeText(getApplicationContext(), "Set",
Toast.LENGTH_SHORT).show();
setEvent();
} else {
alarmManager.cancel(pendingIntent);
MyReceiver.stopService(getApplicationContext());
}
}
});
} // end onCreate
public void setEvent() {
for (int i = 0; i < arrDates.size(); i++) {
// int id = arrDates.get().getId();
int year = Integer.parseInt(arrDates.get(i).getYear());
int month = Integer.parseInt(arrDates.get(i).getMonth());
int date = Integer.parseInt(arrDates.get(i).getDate());
int hour = Integer
.parseInt(firstStringer(arrDates.get(i).getTime()));
Log.v("Hour : ", "" + hour);
int minute = Integer.parseInt(stringer(arrDates.get(i).getTime()));
Log.v("minute : ", "" + minute);
int second = 00;
startAlarm(i, year, month, date, hour, minute, second);
}
}
public void startAlarm(int id, int year, int month, int date, int hour,
int minute, int second) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.DAY_OF_MONTH, date);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
// calendar.set(Calendar.AM_PM, Calendar.PM);
Intent myIntent = new Intent(MainActivity.this, MyReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, id,
myIntent, 0);
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(),
pendingIntent);
}
}
MyAlarmService.java
public class MyAlarmService extends Service {
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
#SuppressWarnings("static-access")
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("ISFA")
.setStyle(
new NotificationCompat.BigTextStyle()
.bigText("Tour Planned for the Day"))
.setContentText("You have planned a tour for today")
.setAutoCancel(true);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
MyReceiver.java (Broadcast receiver) :
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service1 = new Intent(context, MyAlarmService.class);
context.startService(service1);
}
public static void stopService(Context context) {
Intent stopServiceIntent = new Intent(context, MyAlarmService.class);
context.stopService(stopServiceIntent);
}
}
Manifest file:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
In Application tags,
<service
android:name="com.example.brodcastalarm.MyAlarmService"
android:enabled="true" />
<!-- THE BROADCAST RECIEVER WHICH MANAGES THE BROADCAST FOR NOTIFICATION -->
<receiver android:name="com.example.brodcastalarm.MyReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
This is the Database structure.
I use subString methods to get hour and minutes.

Alarm manager needs to be manually disabled, so for doing so use code below, it will disable the alarm.
AlarmManager aManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(getBaseContext(), YourScheduleClass.class);
PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
aManager.cancel(pIntent);

Related

Triggering an alarm at a specific time every day by using setExact()

I am trying to trigger an alarm once at a specific time everyday. But like all others I am using setExact() instead of setRepeating(). Alarm is firing at the correct time. But once it fires it keeps on repeating itself after every 5sec. How can I trigger it only once in a day at a specific time? Here is my code:
MainActivity.java:
public class MainActivity extends AppCompatActivity implements Observer {
private AlarmManager alarmManager = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BroadcastObserver.getInstance().addObserver(this);
}
#Override
public void update(Observable o, Object arg) {
Log.e("MainActivity", "Alarm set through observer");
cancelAlarm();
setAlarm();
}
#Override
protected void onStart() {
super.onStart();
if (!checkAlarm()) {
setAlarm();
}
}
public void setAlarm() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 14);
calendar.set(Calendar.MINUTE, 13);
calendar.set(Calendar.SECOND, 0);
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, MyReceiver.class);
intent.setAction(MyReceiver.ACTION_RECEIVER);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
private boolean checkAlarm() {
Intent intent = new Intent(this, MyReceiver.class);
intent.setAction(MyReceiver.ACTION_RECEIVER);
boolean isSet = PendingIntent.getBroadcast(this, 1001, intent, PendingIntent.FLAG_NO_CREATE) != null;
Log.e("MainActivity", isSet + " :Alarm is set");
return isSet;
}
#Override
protected void onStop() {
super.onStop();
cancelAlarm();
}
private void cancelAlarm() {
Intent intent = new Intent(this, MyReceiver.class);
intent.setAction(MyReceiver.ACTION_RECEIVER);
final PendingIntent pendingIntent =
PendingIntent.getBroadcast(MainActivity.this, 1001, intent,
PendingIntent.FLAG_NO_CREATE);
if (pendingIntent != null) {
alarmManager.cancel(pendingIntent);
pendingIntent.cancel();
}
}
}
BroadcastReceiver:
public class MyReceiver extends BroadcastReceiver {
public static final String ACTION_RECEIVER = "Receiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.e("MainActivity", "triggered");
BroadcastObserver.getInstance().updateValue(intent);
}
}
BroadcastObserver:
public class BroadcastObserver extends Observable {
private static BroadcastObserver instance = new BroadcastObserver();
public static BroadcastObserver getInstance(){
return instance;
}
private BroadcastObserver(){}
public void updateValue(Object data) {
synchronized (this) {
setChanged();
notifyObservers(data);
}
}
}
once it fires it keeps on repeating itself after every 5 sec
You are setting an alarm for 14:13 for a given day. When the alarm fires the Observer is notified and it sets the exact same alarm (for 14:13).
At this point we're past 14:13, so the alarm will fire immediately, notifying the Observer again, resulting in an infinite loop of the above steps.
The simplest solution might be to check the time when setting the alarm and if it's in the past, then add a day to it:
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 14);
calendar.set(Calendar.MINUTE, 13);
calendar.set(Calendar.SECOND, 0);
if (calendar.before(Calendar.getInstance())) {
calendar.add(Calendar.DAY_OF_YEAR, 1);
}
To avoid memory leaks you need to remove the Observer when appropriate:
#Override
protected void onDestroy() {
BroadcastObserver.getInstance().deleteObserver(this);
super.onDestroy();
}
Also, cancelling the alarm in update() is redundant. This is not a repeating alarm, so it makes no sense to cancel it after it fired.

How to create a background notification

I want to implement a Service which permit to show a notification (daily, or after XX minutes) even if I close the application. (Actually, when I press back button, I finish the MainActivity...)
I need a runnable notification even if I didn't start the application (after rebooting the device for example, of course when the trigger is declanched)...
I tried some clear examples and tutorials but I doesn't find what I need.
Please HELP!
Thanks in advance,
Mohamed
You can do it with alarm manger:
public class AlarmHelper {
private Context context;
private AlarmManager alarmManager;
private static final String TAG = "AlarmHelper";
public final static String ALARM_ALERT_ACTION = "com.android.alarmclock.ALARM_ALERT";
public AlarmHelper(Context context) {
this.context = context;
alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
}
public void setNotifyAlarm(Long milliSecond) {
PendingIntent pendingIntent = getNotifyPendingIntent();
alarmManager.cancel(pendingIntent);
alarmManager.set(AlarmManager.RTC_WAKEUP, milliSecond, pendingIntent);
// alarmManager.set(AlarmManager.RTC_WAKEUP, milliSecond, sender);
}
public void cancelNotifyAlarm() {
PendingIntent pendingIntent = getNotifyPendingIntent();
alarmManager.cancel(pendingIntent);
}
private PendingIntent getNotifyPendingIntent() {
Intent intent = new Intent(context, AlarmExpireService.class);
return PendingIntent.getService(context, 0, intent, 0);
}
public void setExpireAlarm(int minute) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, minute - 1);
PendingIntent pendingIntent = getExpirePendingIntent();
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
pendingIntent);
}
public void cancelExpireAlarm() {
PendingIntent pendingIntent = getExpirePendingIntent();
alarmManager.cancel(pendingIntent);
}
private PendingIntent getExpirePendingIntent() {
return PendingIntent.getService(context, 0, new Intent(context,
AlarmExpireService.class), 0);
}
}
Now in the AlarmExpireService.java:
public class AlarmExpireService extends Service {
// private static final String TAG = "AlarmExpireService";
private static final String TAG = "AlarmExpireService";
#Override
public void onCreate() {
super.onCreate();
//your logic for start activity or generate notification.
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
AppLog.Log(TAG, "On start command");
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
Now Register service in the manifest file:
<service android:name="your_package.AlarmExpireService" />
For just call a method from AlarmHelper's setNotifyAlarm method and your work is done pass the time in millisecond (it will start after that time and notification will be pop up).
For more information take a reference of this links:
1. AlarmManager
2. Service
3.Pending Intent

Android: status bar notifications in specific time

I have app which in specific time start notification in status bar.But when that time elapsed, every time when I launch the app he start the notification again.
Thanks in advance.
Here is the code:
Activity: MainActivity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//notifications with solve problem
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
calendar.set(Calendar.HOUR_OF_DAY, 17);
calendar.set(Calendar.MINUTE, 30 );
calendar.set(Calendar.SECOND, 0);
calendar.getTimeInMillis();
long current_time = System.currentTimeMillis();
long limit_time = calendar.getTimeInMillis();
if (current_time > limit_time) {
//nothing
} else {
Intent myIntent = new Intent(MainActivity.this, MyReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);
}
}
}
Activity: MyReceiver
public class MyReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent)
{
Intent service1 = new Intent(context, MyAlarmService.class);
context.startService(service1);
}
}
Activity: MyAlarmService
public class MyAlarmService extends Service{
private NotificationManager mManager;
#Override
public IBinder onBind(Intent arg0)
{
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate()
{
// TODO Auto-generated method stub
super.onCreate();
}
#SuppressWarnings("static-access")
#Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
mManager = (NotificationManager) this.getApplicationContext().getSystemService(this.getApplicationContext().NOTIFICATION_SERVICE);
Intent intent1 = new Intent(this.getApplicationContext(),MainActivity.class);
Notification notification = new Notification(R.drawable.ic_launcher,"Run this app", System.currentTimeMillis() );
intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP| Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingNotificationIntent = PendingIntent.getActivity( this.getApplicationContext(),0, intent1,PendingIntent.FLAG_UPDATE_CURRENT);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.setLatestEventInfo(this.getApplicationContext(), "Horoscope", "Run this app", pendingNotificationIntent);
mManager.notify(0, notification);
}
#Override
public void onDestroy()
{
// TODO Auto-generated method stub
super.onDestroy();
}
}
I solve the problem with this post - Notification at specific time
use
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), SYNC_REPEAT_MILLSECONDS, pendingIntent);
instead of
alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);

How to play alarm based on user enter value into edittext in Android

Hi want to play alarm in my app,so i tried using below code using services when i click start button alarm is playing..but what i want is,same activity i have two editexts in first i have give time 9,and second edittext i have given time 10,so i have to show notification only in 9 and 10 pm only...any one give me some idea.
public class DonnsAlarm extends Activity {
/** Called when the activity is first created. */
EditText e1,e2;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
e1=(EditText)findViewById(R.id.editText1);
e2=(EditText)findViewById(R.id.editText2);
// click listener for the button to start service
Button btnStart = (Button) findViewById(R.id.button1);
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String s1=e1.getText().toString();
String s2=e2.getText().toString();
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(s1));
cal.add(Calendar.SECOND, 10);
Intent intent = new Intent(DonnsAlarm.this, Service_class.class);
PendingIntent pintent = PendingIntent.getService(DonnsAlarm.this, 0, intent,
0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
36000 * 1000, pintent);
PendingIntent pintent1 = PendingIntent.getService(DonnsAlarm.this, 1, intent,
0);
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(s2));
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
36000 * 1000, pintent1);
}
});
// click listener for the button to stop service
Button btnStop = (Button) findViewById(R.id.button2);
btnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stopService(new Intent(getBaseContext(), Service_class.class));
}
});
}
}
public class Service_class extends Service {
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
Intent notifyIntent = new Intent(Intent.ACTION_MAIN);
notifyIntent.setClass(getApplicationContext(), DonnsAlarm.class);
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence from ="It's Time to Play VocCards!";
CharSequence message = "It's Time to Play VocCards!";
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notifyIntent, 0);
Toast.makeText(this, "MyAlarmService.onUnbind()", Toast.LENGTH_LONG).show();
Notification notif = new Notification(R.drawable.ic_launcher,
"It's Time to Play VocCards!", System.currentTimeMillis());
notif.setLatestEventInfo(this, from, message, contentIntent);
nm.notify(1, notif);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
#Override
public void onCreate() {
super.onCreate();
}
}
I see your problem is giving the values of EditTexts to service so service knows which hours to play the alarm. You can put the values of EditText to a bundle (or intent's extras) and start the service using that intent which contains data about the hours.
In your Activity use:
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String s1=e1.getText().toString();
String s2=e2.getText().toString();
Intent intent = new Intent(getBaseContext(), Service_class.class);
intent.putExtra("value1", s1);
intent.putExtra("value2", s2);
startService(intent);
}
});
Than in your Service's onStartCommand method use this:
String val1 = intent.getExtra("value1");
String val2 = intent.getExtra("value2");
And now you have the values in your service!
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String s1=e1.getText().toString();
String s2=e2.getText().toString();
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(s1));
cal.add(Calendar.SECOND, 10);
Intent intent = new Intent(DonnsAlarm.this, Service_class.class);
PendingIntent pintent = PendingIntent.getService(DonnsAlarm.this, 0, intent,
0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
36000 * 1000, pintent);
PendingIntent pintent1 = PendingIntent.getService(DonnsAlarm.this, 1, intent,
0);
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(s2));
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
36000 * 1000, pintent1);
}
});
The above code sets the two alarm one according to the value in 1st edittext and one according to the other

Show a toast (using alarmmanager)

I've a service that runs after android starts. I'd like show a toast every days at 9am. The problem is: how can I implement the code (alarmamanger within service)?
Start service after boot:
public class AutoStart extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent();
serviceIntent.setAction("com.example.startatboot.UnUsedService");
context.startService(serviceIntent);
}
}
public class Service extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast.makeText(UnUsedService.this, "Start Alarm", Toast.LENGTH_LONG).show();
}};
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0); AlarmManager am = (AlarmManager) context.getSystemService (Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(context, 0, new Intent(context, MyClass.class), PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
Just replace your code with my code,
public class Service extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast.makeText(UnUsedService.this, "Start Alarm", Toast.LENGTH_LONG).show();
}};
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0); AlarmManager am = (AlarmManager) context.getSystemService (Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(context, 0, new Intent(context, AlarmReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
Now create a new class AlarmReceiver in the same package and add the following code to it.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm worked.", Toast.LENGTH_LONG).show();
}
}
Now define it in the PendingIntent of the Alarm.
Add following code in the manifest file,
<receiver android:name=".AlarmReceiver" />
Now run your application. that's it. It will definitely show a toast at 9.
Let me know if it worked or not.

Categories

Resources