My app doesn't respond to change in preferences - android

i'm trying to make the user choose the time of alarm but the alarm keeps triggering every 15 minutes "which is default" even if i choose another preference
this is the code related to the problem in my MainActivity
public class MainActivity extends AppCompatActivity {
private SharedPreferences sharedPreferences;
private static String reminder;
private static AlarmManager am;
private ImageButton btn;
private ImageButton cancel;
private EditText et;
private Intent intent;
private PendingIntent pend;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initialize variables
btn = (ImageButton) findViewById(R.id.imageButton2);
cancel = (ImageButton) findViewById(R.id.imageButton);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
// create intents
intent = new Intent(getApplicationContext(), Notifications.class);
pend = getBroadcast(getApplicationContext(), 100, intent, PendingIntent.FLAG_UPDATE_CURRENT);
am = (AlarmManager) getSystemService(ALARM_SERVICE);
// get the user preference
String sel = sp.getString("repeatPref", "1");
final String repeat[] = getResources().getStringArray(R.array.settings_repeat_by_labels);
final int ss = Integer.parseInt(sel);
// action when user presses the "Tweak" button
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pend.cancel();
am.cancel(pend);
// initialize pend and AlarmManager
pend = getBroadcast(getApplicationContext(), 100, intent, PendingIntent.FLAG_UPDATE_CURRENT);
am = (AlarmManager) getSystemService(ALARM_SERVICE);
// if the user didn't type anything
Calendar calendar = Calendar.getInstance();
// notify at different times
if (repeat[ss - 1].equals("15 MINUTES")) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis() + 60*1000 ,60*1000, pend);
}
} else if (repeat[ss - 1].equals("1 HOUR")) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis() + 120 * 1000, 120 * 1000, pend);
}
} else if (repeat[ss - 1].equals("2 HOURS")) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis() + AlarmManager.INTERVAL_HOUR * 2, AlarmManager.INTERVAL_HOUR * 2, pend);
}
});
another button to cancel the alarm
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
am.cancel(pend);
pend.cancel();
Toast.makeText(MainActivity.this,"All cleared", Toast.LENGTH_LONG).show();
}
});
i'm creating the pend and Alarm In the onCreate method and second time when the "btn" is pressed because i'm creating another button to cancel it and i tried "for long time" to check if the PendingIntent "pend" and AlarmManager "am" already exist or no and then depending on the result canceling it but i failed so i thought this approach might work
Now everytime the user wants to cancel alarm and open the app it will create new pending intent and Alarm manager so if the user presses the cancel button without pressing "btn" first The app don't crash and the alarm which was already working gets canceled..i suspect this is part of the problem i'm having now
i know it's alot of stuff but i tried explaining as simple as possible..thanks for taking time to read all of that!

My app wasn't responding to my changes because I was retrieving the shared preferences before I click "btn". It got fixed after I moved the shared preference part to the onClick method.

Related

Listen chrome custom tab progress event

I have an application using Chrome custom tabs to open some links, I need to have event each second during all the time the user stay on Chrome, or know how many time he stay on Chrome. For me the only way to do it is to use a Service. Is it possible to do it differently?
Create your YourBroadCastReceiver class as follows
public class YourBroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Called every 60 seconds","called");
}
}
After starting your custom tab successfully create Alarm PendingIntent that will trigger YourBroadCastReceiver once every 60 sec.
// Retrieve a PendingIntent that will perform a broadcast
Intent repeatingIntent = new Intent(context,
YourBroadCastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, _pendingIntentId, alarmIntent, 0);
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// Set the alarm to start at 10:00 AM
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
manager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 60 * 1000, // repeat for every 60 seconds
pendingIntent);
after closing your custom tab never forget to cancel your PendingIntent
PendingIntent.getBroadcast(
context, _pendingIntentId, alarmIntent, 0).cancel();
For implementation of chrome custom tabs I've followed this tutorial, github link.
My solution basically rely on boolean and System.currentTimeMillis().
Step - 1 : Declare two class global variables,
private boolean isCustomTabsLaunched = false;
private long customTabsEnterTime;
Step - 2 : Set values for above to variables when launchUrl.
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d(TAG, "FloatingActionButton");
// Launch Chrome Custom Tabs on click
customTabsIntent.launchUrl(CustomTabsActivity.this, Uri.parse(URL));
isCustomTabsLaunched = true;
customTabsEnterTime = System.currentTimeMillis();
Log.d(TAG, "customTabsEnterTime = " + customTabsEnterTime);
}
});
Step - 3 : Calculate stay time in onResume method.
#Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
if (isCustomTabsLaunched) {
isCustomTabsLaunched = false;
calculateStayTime();
}
}
private void calculateStayTime() {
long customTabsExitTime = System.currentTimeMillis();
Log.d(TAG, "customTabsExitTime = " + customTabsExitTime);
long stayTime = (customTabsExitTime - customTabsEnterTime) / 1000; //convert in seconds
Log.d(TAG, "stayTime = " + stayTime);
}
In order to make code more robust you may like to store boolean isCustomTabsLaunched and long customTabsEnterTime in preferences or database so in any case these two params get destroyed as your activity may get destroy in background if user stay for long time in chrome custom tab.

Unable to cancel repeating alarm Android

I have read every question there is about Android, AlarmManager and cancelling.
I currently use an Activity starting a receiver through:
long msInterval = 1;
Intent intent = new Intent(this, Updater.class);
intent.setAction("theAction");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 12, intent, 0);
Updater.origin = pendingIntent;
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (msInterval), msInterval, pendingIntent);
This starts the receiver Updater one millisecond after this code was called, with request code 12 (chosen arbitrarily, using 0 produces the same incorrect behaviour). It also sets the origin of Updater to the currently scheduled PendingIntent, which is later used to cancel the alarm.
Updater looks like this:
public class Updater extends BroadcastReceiver {
public static int flaggedClose = 0;
public static PendingIntent origin;
#Override
public void onReceive(Context context, Intent intent) {
// Do some work
Log.w("running", "run");
if (Updater.flaggedClose != 0) {
if(flaggedClose == 1) {
Toast.makeText(context, "Finished!", Toast.LENGTH_SHORT).show();
}
flaggedClose++; // Only show Toast once
Log.w("running", "close");
origin.cancel();
AlarmManager alarms = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarms.cancel(origin);
}
}
}
What it does at the moment is just to log the message "run", which is done ~1000 times/s. When the Activity's onStop() is called, Updater.flaggedClose is set to 1. I can be see this in Logcat since it starts printing the log warning "close". However, the alarm is still on, so every other logged message is "run" and every other is "close". In best case, the alarm is closed after a few seconds. Worst case I need to restart the phone. In the description of AlarmManager, it specifically states that close closes "Any alarm, of any type, whose Intent matches this one (as defined by filterEquals(Intent)), will be canceled". Why are there still alarms being triggered?
As ci_ mentioned in the comments, it is possible that "those 100 "extra" alarms already triggered before the cancel happens". For anyone else who has the same problem, here is a solution. I tested the AlarmManager and it seems to work best if you have a delay of at least 200 ms. for a lower delay use a Handler. Example from the question using Handler:
public class MainActivity extends Activity {
private boolean pressed = false;
private boolean done = false;
private Handler worker;
private Runnable method;
long msInterval = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
worker = new Handler();
method = getMethod();
Button toggle = (Button)(findViewById(R.id.toggle));
toggle.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(!pressed) {
worker.post(method);
pressed = true;
} else {
done = true;
}
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
done = true;
}
private Runnable getMethod() {
return new Runnable() {
public void run() {
Log.w("running", "run");
if (done) {
Toast.makeText(getApplicationContext(), "Finished!", Toast.LENGTH_SHORT).show();
Log.w("running", "close");
} else {
worker.postDelayed(method, msInterval);
}
}
};
}
}
On first button press the handler starts the runnable, and on each call the runnable calls itself. On second button press condition done is set to true, thus the runnable finishes after one (cleanup) round.

Find if alarm is already set? If possible find time left before the next alarm trigger

I have set an alarm using AlarmManager and PendingIntent. The app has text counter which is a typical timer clock that counts backwards until it reaches 0. I would like to know whether a alarm is already set so that I can update my text counter and start/stop button states accordingly if my activity is killed and restored.
Question/Problem:
isAlarmActive flag value is always TRUE.
Returns true even if app is uninstalled and re-installed.
Used solution from the previous question but doesnt seem to work. Any help will be great.
protected void onCreate(Bundle savedInstanceState) {
....
boolean isAlarmActive = (PendingIntent.getBroadcast(MainActivity.this, 0,
new Intent(INTENT_ALARM_ACTION),
PendingIntent.FLAG_NO_CREATE) != null);
if(isAlarmActive)
changeButtonStatus(ButtonStatus.STOP);
else
changeButtonStatus(ButtonStatus.STARt);
}
private OnClickListener mBtnListener = new OnClickListener()
{
#Override
public void onClick(View v) {
if(mButtonStatus == ButtonStatus.START){
setAlarmOnAlarmManager();
changeButtonStatus(ButtonStatus.STOP);
}else{
cancelAlarmOnAlarmManager();
changeButtonStatus(ButtonStatus.START);
}
}
public void setAlarmOnAlarmManager()
{
Calendar cal = Calendar.getInstance();
long triggerTime = cal.getTimeInMillis() + mAlarmInterval;
mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mPendingIntent);
}
public void cancelAlarmOnAlarmManager()
{
MainActivity.this.getSystemService(Context.ALARM_SERVICE);
mAlarmManager.cancel(mPendingIntent);
unregisterReceiver(mAlarmReceiver);
}

How to use a timer?

I want to change the background, but I want to change it using a timer. for example in the morning I have a background and evening I have another background. But I don't know what to use in Android. and if you have an example to follow. any idea?
Just to make sure I understand what you mean, do you want to:
-Change the background after a time or
-change the background at different daytimes?
To accomplish the second one, I would set a switch into your OnCreate() method (or any other place e.g. OnResume(), a button click) that looks for the Time with
Time t = new Time();
t.setToNow();
and then decides what Image to use
Here is the code which repeat the alarm every day. You will have to take out your needed code from this activity(sorry for that). You can use this code to set alarm which will repeat every day at 9am. You can add same for evening at your expected time.
public class AndroidScheduledActivity extends Activity {
/** Called when the activity is first created. */
int id = 115;
Intent myIntent;
PendingIntent pendingIntent;
AlarmManager alarmManager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonStart = (Button)findViewById(R.id.start);
myIntent = new Intent(getBaseContext(), MyScheduledReceiver.class);
myIntent.putExtra("id", id);
pendingIntent = PendingIntent.getBroadcast(getBaseContext(), id, myIntent, 0);
alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
buttonStart.setOnClickListener(new Button.OnClickListener(){
public void onClick(View arg0) {
// TODO Auto-generated method stub
setForMonday();
finish();
}});
}
public void setForMonday() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK,2);
calendar.set(Calendar.HOUR,09);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
System.out.println("Old is set# :== " + calendar.getTime());
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
Here is the alarm receiver
public class MyScheduledReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// here you can add the code to change the background
System.out.println("Receiver");
}
}
Also you will have to add receiver in the manifest file.

Help required in Alarm Application

I am new to Android. I am trying to develop an Alarm Application, which is actually a speaking clock. I just want the clock to use TextToSpeech API and speak out the greeting stuff and the current time as soon as the alarm time is ticked. The speech part is done. And now I want to implement the Alarm functionality. But Initially I am just trying to display a toast after 10 secs in order to check whether my classes are working properly. And I am not getting the desired response and I don't know why ? Following are the classes
Main Class aClockActivity
public class aClockActivity extends Activity {
/** Called when the activity is first created. */
private PendingIntent mAlarmSender;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button1 = (Button)findViewById(R.id.buttonOn);
button1.setOnClickListener(mStartAlarmListener);
Button button2 = (Button)findViewById(R.id.buttonOff);
button2.setOnClickListener(mStopAlarmListener);
}
private OnClickListener mStartAlarmListener = new OnClickListener() {
public void onClick(View v) {
// We want the alarm to go off 30 seconds from now.
//long firstTime = SystemClock.elapsedRealtime();
EditText Ehour = (EditText) findViewById(R.id.hour);
EditText Eminute = (EditText) findViewById(R.id.minute);
CharSequence CharHour = Ehour.getText();
CharSequence CharMinute = Eminute.getText();
int hour = Integer.parseInt(CharHour.toString());
int minute = Integer.parseInt(CharMinute.toString());
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
// calendar.add(Calendar.MINUTE, 1);
cal.add(Calendar.SECOND, 10);
mAlarmSender = PendingIntent.getBroadcast(aClockActivity.this,
0, new Intent(aClockActivity.this, Alarm_Broadcast.class), 0);
// Schedule the alarm!
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP,
cal.getTimeInMillis(), mAlarmSender);
// Tell the user about what we did.
Toast.makeText(aClockActivity.this, "The Alarm is Set",
Toast.LENGTH_LONG).show();
}
};
private OnClickListener mStopAlarmListener = new OnClickListener() {
public void onClick(View v) {
// And cancel the alarm.
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.cancel(mAlarmSender);
// Tell the user about what we did.
Toast.makeText(aClockActivity.this, "Setting off the alarm",
Toast.LENGTH_LONG).show();
}
};
Second Class Alarm_Broadcast
public class Alarm_Broadcast extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm worked", Toast.LENGTH_LONG).show();
}
}
Note: Just ignore the Edittext part in the OnClick() method, I'd use it later on.
Apart from the above problem there are few questions that I would like to ask.
1) How can I implement this app so that when the alarm is set, it can actually run as a service in the notification bar where the original AlarmClock runs. So that even if the app is closed its still running to invoke the alarm message at the right time.
2) I cannot show any Dialog box or can use TTS if the AlarmManager invokes a Class that extends either Service or BroadcastReciever.
3) I would appreciate if some one give me the idea to implement this app, I am sure there are many experts who would have gone through the same application.
Regards
Omayr
Here is some sample code i used in an alarm clock app hope it helps.
To set the alarm:
private void setAlarm(){
Context context = getApplicationContext();
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, OnAlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
myCal = Calendar.getInstance();
myCal.setTimeInMillis(TIME_THE_ALARM_SHOULD_GO_OFF_AS_A_LONG);
mgr.set(AlarmManager.RTC_WAKEUP, myCal.getTimeInMillis(), pi);
Log.i(myTag, "alarm set for " + myCal.getTime().toLocaleString());
Toast.makeText(getApplicationContext(),"Alarm set for " + myCal.getTime().toLocaleString(), Toast.LENGTH_LONG).show();
}
This goes in the onAlarmReceiver class:
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, AlarmActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
this will start AlarmActivity whenever it needs to go off. In your case you'd put the toast and speech into the AlarmActivity.
How can I implement this app so that when the alarm is set, it can actually run as a service in the notification bar where the original AlarmClock runs. So that even if the app is closed its still running to invoke the alarm message at the right time.
Do not do this. Having a service stick around in memory 24x7 to watch a clock is a waste of RAM and will get you attacked by task killers, reducing your app's effectiveness. Please stick with AlarmManager.
I cannot show any Dialog box or can use TTS if the AlarmManager invokes a Class that extends either Service or BroadcastReciever.
Start an activity, perhaps a dialog-themed activity.
Just got the answer, whatever service, receiver, activity and etc you are using, you need to register it in your AndroidManifest.xml. Or else it wont work

Categories

Resources