Configure Back Button to Skip First View - java

I have an app with a title screen. When the app first starts, I have an onCreate method that contains the following code:
setContentView(R.layout.title_screen);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
setContentView(R.layout.main_screen);
}
}, 2000);
When I run my app and press the back button while on the main_screen layout, it closes the app (as it should). However, when I reopen the app, it displays the title_screen layout for two seconds again even though the app is already running. How can I prevent this?

This will prevent the delay appearing again when resumed:
private static boolean flag = false;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!flag){
setContentView(R.layout.title_screen);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
setContentView(R.layout.main_screen);
}
}, 2000);
flag = true;
} else {
setContentView(R.layout.main_screen);
}
}
Btw, if your app was on background and it is calling onCreate again while being resumed, it means that it is killed by the OS. Therefore it is normal to have the initial delay again.
What I would do is to implement two different activities first one showing title_screen and the second which is started after 2s should show your main screen.

After looking at your code I can see that you ALWAYS start with title_screen then after 2s, you change to main_screen. Therefore, when you press back, that means you finish your activity. When you re-open your app, onCreated is called again, and it run every line of code as the previous opening.Of course, there's no difference in 2 times you open your app. To overcome it, I recommend to use SharedPreference to store the flag to check main_screen or title_screen.

Related

display activity countdowntimer in fragment

I am just starting to learn Android, Java and need help.
I have an activity with the countdowntimer, which works fine. However, I want it to be displayed in the fragment. What is the best way to do it?
I tried calling Timer.getCountdowntimer, I tried calling Timer.getUserTime (userTime is the user selected time for the countdowntimer), but the textview in my fragment doesn't display the timer.
thanks in advance!
If you are coding in Java purely, and want to use the android SDK to do it, I would recommend:-
//Create a handler that runs on main loop so we can update UX
final android.os.Handler handler = new android.os.Handler(Looper.getMainLooper());
//Get a callback in 1 second
handler.postDelayed(new Runnable() {
int timer;
#Override
public void run() {
timer += 1;
myTextView.setText(String.valueOf(timer));
//Recursively get another callback in a second
handler.postDelayed(this, 1000);
}
}, 1000);
Make sure you add some logic to stop the timer when you want, and also onPause/onResume

How to display a screen only for some seconds Android Studio

I am new in Android Development. I have been trying to figure out how to display a screen in android studio only for 5 seconds and then get transfered into a new activity.
For example:
Activity A -> Activity B (Shown for 5 seconds) -> Activity C
Also I want to make sure that when a user clicks on the back button while he is in Activity B nothing happens (It doesnt go back to Activity A).
What is the easiest way to do that?
I know I have to use Intent.
try this. I have commented it out, but if you have any questions about it feel free to ask.
public class ClassB extends AppCompatActivity {
//Handler allows you to send and process Runnable Objects (Classes in this case)
private Handler mHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_classb);
//postDelayed method, Causes the Runnable r (in this case Class B) to be added to the message queue, to be run
// after the specified amount of time elapses.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
//Create a new Intent to go from Class B to Class C and start the new Activity.
Intent intent = new Intent(ClassB.this, ClassC.class);
startActivity(intent);
finish()
}
//Here after the comma you specify the amount of time you want the screen to be delayed. 5000 is for 5 seconds.
}, 5000);
}
//Override onBackPressed method and give it no functionality. This way when the user clicks the back button he will not go back.
public void onBackPressed() {
} }
In Kotlin you can do:
Handler().postDelayed({
// Start activity
startActivity(Intent(this, YourTargetActivity::class.java))
// terminate this activity(optional)
finish()
}, 5000)

Android Thread Allocation - growing heap?

Hi everyone out there,
i am developing an android application against API 7 at the moment in which i use an activity which need to be restarted. Lets say my activity looks like this:
public class AllocActivity extends Activity implements OnClickListener{
Button but;
private Handler hand = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_alloc);
but = (Button) findViewById(R.id.button);
but.setText("RELOAD");
but.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0){
Intent intent = getIntent();
startActivity(intent);
finish();
}
});
}
#Override
protected void onDestroy(){
super.onDestroy();
System.gc();
}
/****** THREADS AND RUNNABLES ******/
final Runnable fullAnim = new Thread(new Runnable(){
#Override
public void run(){
try{
hand.post(anim1);
Thread.sleep(2000);
hand.post(anim2);
Thread.sleep(1000);
// and so on
}catch(InterruptedException ie){ie.printStackTrace();}
}
});
final Runnable anim1 = new Runnable() {
#Override
public void run(){
// non-static method findViewById
ImageView sky = (ImageView)findViewById(R.id.sky);
}
};
}
The problem is that the gc doesnt seem to free the fullAnim thread so that the heap is growing by ~100K at every restart - till it slows down and crashes. Declaring fullAnim as static does solve this problem - but as i use non static references this doesnt work out for me.
So at this point i am kindof lost - and i hope u can advice me where to go next. Is there something i might be doing wrong or is there a tool i can use to manage threads to drop and free heap after restart.
kindly regards
UPDATE
thanks to everyone who answered - helped alot. using TimerTask did the trick in the end. i did the following change:
/****** THREADS AND RUNNABLES ******/
final TimerTask fullAnim = new TimerTask(){
#Override
public void run(){
try{
hand.post(anim1);
Thread.sleep(2000);
hand.post(anim2);
Thread.sleep(1000);
// and so on
}catch(InterruptedException ie){ie.printStackTrace();}
}
};
as the activity was more than 6k loc long this was a pretty decent solution without facing bigger impacts. KUDOS!
i dont use a Timer to shedule the task - dont know if its bad practice but
the animation is called like this:
Thread t = new Thread(fullAnim);
t.start();
A running Thread is never garbage collected.
A Thread is not stopped automatically if your Activity stops or is destroyed. It could run forever.
Every non-static inner class keeps a reference to the enclosing instance. E.g. hand.post(anim1); works inside that inner class because it has an implicit reference to AllocActivity.this.
So what you effectively do is to keep a reference to your Activity alive for longer than it is supposed to be alive, i.e. until after onDestroy.
Make sure to stop threads manually if you don't want them anymore.
Because final variable have low priority for GC. So you need to explicitly release the runneable objects in onPause() method because there is not ensurence onDestory() will call immediate after finish() call .
#Override
protected void onPause(){
super.onPause();
//cancel timer to stop animations
if(t!=null){
t.cancel();
}
System.gc();
}
UPDATE
use timer to achieve this
boolean isFirstAnim=true;
Timer t = new Timer();
t.schedule(new TimerTask() {
#Override
public void run() {
if(isFirstAnim){
// play your first animation at every
}else{
// play your second animation at every
}
}
}, 0, 3000);
What happens when all activities of an application finishes?
"When you call finish() this doesn't mean the Activity instance is
garbage collected. You're telling Android you want to close the
Activity (do not show it anymore). It will still be present until
Android decides to kill the process (and thus terminate the DVM) or
the instance is garbage-collected."
You need to implement your own stop method to stop the running thread, you can make a call to it in onDestroy
refer this Stopping a runnable
Alternatively
you can perform your operation in an asynctask and use onProgressUpdate() to publish progress on UI thread and use cancel(true) in combination with check in doInBackground() whether cancel has been called to stop the task.

Handler().postDelayed() sending multiple intents when orientation changes

Ok I'm working on a splash screen that pauses for 1.5 seconds and works great, except for one thing. Once the timer is started in onCreate if the configuration (orientation) changes then the timer gets reset and then end result is it starts my ParchmentActivity.java twice.
How can I prevent the handler from sending the intent twice?
Thanks in advance!
Full code can be found #: https://github.com/n00bware/android_apps_parchment
Here is my code (from example http://www.anddev.org/novice-tutorials-f8/splash-fade-activity-animations-overridependingtransition-t9464.html):
public class SplashScreen extends Activity {
private static final int SPLASH_DISPLAY_TIME = 1500; /* 1.5 seconds */
private static final String TAG = "Parchment";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* Create a new handler with which to start the main activity
and close this splash activity after SPLASH_DISPLAY_TIME has
elapsed. */
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent parchment = new Intent(SplashScreen.this, ParchmentActivity.class);
SplashScreen.this.startActivity(parchment);
SplashScreen.this.finish();
overridePendingTransition(R.anim.fade_main_in, R.anim.fade_splash_out);
}
}, SPLASH_DISPLAY_TIME);
}
/* I found a suggestion to try overriding onConfigurationChanged()
but it doesn't stop a new timer from being started */
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
/* I also tried overriding onStart() but this also doesn't stop a
new timer. What exactly is called when an orientation configuration
changes happens? */
#Override
public void onStart() {
super.onStart();
setContentView(R.layout.splash);
}
you can create a new static boolean, set it false and in on create do the Handler action only if the flag is false...
PS: inside the if statement, you must set the boolean flag to true :)
Good luck!
Create the handler in onCreate, release it in onDestroy, send a message / post a runnable in onStart, remove message / runnable in onStop.
This will reset the timer with each rotate, so you could potentially keep the splash screen up if you rotated the device every second.
In Android it can take a second or so to switch rotations, you probably want this behaviour because it would be possible to start app, rotate and not see the splash.

How to close a window/activity after a certain amount of inactivity

I'm designing a music player app for Android that will feature pop-up controls. I'm currently trying to get these controls to close after a certain period of inactivity but there doesn't seem to be a clearly documented method of doing this. So far I have managed to cobble the following solution together using a few suggestions both from this site and others.
private Timer originalTimer = new Timer();
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.playcontrols);
View exitButton = findViewById(R.id.controls_exit_pane);
exitButton.setOnClickListener(this);
View volUpButton = findViewById(R.id.controls_vol_up);
volUpButton.setOnClickListener(this);
View playButton = findViewById(R.id.controls_play);
playButton.setOnClickListener(this);
View volDownButton = findViewById(R.id.controls_vol_down);
volDownButton.setOnClickListener(this);
musicPlayback();
originalTimer.schedule(closeWindow, 5*1000); //Closes activity after 10 seconds of inactivity
}
And the code that should close the window
//Closes activity after 10 seconds of inactivity
public void onUserInteraction(){
closeWindow.cancel(); //not sure if this is required?
originalTimer.cancel();
originalTimer.schedule(closeWindow, 5*1000);
}
private TimerTask closeWindow = new TimerTask() {
#Override
public void run() {
finish();
}
};
The above code makes perfect sense to me but it force closes upon any user interaction. It does however close normally if untouched and won't close after interaction if I remove the second schedule, so this seems to be the problem. Also note that I imagine I will be moving this timing task to another thread to help keep the UI snappy. I need to get it working first though :D. If there's any more info I need to supply please ask and thanks for any help...Ye guys are brilliant!
Based on #CommonsWare's suggestion, switched to a Handler. Works perfectly. Thanks very much!
private final int delayTime = 3000;
private Handler myHandler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.playcontrols);
View exitButton = findViewById(R.id.controls_exit_pane);
exitButton.setOnClickListener(this);
View volUpButton = findViewById(R.id.controls_vol_up);
volUpButton.setOnClickListener(this);
View playButton = findViewById(R.id.controls_play);
playButton.setOnClickListener(this);
View volDownButton = findViewById(R.id.controls_vol_down);
volDownButton.setOnClickListener(this);
musicPlayback();
myHandler.postDelayed(closeControls, delayTime);
}
and the other methods...
//Closes activity after 10 seconds of inactivity
public void onUserInteraction(){
myHandler.removeCallbacks(closeControls);
myHandler.postDelayed(closeControls, delayTime);
}
private Runnable closeControls = new Runnable() {
public void run() {
finish();
overridePendingTransition(R.anim.fadein, R.anim.fadeout);
}
};
To complete the answer above, note that the Activity.onUserInteraction() is adequate only if you care about clicks.
The documentation at http://developer.android.com/reference/android/app/Activity.html#onUserInteraction%28%29 states: "Note that this callback will be invoked for the touch down action that begins a touch gesture, but may not be invoked for the touch-moved and touch-up actions that follow."
Actual implementation proved it indeed ignores all movements on the tablet, which means the clock is never reset while, say, drawing without releasing the finger. On the other hand, it also means that the clock is not reset too often, which limits the overhead.

Categories