setResult works MOST of the time - android

I've worked with setResult(RESULT_OK, intent) for a while now, and am experiencing something strange.
MOST of the time, about 3/4 of the time that I enter an activity then exit from it using the following code which is ALWAYS executed:
Intent intent = new Intent();
intent.putExtra(KEY_ENVIRONMENT_SURVEY, esurvey);
setResult(RESULT_OK, intent);
finish();
In the activity being returned to, most of the time, RESULT_OK is returned, but sometimes RESULT_CANCELLED is returned, seemingly quite randomly. What could be causing this? Could finish() be called before the esurvey is attached (it's parcelable) and the default is RESULT_CANCELLED? If so how can I fix this? Use a handler and use postDelayed or check to see if RESULT_OK was set (I don't know how to do this, so please specify if that's the solution)?
Thanks!

Try to move this code into overridden finish() method. This will ensure it's called every time activity is finished.
#Override
public void finish() {
Intent intent = new Intent();
intent.putExtra(KEY_ENVIRONMENT_SURVEY, esurvey);
setResult(RESULT_OK, intent);
super.finish();
}

I'm revisiting this because I found the glitch in my application. The "back" button was very close to a button I had designated as moving to the next activity. I was allowing button presses to be registered after the first one, so sometimes the activity would seem to have completed by touching the "done" button, but was actually being navigated back to by the "back" button.
I fixed this using a boolean flag, checking to see if it was true upon a butotn press, and then setting it to true if it equaled false.

Related

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

Android Start Activity for Result returns different resultCode

There are a lot of questions out there on similar topics, but after searching around I haven't found one that matches my issue.
I know about starting intents for result, and overriding onActivityResult() to handle these intents, but for some reason, I'm having issues when I'm coming back from activity b to activity a. So, for example, in the last of 3 activities (AddDirections class) I start in my project, I call this method to return back to the previous activity:
public void finish(View v){
Intent intent = new Intent(getApplicationContext(), AddIngredients.class);
intent.putExtra(Home.RECIPE_INTENT, (Parcelable)recipe);
intent.putExtra(Home.RECIPE_ID_INTENT, recipe.getId());
setResult(RESULT_OK, intent);
finish();
}
In the AddIngredients class, I have this method:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK && requestCode == DIRECTIONS_REQUEST){
Intent intent = new Intent(getApplicationContext(), NameRecipe.class);
Recipe recipe = data.getParcelableExtra(Home.RECIPE_INTENT);
intent.putExtra(Home.RECIPE_INTENT, (Parcelable)recipe);
setResult(RESULT_OK, intent);
finish();
}
}
This should accept the returned result from the AddDirections class, and pass it off to NameRecipe, where I have the exact same method (Except for in the new Intent method it says Home.class). In the Home class, I have basically the same method again to receive the intent as it backs all the way out of the app.
Now, I will say that this works if I go straight through the steps from beginning to end. But if I use the up navigation to go the current activity's parent activity, then it messes everything up. Then when I click finish in the final step it messes up the resultCodes that I set for each intent. I make sure to explicitly set the correct result to RESULT_OK (which equals 1) but then for some reason, sometimes it changes what I've set to be the resultCode to be 0 instead.
Here's what I do in an activity if the user clicks the up navigation:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent intent = NavUtils.getParentActivityIntent(this);
intent.putExtra(Home.RECIPE_INTENT, (Parcelable)recipe);
setResult(RESULT_OK, intent);
NavUtils.navigateUpTo(this, intent);
finish(); //Have tried with and without this
return true;
}
return super.onOptionsItemSelected(item);
}
Like I said, I've searched for a lot of reasons why the resultCode gets overwritten after using the up navigation, but I haven't found a single reason why.
Any help would be greatly appreciated.
It looks like the underlying question is really how do I navigate between multiple activities through the stack using the up navigation that is built in. I am wondering if the project is setup correctly for this type of navigation. From the android developer resources, up navigation from google, you have to setup the navigation buttons with a parent activity. Then the application can traverse between the different activities. From what it looks like this should allow A->B B->C c->D and back to A if needed. I would also add in a button that would allow a direct path back to A if the user so chooses.
If you have more information on what you are trying to accomplish between activities whether it is data passed back and forth or just returning to the previous activity that would be helpful. Hopefully the link will help your issue with this.
your problem seems to be the NavUp, this util class tends to clear everything to navigate to the parent including your resultCode and the instance of the activity, resulting in a Canceled result (if started for result) to a new instance of the parent activity, in order to fix that a quick fix would be to declare android:launchMode="singleTop" in your manifest, but I wouldn't recommend to use that unless you are 100% that you want that, instead I would go into my navigator class, or my method for navigate and overwrite that specific navigation to something like:
Intent parentActivityIntent = NavUtils.getParentActivityIntent(this);
parentActivityIntent.setFlags(
Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP
);
NavUtils.navigateUpTo(this, parentActivityIntent);
Hope this helps!!
Sorry for the late answer :p
if by 'up navigation' you mean back key pressed then you need to override a function
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
}
if from what it seems to be you are trying to get back when clicking an item from the Options Menu to your parent activity directly then i think you will need to go back step by step as at this moment there is already an activity running and waiting for a result so when you go directly to home activity its already waiting an answer from activity B and not activity C i hope i explained it right :)

Refresh activity and re-open

This is my first post, so please be nice :)
I have a question and no one gave the answer in the post I've seen.
My app has a list and a button to open an activity, this activity creates a new item to show in the list of the previous activity when pressing the button Create.
How can I do this?
This is the code I made for the first button:
intent = new Intent(this.getBaseContext(), NewTestActivity.class);
this.finish();
startActivity(intent);
and this is the code to go back an refresh:
Intent intent = new Intent(getBaseContext(), TestListActivity.class);
startActivity(intent);
But the code to goback is useful, because the activity don't refresh.
I have to call the new activity in a diferent way? Or go back to previus activity in a diferent way? Or go back normally and refresh the activity when I'm back in the previus activity?
Well...this is all.
Sorry for my bad english and, if this question has been answered in another thread, give me the link to read, because I can't find it :)
PS: I started with android in December.
Thanks for your help.
When you are going to start new activity you shouldn't close a current one until you actually need this behaviour. (remove this.finish(); row from your code)
Also you shouldn't close an active activity manually until you actually need it. When the user presses the "back" button on the device Android pops the previous activity from the "back stack". Read once more Activity documentation.
According to your description you have a list of elements. So in order to refresh the list you need to update your dataset and notify the list about it by ListView.notifyDataSetChanged() method call.
Before getting to a real answer, I'd like to show some improvements to your code.
First, when creating an Intent (or when you need a context in general) from an Activity there is no need to call getBaseContext(), you can just use this:
intent = new Intent(this, NewTestActivity.class);
Second, android is good at handling Activities, you do not have to close your first activity manually with finish(). Android will automatically pause or stop your first activity and bring it back when you return to it.
Third, in your case you might want to use startActivityForResult() instead of startActivity() for reasons I will explain below.
This will make your code look like the following:
private static final int MY_REQUEST_CODE = 33487689; //put this at the top of your Activity-class, with any unique value.
intent = new Intent(this, NewTestActivity.class);
startActivityForResult(intent, MY_REQUEST_CODE);
Now, the startActivityForResult() starts an activity and waits for a result from that new Activity. When you call finsih() in the new Activity you will end up in the first Activitys onActivityResult()-method, with data supplied from the new Activty that is now closed:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode != MY_REQUEST_CODE) return; //We got a result from another request, so for this example we can return.
if(resultCode != RESULT_OK) return; //The user aborted the action, so we won't get any data.
//After the above if-statements we know that the activity that gives us a result was requested with the correct request code, and it's action was successful, we can begin extracting the data, which is in the data-intent:
Item item = (Item) data.getSerializableExtra("customData"); //casts the data object to the custom Item-class. This can be any class, as long as it is serializable. There are many other kinds of data that can be put into an intent, but for this example a serializable was used.
itemList.add(item); //This is the list that was specified in onCreate()
//If you use an Adapter, this is the place to call notifyDataSetChanged();
}
For this all to work, we need to do some things in the second Activity:
When the item has been created, we must set a result:
//We begin by packing our item in an Intent (the Item class is an example that is expected to implement Serializable)
Item theCreatedItem; //This is what was created in the activity
Intent data = new Intent();
data.putSerializable(theCreatedItem);
setResult(RESULT_OK, data);
finish();
This should return to the first Activitys onActivityResult()-method with the item, as explained above.

How i can close/exit button on my app?

i have a button to close my app with this code:
finish();
the problem is that this button doesn't exit of my app... it simply closes the current intent ant returns to the previous intent (window) of my app....
how i can do a real exit/close button?
i tryed with this:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
but it doesn't works, because when i turn back into my app, the app comes in the last opened window, and not in the first window of the app, how i can do that? i need that when i re-open my app it starts on the first window of my app
If you really want your app to die. You could initiate each intent with startActivityForResult(). then before each finish() set the result to send back. in each parent activity you can override onActivityResult() to test whether the result received means the application needs to end. if so you can call another set result and finish(). repeat this in all activities and you will find that your application terminates entirely.
Incidentally I'm writing this from memory. function names may not be exact.
Hope that helps.
p.s. re-read your requirements. you can always stop the finish loop at your first activity.
I would do it this way:
I would define my initial activity (i.e. MainMenu) with a Launch Mode of singleTop
I would then invoke my MainMenu from the activity that is going to close the application.
startActivity(new Intent(this, MainMenu.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP).putExtra("closeProgram", true);
Then override the onNewIntent in the MainMenu activity; check for the extra boolean of "closeProgram", if the value is true, then do a finish();
Haven't tried it but I think it should work.
I recommend you read this: http://blog.radioactiveyak.com/2010/05/when-to-include-exit-button-in-android.html
Chances are, you don't want an exit button. Perhaps a logout button, but that's it.
finish() closes activity (this is what you call intent, but it's not correct), not application. Application can not be finished at all (only forcefully killed like task killers do). You should design your activity stack in such a way that it will suit your needs. May be you should look at stack rearrangement examples in ApiDemos.
you can try this: System.exit(0);

onActivityResult doesn't work?

I am facing with a problem related startActivityForResult()
To start SecondActivity from FirstActivity :
Intent intent = new Intent();
intent.setClass(FirstActivity.this, SecondActivity.class);
intent.putExtra("key1", "12345");
startActivityForResult(intent, 0);
And handles result :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//TODO handle here.
}
To send the message to FirstActivity from SecondActivity :
in SecondActivity :
setResult(0);
I can't handle the result on onActivityResult in FirstActivity.
It never works for my application.
My OS is : 1.5
What is wrong here?
startActivityForResult is meant to be used for situations where you want to select a piece of data, or perform some sort of action that your Activity or application cannot do.
For example, you want to pick a contact, so you launch the contacts application, the user chooses the person they want, and you get sent the result. Or you want to take a photo, so you launch the camera application and ask it to send you the photo once it's done. This action is completely separate from your first activity that calls startActivityForResult.
The Activity you're launching will not send you the result until that Activity has completed, i.e. finish() has been called.
So in your case, you need to call this in SecondActivity:
setResult(...);
finish();
before FirstActivity will receive the result in its onActivityResult method. Of course, this means that SecondActivity is now gone and FirstActivity is top of the stack again.
It's not possible to send the result to FirstActivity then close it while keeping SecondActivity still active. In this case you should just handle whatever this 'result' is in SecondActivity, or send it off to a Service you define to do whatever processing it is you want.
I was stuck here for a while. Adding my problem here to make sure that you don't scratch your head as well.
The second parameter of this function has to be 0 or higher.
startActivityForResult(intent, 0); // <- this is OK
I was setting the second parameter to RESULT_OK, which is -1, and my onActivityResult callback was never getting called. So if you get stuck like me, you can also check if your second parameter is correct.
startActivityForResult(intent, RESULT_OK); // <- this is wrong
The above line will fail to call onActivityResult.
I was also stuck on the same problem - but due to a different reason as matangs. Apparently startActivityForResult only works if you have android:launchMode set to standard for main activity (in manifest). Hope it helps someone.
Your code seems ok, but do you stop your second activity ?
Try this in it :
setResult(0);
finish();
If you are doing actions on onPause (like unbinding a service) try to comment it and see if onActivityResult is called (I wasted few good hours on this..)
Thanks to #johndodo (that point to the manifiest) - I find my solution for the same problem.
removing android:noHistory=true at the manifiest" solved this problem for me.

Categories

Resources