I am creating an android app to set alarm using broadcast receiver. Its working fine when the app is open but when I closed the app completely then there is no notification generated. How to resolve this issue?
Broadcast Receiver class
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("Alarm Fired");
MediaPlayer mediaPlayer = MediaPlayer.create(context, Settings.System.DEFAULT_RINGTONE_URI);
mediaPlayer.start();
Toast.makeText(context,"ALarm fired",Toast.LENGTH_SHORT).show();
} }
Main Activity class
public class MainActivity extends AppCompatActivity {
//the timepicker object
TimePicker timePicker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//getting the timepicker object
timePicker = (TimePicker) findViewById(R.id.alarmTimePicker);
//attaching clicklistener on button
findViewById(R.id.buttonAlarm).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//We need a calendar object to get the specified time in millis
//as the alarm manager method takes time in millis to setup the alarm
Calendar calendar = Calendar.getInstance();
if (android.os.Build.VERSION.SDK_INT >= 23) {
calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH),
timePicker.getHour(), timePicker.getMinute(), 0);
} else {
calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
timePicker.getCurrentHour(), timePicker.getCurrentMinute(), 0);
}
setAlarm(calendar.getTimeInMillis());
}
});
}
private void setAlarm(long time) {
//getting the alarm manager
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//creating a new intent specifying the broadcast receiver
Intent i = new Intent(this, MyBroadcastReceiver.class);
//creating a pending intent using the intent
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
//setting the repeating alarm that will be fired every day
am.setRepeating(AlarmManager.RTC_WAKEUP, time, AlarmManager.INTERVAL_DAY, pi);
Toast.makeText(this, "Alarm is set", Toast.LENGTH_SHORT).show();
} }
AndroidManifest.xml
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true">
</receiver>
Related
I am working on alarm with android and broadcast receiver. Setting up and playing an alarm works but I cannot turn off the alarm. I have two button for set alarm and stop alarm .My codes is here;
public class MainActivity extends AppCompatActivity {
Button btn;
private Button startAlarmBtn;
private TimePickerDialog timePickerDialog;
final static int REQUEST_CODE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button cancel;
startAlarmBtn = (Button) findViewById(R.id.startAlarmBtn);
startAlarmBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openPickerDialog(false);
}
});
cancel=(Button)findViewById(R.id.cancel);
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stopAlarm();
}
});
}
private void openPickerDialog(boolean is24hour) {
Calendar calendar = Calendar.getInstance();
timePickerDialog = new TimePickerDialog(
MainActivity.this,
onTimeSetListener,
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
is24hour);
timePickerDialog.setTitle("Alarm Ayarla");
timePickerDialog.show();
}
TimePickerDialog.OnTimeSetListener onTimeSetListener
= new TimePickerDialog.OnTimeSetListener(){
#Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Calendar calNow = Calendar.getInstance();
Calendar calSet = (Calendar) calNow.clone();
calSet.set(Calendar.HOUR_OF_DAY, hourOfDay);
calSet.set(Calendar.MINUTE, minute);
calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0);
if(calSet.compareTo(calNow) <= 0){
calSet.add(Calendar.DATE, 1);
}
setAlarm(calSet);
}};
private void setAlarm(Calendar alarmCalender){
Toast.makeText(getApplicationContext(),"Alarm OK!",Toast.LENGTH_SHORT).show();
Intent intent = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), REQUEST_CODE, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, alarmCalender.getTimeInMillis(), pendingIntent);
}
private void stopAlarm(){
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), REQUEST_CODE,
new Intent(getApplicationContext(), AlarmReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
pendingIntent.cancel();
}
}
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Uri alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
if (alarmUri == null)
{
alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
}
Ringtone ringtone = RingtoneManager.getRingtone(context, alarmUri);
ringtone.play();
}
}
How do I turn off the alarm?
My other question is, is it appropriate to have them in the main thread?
Should I use AsyncTask or multi-threading?
Thank you.
The alarm is not stopping because you don't have a handle to the ringtone instance you are playing.
I suggest you add a timer to auto stop the ringtone, or you create a global instance of the ringtone, which on second thought might be a bad idea, because if you forget to clean up, it may leak and cause other problems.
A simple approach to timing this is as shown below:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Uri alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
if (alarmUri == null)
{
alarmUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
}
Ringtone ringtone = RingtoneManager.getRingtone(context, alarmUri);
ringtone.play();
new CountDownTimer(30000, 1000) { // a timer for 30 seconds, that updates approximately every second
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
// stop your ringtone here, or do other necessary stuff here
// you might want to check if the ringtone was not stopped before this method
}
}.start();
}
}
In response to your second question, you could as well use a thread with a handler or runnable to manage the ringtone accordingly. An AsyncTask may be too much work for something relatively simple.
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.
I'm currently working with Android Alarm Manager and found a working example. But it does not work properly in my situation. Let me explain. Basically my goal is to execute a method from the MainActivity each 5 mins. For this purpose I use Alarm Manager to schedule that task.
Basically this is the working stuff:
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.sendBroadcast(new Intent("SERVICE_TEMPORARY_STOPPED"));
}
}
MainActivity.java
public class MainActivity extends Activity{
private PendingIntent pendingIntent;
private AlarmManager manager;
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "I'm running", Toast.LENGTH_SHORT).show();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
registerReceiver(broadcastReceiver, new IntentFilter("SERVICE_TEMPORARY_STOPPED"));
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startAlarm();
}
});
}
public void startAlarm() {
manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
int interval = 300000;
manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
Log.d(TAG, "Alarm Set");
}
}
Everything is good. "I'm running" Toast is executed every 300000 ms (5 mins). The AlarmReceiver class send a broadcast to my main Activity with the message "SERVICE_TEMPORARY_STOPPED". I already registered that message in my MainActivity via registerReceiver(broadcastReceiver, new IntentFilter("SERVICE_TEMPORARY_STOPPED"));. But, when I add another method, let's say stopAlarm() in the broadcastReceiver, which is going to stop the alarm after 5 mins, the time interval (5 mins) is not applied anymore. In something like 10 secs, it calls the Broadcast Receiver and stop the alarm. And this is the issue. Take a look at the stop() method and how I call it on the broadcastReceiver:
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "I'm running", Toast.LENGTH_SHORT).show();
stopAlarm();
}
};
public void stopAlarm() {
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
manager.cancel(pendingIntent);
Log.d(TAG, "Alarm Cancelled");
}
Any clue?
AlarmManager.setRepeating doesn't work properly on different android versions.
Try setExact. It won't repeat but you can achieve repeating functionality as mentioned below:
Updated AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.sendBroadcast(new Intent("SERVICE_TEMPORARY_STOPPED"));
long repeatCount = PreferenceManager.getDefaultSharedPreferences(context).getLong("REPEAT_COUNT", 0L);
repeatCount++;
PreferenceManager.getDefaultSharedPreferences (context).edit().putLong("REPEAT_COUNT", repeatCount).apply()
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
manager.setExact(AlarmManager.RTC_WAKEUP, (repeatCount *System.currentTimeMillis()),pendingIntent);
}
}
Here we maintain a repeatCount & variable (preference based) and increment it in your AlarmReceiver & schedule alarm again by calculating nextAlarmTime using repeatCount * System.currentTimeMillis();
I want to set an alarm on android but its not working, here is my code..
I used the pending intent to start the alarm at a specific time, but when I run the app on my device it doesn't starts.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent alarmIntent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, alarmIntent, 0);
findViewById(R.id.startAlarm).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 16);
calendar.set(Calendar.MINUTE, 39);
/* Repeating on every 20 minutes interval */
manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60 * 20, pendingIntent);
Toast.makeText(MainActivity.this, "Alarm Set", Toast.LENGTH_SHORT).show();
}
});
findViewById(R.id.stopAlarm).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
manager.cancel(pendingIntent);
Toast.makeText(MainActivity.this, "Alarm Canceled", Toast.LENGTH_SHORT).show();
}
});
}
I am new to android, so please help.
And here is my receiver class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// For our recurring task, we'll just display a message
Toast.makeText(context, "I'm running", Toast.LENGTH_SHORT).show();
}
}
Have you declared your receiver in the manifest?
<receiver android:name="myPackage.AlarmReceiver"
android:enabled="true" >
</receiver>
I have created the start alarm as shown below
public class MyScheduleReceiver extends BroadcastReceiver {
// Restart service every 30 seconds
private static final long REPEAT_TIME = 1000 * 5;
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager service = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyStartServiceReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,
PendingIntent.FLAG_CANCEL_CURRENT);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 5);
service.setInexactRepeating(AlarmManager.RTC_WAKEUP,
cal.getTimeInMillis(), REPEAT_TIME, pending);
I crate this for stop alarm and i call it from main activity.Manifest i think is ok...Work repeat but no stop!!!
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.setup);
sendBroadcast(new Intent(this,MyScheduleReceiver.class));
}
public void StopRepeat(View view) {
sendBroadcast(new Intent(this,MyStopReceiver.class));
}
public class MyStartServiceReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Repeat service!.",
Toast.LENGTH_LONG).show();
}
public class MyStopReceiver extends BroadcastReceiver {
// Restart service every 30 seconds
private static final long REPEAT_TIME = 1000 * 5;
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager service = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent istop = new Intent(context, MyStartServiceReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(context, 0, istop,
PendingIntent.FLAG_CANCEL_CURRENT);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 5);
service.cancel(pending);
But the service is not stopping. What might be the issue?Thanks.
The simplest option is to restart your device. (If you created a BOOT_COMPLETED listener just remove it for now.)
You can also cancel an alarm by passing the PendingIntent you used to create the alarm to AlarmManager#cancel(). You have already written the code to do this, but do you have a Button with the XML attribute android:onClick="StopRepeat" in setup.xml? Did you click it?
Solution
We eventually discovered you had a mistake in your Manifest file, so MyStopServiceReceiver was never called...