Android Crashing on user logout - android

I have the following code which is executed once the user clicks a button
public void logout(){
// redirect user back to login screen activity
Intent i = new Intent(this, LoginActivity.class);
// Closing all the Activities
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// Add new Flag to start new Activity
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// start Login Activity
startActivity(i);
}
However each time the button is clicked, the emulator crashes. Any ideas what i might be doing wrong?

You can set flags instead by doing
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK));
I doubt this is your issue though, make sure you are calling startActivity from within the Activity and the correct Thread, and make sure there are no issues with the onCreate of your LoginActivity.
Is this consistent with more than one emulator? Try a different configuration, and also check your AndroidManifest.xml file, is the second Activity defined?

The issue was prior to this method being called. I was trying to set the text on an EditText item that was part of another layout

Related

Best way to handle activity state

I'm making an app that shows another activity when I correctly login however in the home screen when I pressed back and then returned to the app the login activity showed.
I was able to avoid this overriding the onBackPressed this way:
public void onBackPressed()
moveTaskToBack(true);
}
Is this the best way to do it? Is there a more proper way to keep the state of the application when I exit it?
In your login activity after starting intent call finish()
finish destroy your activity and avoid to run it again automatically.
Your issue is that you kept LoginActivity in stack. so when you press back it will kill MainActivity(after login) and since LoginAcitivity still there. it will be shown again. best is to kill LoginAcitivty after starting new activity.
call this in LoginActivity:
Intent intent = new Intent(context, MainActivity.class);
startActivity(intent);
finish();
As you question I understand, you want to clear the entire history stack and start a new activity. For this, in API level 11 a new Intent Flag was added which is: Intent.FLAG_ACTIVITY_CLEAR_TASK
Just to clarify, use this:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
For API <=10 now one can use IntentCompat class for the same. One can use IntentCompat.FLAG_ACTIVITY_CLEAR_TASK flag to clear task. So you can support pre API level 11 as well.

Passing current Intent as extra to another Activity

I have a problem with my Login screen. When it's started, I check for network connection, and if it's disabled, I want to show NoNetworkActivity. And the same for every other screen: when Activity is launched, I check network connection and navigate to NoNetworkActivity is needed. When navigating, I want to save the Intent which launched this previous activity and finish it to disable the Back button redirection when on NoNetworkActivity. So, when connection is restored, I want to launch that intent and get actual state of the app before this error:
LoginActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
if (!App.getInstance().isNetworkConnected()) {
Intent noNetwork = new Intent(this, NoNetworkActivity.class);
noNetwork.putExtra(NoNetworkActivity.EXTRA_FAILED_INTENT, getIntent());
startActivity(noNetwork);
finish();
}
...
NoNetworkActivity
private void checkNetworkConnection() {
mCheckButton.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
if (App.getInstance().isNetworkConnected()) {
Intent failedIntent = getIntent().getParcelableExtra(EXTRA_FAILED_INTENT);
startActivity(failedIntent);
finish();
} else {
mCheckButton.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.INVISIBLE);
App.toast("Connection failed");
}
}
And it's getting strange: startActivity(failedIntent) does NOTHING. I've tried to remove finish() from next line, and NoNetworkActivity just stays on top without anything happening.
And one more thing. You can suggest passing Activity actual class names instead of intents, but I realy need Intent. That's because I'm using a lot of starting actions for every activity and a bunch of extras.
Thanks in advance for any help. Cheers!
Very bad approach. Don't use it.
First, you don't need to finish previous activity just to disable Back action. You can override onBackPressed().
Second, you don't need to start parent activity again. Just call a new activity with startActivityForResult(); and override onActivityResult() callback.
Third, but most important. Why do you want to call a new activity just to show 'No Network' message? And what if network won't be re-established? Just create isNetworkEnabled() method and call it when user attempts to get data from the Internet, before sending actual request to server. If no network - notify a user with an alert or toast.
I suggest you use fragments instead of activities first of all.
Using fragments you can set retainInstance(true);
To disable coming back from an activity to the previous :
1)call finish() on that activity
2)
Intent i = new Intent();
i.setClass(this, MyActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);`
It works with an explicit Intent.
In LoginActivity substitute:
noNetwork.putExtra(NoNetworkActivity.EXTRA_FAILED_INTENT, getIntent());
with:
noNetwork.putExtra(NoNetworkActivity.EXTRA_FAILED_INTENT, new Intent(this, LoginActivity.class));
Btw, Alexander Zhak has some good points in his answer

How to Clear the activity stack SDK < 11

I need to clear the activity stack. All the activity except the current one in SDK 8. I want after logout from any activity I can reach to the Login Activity and All previous Activity will get Removed from the activity stack.
I have tried this solution
Intent i = new Intent(BaseActivity.this, LoginActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
But it is not working. I can't use finish() because user can logout from any activity.
Your Help is Highly appreciable.
Just use this flag on its own Intent. FLAG_ACTIVITY_CLEAR_TASK
Use This
Normally when we launch new activity, it’s previous activities will be kept in a queue like a stack of activities. So if you want to kill all the previous activities, just follow these methods
Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);
I have got two Beautiful solution of my problem.
SOLUTION 1:
One is by using Broadcast Receiver. That I can broadcast a message to all my activity and onRecive() I can finish all my activity. As this Link says.
SOLUTION 2 (A Much Easier way):
Second is by managing a flag in ShearedPrefrences or in Application Activity. In starting of app (on splash screen) set the flag = false; OnLogout click event, just set the flag true and in OnResume() of every activity check if flag is true then call finish().
It works like a charm :) And please If you can't answer at least don't abuse the question.

Returning to the Home Screen and then returning to last activity

Having real issue understanding how to sort my issue out.
On the Home screen I have 2 buttons
When the user clicks the first button it starts a new Activity. What I am looking for is if the user clicks back the app returns to the home screen. If the user clicks the first button again it starts a new activity.
If the user clicks the second button it returns to the activity that was last started by clicking button 1
What I am having issue with is how to save the state of the activity when the user clicks back
Also how to call that activity when the second button is pressed
Thanks for your Time
UPDATE
I have gone down part of this but still having issues. If I put some of the code I am using perhaps someone can point where I gone wrong.
Code for calling the new activity from main menu
Intent intent = new Intent(MainMenu.this, NewClass.class);
intent.putExtra("value1", value1);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Within the new class I have added the following :
#Override
public void onBackPressed() {
//super.onBackPressed();
Intent intent = new Intent(RoundScoring.this, MainMenu.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
Toast.makeText(this, "Back Button Pressed", Toast.LENGTH_LONG).show();
}
I do not have either a onrestoreinstancestate or onresumne in this class. only a oncreate. Do I have to add something like this to bring back the instance
On the second button on the main menu I have added this
Intent intentContiune = new Intent(MainMenu.this, NewClass.class);
intentContiune.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intentContiune);
Thanks
Try this:
Home Screen Left Button:
Open the new activity with an intent flag, FLAG_ACTIVITY_NEW_TASK
Activity:
Override onBackClick() on the started activity to call the home screen with an Intent instead of finishing it. Use the flag FLAG_ACTIVITY_REORDER_TO_FRONT
Save activity state overriding OnSaveInstanceState
Home Screen Right Button:
Call the activity with the flag FLAG_ACTIVITY_SINGLE_TOP
More info about flags:
http://blog.akquinet.de/2010/04/15/android-activites-and-tasks-series-intent-flags/
One solution may involve passing bundles around that include the state of your activity. Using startActivityForResult(), you can return a bundle with the activity's state. When the user clicks your second button, pass in that bundle and have the activity set itself up with respect to the contents of the bundle. If the bundle doesn't contain the information you're looking for, then use the default values as if you were just starting it.
For more information:
Android: Capturing the return of an activity

Removing an activity from the history stack

My app shows a signup activity the first time the user runs the app, looks like:
ActivitySplashScreen (welcome to game, sign up for an account?)
ActivitySplashScreenSignUp (great, fill in this info)
ActivityGameMain (main game screen)
so the activities launch each other in exactly that order, when the user clicks through a button on each screen.
When the user goes from activity #2 to #3, is it possible to wipe #1 and #2 off the history stack completely? I'd like it so that if the user is at #3, and hits the back button, they just go to the homescreen, instead of back to the splash screen.
I think I can accomplish this with tasks (ie. start a new task on #3) but wanted to see if there was simpler method,
Thanks
You can achieve this by setting the android:noHistory attribute to "true" in the relevant <activity> entries in your AndroidManifest.xml file. For example:
<activity
android:name=".AnyActivity"
android:noHistory="true" />
You can use forwarding to remove the previous activity from the activity stack while launching the next one. There's an example of this in the APIDemos, but basically all you're doing is calling finish() immediately after calling startActivity().
Yes, have a look at Intent.FLAG_ACTIVITY_NO_HISTORY.
This is likely not the ideal way to do it. If someone has a better way, I will be looking forward to implementing it. Here's how I accomplished this specific task with pre-version-11 sdk.
in each class you want to go away when it's clear time, you need to do this:
... interesting code stuff ...
Intent i = new Intent(MyActivityThatNeedsToGo.this, NextActivity.class);
startActivityForResult(i, 0);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == R.string.unwind_stack_result_id) {
this.setResult(R.string.unwind_stack_result_id);
this.finish();
}
}
then the one that needs to set off the chain of pops from the stack needs to just call this when you want to initiate it:
NextActivity.this.setResult(R.string.unwind_stack_result_id);
NextActivity.this.finish();
Then the activities aren't on the stack!
Remember folks, that you can start an activity, and then begin cleaning up behind it, execution does not follow a single (the ui) thread.
One way that works pre API 11 is to start ActivityGameMain first, then in the onCreate of that Activity start your ActivitySplashScreen activity. The ActivityGameMain won't appear as you call startActivity too soon for the splash.
Then you can clear the stack when starting ActivityGameMain by setting these flags on the Intent:
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
You also must add this to ActivitySplashScreen:
#Override
public void onBackPressed() {
moveTaskToBack(true);
}
So that pressing back on that activity doesn't go back to your ActivityGameMain.
I assume you don't want the splash screen to be gone back to either, to achieve this I suggest setting it to noHistory in your AndroidManifest.xml. Then put the goBackPressed code in your ActivitySplashScreenSignUp class instead.
However I have found a few ways to break this. Start another app from a notification while ActivitySplashScreenSignUp is shown and the back history is not reset.
The only real way around this is in API 11:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
I use this way.
Intent i = new Intent(MyOldActivity.this, MyNewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);
I know I'm late on this (it's been two years since the question was asked) but I accomplished this by intercepting the back button press. Rather than checking for specific activities, I just look at the count and if it's less than 3 it simply sends the app to the back (pausing the app and returning the user to whatever was running before launch). I check for less than three because I only have one intro screen. Also, I check the count because my app allows the user to navigate back to the home screen through the menu, so this allows them to back up through other screens like normal if there are activities other than the intro screen on the stack.
//We want the home screen to behave like the bottom of the activity stack so we do not return to the initial screen
//unless the application has been killed. Users can toggle the session mode with a menu item at all other times.
#Override
public void onBackPressed() {
//Check the activity stack and see if it's more than two deep (initial screen and home screen)
//If it's more than two deep, then let the app proccess the press
ActivityManager am = (ActivityManager)this.getSystemService(Activity.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(3); //3 because we have to give it something. This is an arbitrary number
int activityCount = tasks.get(0).numActivities;
if (activityCount < 3)
{
moveTaskToBack(true);
}
else
{
super.onBackPressed();
}
}
In the manifest you can add:
android:noHistory="true"
<activity
android:name=".ActivityName"
android:noHistory="true" />
You can also call
finish()
immediately after calling startActivity(..)
Just set noHistory="true" in Manifest file.
It makes activity being removed from the backstack.
It is crazy that no one has mentioned this elegant solution. This should be the accepted answer.
SplashActivity -> AuthActivity -> DashActivity
if (!sessionManager.isLoggedIn()) {
Intent intent = new Intent(context, AuthActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
context.startActivity(intent);
finish();
} else {
Intent intent = new Intent(context, DashActivity.class);
context.startActivity(intent);
finish();
}
The key here is to use intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); for the intermediary Activity. Once that middle link is broken, the DashActivity will the first and last in the stack.
android:noHistory="true" is a bad solution, as it causes problems when relying on the Activity as a callback e.g onActivityResult. This is the recommended solution and should be accepted.
It's too late but hope it helps. Most of the answers are not pointing into the right direction. There are two simple flags for such thing.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
From Android docs:
public static final int FLAG_ACTIVITY_CLEAR_TASK
Added in API level 11
If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the
activity to be cleared before the activity is started. That is, the
activity becomes the new root of an otherwise empty task, and any old
activities are finished. This can only be used in conjunction with
FLAG_ACTIVITY_NEW_TASK.
Just call this.finish() before startActivity(intent) like this-
Intent intent = new Intent(ActivityOne.this, ActivityTwo.class);
this.finish();
startActivity(intent);
Removing a activity from a History is done By setting the flag before the activity You Don't want
A->B->C->D
Suppose A,B,C and D are 4 Activities if you want to clear B and C then
set flag
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
In the activity A and B
Here is the code bit
Intent intent = new Intent(this,Activity_B.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
super.finishAndRemoveTask();
}
else {
super.finish();
}
Here I have listed few ways to accomplish this task:
Go to the manifest.xml- and put android:noHistory="true", to remove the activity from the stack.
While switching from present activity to some other activity, in intent set flag as (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK). It is demonstrated in the example below.
Intent intent = new Intent(CurrentActivity.this, HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(intent);here
Note :Putting the intent flags can cause blank screen for sometime (while switching activity).
Try this:
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)
it is API Level 1, check the link.

Categories

Resources