Android Intent flags - android

My problem is in understanding how to correctly use intents. After googling and reading all the documentations and articles on this topic, I still cannot sort out my problem. I have two activities: "Searchable" and "ActivityWordInfo". The "Searchable" activity searches a word in the database, and displays search results or suggestions. After the user cliks one of the search results, "ActivityWordInfo" activity is launched and diplays the word definition. Here is some part of the code:
Searchable:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Get the intent, verify the action and get the query
if( savedInstanceState != null ){
//the application is being reloaded
query = savedInstanceState.getString("searchedWord");
doMySearch(query); //does the search in the database
}else{
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
query = intent.getStringExtra(SearchManager.QUERY);
doMySearch(query);
}
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("searchedWord", query);
//saves the searched word if this activity is killed
}
#Override
public void onClick(View v) { //when one of the search results is clicked
int wordID = (Integer) v.getTag();
Intent intent = new Intent(Searchable.this, ActivityWordInfo.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
Bundle b = new Bundle();
b.putInt("key", wordID);
b.putInt("calling_activity", callingActivityId);
intent.putExtras(b);
startActivity(intent);
}
ActivityWordInfo:
public void onCreate(Bundle savedInstanceState) {
...
Bundle b = getIntent().getExtras();
current_word_id = b.getInt("key", 0);
callingActivityId = b.getInt("calling_activity", 0);
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
switch(callingActivityId){
case 3: //which is the ID of Searchable activity
Intent intent3 = new Intent(ActivityWordInfo.this, Searchable.class);
intent3.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent3);
break;
}
break;
}
When the user is in ActivityWordInfo and navigates up, I expect to go to Searchable activity, which should have saved its instance state (the list of results should be still there). What in reality happens:
-The word typed by the user is assigned to 'query' variable and then the results and suggestions are displayed in "Searchable"
-the user clicks one of the words and "ActivityWordInfo" is created
-then, when the user navigates up, the onSaveInstanceState is called for the "Searchable" activity, then it is destryed and created. The result is an empty layout :(
I cannot understand why "Searchable" is destroyed and then created! This only happens in Android 4.2 and not in lower APIs (in 2.3.3 worked perfectly as I expected). Is there any difference in the activity lifecycle in JellyBean?
Note: I cannot use the parentActivity attribute in the manifest since the ActivityWordInfo is called by multiple parents.

The behavior of "up" navigation changed between 2.3 and 4.0. I suggest you look at the topic "Tasks and Back Stack" at developer.android.com.

Related

getSerializableExtra() is null randomly

There is a link in one activity, after I click on it it opens another activity. I add an enum parameter for the second activity.
#Override
protected void onCreate(Bundle savedInstanceState) {
binding.myLink.setOnClickListener(new View.OnClickListener() {
// ...
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivityContext(), SecondActivity.class);
intent.putExtra(KEY, MyEnum.ENUM_VALUE);
startActivity(intent);
}
});
// ...
}
In onCreate of second activity I read this parameter
#Override
protected void onCreate(Bundle savedInstanceState) {
// ...
// get value
FirstActivity.MyEnum value = (FirstActivity.MyEnum ) getIntent()
.getSerializableExtra(AboutActivity.KEY);
// ...
}
Everything works but in Crashlytics I see that for some users value is null. Second activity is called only from first one and from nowhere else.
Can someone suggest me the scenario with this behavior? When can it happen like this?
I opened my app, opened the second activity and put app to background. After several hours I opened my app from the list of apps and everything is ok. No more ideas when it can happen.
use this :
#Override
public void onClick(View view) {
Intent intent = new Intent(getActivityContext(), SecondActivity.class);
Bundle bundle=new Bundle();
bundle.putSerializable(serializableKEY,yourSerializableClass);
intent.putExtras(KEY, bundle);
startActivity(intent);
}
});
and in second activity :
Bundle bundle=getIntent().getExtras();
yourSerializableClass clazz=(yourSerializableClass)bundle.getSerializable(serializableKEY);

Android Java - Passing data between intents but need to save it on main activity

I have an app that for right now, consists of 2 buttons (will later consists of 20+). When I click on a button, it takes me to a new activity that has a list of items I can select. After selecting something and clicking the Back button, it starts a new activity that passes on the item's information (in this case, "orange") and then it assigns the word "orange" to the button that was clicked.
Now when I click on the other button to assign it's information, I lose all of my first button information. What are my options for saving the previous information? Would I have to create an intent for it and keep passing it back and forth between actvities?
At the end, I need to collect all the information that was assigned to both buttons and pass that onto another activity, as this is just the customizing page. Is there a way I can just have the Strings set such that leaving the activity won't delete the String information?
Here's my MainActivity
Bundle extras = getIntent().getExtras();
if (extras != null) {
btnValue = extras.getString("btnValue");
itemValue = extras.getString("itemValue");
}
if (btnValue.equals("btn1")){
btn1.setText(itemValue);
} else if (btnValue.equals("btn2")) {
btn2.setText(itemValue);
}
}
public void onClickBtn1(View v) {
Intent myIntent = new Intent(this, Main2Activity.class);
myIntent.putExtra("btn", "btn1");
startActivity(myIntent);
}
public void onClickBtn2(View v) {
Intent myIntent = new Intent(this, Main2Activity.class);
myIntent.putExtra("btn", "btn2");
startActivity(myIntent);
}
and my 2nd activity
Bundle extras = getIntent().getExtras();
if (extras != null) {
btnValue = extras.getString("btn");
}
listView = (ListView) findViewById(R.id.list);
String[] values = new String[] { "apple", "banana", "orange", "cherry"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
itemPosition = position;
itemPositionString = String.valueOf(itemPosition);
}
});
}
public void onClickBack (View v) {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("btnValue", btnValue);
intent.putExtra("itemValue", itemValue);
startActivity(intent);
}
You can use the Android lifecycle to manage the activity's state.
To save the activity state you need to do your work on the method onSaveInstanceState.
onSaveInstanceState(Bundle bundle)
On restoration you either check the bundle the following methods
onRestoreInstanceState(Bundle bundle)
onCreate(Bundle bundle)
You can find more details here:
https://developer.android.com/training/basics/activity-lifecycle/recreating.html
When you use startActivity it creates new activity. So you lose old information. You need to use startActivityForResult from MainActivity while starting second activity and from the second activity you should use setResult
Intent returnIntent = new Intent();
returnIntent.putExtra("result",result);
setResult(RESULT_OK, returnIntent);
finish();
And you handle the result in MainActivity with
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
..
..
}
Here, there is an example How to manage `startActivityForResult` on Android?
You basically have 3 choices:
Pass all data in the Intent and return any new/changed data in another Intent using startActivityForResult().
Save the data in a static variable somewhere (globals). All activities can then reference the current data and make changes to it that are then seen by all other activities. This is the quick-and-dirty solution which is suitable for small, trivial or "homework" solutions.
Save the data in a persistent storage (a file or an SQLite database). All activities can read all the current data, display it and make changes. After the BACK button is pressed, the underlying Activity should read the current data from the persistent storage to refresh the views.

calling the same activity using a for

Hi everyone.
I'm new in android and I'm working on an app in which I need to recall the same activity to enter the information of a variable amount of entities (passengers).
I have the following:
btnContinue3.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
for (int i=0; i<Pssngr; i++){
passenger[i] = new
Intent(getApplicationContext(), Pasajeros.class);
startActivity(passenger[i]);
}
}
});
Pssngr is the amount of passsengers or entites that need a unique activity to get their information entered.
The trigger is the button then the activities will be called one by one following an array
I try this code but after clicking on the button the app crashed.
Please someone help me find a way to make this work.
thanks
It crashes because You are trying to start x number of Activities at once.
If You have to run new Activity for each of Passengers best in this scenario will be startActivityForResult
I beliver effect You trying to get is that user clicks on button just once and activities for each passenger will open one after another.
To do it in method onClick You will start only first activity, don't use loop.
You start consequently next activities in onActivitiyResult
In addition to what Gustek mentions above, a better way to approach this would be to have one activity and just pass the different values from the parent (PassengersAvitivty) activity through the intent as below:
final Intent intent = new Intent(PassengersAcitivty.this, PassengersEntityActivity.class);
intent.putExtra("PASSENGER_FIRSTNAME", passenger[i].getName());
intent.putExtra("PASSENGER_LASTNAME", passenger[i].getLastName());
intent.putExtra("PASSENGER_EMAIL", passenger[i].getEmail());
startActivity(intent);
and here is how you can retrieve them on your activity (PassengerEntityActivity)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
if (extras != null)
{
firstname = extras.getString("PASSENGER_FIRSTNAME");
lastname = extras.getString("PASSENGER_LASTNAME");
email = extras.getString("PASSENGER_EMAIL");
}
else
{
//Log.v("NO VALUE", "OOPS");
}
I can clarify further if needed.

How to getValue the data on setActivityForresult

This is what i want to do. When a user starts the game, he is taken to a dashboard screen with several categories that he is suppossed to choose from. On clicking any of the categories one is lead to to the a single activity where i need to know how to find which category button was choosen in the ActivityB.
So, in the DashboardActivity, i have this code:
public void onGeneralKnowledgeClick(View v) {
createIntent("GENERAL_KNOWLEDGE", 1);
}
........
........
........
public void onCelebritiesClick(View v) {
createIntent("CELEBRITIES", 6);
}
private void createIntent(String category, int result) {
Bundle bundle = new Bundle();
bundle.putInt(category, result);
Intent intent = new Intent(this.getApplicationContext(),
QuestionActivity.class);
intent.putExtras(bundle);
startActivityForResult(intent, 0);
}
Now, in my QuestionActivity class, i have a method that tries to get the categoryNumber associated with the intent that was started. So, i have something like this:
private int getCategory() {
Bundle bundle = this.getIntent().getExtras();
int categ = bundle.getInt("GENERAL_KNOWLEDGE");
return categ;
}
My problem is that, how do i return the integer category such and not hardcording as i did up here. I want this method to return a the integer from the respective bundle. my idea is to have a switch statement inside the getCategory but i don't know what case value to use. Also, i saw someone saying that onActivityResult can be used but i don't see how.
Please help!
I believe you're a bit confused. You merely need to do:
bundle.putInt("CATEGORY", result); //where result == the categoryId and "CATEGORY" is always "CATEGORY"
Then in your getCategory():
int categ = bundle.getInt("CATEGORY") //you'll get the int value that you fed before
Unless I misunderstood.

Saving view values while switching between activities in android

I'm working on a tabbed application in android. In the first tab I've a search engine with textviews, spinners.. and if I filled these params and switch to other tab or to the search results activity, and I return back to this tab (search engine tab) I found that all the fields are reinitialized. But I want to keep their value in order to remember what I searched for..
Is there a way to keep my data when I switch between activities ?
Thanks for your help.
You can override onSaveInstanceState (which will be called before you transition to a new activity) and onRestoreInstanceState (which will be called before your activity is resumed) e.g. :
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putBoolean("MyBoolean", true);
savedInstanceState.putDouble("myDouble", 1.9);
savedInstanceState.putInt("MyInt", 1);
savedInstanceState.putString("MyString", "Welcome back to Android");
// etc.
super.onSaveInstanceState(savedInstanceState);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
double myDouble = savedInstanceState.getDouble("myDouble");
int myInt = savedInstanceState.getInt("MyInt");
String myString = savedInstanceState.getString("MyString");
}
I guess you are creating intent object to initiate your tab's activity with addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP). Just remove this function if you have done something like this. For example , create intent object like below,
Intent intent = new Intent(this, tabActivity.class);
Not like this,
Intent intent = new Intent(this, tabActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
If you do so , your will get the exact state of a tab as u left it before switching to another tab.

Categories

Resources