Android App close and reopen start at beginning again - android

I have created a simple app for android, that uses buttons to navigate different activities the app starts at page 1, you click on page 2 or 3 button etc and that starts the required activity, simple.
What im having problems with (more of annoyance than problem) when you click HOME or come out of the app, because android doesn't kill the app straight away it is keeping the page you are on remembered and is opening the app at activity 2 or 3 for example. I want the app when closed to go back to the beginning of the app again and open at 1, i can go back to 1 by clicking back but this is really not what i wanted.
I hope someone can read this and understand, simplest solution possible please

What you need to do is use the Activity lifecycle to your advantage. When a screen is hidden for any reason, its onPause method gets called. When it's displayed again, onResume gets called. However, onResume is called even the first time a new Activity is displayed. Another problem is that onPause is called when transitioning between Activities.
So you ultimately want to "restart" the app when the last Activity's onPause and onResume are called in succession. Try this class, and have all of your Activity's extend this instead of Activity.
public abstract class BaseActivity extends Activity {
private static BaseActivity lastPausedActivity = null;
#Override
protected void onPause() {
super.onPause();
lastPausedActivity = this;
}
#Override
protected void onResume() {
super.onResume();
if(this == lastPausedActivity) {
lastPausedActivity = null;
Intent intent = new Intent(this, FirstActivity.class);
intent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP );
startActivity( intent );
}
}
}
I haven't tested this code, so it may need a few tweaks, but the logic should be sound.

Related

How to kill a specific Instance of a Activity?

I know we can keep only one instance by
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
but I need that my app can create maximum two instances of certain activity not more than that.
I am using a chained search feature like image below
When Instance3 of the activity1 is created i want to destroy:-
Instance1 of activity1
Instance1 of activity2
Tried to used this to kill a specific activity but activity have same Pid for all processes in an app
android.os.Process.killProcess( stack.getLast());
is there a way we can moderate which instances should be kept alive?
any help would be great thanks!
In my opinion this is the wrong architecture. For chained search you should only ever have a single instance of each Activity. You should flip between the different Activity instances by calling startActivity() and setting Intent.FLAG_ACTIVITY_REORDER_TO_FRONT in the Intent you use. Also add the data you want to display as "extras" in the Intent.
To be able to use the BACK button to back through the chain (no matter how long it is), each Activity should manage a stack that contains the data that it needs to recreate the page whenever the user backs into it. In onCreate() and in onNewIntent() the data (from the "extras") should be pushed onto the stack and displayed. You then override onBackPressed() and go back to the previous Activity by calling startActivity(), and setting Intent.FLAG_ACTIVITY_REORDER_TO_FRONT in the Intent you use. You also add an "extra" to the Intent that indicates the user wants to "go back". In onBackPressed() you should also discard the top element off the data stack of the Activity that is being left. This will ensure that the stack is correct when the user then backs into this Activity.
In onNewIntent() if the user just backed into the Activity, you just display the data that is already on top of the stack of managed data.
In this way, you only ever have one instance of each Activity, the user can chain all day through the set of activities and the BACK button always works and you don't have to worry about running out of memory.
Trying to accomplish this using taskAffinity or Intent flags or similar will not work. Don't waste your time. It is also bad programming style.
I hope this is clear.
Basically you want to remove entries 1 and 2 from the backstack when you create the 5th one, but leave the 3rd and 4th. Unfortunately, the backstack doesn't work that way, you can only manipulate it from the top. You have the option of clearing all the activities except the last one if you set the flags FLAG_ACTIVITY_CLEAR_TASK and FLAG_ACTIVITY_NEW_TASK, you will have an empty task only with the just started activity.
If I were you, I wouldn't worry about memory consumption by the old activities though. As long as you stop the resource-consuming processes in your activities when they leave the screen and don't hold the references to them so they can be garbage collected, Android can manage the memory itself fine. What you should think about is whether it makes sense for the user to come back to the old activities if he presses back. If yes, then leave them, if no, then don't.
In case you want to kill all your activities on the back button press, there is an Activity.finishAffinity() method. Just override the onBackPressed method to call it.
You can use a little hack with EventBus or BroadcastReceiver or some other Bus. Check my following code for my idea. For this app, I will keep maximum 2 instances of MainActivity
public class MainActivity extends AppCompatActivity {
public static int count = 0;
int id;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
count ++;
id = getIntent().getIntExtra("ID", 0);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, MainActivity.class);
intent.putExtra("ID", count);
startActivity(intent);
}
});
}
#Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
EventBus.getDefault().post(new Event(count));
}
#Subscribe
public void onEvent(Event event) {
if (id < (event.getID() - 2)) {//put your logic code to finish the activity here
Log.i("MainActivity", id + " is killed ");
finish();
}
}
#Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
}
you can do this bro,
declare one Activity object like this
public static Activity factivity;
onCreate()
{
factivity = this;
}
now you can use that object to kill that specific activity on another activity like this:
onCreate()
{
FirstActivity.factivity.finish();
}

Restart app each time it's ran?

I have 2 activities, a 4 digit pin style login Activity (MainActivity) and a content Activity.
This app stores private information and such that should not be able to be seen when resuming an activity, therefore i want the app to completely restart on the login activity each time it's launched, rather than picking up where it left off.
I've tried messing around within the content activity's onStop() and onResume methods, but these seem to be highly unreliable as sometimes when i have the onRestart setup to relaunch the login activity, it won't launch it at all, and calling for the login screen to be activated in the onStop() will prevent me from being able to finish up tasks in the background, such as saving data.
Is there anything i can add to the manifest file that will tell the app to restart from the login activity no matter what? One of the worst things that can happen when working on an app like this is that the information is accessible to someone other than the owner that wasn't forced to login..
What you need is to focus on two calls in your Content Activity:
onPause(): This is where you kill Content activity and remove it from the stack. You can do this easily:
#Override
public void onPause() {
super.onPause();
//Save your data here
finish(); //Kill Contect Activity.
}
onRestart(): This is where you redirect the user to the Main Activity.
#Override
public void onRestart() {
super.onRestart();
Intent i = new Intent(this, MainActivity.class);
startActivity(i);
finish(); //Kill Contect Activity.
}
This graph might help you in understanding the Activity lifecycle:
What you need is setting the flag android:clearTaskOnLaunch and android:excludeFromRecents for your activities in the Manifest.

How to Quit Android App

I have an Android App, and has several activities. I need to provide the button for each activity or specific activity which should allow to Close the App, without going to back to previous activities or run in background.
I tried
finish();
System.exit(0);
Both combination and individually its not working but closing the current activity and navigate to previous activity.
I looked the code from the following question
Need code for exit from app in android
First, having a Quit button is not reccomended in Android as it's not part of the expected UX.
But if you really need it, then you can call your home activity with an intent containing an extra, for instance :
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.putExtra("FORCE_EXIT", true);
Finally in your home activity, when handling the intent (in the onNewIntent() method), if the "ForceExit" extra is set, then finish the activity.
The stack will have been cleared completely by the FLAG_ACTIVITY_CLEAR_TOP and your app will then stop.
The most recommended approach that works for most cases is to feature only 1 Activity, using fragments for content displaying and logic.
This way you only need to finish() the main Activity since it will control the app lifecycle by design.
You will have many other benefits, such as dependency control and reusability, aswell as built-in functionality like animations using fragment transactions while having the possibility of keeping a fragment backstack, which you can manage accordingly towards your expected user interaction and without affecting the conveniency of finishing your app by calling finish() on your host Activity.
Another thing you can do, is to flag intents like this: intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); before launching a new Activity.
This way you can maintain your back trace clean, hence finishing the application whenever the user press the back button or call finish() from any event. However the use of flags is discouraged and considered bad practise.
This may be a hack to solve your problem. but i have just made an app and tested my code and it is working fine.
You will need to create a new activity called QuitActivity or whatever you want to name it and when you want to finish your app or quit your app you will have to start that activity via using this code
Intent i = new Intent(getApplicationContext(), QuitActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
this.finish();
then this is my code for quit activity that does nothing but closes it self after clearing the backstack so your app will quit.
public class QuitActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.finish();
}
}
hope this helps you.
First Finish your current Activity while moving to next by this code
startActivity(intent);
Classname.this.finish();
Second thing just override onBackPressed
#Override
public void onBackPressed() {
//do nothing
}
Use:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
when starting a new Activity, as described in API Documentation.
type only System.exit(0);
or create static boolean needToExit;
set needToExit = true;
in place where you call
finish();
System.exit(0);
in all other activity overwrite onresume
public void onResume(){
super.onResume();
if (MySettingsClass.needToExit){
finish();
System.exit(0);
return;
}
//your other code;
}
I tried some of the answers here using the flags or System.exit(0), but for me it either didn't work or it resulted in weird behavior. Sometimes it would kill the app, but then immediately restart it. I realized that I should just be doing things more of the standard way using request and result codes.
Basically, in your parent activity, start your child activity with:
startActivityForResult(new Intent(this, ChildActivity.class), CHILD_ACTIVITY_REQUEST_CODE);
where CHILD_ACTIVITY_REQUEST_CODE is just a constant (static final) integer. Then in your child activity, when they press the exit button, finish the activity with:
setResultAndFinish(RESULT_CODE_EXIT);
where RESULT_CODE_EXIT is another constant (static final) integer. Then back in your parent activity, handle the result code and finish the parent activity too:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == CHILD_ACTIVITY_REQUEST_CODE) {
if(resultCode != ChildActivity.RESULT_CODE_EXIT) {
finish();
return;
}
}
}

startActivity causes onCreate()

I have application and when I navigate back using Intent and startActivity(), views are null, onCreate() is called and activities are re-initialized. Why is that and how to bypass it?
I navigate back to activity like that:
#Override
public void onBackPressed() {
if (this.getClass() == XXX.class) {
Intent i = new Intent(this, YYY.class);
startActivity(i); //<-- activity restarts
return;
}
}
super.onBackPressed();
}
I use ActionbarSherlock, so I have activity with ActionBar initialization and every single activity just extends it. The way I navigate back to activity is described in this activity.
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
initUIComponents();
setListeners();
resetProgress();
}
and initUI() initializes UI.
EDIT
What I mean, how can I go back to previously created activity (not the one that is called via onBackPressed) and not recreate it? I use startActivity(), but apparently it recreates the whole thing
If you want that when you press back, you want to show the previous screen, then you don't have to do it in your code. Android Runtime internally maintains the stack, and will take care of showing the last-shown-activity when you press back. No need to handle it via onBackPressed()
However, if you want something other than this default action, that is when you should use onBackPressed(). Else, just let Android handle it.
So, in your application, if Activity 1 calls Activity 2, and user presses back, then the default action would be to show Activity 1 again. Don't override the onBackPressed() method
Edit:
For a custom flow of activities, you'll have to build the logic yourself. You need to override onRestart() in Activity 1, and onStop() in Activity 3. That way, onCreate won't be called again. By your logic, I mean, flags to keep track of which activity you're in, checking those flags, and calling the desired activity from there.
Edit 2:
This previous SO question, answers what you need:
Android Activity management , which suggests setting the flag FLAG_ACTIVITY_REORDER_TO_FRONT on the intent, and then calling startActivity()
Check out Android activity stack management using Intent flags for other stack reordering options: Stack management

OnRestart vs. OnResume - Android Lifecycle Question

My end-goal is to have an application that runs a block of code when it (the application, not the activity) is opened up after being left ( back from home screen, etc... )
According to the Activity Lifecycle, this should be the onRestart() event on a per activity basis ( at least how I interpret it )
Both onRestart() and onResume() are being called whether I am returning to the Activity within the application (back button) AND when the app is called back up.
Given this diagram
I am interpreting it this way:
RED = movement between activities within the application
BLUE = moving to an activity outside the Application
Is my understanding incorrect?
EDIT (Clarifying specific use case)
I'm attempting to use onRestart() to replicate some security logic (PIN Validation) found in onCreate(), but it's being called even when I press the back button inside the application...
My observation is that its hard to tie the lifecycle events to user behavior on the device or emulator. Where your app is paused, if the device needs memory or wants to recover resources, it will terminate the activity, causing onCreate to be called. There is just too many scenarios to build an adequate state machine to tell yourself "how" or "why" your activity was terminated.
The only way I've found to manage this is to create a service to hold the application state and manually manage the state. The problem is trying to use the Activity state to manage the application state. The Activity design seems to have limitations that just make it a poor choice for achieving the goal you've stated.
That would be because when unless your are using Fragments each "screen" in your application is a new activity, when you click the back button it restarts the activity of the page before it.
If I am understanding what you want to do correctly you want to put your code on onCreate, not onRestart.
SEE COMMENT THREAD FOR ANSWER
Here is how to do this:-
Have a base activity that all your activities are derived from.
Add in to the base activity:-
int nAppState;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
nAppState = 0;
.
.
}
protected override void OnStop()
{
AppState();
base.OnStop();
}
public static int IMPORTANCE_BACKGROUND = 400;
protected override void AppState()
{
ActivityManager am = (ActivityManager)GetSystemService(Context.ActivityService);
IList<ActivityManager.RunningAppProcessInfo> list2 = am.RunningAppProcesses;
foreach (ActivityManager.RunningAppProcessInfo ti in list2)
{
if (ti.ProcessName.ToLower() == "com.mycompany.myapp")
{
nAppState = ti.Importance;
break;
}
}
}
protected override void OnRestart()
{
base.OnRestart();
if (nAppState == IMPORTANCE_BACKGROUND)
{
// Show a log in screen
RunOnUiThread(delegate { StartActivity(new Intent(this, typeof(LoginAppearActivity))); });
nAppState = 0;
}
}
Please note that this is in Mono C#, it will be the same code for Java, I'll leave it up to you to convert it!!
Yes, your assertions for red and blue are correct.
However, note the alternate pathway from onPause() and onStop(). Process being killed for memory reasons is a) out of your control and b) imperceptible to you if you only use onRestart() to detect "coming back" to the activity.
You have an option to avoid the previous activity by avoiding/removing the activity to come in Stack by setting some flag before calling the startActivity(intent):
intent.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NO_HISTORY);
This will avoid the present activity to get called on back press. Alternatively you can also ovverride the onBackPressed() method of the current activity.

Categories

Resources