Time based actions or texts - android

I am trying to make an app for students, and in the home screen of the app I would like to display a message like "Hey! Good Morning" and it should change to "Hey!Good evening" when it is after 15:00hrs of a day and so on.
How can I achieve this ?

Please check this one.It may help you.
Calendar c = Calendar.getInstance();
int timeOfDay = c.get(Calendar.HOUR_OF_DAY);
if(timeOfDay >= 0 && timeOfDay < 12){
Toast.makeText(this, "Good Morning", Toast.LENGTH_SHORT).show();
}else if(timeOfDay >= 12 && timeOfDay < 16){
Toast.makeText(this, "Good Afternoon", Toast.LENGTH_SHORT).show();
}else if(timeOfDay >= 16 && timeOfDay < 21){
Toast.makeText(this, "Good Evening", Toast.LENGTH_SHORT).show();
}else if(timeOfDay >= 21 && timeOfDay < 24){
Toast.makeText(this, "Good Night", Toast.LENGTH_SHORT).show();
}

you can get the time or hour by
import java.util.Calendar
Calendar c = Calendar.getInstance();
int hours = c.get(Calendar.HOUR);
from this you can choose a String for your textview:
TextView mytextview=(TextView) findViewByID(...);
String message="";
if(hours<11){
message="good morning"
}else if(hours>=11 & hours<17){
message=...}
mytextview.setText(message);

You can place a check for time of day in your activity in onResume(). This will check whenever the screen which has to display the text comes to foreground. So, even when you return to it from a different screen, the check will be made. For realtime check you will need a mechanism for absolute callback of the event [of 1500 hrs].
This might be a bit cumbersome and we need more info to decide on a mechanism. You should also decide if this is exactly what you want to do or not.
Not showing checking code because of its trivial nature.

Related

Using UsageStatsManager to get the foreground app

I'm trying to use UsageStatsManager to get the foreground app on a Nexus 5 with Marshmallow. I remember it used to work, but for some reason I'm getting null strings for package/class names now.
Here's my implementation
public String[] getForegroundPackageNameClassNameByUsageStats() {
String packageNameByUsageStats = null;
String classByUsageStats = null;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager mUsageStatsManager = (UsageStatsManager)getSystemService("usagestats");
final long INTERVAL = 1000;
final long end = System.currentTimeMillis();
final long begin = end - INTERVAL;
final UsageEvents usageEvents = mUsageStatsManager.queryEvents(begin, end);
while (usageEvents.hasNextEvent()) {
UsageEvents.Event event = new UsageEvents.Event();
usageEvents.getNextEvent(event);
if (event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
packageNameByUsageStats = event.getPackageName();
classByUsageStats = event.getClassName();
Log.d(TAG, "packageNameByUsageStats is" + packageNameByUsageStats + ", classByUsageStats is " + classByUsageStats);
}
}
}
return new String[]{packageNameByUsageStats,classByUsageStats};
}
For some reason, it doesn't go into the while loop, i.e. usageEvents.hasNextEvent() is false. Because of this, it returns null package/class names.
Any idea what I'm doing wrong?
Thanks.
OK, so I found that once I set the interval to 10000 instead of 1000, it works. Apparently a 1s interval is too small.
I am using this myself. I think the usage stats will only be updated when an app comes to foreground. So if the foreground app got to the foreground (and stayed) before your 'begin' timestamp then you will not get it. :(
On the other hand when you use a long time ago you will get a giant list where you only need the highest time to determine the foreground app.
So what I do is I create 3 different times: 1min ago, 1 hour ago and 12 hours ago.
When I get an empty list on 1min I repeat request with 1h and so on. That way I get foreground most of the time. But I never get it to work ALL of the time.
I really miss the old way of just asking the package manager which app is foreground (prior to android 5), the new way is a bit messy.

Widgets, AlarmManager and KitKat API19

Since API19 (KitKat), AlarmManager broadcasts are not acted on immediately, but batched together. The documentation says that it should act immediately in KitKat if the app is targeted to API 18 or less, but this doesnt seem to work.
Example, my clock widget is targeted to API 18 but it doesnt update when required on KitKat emulator (i dont have a device to test on). I read online that many people report their old clock widgets no longer updating on their KitKat devices.
The AlarmManager doc suggests this is to avoid wakeups, but it affects my RTC alarm also.
The docs suggest setExact, but this is only for API19+. Is there a way to trigger updates that will be processed immediately on API8+ including API19? Or is it better to add a separate AlarmManager for API19+?What could be a good solution for getting widgets to update properly on API19+ and still work properly on older devices?
One strategy that has a single solution for both pre-API19 and API19+ that works for me: replace AlarmManager's setRepeating() broadcast with a new set()/setExact() created each time the widgets are updated.This strategy allows continued use of AlarmManager's RTC alarm type, which doesnt trigger while the phone is asleep. It causes the widget to update at the intended time on any API and keeps my widget as power efficient as it was using setRepeating().Instead of creating a setRepeating() alarm in the onEnabled method in the "widget manager" class... Create a set() for API18 or less, or setExact() for API19+ in the "Update Widget" class, after the widget update code is run. Everytime the widget is updated, a new alarm is set for whatever time is next required.Here is a section of code (incomplete) from within onStartCommand() in the "updateservice" class, that is called by both onEnabled() and the broadcast receiver class.
public int onStartCommand(Intent intent, int flags, int startId) {
Log.w(LOG, "UpdateService.onStartCommand activated");
// reset the time dependent millis addition
long alarmAddMillis = 0;
// get time instance and values
Calendar rightNow = Calendar.getInstance();
int thisMin = rightNow.get(Calendar.MINUTE);
int thisHour = rightNow.get(Calendar.HOUR);
// set correct hour values to update widget
nextHour = thisHour + 1;
if (thisHour == 0) {thisHour = 12;}
if (nextHour == 13) {nextHour = 1;}
// set text values based on minutes
// set the values for the next alarm time
if (thisMin >= 0 && thisMin <= 6) {
clockH = thisHour; nextAlarmMin = 8; alarmAddMillis = 0;}
if (thisMin >= 7 && thisMin <= 21) {
clockH = thisHour; nextAlarmMin = 22; alarmAddMillis = 0;}
if (thisMin >= 21 && thisMin <= 35) {
clockH = thisHour; nextAlarmMin = 37; alarmAddMillis = 0;}
if (thisMin >= 36 && thisMin <= 50) {
clockH = nextHour; nextAlarmMin = 52; alarmAddMillis = 0;}
if (thisMin >= 51 && thisMin <= 59) {
clockH = nextHour; nextAlarmMin = 8; alarmAddMillis = 3600000;}
----CODE FOR UPDATING THE WIDGETS GOES IN HERE----
// cancel any unsent alarm
if (alarmManager != null){
alarmManager.cancel(pendingIntent);
Log.w(LOG, "UpdateService.onStartCommand unsent alarm canceled");}
// SET UP THE NEXT ALARM
// set the time using values set above
Calendar nextAlarm = Calendar.getInstance();
// add one hour of millis if its for the next hour
nextAlarm.setTimeInMillis(System.currentTimeMillis() + alarmAddMillis);
// set the correct minute
nextAlarm.set(Calendar.MINUTE, nextAlarmMin);
nextAlarm.set(Calendar.SECOND, 0);
nextAlarm.set(Calendar.MILLISECOND, 0);
// request the alarm
alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent usIntent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, usIntent, 0);
// ACCOUNT FOR DIFFERENT APIs HERE...
// use onExact for API19+
int currentApiVersion = android.os.Build.VERSION.SDK_INT;
if (currentApiVersion <= 18) {
alarmManager.set(AlarmManager.RTC, nextAlarm.getTimeInMillis(), pendingIntent);
Log.w(LOG, "FuzzyTimeWidget.onEnabled pre-kitkat AlarmManager requested");
}else{
alarmManager.setExact(AlarmManager.RTC, nextAlarm.getTimeInMillis(), pendingIntent);
Log.w(LOG, "FuzzyTimeWidget.onEnabled API19+ AlarmManager requested");
}
The only code required to manage the different API's is at the point of setting the alarm. Just choosing set() or setExact(). All the other code is for any API. In my case, I use nextAlarmMin to set the exact time for the next Alarm, which goes off 4 times per hour at 8, 22, 37, 52.For widgets that update every minute, I'm not sure how this strategy would be for the battery life.

why my code is so slow?

i runing this code on android after load a cursor with the query i pass to the adapter, but my date is in long in milliseconds format so i need to format properly before load the adapter!
problem is this code is taking 14 seconds to pass a 50 items load, the problem get worst if i call it inside the adapter getView cause get slow when i scrool, if i take this function out the program runs smoothly
this is call inside my listfragment
private String dateFormatPatternEdited(long timeMS) {
android.text.format.DateFormat df = new android.text.format.DateFormat();
final Calendar eDate = Calendar.getInstance();
Calendar sDate = Calendar.getInstance();
sDate.setTimeInMillis(timeMS);
long daysBetween = 0;
while (sDate.before(eDate)) {
sDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}
String mDateFormatPattern = FuelTrackerApplication.dateFormat.format(timeMS);
if (daysBetween < 2){
mDateFormatPattern = FuelTrackerApplication.timeFormat.format(timeMS);
} else if(daysBetween < 365){
mDateFormatPattern = df.format(FuelTrackerApplication.dateFormatPattern,timeMS).toString();
}
return mDateFormatPattern;
}
and this is were i initialize the date formats i gonna use its called inside onCreate in FuelTrackerApplication i dont think theres nothing wrong with this
public void initializeDateFormat() {
android.text.format.DateFormat df = new android.text.format.DateFormat();
dateFormatPattern = "MMM dd";
if (android.os.Build.VERSION.SDK_INT >= 18){
dateFormatPattern = df.getBestDateTimePattern(Locale.getDefault(), dateFormatPattern);
}
dateFormat = df.getMediumDateFormat(getApplicationContext());
timeFormat = df.getTimeFormat(getApplicationContext());
dateFormat2 = df.getLongDateFormat(getApplicationContext());
}
Ok just a few things. Depending on how long ago your dates are going back. You are only interested if the days between go more then 365. So if your dates are going back for years, you're doing extra work.
while (sDate.before(eDate) && daysBetween <= 365) {
sDate.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}
Will let it break, it means if you have 20 entries going back 5 years, you don't do so much work.
It might be worth while to possibly just check the milliseconds difference. I'm not sure if this is precise enough, but it should work. It means you don't need to loop everything E.g
long millisecondsToday = getMilliseconds;
long timeMs = // you already have this
long millisecondsDifference = millisecondsToday - timeMs;
if (millisecondsDifference < MILLISECONDS_TWO_DAYS) // set a final variable out of this method
// etc
If might also be worth while initialising some of your variables once outside of the method. Like your df, that is being created 50 times, and then just having something set on it. Same with your eDate.
i got this incredible faster and practicaly remove the hole function
instead goes like this
lDateBetween = NOW - timeMS;
if (lDateBetween < DAY)
return FuelTrackerApplication.timeFormat.format(timeMS);
else if (lDateBetween < YEAR)
return df.format(FuelTrackerApplication.dateFormatPattern,timeMS).toString();
else return FuelTrackerApplication.dateFormat.format(timeMS);
all calculation is made using milliseconds i also put 2 final NOW and YEAR, also df and lDateBetween
i think is the fastest i can get!

Convert to time to millisecond

I want to checked if set time is less than calender(mobile device)time. It shows alarms set and if set time is not more that 1.5 hr it shows "ruko ruko" message. If both conditions are false then it will go to else condition. It does not gave me expected results. Here is my code:
GregorianCalendar mcalender=new GregorianCalendar();
mcalender.set(2013, 7, 17, 13, 0);
if(mcalender.getTimeInMillis()<=cal.getTimeInMillis()){
Toast.makeText(getBaseContext(), "sets ", Toast.LENGTH_SHORT).show();
}
else if(mcalender.getTimeInMillis()+5400000<=cal.getTimeInMillis()){
Toast.makeText(mContext, "ruko ruko", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getBaseContext(), "Time not gone ", Toast.LENGTH_SHORT).show();
}
The problem is that mcalender.getTimeInMillis() is checked first. For example, when you alarm is set for 5:30, at 4:30 the first part will be true already, so the else if section is entirely skipped. Just got to reverse the order and that will do :)
if(mcalender.getTimeInMillis()+5400000<=cal.getTimeInMillis()){
//If still have more than 1.5 hours to go (i.e. 2 hours left etc)
Toast.makeText(mContext, "ruko ruko", Toast.LENGTH_SHORT).show();
}
else if(mcalender.getTimeInMillis()<=cal.getTimeInMillis()){
//Not more than 1.5 hours, but still not time up yet.
Toast.makeText(getBaseContext(), "sets ", Toast.LENGTH_SHORT).show();
}
else{
//Time is up. Run action.
Toast.makeText(getBaseContext(), "Time not gone ", Toast.LENGTH_SHORT).show();
}

Android Dev: Time span past midnight calculation

im working on auto profile changer application for android...this is my 2nd application im developing on android, so dont know all the bells and whistles of android development...
any way...i am having some trouble calculating the next time when the timer code is suppose to execute...mainly the issue is around the time that spans over midnight into the next day...
for example, say that the user created a sleeping profile that starts at 10:30PM and goes until 8AM the next day...using this as a example, the execution is getting inside the proper condition that i have placed in the code, but the nextUpdateInterval is not being set correctly...im still trying to figure out how to account/calculate time that spans over to the next day, and at this point im starting to think that im might be making this task overly complicated? any suggestions?
here is the snippet of the code:
timer.scheduleAtFixedRate( new TimerTask() {
public void run() {
//..... some code to convert user stored times into proper time formats
//PM to PM
if(isFromTimePM == true && isToTimePM == true){
}//PM to AM
else if(isFromTimePM == true && isToTimePM == false){
if(rightNowDate.getTime() >= fromDate.getTime() && rightNowDate.getTime() >= toDate.getTime()){
foundProfileIndex = i;
i = profileArrayListSize;
nextUpdateInterval = rightNowDate.getTime() - toDate.getTime();
}
}//AM to AM
else if(isFromTimePM == false && isToTimePM == false){
}//AM to PM
else if(isFromTimePM == false && isToTimePM == true){
}}, 0, nextUpdateInterval);
Thanks,
P
Forget about PM and AM. Since you appear to be using dates, when you use the getTime() method you are getting the number of milliseconds elapsed since the Epoch. Simply subtract these two and you will have the time interval in milliseconds:
long nextUpdateInterval = secondDate.getTime() - firstDate.getTime();
The nextUpdateInterval is a long and is 'time in milliseconds between successive task executions'.
none of this secondDate - firstDate was ever necessary, what i ended up doing was the following:
converted all times to miliseconds
converted the milliseconds into the date objects
used the compareTo to compare the 'to' 'from' dates to current date/time
if i found a profile match, then i stored the 'to' date as the next run date
created a reScheduleTimer method that took date as a paramter...and i just used the .schdule(timertask, date) to resechule the timer...

Categories

Resources