Change an image according to time of day - java

I want the functionality of Google Now app, like when it's day time, the header is a sunny image, when it becomes noon or sundown, the image changes to a sundown image, when it's night the image changes to a night image, and same for the morning one.
I'm trying to implement my background which does this very same thing, how must I go about implementing this? I've searched up on this but the answers are for html and website development.
And most of the others are based on time interval and I think that's what I should use but I would like something like this. Written in non-tech language
01:00/1am - Morning - Image changes to Morning.png on the imageview (R.id.view).
09:00/9am - Normal - Image changes to Daytime.png on the imageview (R.id.view).
12:00/12pm - Noon - Image changes to Noon.png on the imageview (R.id.view).
19:00/7pm - Night - Image changes to Noon.png on the imageview (R.id.view).
How I can achieve something similar to this?

Well the best candidate for this job is an AlarmManager!
Lets assume you only need to change the background when your Activity is running.
You can set up your alarm when you Create your Activity:
private PendingIntent pi=null;
private AlarmManager mgr=null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mgr=(AlarmManager)getSystemService(ALARM_SERVICE);
pi=createPendingResult(ALARM_ID, new Intent(), 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + PERIOD, PERIOD, pi);
}
PERIOD (ms) is how often we want to get control (onActivityResult). The createPendingResult(ALARM_ID, new Intent(), 0); line creates an Intent that can be caught in your Activities onActivityResult method:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ALARM_ID) {
// This is where you check the time and change your background!
}
}
You also need to cancel your alarm in onDestroy:
#Override
public void onDestroy() {
mgr.cancel(pi);
super.onDestroy();
}
To check if a Date is in a specific interval you can use:
boolean isWithinRange(Date testDate) {
return testDate.getTime() >= startDate.getTime() &&
testDate.getTime() <= endDate.getTime();
}

I advice you write a class which has a listen method. This listen method which checks time and raises a custom event (you can use interface here) on Activity level must be called periodically. You can use Timer and TimerTask or CountdownTimer to call.

Related

How to keep the countDownTimer counts after i swap the activity?

i need a countDownTimer keep running when i swap between activities.. i have more than one activity, i put the countDownTimer in the main activity but when i swap to another activity and back to the main activity it turns back to count again from the start, i believe because the method countDownTimer is onCreate method.
So, how should I go about doing this?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
questionTime();
}
public void updateTimer(int secondsLeft){
int minutes = (int) secondsLeft / 60;
int seconds = secondsLeft - minutes * 60;
String secondString = Integer.toString(seconds);
timerTextView.setText(Integer.toString(minutes) + ":" + secondString);
}
private void questionTime(){
new CountDownTimer(10000, 1000){
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
timerTextView.setText("0:00");
Log.i("finished", "timer Done");
}
}.start();
}
Update: That helped me to reach my purpose How to run CountDownTimer in a Service in Android?
Maybe this is a little far fetched, but the way that I think to solve this issue and not worrying for the Activities is using an IntentService.
Even if you store some sort of value in the Bundle of the onSaveInstance() hook method this can lead to some pretty messy results if you enable the "Don't keep activities" flag in the device's settings.
What I would do is create an IntentService that when It's triggered starts the countdown, then It broadcast the changes of that countdown through EventBus/Otto/BroadcastReceiver back to the UI.
Another way of doing it is having the countdown instance in your Application class, and check it from there.
I would go with the IntentService solution because having a countdown instance running in the Application class sounds a little off.
Let me know if you want any specifics on how to implement the IntentService but a little bit of Googling should show you how to do it.
As soon as the time starts, write the time (unix timestamp) to properties file. And when the user comes back to your main activity, read the properties file and compare it the time in the properties file with current timestamp and update the timer based on that.

Recurring background task Android - Handler vs AlarmManager

I am working on an application for research purposes. We want to track some user activity on the phone: if some actions are easily detactable with broadcast receivers, we want also to check current running applications.
This application works only on Android devices that runs android 5.0 or lower.
My problem is that I post a Runnable Obj in a handler, Runnable posts again itself in handler after HALF_SECOND (see code for details). In runnable I get information and send them to IntentService to perform work.
Everything works fine: app starts at boot, handler and runnable do their job in background UNLESS I open the main Activity.
The app is able to keep going for days, but if I open the main Activity and then close it from "recent open activities" with a swipe, or from the memory task manager, handler and runnable stop, even if they are not called/accessed by the activity (they are in a Separate Service).
Moreover, not always a call to onDestroy (of the activity or Service) is made.
Reading online I understand that swipe or task manager remove the app from memory abrouptly thus not always calling onDestory.
What I want to achive is to make the handler start again soon after the main activity is closed.
What I have tried is to put some check in onPause method of the activity, making sure to remove this check if onStart is called again (like in case the the app switches from vertical to horizontal layout, or if home button is pressed and then app is opend again). Also implemented a way to make the handler send "ImAlive" intent to a broadcast receiver, which should restart the service that starts the handler, if intents do not arrive before a count down is finished. Unfortunately, as soon the main activty stops existing, even the broadcast is automatically unregistered and destroyed.
My question is, is there a way to create something that is able to make my handler restart if the activity is closed? Or is there some other pattern that can help me as workaround for what I want to achieve? Because I am polling data every half second I read is better to use handler, because Timer augments small interval to a greater interval, and AlarmManager is not precise enough for very small interval.
What I want to achieve is something similar to Facebook, Instagram, Whatsapp, Telegram app, that are always in memory, and even if you force to terminate them, after a few seconds are back again there... how?
We are not interested in battery issues because of continuous polling to data. As for research purposes we don't mind if the phone on which we are testing last 2 days straight, 1 day or 12 hours or less.
Here the code: OnBootService is started from broadcast receiver, declared in manifest when onBootCompleted and ShutDown actions are received, in order to start and stop handler.
public class OnBootService extends Service{
private static final Handler handler = new Handler();
private final long HALF_SEC = 500;
private RunnableTest r = null;
private Context myContext = this;
private final String TAG = "BootService";
// Extras
public static final String START = "start";
public static final String STOP = "stop";
#Override
public IBinder onBind(Intent intent){
return null;
}
#Override
public int onStartCommand(Intent intent, int flag, int startId){
String action = intent.getAction();
switch(action){
case START: startHandler();
break;
case STOP: stopHandler();
break;
}
return START_NOT_STICKY;
}
private void startHandler(){
if(r == null){
r = new RunnableTest();
handler.post(r);
Log.i(TAG, "----Handler started!");
}
}
private void stopHandler(){
if(r != null){
Log.i(TAG, "----calling STOP");
handler.removeCallbacks(r);
r = null;
}
}
private class RunnableTest implements Runnable {
private String TAG = "RunnableTest";
public RunnableTest(){}
#Override
public void run(){
handler.removeCallbacks(this);
// Do stuff
Intent i = new Intent(myContext, MyIntentService.class);
i.putExtra("addStuff", myStuff);
myContext.startService(i);
handler.postDelayed(this, HALF_SEC);
}
}
Activity is empty: all method overridden just to understand proper Activity lifecycle, but else is empty for now.
public class MainActivity extends AppCompatActivity {
private final String TAG = "Activity";
private Context myContext = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// access a file and get stored information to show
setContentView(R.layout.activity_main);
Toast.makeText(getBaseContext(), "Application open successfully", Toast.LENGTH_LONG).show();
}
#Override
protected void onRestart(){
super.onRestart();
Log.e(TAG, "----onRestart Called");
}
#Override
protected void onStart(){
super.onStart();
Log.e(TAG, "----onSTART Called");
}
#Override
protected void onResume(){
super.onResume();
Log.e(TAG, "----onRESUME Called");
}
#Override
protected void onPause(){
super.onPause();
Log.e(TAG, "----onPAUSE Called");
}
#Override
protected void onStop(){
super.onStop();
Log.e(TAG, "----onSTOP Called");
}
#Override
protected void onDestroy(){
super.onDestroy();
Log.e(TAG, "----onDestroy Called");
}
}
Any help is really appreciated, if you need some more information on the code, I will update the post.
Thank you!
Android system can restart the service if u return START_STICKY inside onStartCommand().
It works perfectly on all lower version than Lollipop in Android.
No need of CountDownTimer.

Android - Activity finish() results black screen

I have an AlertActivity and an Activity. When a broadcast is received, both activities needs to finish. But the below code results Black screen if AlertActivity is on top of Activity.
Below is the code in Activity:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("BROADCAST_INTENT")){
if(alertActvity != null)
alertActivity.finish();
finish();
}
}
And code in AlertActivity:
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("BROADCAST_INTENT"))
finish();
}
}
First, Activity's onStop() is getting called before AlertActivity's onStop() is called which results in Black screen, even AlertActivity's finish() called before Activity's finish().
Please help me in this regard.
Finally, I found a solution for this:
Finishing an Activity with a delay of 1 second which really works. By that time, AlertActivity finishes and black screen cannot be displayed.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
finish();
}
}, 1000);
as in both AlertActivity and Activity, you are checking for same action "BROADCAST_INTENT", I assume you registered both receiver in their own class.
If you did so, then actually you have two broadcast receiver waiting for same event. when this event occurs, both of your receiver are going to get it.
So in your AlertActivity is getting finished twice.
I think #Amit K. Saha, is right, your AlertActivity may be finishing twice
Solution :
If your application is running >= API 16 then you can use finishAffinity() method :
Finish this activity as well as all activities immediately below it in the current task that have the same affinity. This is typically used when an application can be launched on to another task (such as from an ACTION_VIEW of a content type it understands) and the user has used the up navigation to switch out of the current task and in to its own task. In this case, if the user has navigated down into any other activities of the second application, all of those should be removed from the original task as part of the task switch.
Note that this finish does not allow you to deliver results to the
previous activity, and an exception will be thrown if you are trying
to do so.
You can call finishAffinity() from AlertActivity because it is on top of Activity. This will finish AlertActivity as well as Activity
My transparent Activity finish results black screen, after a search, i find it is caused by activity switching animation in Android 4.4. But above android 5.1 the phenomenon does not show up.
So I add the below code:
#Override
public void finish() {
super.finish();
overridePendingTransition(0, 0);
}
The black screen after finish is gone.
I think this may be helpful.
try this
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("BROADCAST_INTENT"))
context.finish();
}
}

Run App Twice To Work

I'm making an android app that test if certain security features on your phone are enabled. For example, if you have password log in enabled or if your data is encrypted on your phone.
For some reason, the app has to be run twice to test and see if these security features are enabled on the phone or not, and this is the problem I'm trying to solve. I'd like it to test and see if the security features are enabled when the app is created and the first time the app is run, not the second time it is run.
I test if these features are enabled in the onStart() function in my MainActivity file. I included the functions code below:
#Override
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
#SuppressLint("NewApi")
public void onStart()
{
super.onStart();
//determine if phone uses lock pattern
//It returns 1 if pattern lock enabled and 0 if pin/password password enabled
ContentResolver cr = getBaseContext().getContentResolver();
lockPatternEnable = Settings.Secure.getInt(cr, Settings.Secure.LOCK_PATTERN_ENABLED, 0);//Settings.System
//returns 1 if pin/password protected. 0 if not
KeyguardManager keyguardManager = (KeyguardManager) getBaseContext().getSystemService(Context.KEYGUARD_SERVICE);
if( keyguardManager.isKeyguardSecure())
{
//it is pin or password protected
pinPasswordEnable=1;
}
else
{
//it is not pin or password protected
pinPasswordEnable=0;
}//http://stackoverflow.com/questions/6588969/device-password-in-android-is-existing-or-not/18716253#18716253
//determine if adb is enabled. works
adb=Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED, 0);
//determine if bluetooth is enabled.works
bluetooth=Settings.Global.getInt(cr, Settings.Global.BLUETOOTH_ON, 0);
//Settings.System BLUETOOTH_DISCOVERABILITY
//determine if wifi is enabled. works
WifiManager wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled())
{
//wifi is enabled
wifiInt=1;
}
else
wifiInt=0;
//determine if data is encrypted
getDeviceEncryptionencryption();
//determine if gps enabled
}//end of onStart() function
If any more code needs to be posted to answer this question, just let me know, and thanks for your help. Maybe the issue has something to do with the super.onStart();
Does anyone think that a splash loading screen might help solve the issue?
Here is good explanation how app lifecycle flows.
onStart() can be executed many times. You can keep counter how many times you had entered this method and act differently on each time:
static int counter=0;
public void onStart()
{
counter++;
Log.i("MyApp", "onStart() run "+counter);
switch (counter){
case 1: break; // first run
case 2: break; // second run
default: break;// other runs
}
}
To be more clear about life cycle and why your onStart() method is called twice I suggest to have counter and Log.i() in each important state of the cycle - at least in onCreate() and onRestart().
Keep in mind that app stays in memory when you click Home button. When you click app icon again it restarts already running app (calls onRestart() and then onStart() methods and no onCreate() ). When you really kill you app for real then sequence would be onCreate and onStart without onRestart. Having logcat records really helps you to understand app lifecycle flow and why your onStart() is called twice or more times.
Using a static variable to check how many times onStart has been called isn't a good idea, because an app can be killed if Android needs more memory for other apps while still allowing the user to navigate back to the app. That would be the path through the red box in the picture below (http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle):
A static variable would be 0 again after that and your app would run the security check again.
What you need to do is use an instance variable that you persist in onSaveInstanceState and restore in onCreate. In case the app is killed, onSaveInstanceState is called and you save your Activity's state. If the user goes back to the app, onCreate is called and the state would be restored. This works for all other cases too when the app isn't killed but the user just navigates away from the app and later re-opens it. Here's a simple example of an app saving and restoring:
public class MainActivity extends Activity {
private boolean mSecurityCheckDone;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mSecurityCheckDone = savedInstanceState.getBoolean("mSecurityCheckDone");
}
}
#Override
protected void onStart() {
super.onStart();
if (! mSecurityCheckDone) {
// run the security check
mSecurityCheckDone = true;
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("mSecurityCheckDone", mSecurityCheckDone);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null) {
mSecurityCheckDone = savedInstanceState.getBoolean("mSecurityCheckDone");
}
}
}
how about using flag ?
singleTop
If an instance of the activity already exists at the top of the target
task, the system routes the intent to that instance through a call to
its onNewIntent() method, rather than creating a new instance of the
activity.
singleTask
The system creates the activity at the root of a new task and routes
the intent to it. However, if an instance of the activity already
exists, the system routes the intent to existing instance through a
call to its onNewIntent() method, rather than creating a new one.
singleInstance
Same as "singleTask", except that the system doesn't launch any other
activities into the task holding the instance. The activity is always
the single and only member of its task.
http://developer.android.com/guide/topics/manifest/activity-element.html
I'm not sure why you are using onStart(), if you want it to be run the first time the activity is created I would probably use onCreate() instead.
There is no API in Android that will tell you if the app has been run at least once so you will need to use some type of persistent storage for that, e.g. SharedPreferences could be used to persist a flag that would be set the first time your app is run and thereafter you can check it as shown here.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences settings = getSharedPreferences("Prefs", 0);
if (settings.getBoolean("first_time", true)) {
//the app is being launched for first time, do something
Log.d("Comments", "First time");
// first time task
// record the fact that the app has been started at least once
settings.edit().putBoolean("first_time", false).commit();
}
}

too little fps in android emulator / wrong error message at start

I have an app that, for now, runs a loop where it updates the game state ~25 times/s and tries so draw it 40 times/s. the update works fine, it shows just a bit more than 25. but on the emulator, the game draws under 20 fps, no matter how much there is to draw. even if I only paint the background green it has low fps.
I sent the app to someone who tested it on his phone, there it runs correctly with 40fps drawing speed and 25fps updating speed.
I tested it on the emulator with different API levels, the drawing fps is always way too slow. I use eclipse. do I have to make any special setting for the emulator or so?
There was another problem too, the guy who tested it on his phone got an error message when starting the app, it said the app wouldn't react and the option for wait and shutdown. after waiting 5-10 seconds the content view would be displayed. I create the content view and assign the variable in the onCreate method, without starting the loop. In the onStart method I set the contentView and start the loop, but it runs an empty while loop until I set a boolean in the onResume method. any ideas?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view= new MainMenu(this); }
protected void onStart() {
super.onStart();
this.setContentView(view);
view.startGameView();
}
public void startGameView() {
loop=new GameLoop(this);
loop.start();
}
protected void onResume() {
super.onResume();
view.resumeGameView();
}
public void resumeGameView() {
loop.b_pause=false;//loop starts to execute code for drawing/updating
}
the code for the activity change:
public void changeActivity(Class c, String str)
{
Intent i=new Intent(this, c);
startActivity(i);
}

Categories