I want to write an app that increase an int number every fifteen minute using alarm manager and saves new value in shared preferences and then showing value in text view. I am totally new and tried many things but in vain.please be kind if you find some thing that is not well and explain me. thank you.
here is code.
public class MainActivity extends AppCompatActivity {
AlarmManager am;
int d=3;
TextView tv;
SharedPreferences sp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.ed);
}
public void time(Context context,Intent intent){
am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent alarmIntent;
Intent intnt = new Intent(context, MyAlarm.class);
// Set the alarm to start at approximately 2:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
d++;
// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_FIFTEEN_MINUTES, alarmIntent);
}
public void shared(){
sp = (SharedPreferences) getSharedPreferences("sha", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putInt("as", d);
editor.commit();
}
public void show(int i){
tv=(TextView)findViewById(R.id.ed);
int q=sp.getInt("as",d);
tv.setText(q);
}
}
and service is;
public class MyAlarm extends BroadcastReceiver {
//the method will be fired when the alarm is triggerred
#Override
public void onReceive(Context context, Intent intent) {
}
}
Your implementation of the increment could be done in the MyAlarm class, in the onReceive method, when you receive the alarm, this is the place you should be responding to.
public class MyAlarm extends BroadcastReceiver {
//the method will be fired when the alarm is triggerred
#Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sp = (SharedPreferences) getSharedPreferences("sha", Context.MODE_PRIVATE);
int d = sp.getInt("as", 0);// get the previous value
d = d + 1;
SharedPreferences.Editor editor = sp.edit();
editor.putInt("as", d);
editor.commit();// finally, save it
}
}
Your activity can then be cleaned up to look something similar to this:
public class MainActivity extends AppCompatActivity {
AlarmManager am;
int d=3;// do you really need this?
TextView tv;
SharedPreferences sp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.ed);
int q=sp.getInt("as",0);// this should return an integer if available, otherwise 0
tv.setText(String.format("%d", q));// format the integer as a String
am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent alarmIntent;
Intent intnt = new Intent(this, MyAlarm.class);// I replaced context with `this` because AppCompatActivity and any Activity is a Context in Android applications
// Set the alarm to start at approximately 2:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);
alarmIntent = PendingIntent.getBroadcast(this, 0, intnt, 0);
d++;// you never used this value here, is it really needed?
// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_FIFTEEN_MINUTES, alarmIntent);
}
/* Function is not used in the flow
public void shared(){
sp = (SharedPreferences) getSharedPreferences("sha", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putInt("as", d);
editor.commit();
}*/
/* Function could be inlined in the onCreate method
public void show(int i){
tv=(TextView)findViewById(R.id.ed);
int q=sp.getInt("as",d);
tv.setText(q);
}*/
}
If you are having problems with this, I think you should find the docs and read about Activity life cycles, AlarmManager and you can find some good books on Android development online. Video tutorials are also good for some people, but I suggest you read books and network with as many other developers as you meet. There's a future ahead!
Related
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 want to increase a number and show it in a TextView using AlarmManager at a specific time of day, but it is not working.
App is debugging and showing 0, but not increasing the int number.
Please help, here is the code.
public class MainActivity extends AppCompatActivity {
TextView tv;
int a = 3;
Calendar calendar = Calendar.getInstance();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
MyAlarm alarm = new MyAlarm();
setAlarm(calendar.getTimeInMillis());
int g = alarm.i;
tv.setText(String.format("%d", g));
}
private void setAlarm(long time) {
calendar.setTimeInMillis(System.currentTimeMillis());
//getting the alarm manager
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//creating a new intent specifying the broadcast receiver
Intent i = new Intent(this, MyAlarm.class);
//creating a pending intent using the intent
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
calendar.set(Calendar.HOUR_OF_DAY, 17);
calendar.set(Calendar.MINUTE, 55);
calendar.set(Calendar.SECOND, 0);
//setting the repeating alarm that will be fired every day
am.setRepeating(AlarmManager.RTC, time, AlarmManager.INTERVAL_FIFTEEN_MINUTES, pi);
Toast.makeText(this, "Alarm is set", Toast.LENGTH_SHORT).show();
}
}
broad cast is here,
public class MyAlarm extends BroadcastReceiver {
int i;
#Override
public void onReceive(Context context, Intent intent) {
i++;
}
}
To add a default constructor, try the following in your MyAlarm class:
MyAlarm(){
}
Also add this method:
public int setI(){
i = i+1;
return i;
}
This is what it should look like now:
public class MyAlarm extends BroadcastReceiver{
int i;
MyAlarm(){
i=0;
}
public int setI(){
i = i+1;
return i;
}
#Override
public void onReceive(Context context,Intent intent) {
i++;
}
}
Now, call this in onCreate() and it will increment i.
You can say
int g = myAlarm.setI();
in your setAlarm() function or wherever you want to increment it.
g will now be incremented. I hope this helps!
I want to trigger a one-time alarm with the following, which is basically a replicate from https://developer.android.com/training/scheduling/alarms.html (second ELAPSED_REALTIME_WAKEUP example).
This is inside public static class PlaceholderFragment extends Fragment implements View.OnClickListener:
#Override
public void onClick(View v) {
Intent intent;
intent = new Intent(this.getActivity(), MuteReceiver.class);
AlarmManager alm = (AlarmManager)(this.getActivity().getSystemService(Context.ALARM_SERVICE));
PendingIntent alarmIntent = PendingIntent.getBroadcast(getActivity(), 0, intent, 0);
alm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 60*1000,
alarmIntent);
Log.d("MainActivity", "alarm set");
}
public class MuteReceiver extends BroadcastReceiver is like this:
public MuteReceiver() {
Log.d("MuteReceiver", "constructed");
}
#Override
public void onReceive(Context context, Intent intent) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean started = prefs.getBoolean(MuteService.STARTED, false);
Log.d("MuteReceiver", "Started=" + started);
}
I pressed the button in the Fragment, saw the log message "alarm set", but after one minute (and much later), still no log about MuteReceiver being constructed or MuteReceiver started (in onReceive)
You have a guaranteed list file with a registered broadcast
PROBLEM
I want to know some concept to do like the topic said
what should be a requirement to do that
I think that PendingIntent and AlarmManager would be help to restart the service
at time x but I don't know that way to let it call function that I need
Please advice.
FOR EXAMPLE
I have 2 functions in my service class and I want to register it
to run one of these two (Depend on user propose) in the future at time x
SOME CODE THAT I WORK AROUND (EDIT)
public class MyActivity extends Activity implements View.OnClickListener {
private Button b1;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
b1 = (Button)findViewById(R.id.cmd1);
b1.setOnClickListener(this);
}
#Override
public void onClick(View view) {
startIntentAt(5,MyReceiver.class);
finish();
}
private void startIntentAt(int seconds, Class<?> c) {
Intent myIntent = new Intent(getBaseContext(), c);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(),0, myIntent, 0);
AlarmManager alarmManager= (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, seconds);
//long interval = 60 * 1000; //
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
public class MyReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Intent scheduledIntent = new Intent(context, TargetActivity.class);
scheduledIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(scheduledIntent);
}
}
}
When binding onClick in activity_main.xml to setAlarm to one button and unsetAlarm to another button in the same activity, the following code will not let you unset the alarm when clicking the button linked to the unsetAlarm method.
...package name and includes ommitted...
public class MainActivity extends Activity {
private AlarmManager alarmManager;
private PendingIntent notifyIntent;
private static final String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
}
public void setAlarm(View v) {
Intent myIntent = new Intent(MainActivity.this,
NotificationService.class);
notifyIntent = PendingIntent.getService(MainActivity.this, 0,
myIntent, 0);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, 1);
Log.v(TAG, "time for alarm trigger:" + calendar.getTime().toString());
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 1 * 60 * 1000, notifyIntent);
}
public void unsetAlarm(View v) {
alarmManager.cancel(notifyIntent);
Log.v(TAG, "cancelling notification");
}
}
The solution was to (as I was provided in Notifications and AlarmManager - cancelling the alarm I set) recreate the pendingIntent in the unsetAlarm method:
public void unsetAlarm(View v) {
Intent myIntent = new Intent(MainActivity.this,
NotificationService.class);
notifyIntent = PendingIntent.getService(MainActivity.this, 0,
myIntent, 0); // recreate it here before calling cancel
alarmManager.cancel(notifyIntent);
Log.v(TAG, "cancelling notification");
}
My question is: Why can I not reuse the PendingIntent, stored in the field "notifyIntent" in the first code snippet? Why do I have to recreate it to cancel it? I have set the of MainActivity to have the attribute android:launchMode="singleInstance" so I should believe it was using the same instance when I click the notification created in the NotificationService (I have ommitted it but it just shows a notification).