I'm making an alarm app that goes off at exact given time by user.
Since Doze mode has come out, I heard I need to use setExactAndAllowWhileIdle() on
API 23 or higher.(I'm targeting on API 26).
But the problem is Whenever I set the alarm, it goes off(only toast message at this moment) 3 seconds later no matter what. I have no idea why.
Any type of feedback will be greatly appreciated.
Note: I already registered BroadcastReceiver on Manifest.xml
public class MainActivity extends AppCompatActivity {
static final String CP ="checkpi";
MediaPlayer mp;
Calendar c= Calendar.getInstance();
TimePickerDialog.OnTimeSetListener otsl;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textView = (TextView)findViewById(R.id.tv);
Button testbtn = (Button)findViewById(R.id.test);
testbtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
new TimePickerDialog(MainActivity.this,android.R.style.Theme_Holo_Light_Dialog,otsl,
c.get(Calendar.HOUR_OF_DAY),c.get(Calendar.MINUTE),true).show();
}
});
otsl = new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
textView.setText(hourOfDay+":"+minute);
//c.set(Calendar.HOUR_OF_DAY,hourOfDay);
//c.set(Calendar.MINUTE,minute);
setAlarm(c.getTimeInMillis());
}
};
Button canceltestbtn = (Button)findViewById(R.id.canceltest);
canceltestbtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(!textView.equals("")){
textView.setText("");
}
cancelAlarm();
}
});
}
public void setAlarm(long timeinmils) {
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent i = new Intent(MainActivity.this,Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(this,0,i,PendingIntent.FLAG_UPDATE_CURRENT);
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,timeinmils,pi);
}
public void cancelAlarm() {
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent i = new Intent(MainActivity.this,Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(this,0,i,PendingIntent.FLAG_UPDATE_CURRENT);
am.cancel(pi);
pi.cancel();
if(pi==null){
Log.v(CP,"Pendingintent==null");
}
else{
Log.v(CP,"Pendingintent!=null");
}
}
}
// ---------------------------------------------
public class Alarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Wake up!!",Toast.LENGTH_SHORT).show();
}
}
Related
I have written some related code for AlarmManager App.
I want to do something like writting a Toast massage in the activity, for sure i can not do that in onReceive() method the question is that how can i do it in the activity?
public class MainActivity extends AppCompatActivity implements View.OnClickListener,BroadConnect.IsConnect {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vv();
setRecurringAlarm(MainActivity.this);
}
private void setRecurringAlarm(Context context) {
Calendar updateTime = Calendar.getInstance();
//updateTime.setTimeZone(TimeZone.getTimeZone("GMT+5:00"));
updateTime.setTimeZone(java.util.TimeZone.getTimeZone("GMT+5:00"));
updateTime.set(Calendar.HOUR_OF_DAY,10);
//updateTime.set(Calendar.MINUTE,31);
updateTime.set(Calendar.MINUTE,1);
updateTime.set(Calendar.SECOND,20);
Intent intent = new Intent(context, BroadConnect.class);
PendingIntent recurringDownload = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, recurringDownload);
}
#Override
public void onReceiveTimer() {
Toast.makeText(MainActivity.this,"OK",Toast.LENGTH_LONG).show(); //This will not be displayed
}
}
public class BroadConnect extends BroadcastReceiver {
private IsConnect isConnect;
public interface IsConnect{
void onReceiveTimer();
}
public void setIsConnect(IsConnect isConnect) {
this.isConnect = isConnect;
}
#Override
public void onReceive(Context context, Intent intent) {
isConnect.onReceiveTimer(); //It runs this and makes a ERRORE
}
}
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);
}
};
I'm trying to make something where a set number will decrease everyday, even if the app is closed, and not active. For instance, if you don't open the app for 5 days, when you do open it, the number will be 5 numbers lower. I've been trying to use AlarmManager, but I can only get it to make a Toast and not run a function in the main activity. Here is my code...
Main Activity
private TextView mTest;
private Button mButton;
private int number = 100;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.button);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
scheduleAlarm();
}
});
}
public void scheduleAlarm(){
Intent intentAlarm = new Intent(this, AlarmReceiver.class);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 100000, 100000, PendingIntent.getBroadcast(this, 1, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT ));
Toast.makeText(MainActivity.this, "This is starting!", Toast.LENGTH_SHORT).show();
}
public void subtract(){
mTest = (TextView) findViewById(R.id.textView);
number -= 1;
String numberString = Integer.toString(number);
mTest.setText(numberString);
}
and Here is the broadcast
private MainActivity mMainActivity = new MainActivity();
#Override
public void onReceive(Context context, Intent intent) {
mMainActivity.subtract();
Toast.makeText(context, "This is bogus", Toast.LENGTH_LONG).show();
}
You can easily accomplish this using a Timer (https://developer.android.com/reference/java/util/Timer.html)
Follow this example:
long MINUTE_TO_MSEC = 60000;
long DAY_TO_MSEC = MINUTE_TO_MSEC * 60 * 24;
Timer timer = new Timer();
TimerTask countdownTask = new TimerTask() {
public void run() {
/* your function goes here */
}
}
timer.scheduleAtFixedRate(task,0,DAY_TO_MSEC);
This will run your code every 24 hours.
I am trying to make a simple android alarm app that basically take the time from the user and set an alarm every day in that time
i am using alarmmanger , the app runs fine with no errors but the alarm doesn't work !!
here is the where the user set the time
buttonSet.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.i("syso","1");
String sTime = eReminderTimeAM.getText().toString();
String aTime[] = sTime.split(":");
Log.i("syso","2");
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(aTime[0]));
calendar.set(Calendar.MINUTE, Integer.parseInt(aTime[1]));
Log.i("syso",aTime[1]);
alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent( getBaseContext(), Alarm.class);
alarmIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0);
Log.i("syso","3");
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
}
});
and here is the other activity that should run
MediaPlayer mp=null ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_alarm);
Button stopAlarm = (Button) findViewById(R.id.stopAlarm);
mp = MediaPlayer.create(getBaseContext(),R.raw.toha);
stopAlarm.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
mp.stop();
finish();
return false;
}
});
playSound(this, getAlarmUri());
}
private void playSound(final Context context, Uri alert) {
Thread background = new Thread(new Runnable() {
public void run() {
try {
mp.start();
} catch (Throwable t) {
Log.i("Animation", "Thread exception "+t);
}
}
});
background.start();
}
#Override
protected void onDestroy() {
super.onDestroy();
mp.stop();
}
Is "Alarm.class" a "BroadcastReceiver"? else please create a "BroadcastReceiver" and onReceive method of "BroadcastReceiver" call activity
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
}
}
Don't forget to add receiver to your Manifest
You have to add the receive class
public class Alarm extends BroadcastReceiver {
private Context context;
#Override
public void onReceive(Context context1, Intent intent) {
context = context1;
}
}
in android manifest also declare the receiver
<receiver android:name="Alarm" >
it was a silly mistake at the end ..
just had to replace PendingIntent.getBroadcast to PendingIntent.getActivity and it worked fine
Ok, I've tried two examples of AlarmManager- one from the commonsware website, and one from the manning website.
The code I am currently working with is from the manning website : [http://unlocking-android.googlecode.com/svn/chapter8/trunk/SimpleAlarm/][1]
There are two classes, AlarmReceiver and GenerateAlarm. Anyone have any idea why the toast will not display in the emulator? I was thinking that it was because I am located in the Eastern Time Zone and it uses UTC, but I have fiddled with different things and none of them seem to work.
public class GenerateAlarm extends Activity {
Toast mToast;
#Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
Button button = (Button) findViewById(R.id.set_alarm_button);
button.setOnClickListener(this.mOneShotListener);
}
private OnClickListener mOneShotListener = new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(GenerateAlarm.this, AlarmReceiver.class);
PendingIntent appIntent = PendingIntent.getBroadcast(GenerateAlarm.this, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
// calendar.add(Calendar.MINUTE, 1);
calendar.add(Calendar.SECOND, 10);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), appIntent);
if (GenerateAlarm.this.mToast != null) {
GenerateAlarm.this.mToast.cancel();
}
GenerateAlarm.this.mToast = Toast.makeText(GenerateAlarm.this, R.string.alarm_message, Toast.LENGTH_LONG);
//GenerateAlarm.this.mToast.show();
}
};
}
public class AlarmReceiver extends BroadcastReceiver {
public void onReceiveIntent(Context context, Intent intent) {
Toast.makeText(context, R.string.app_name, Toast.LENGTH_SHORT).show();
}
#Override
public void onReceive(Context context, Intent intent) {
}
}
You have to add your toast in the onReceived method where you should add the handling of the intent received.
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, R.string.app_name, Toast.LENGTH_SHORT).show();
}
onReceiveIntent is not a method of broadcastreceiver
public abstract void onReceive
(Context context, Intent intent)
Since: API Level 1 This method is
called when the BroadcastReceiver is
receiving an Intent broadcast.