Alarm is not stopping - android

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.

Related

Alarm Manager using Broadcast receiver

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>

How to show remaining time for alarm to ring using AlarmManager?

I want to know how I can show the time that is remaining for the alarm to ring. And I also want to know that how we can increment/change a variable value of different class from a different class. Suppose if I have a game where users get life every day at 12 am. So how can I provide life to users using AlarmManager.
Here is my code for MainActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.timeRemain);
long timeRemaining;
final TimePicker timePicker = findViewById(R.id.timepicker);
findViewById(R.id.alarm).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Calendar calendar = Calendar.getInstance();
if (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 timeInMillis) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC, timeInMillis, AlarmManager.INTERVAL_DAY,
pendingIntent);
Toast.makeText(this,"Alarm is Set", Toast.LENGTH_SHORT) .show();
}
}
My alarmReciever class
public class Alarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
MediaPlayer mediaPlayer = MediaPlayer.create(context, Settings.System.DEFAULT_RINGTONE_URI);
mediaPlayer.start();
}
}
Any Suggestions? Thanks in Advance.
I found the answer. we can use CountdownTimer to find the remaining time.
Here is the code:
long total = calendar.getTimeInMillis();
diff = total-System.currentTimeMillis();
countDownTimer = new CountDownTimer(diff, 1000) {
#Override
public void onTick(long millisUntilFinished) {
diff = millisUntilFinished;
int minutes = (int) (diff/1000) / 60;
int seconds = (int) (diff/1000) %60;
textView.setText("TIme Remain:" + minutes + ":" + seconds);
}
#Override
public void onFinish() {
textView.setText("00:00");
}
}.start();

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.

Dismiss alarm in android

The first time I worked on broadcast part and run this app, it worked (the alarm went off).
But second time I added cancelAlarm() part and ran it again. It didn't even go off. So I was guessing the previous alarm I had set wasn't removed so the app cant get new input(Alarm) by user.
However I'm not sure. I will really appreciate your feedback. Here's what I have right now.
public class MainActivity extends AppCompatActivity {
Calendar calendar = Calendar.getInstance();
TextView dp0;
AlarmManager alarmManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dp0 = (TextView) findViewById(R.id.tv);
Button sButton = (Button)findViewById(R.id.btn);
sButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new TimePickerDialog(MainActivity.this,android.R.style.Theme_Holo_Light_Dialog,onTimeSetListener,
calendar.get(Calendar.HOUR_OF_DAY),calendar.get(Calendar.MINUTE),true).show();
}
});
}
TimePickerDialog.OnTimeSetListener onTimeSetListener = new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Toast.makeText(getApplicationContext(), "Set", Toast.LENGTH_SHORT).show();
setAlarm(calendar.getTimeInMillis());
dp0.setText(hourOfDay + ":" + minute);
final Button sButton1 = (Button) findViewById(R.id.cancelbtn);
sButton1.setVisibility(View.VISIBLE);
sButton1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dp0.setText("");
sButton1.setVisibility(View.INVISIBLE);
cancelAlarm();
}
});
}
};
public void setAlarm(long timeInMillis) {
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this,MyAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,0,intent,0);
alarmManager.set(AlarmManager.RTC_WAKEUP,timeInMillis,pendingIntent);
}
public void cancelAlarm() {
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent("Myalarm");
PendingIntent sender = PendingIntent.getBroadcast(this,0,intent,0);
alarmManager.cancel(sender);
sender.cancel();
Toast.makeText(getApplicationContext(),"Canceled",Toast.LENGTH_SHORT).show();
}
}
And the BroadcastReceiver:
public class MyAlarm extends BroadcastReceiver {
MediaPlayer mediaPlayer;
#Override
public void onReceive(Context context, Intent intent) {
mediaPlayer = MediaPlayer.create(context, Settings.System.DEFAULT_RINGTONE_URI);
mediaPlayer.start();
}
}
I think you need to use PendingIntent.FLAG_UPDATE_CURRENT. Moreover, I would like to recommend some changes in your code.
For setting the alarm change your function setAlarm() like this.
public void setAlarm(long timeInMillis) {
Intent myIntent = new Intent(getApplicationContext(), MyAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), 1, myIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, timeInMillis, pendingIntent);
}
And for cancelling, the cancelAlarm() should look like.
public void cancelAlarm() {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent myIntent = new Intent(getApplicationContext(), MyAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), 1, myIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(pendingIntent);
}
You might consider taking the onClickListener of sButton1 out of the function onTimeSet. Move the click listener to onCreate function.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dp0 = (TextView) findViewById(R.id.tv);
Button sButton = (Button)findViewById(R.id.btn);
Button sButton1 = (Button)findViewById(R.id.cancelbtn);
sButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new TimePickerDialog(MainActivity.this,android.R.style.Theme_Holo_Light_Dialog,onTimeSetListener,
calendar.get(Calendar.HOUR_OF_DAY),calendar.get(Calendar.MINUTE),true).show();
}
});
sButton1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dp0.setText("");
sButton1.setVisibility(View.INVISIBLE);
cancelAlarm();
}
});
}
TimePickerDialog.OnTimeSetListener onTimeSetListener = new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Toast.makeText(getApplicationContext(), "Set", Toast.LENGTH_SHORT).show();
setAlarm(calendar.getTimeInMillis());
dp0.setText(hourOfDay + ":" + minute);
sButton1.setVisibility(View.VISIBLE);
}
};

How to keep my alarm to be ringing for 1 minute in android?

I need to ring my alarm for 1 minute on my application.But it just ringing only for a single second.
Suggestions plz..
Thanks for your precious time!..
Please find my sources for reference
AndroidAlarmService.java
public class AndroidAlarmService extends Activity {
private PendingIntent pendingIntent;
private static final int PERIOD=60000; // 1 minute
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent myIntent = new Intent(AndroidAlarmService.this, RepeatingAlarm.class);
pendingIntent = PendingIntent.getBroadcast(AndroidAlarmService.this, 0, myIntent, 0);
AlarmManager aM = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar c=Calendar.getInstance();
c.set(Calendar.HOUR, 6);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(getApplicationContext(),AndroidAlarmService.class),PendingIntent.FLAG_UPDATE_CURRENT);
aM.setRepeating(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(),PERIOD,pendingIntent);
}
}
RepeatingAlarm.java
public class RepeatingAlarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Toast.makeText(context,"Alarm Started.....", Toast.LENGTH_LONG).show();
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(context, notification);
r.play();
// Vibrate the mobile phone
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(500);
}
}
I think with Ringtone You will have no success. There is a little post on looping ringtones here:
http://xanderx.com/2010/08/25/making-ringtones-loop-on-android/
but I have not tested it. Instead, You can use MediaPlayer for looping and create a custom countdown timer that stops the mediaPlayer onFinished(). But this is only one possible solution....
try {
Uri ringtoneAlert = RingtoneManager.
getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
mRingtoneLooper = new MediaPlayer();
mRingtoneLooper.setDataSource(this, ringtoneAlert);
final AudioManager audioRingtoneManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
if (audioRingtoneManager.getStreamVolume(AudioManager.STREAM_RING) != 0) {
mRingtoneLooper.setAudioStreamType(AudioManager.STREAM_RING);
mRingtoneLooper.setLooping(true);
mRingtoneLooper.prepare();
mRingtoneLooper.start();
//start custom countdown timer for 60 seconds, counts every second down
//counting every second down is not necessary, You could even set every 5 seconds or whatever You want
RingtoneStopper stopper = new RingToneStopper(60000,1000);
stopper.start();
}
} catch(Exception e) {
//do some message to user if some error occurs
}
//define a countdown timer for 60 seconds that stops the MediaPlayer
public class RingtoneStopper extends CountDownTimer{
public RingtoneStopper(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
mRingtoneLooper.stop();
}
#Override
public void onTick(long millisUntilFinished) {
//need nothing to do on tick events
}
}
Please check this code i think this will helps you.
Ringtone _ringtone = RingtoneManager.getRingtone(context, notification);
Timer _start_ringtone = new Timer();
while (_ringtone!=null) {
if(!_ringtone.isPlaying()){
_ringtone.play();
}
}
_start_ringtone.schedule(new TimerTask() {
#Override
public void run() {
_ringtone.stop();
_ringtone=null;
}
}, 60000);

Categories

Resources