So I have the following currently:
public void addProject(View v) {
String pn = "";
Bundle extras = new Bundle();
Intent i = new Intent(mMainContext, AddProject.class);
mMainContext.startActivity(i, extras);
if(extras.getString("projectName") != null) {
pn = extras.getString("projectName");
}
}
This is just an example, the first bit is correct though the if statement may not be but this isn't about that block.
What I have noticed is that if I place breakpoints on the new intent, start activity and then the if statement,
Android seems to skip past the startActivity and go onto the if statement.
If I then remove the if statement and run it again, it then launches the intent.
So what I've realised is that it runs to the end of the addProject block and then actually launches the intent...
Why is this? And more importantly, how I do stop it doing that?
Intended outcome is as follows:
1) user presses "Add Project" button
2) intent launched and user inputs project name and presses submit
3) calling intent then receives the p name for use later in the function.
Why is this?
startActivity() is asynchronous. When it returns, the activity is not yet started.
how I do stop it doing that?
You can't.
Intended outcome is as follows: 1) user presses "Add Project" button 2) intent launched and user inputs project name and presses submit 3) calling intent then receives the p name for use later in the function.
Having separate activities may not be the best plan for this (compared with using fragments).
If you wish to use activities, the most natural approach is:
Use startActivityForResult() instead of startActivity()
Have AddProject use setResult() to create a result Intent to deliver back to your first activity
Have your first activity override onActivityResult(), where it can receive a copy of that result Intent and get the results from it
Note that this still will all happen after addProject() returns. However, you will (eventually) get your results.
The Android documentation does not cover this very well, but this is what it has on the subject.
you must use onActivityResult for such task.
From your main Activity use: startActivityForResults(intent) in place
of startActivity();
In your AddProject Activity when user inputs project name and press the
button .
Intent i = new Intent();
i.putExtra("projectName",userInputTextFromEditText);
setResults(RESULT_OK,i)
In your MainActivity
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data){
pn = intent.getExtras.getStringExtra("projectName","");
}
this way you will find your result
Related
Consider scenario 1:
I have activity and launch another activity to do something. After 2nd activity done (action complete) - I need to update 1st activity. I understand this can be done using "launch for result"
Scenario #2:
I have service that runs on background, fetches data, etc. This also can update 1st activity. In this case activity can be live or it can be paused too.
In iOS I just use NotificationCenter and it works. How can I "register" to receive events in Activity and make sure it is updated even if activity sleeps at that moment? I was thinking about creating global flags and check them onResume, but not sure what is the proper way to handle this scenarios most proper and "loose" way?
There are two common options.
LocalBroadcastManager is provided by the compatibility library and will allow Android components in the same app to send and receive messages in the form of Intents. It's a lot like normal broadcasts.
You can also find a third party "event bus" library, which will be a little more flexible.
You are correct, you would use startActivityForResult() when starting your second activity. Then, in your first activity, override onActivityResult() which you will put logic in to receive the result from the second activity. For example:
First Activity
int REQUEST_CODE = 1;
Intent newActivityIntent = new Intent(this, SecondActivity.class);
startActivityForResult(newActivityIntent, REQUEST_CODE);
then override onActivityResult()
#Override
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
// Make sure the result is OK.
if (resultCode == RESULT_OK) {
// Make sure this result is from the corresponding request.
if (requestCode == REQUEST_CODE) {
// Extract your data from the intent.
MyData myResultData = data.getExtra("my_extra"); // Generic example.
}
}
}
In the second activity you simply gather the information needed to send back when the user is finished, and put it in the return intent.
Second Activity
Intent returnIntent = new Intent();
returnIntent.putExtra("my_extra", data);
// Now set the result.
setResult(RESULT_OK, returnIntent);
// Call finish, and the return intent is passed back.
finish();
This is probably the easiest and least complex way to achieve what you want. This way, you know the activity receiving the result will always be unpaused when it gets the result.
I have been spending lots of hours figuring the reason why top of the stack is not cleared yet.
Well I tried the following:
Intent intent = new Intent(ActionBarActivity.this, MainActivity.class);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
And it turned me to the MainActivity. Then when I try to press back button, the program does not exit, but instead it turns me to the first page of ActionBarActivity.
Let me be more specific:
In MainActivity I call ActionBarActivity. In the ActionBarActivity I have a search bar and I enter a query there and just print the value of the query.
If you think how it will work is a below:
MainActivity -> ActionBarActivity1 -> ActionBarActivity2 -> ActionBarActivity3 -> ..
In that ActionBarActivity I have also an option which brings me back to the MainActivity.
So as I said when I run application with the way above, it will bring me to the MainActivity.
Nice so far, but when I press the back button I expect it to exit, but instead it goes to ActionBarActivity1. I doubt the stack is not properly erased.
What should I do in this case. Thanks
I'm assuming you've seen this post: Android: Clear the back stack and it is not what you want
The FLAG_ACTIVITY_NEW_TASK is creating an new task stack. When you hit "back" that is the only activity in that stack, so Android goes to the previous task - which has the calling activity at the top.
If you remove that flag, then MainActivity is already in the task stack and is brought to the top. And "back" removes it and brings you back to the calling activity. So far, that is the expected Android behavior.
EDIT: Since you commented that you only have 2 activities, then one option is to "finish()" ActionBarActivity after it starts MainActivity like this:
startActivity(intentMainActivity);
finish();
To get the behavior you want with many activities or only in certain situations, you need to use SET_RESULT and finish the activities in the stack when you hit the button to go to the MainActivity. In other words, Android assumes you want to keep activities even when new ones start. But in this case you don't, so you have to tell the activity to destroy itself.
i.e. call setResult(DONE) and then use startActivityForResult and check for your "DONE" flag in the onActivityResult method.
then this:
MainActivity -> ActionBarActivity1 -> ActionBarActivity2 -> ActionBarActivity3
-> MainActivity
becomes:
MainActivity -> ActionBarActivity1 -> ActionBarActivity2 -> ActionBarActivity3
-> call "Done"
Destroy ActionBarActivity3
Destroy ActionBarActivity2
Destroy ActionBarActivity1
MainActivity remains
For example, in ActionBarActivity2:
startActivityForResult(intentActionBarActivity3, ActionBarActivity2_ID);
Then in ActionBarActivity3:
public void exitButton(View view) {
setResult(MY_DONE_FLAG);
finish();
}
And back in ActionBarActivity2:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ActionBarActivity2_ID && resultCode == MY_DONE_FLAG) {
setResult(MY_DONE_FLAG, data);
finish();
}
}
And so on with all activities that you want to "close" when that button is pressed.
try
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
finish();
insetead of
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
and you should also use it with every intent which leads you to ActionBarActivity.
i mean if you are going back to ActionBarActivity form ActionBarActivity1 then you use it with intent.
then create intent for MainActivity in your so called ActionBarActivity.
Intent intent = new Intent(ActionBarActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
Good luck !!!
I'm still quite new to android programming. I currently have a button on the home page that takes the user to a second activity. On the second activity, the user fills in two EditText boxes and clicks a button at the bottom of the page that should send information that the user entered with it. The button that returns to the main activity uses the following code:
Intent returnIntent = new Intent();
String strData = "your data";
EditText foodName = ((EditText) findViewById(R.id.foodLabel));
String foodNameString = foodName.getText().toString();
returnIntent.putExtra("data", foodNameString);
setResult(RESULT_OK, returnIntent);
finish();
Where would I put code in my main activity that should run as soon as this button is clicked? And how can I access the information I sent back? Right now it returns to the main activity but does nothing.
If you expect a result from your second activity, you need to start second activity via startActivityForResult() (not the startActivity()). In this case, once activity you launched is finished, Android will trigger onActivityResult() callback within your main activity. All the data you specified via setResult() will be passed in this callback
In fact, I am new to Android App Development. In my application, I have a couple of activities and I have provided my users with an exit option menu to be able to leave the application. But there is a problem. When they hit the Exit button, they are able to leave the application but when they enter the application for the second time, the page that they left off the last time will be launched.
Here comes my code:
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
switch (item.getItemId()) {
case 0 :
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
Toast.makeText(this, "Goodbye Dear", Toast.LENGTH_LONG).show();
break;
Android Activity has two methods onPause and onDestroy where you can do the necessary cleanup.
http://developer.android.com/reference/android/app/Activity.html
Instead of using finish(), use System.exit(0);.
You have to override onPause and/or onDestroy methods inside your activity and delete your view within these methods.
The problem in your code is that Intent.FLAG_ACTIVITY_NEW_TASK doesn't remove your current Task. Read more about it here: Task and Back Stack | Android Developers.
Try using Intent.FLAG_ACTIVITY_CLEAR_TOP. From the documentation we can see that this gives the desired behavior.
If set, and the activity being launched is already running in the
current task, then instead of launching a new instance of that
activity, all of the other activities on top of it will be closed and
this Intent will be delivered to the (now on top) old activity as a
new Intent.
Say I have 2 activities (ActivityOne and ActivityTwo). How would I call ActivityTwo from ActivityOne? Then how would I return to ActivityOne from ActivityTwo? For example, I have a listview with all the contacts on the host phone. When I tap on a contact, another activity shows information and allows editing of that contact. Then I could hit the back button, and I would go back to the exact state that ActivityOne was in before I called ActivityTwo. I was thinking an Intent object, but I am not sure. Could someone post some code?
In your first activity (AcitvityOne) you could call
Intent intent = new Intent(this, ActivityTwo.class);
startActivityForResult(intent, CODE);
Then you can override
public void onActivityResult(int reqCode, int resultCode, Intent data) {
to receive the result of this activity
In your example, it seems like you will want to pass data between Activity One and Activity Two (namely, the reference of the contact you want to edit), so you should use a Bundle with your intent in Activity One.
Intent myIntent = new Intent(this, ActivityTwo.class);
myIntent.putExtra("CONTACT", position);
this.startActivity(myIntent);
"CONTACT" is a key and position is a value (position would have been defined before, it could be whatever you want it to be, for example an integer. The way you retrieve it is slightly different based on what type it is, note the getInt() in Activity Two code below).
And in Activity Two, in onCreate()
Bundle extras = getIntent().getExtras();
if (extras != null) {
contact = extras.getInt("CONTACT");
/**Do what you want with the integer value you have retrieved**/
}
As for your other question, the back button removes the current Activity from the top of the tasks stack and therefore, you return to the previous Activity, normally in exactly the same state as you have left it.
However, if the phone is running low on memory, Android might kill off a process or Activity so it is possible in theory that your previous Activity will not show in exactly the same state as you have left it. If you have any important data, you should save it before launching Activity Two. If you just want to return to Activity One in the same state for user friendliness, then it's fine to rely on the back button.