How to keep intent for second activity? - android

I have a MainActivity with some cards which have different names. onClick, the title is passed as an intent via the adapter to the secondActivity and displayed as the header. From there, I can go to other activities. If I come back from one of these other activities (via the back button created by establishing second activity as the parent activity) the header is gone. How do I keep the header that was originally passed on as an intent or should I go about this completely different?
I have tried using onResume() and onStart() in the secondActivity to reassign the intent from a global variable.
The adapter class, where the card onClick method is written:
#Override
public void onBindViewHolder(final TripHolder tripHolder, final int position) {
Trip trip = trips.get(position);
tripHolder.setDetails(trip);
tripHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, SecondActivity.class);
TextView card_title = v.findViewById(R.id.TripNamecl);
intent.putExtra("card_title", card_title.getText().toString());
context.startActivity(intent);
}
});
}
The secondActivity where the header should be displayed:
public class SecondActivity extends AppCompatActivity {
String name;
TextView header;
static final String STATE_HEADER = "header";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
name = getIntent().getStringExtra("card_title");
header = findViewById(R.id.TripsHeader);
header.setText(name);
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString(STATE_HEADER, name);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
name = savedInstanceState.getString(STATE_HEADER);
header.setText(name);
}
public void launchMapsActivity(View view) {
Uri gmmIntentUri = Uri.parse("geo:48.8566°,2.3522");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
if (mapIntent.resolveActivity(getPackageManager()) != null) {
startActivity(mapIntent);
}
}
public void launchTravelActivity(View view) {
Intent intent = new Intent(this, TravelActivity.class);
startActivity(intent);
}
public void launchPlansActivity(View view) {
Intent intent = new Intent(this, PlansActivity.class);
startActivity(intent);
}
}
SOLUTION:
The solution was to put android:launchMode="singleTop" into the manifest file for the secondactivity. It's described in more detail here: How can I return to a parent activity correctly?

In order to do it you should override onSavedInstanceState in your SecondActivity.
You can use something like that, obv adapt it to your needs:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
//here you can save your variables
savedInstanceState.putString("myHeader", name);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//here you can retrieve your variables
name = savedInstanceState.getString("myHeader");
}
Let me know if this worked! good luck

remove header.setText(name); from onResume and onStart methods

If you want to save data in first activity between lifecicle method calls you have to save your data in Bundle object.
Override method onSaveInstanceState(Bundle bundle) of your activity:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("AStringKey", variableData);
outState.putString("AStringKey2", variableData2);
}
And also override Activity method onRestoreInstanceState(Bundle savedInstanceState):
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
variableData = savedInstanceState.getInt("AStringKey");
variableData2 = savedInstanceState.getString("AStringKey2");
setYourHeaderMethodExample(variableData2)
}

When coming back from third activity to second activity onStart() and onResume() method call executes. Try not using onStart() and onResume() for setting the header and use onCreate method for setting the header.
onCreate() method executes only once in its lifetime, but onStart() and onResume() will execute whenever the activity comes to screen. So when coming back from third activity we don't have any values in the intent.

In your second activity's onCreate method add:
getSupportActionBar().setHomeButtonEnabled(true);
and override the onOptionsItemSelected() method in the class and add the following code:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
You don't need to override the onStart() and onResume() methods.

Related

how to define callback for my program in android Studio?

I want to define callback for a Notebook program that way after note saved in EditActivity,in Main Activity Update list of notes,But This does not happen.
EditActivity:
public interface OnClickDoneListener{
void onClickDone();
}
public void setOnClickDoneListener(OnClickDoneListener onClickDoneListener){
this.onClickDoneListener=onClickDoneListener;
}
btnDone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (extras != null) {
myDatabase.updateRow(id, txtTitle.getText().toString(), txtDesc.getText().toString());
NoteModel noteModel = new NoteModel();
noteModel.setTitle(txtTitle.getText().toString());
noteModel.setDesc(txtDesc.getText().toString());
Intent intent = new Intent(EditActivity.this, MainActivity.class);
startActivity(intent);
onClickDoneListener.onClickDone();
} else {
Done();
}
}
});
Main Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setupViews();
getDataFromDB();
recyclerView.setAdapter(new NoteAdapter(MainActivity.this,dataList));
noteAdapter = new NoteAdapter(MainActivity.this,dataList);
recyclerView.setAdapter(noteAdapter);
fabAdd = (FloatingActionButton)findViewById(R.id.fab_main_add) ;
EditActivity editActivity = new EditActivity();
editActivity.setOnClickDoneListener(new EditActivity.OnClickDoneListener() {
#Override
public void onClickDone() {
noteAdapter.notifyDataSetChanged();
}
});
please help me.
My English is poor,sorry for it.
You want your data to be updated when the MainActivity is shown, right ?
You just have to call your getDataFromDB part in onResume() instead of onCreate()
EditActivity editActivity = new EditActivity();
editActivity.setOnClickDoneListener(new EditActivity.OnClickDoneListener() {
#Override
public void onClickDone() {
noteAdapter.notifyDataSetChanged();
}
});
What you are doing here is setting the value of OnClickDoneListener in a new instance of EditActivity that you will never use. Because when you use new Intent(MainActivity.this, EditActivity.class) to start the EditActivity it will create a new instance of EditActivity and your interface would be null.
I suggest you use android's Broadcast Receiver instead of a callback in this case. All you have to do is:
In MainActivity: You will need to instantiate a broadcast receiver. You need to register it onCreate or onStart and unregister it onStop or onDestory.
In EditAcitivity: You send a broadcast whenever you want to notify your MainActivity to update the list.
Check out this example:
https://riptutorial.com/android/example/18305/communicate-two-activities-through-custom-broadcast-receiver

Put And Get Extras From Another Class

I have Act_01 (where I put value) and Act_02 (where I get value) but have declared these methods in a Extras class, getting value from Act_02 returns null value:
Act_01: (Where I want to pass the value Name to Act_02)
public class Act_01 extends Activity {
Extras cc_Extras;
Button btn1;
Intent intent;
String str_Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_01);
cc_Extras = new Extras();
str_Name = "Buck";
btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
cc_Extras.putExtras();
startActivity(intent);
}
});
}
}
Act_02: (Where I want ot receive value Name from Act_01 but the app crashes with null value)
public class Act_02 extends Activity {
Extras cc_Extras;
String str_Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_02);
cc_Extras = new Extras();
if(getIntent() != null && getIntent().getExtras() != null)
{
cc_Extras.getExtras();
}
Toast.makeText(getApplicationContext(), "Name: "+str_Name, Toast.LENGTH_SHORT).show();
}
}
Extras: (Where I define the methods to put and get Extras)
public class Extras extends Activity {
String str_Name;
Intent intent;
public void putExtras() {
// TODO Auto-generated method stub
intent.putExtra("KEY_Name", str_Name);
}
public void getExtras() {
// TODO Auto-generated method stub
str_Name = getIntent().getExtras().getString("KEY_Name");
}
}
EDIT: I do not want to pass and get data directly between activities, I want to use the 3rd class (Extras.java) because I have too many activities having too many values between each other and want to sort of define them globally in Extras so that all my other activities can just call one method instead of getting and putting too many values in my activities.
Your app crashes not with a null value, but a null pointer reference because you created a new Activity manually
cc_Extras = new Extras();
Then called a lifecycle method on it
cc_Extras.getExtras()
Which calls getIntent(), but the Intent was never setup by the Android framework, and cc_Extras.getExtras() wouldn't have any of the data you wanted anyway in the second Activity because it was just created there, not from the first Activity.
Briefly, you should never make a new Activity, and your Extras class does not need to be an Activity in the first place (nor does it provide much benefit).
Just use the Intent object provided by the first Activity to start the second Activity, and get extras like normal. Don't overcomplicate your code. Regarding the title of the question, Intent and Bundle are already "another class" designed by Android for you to transfer data.
On both activities you are creating a new instances of Extras class means they dont hold the same value you can do this to transfer data from A to B
public class Act_01 extends Activity {
Button btn1;
Intent intent;
String str_Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_01);
str_Name = "Buck";
btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
intent = new Intent(Act_01.this, Act_02.class);
intent.putExtra("data", str_Name)
startActivity(intent);
}
});
}
}
And receieve data like this
public class Act_02 extends Activity {
String str_Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_02);
// cc_Extras = new Extras();
if(getIntent() != null)
{
if (getIntent().getStringExtra("data") != null) {
Toast.makeText(Act_02.this, "Name: "+getIntent.getStringExtra("data"), Toast.LENGTH_SHORT).show();
}
}
}
}
Also you should consider using Activity Context instead of the application context
Ok! so here are the few things I might wanna suggest you to correct.
Changes needs to be done in the code.
You are not assigning anything to "intent" object , and you have passed a intent without assigning anything to it.
Your instance cc_Extra isn't doing anything in the activity1. You might wanna pass the "intent" object in your constructor of class like cc_Extras= new Extras(intent); and in the Extras class do the following- Intent intent;
Extras(Intent i)
{
this.intent=i;
}
In the activity2 you are creating the new Instance of Extras(). So according to your code it is going to be NULL by default. If you have done the changes from the previous step, you can create new instance by doing cc_Extras(getIntent());
Corrections in the code
1) In Extras class getExtras() method instead of str=getIntent() use str=intent.getExtras.getString().
2) In the activity2 you are not assigning anything to your String str_Name, so you need to return the string you got in getExtras() method. You can do it by changing the return type to String. Below is the sample code.
public String getExtras()
{
str_Name=intent.getExtras().getString("KEY_Name");
//OR
//str_Name=intent.getStringExtra("KEY_Name");
return str_Name;
}
3) By the doing this you need to catch this string in the activity2 by doing `
if(getIntent() != null && getIntent().getExtras() != null)
{
str_Name=cc_Extras.getExtras();
}`
4) Another thing is you must create intent like this-
Intent intent=new Intent(currentActivityName.this,anotherActivity2.class);
//then use the intent object
EDIT- Your code must look like this in the end...
Act1
public class Act_01 extends Activity {
Extras cc_Extras=null;
Button btn1;
String str_Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_01);
str_Name = "Buck";
btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//changes to do
Intent intent= new Intent(Act01.this,Act02.class);
cc_Extras= new Extras(intent);
cc_Extras.putExtras(str_Name);
//end
startActivity(intent);
}
});
}
}
Act02
public class Act_02 extends Activity {
Extras cc_Extras;
String str_Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_02);
cc_Extras = new Extras(getIntent());
if(getIntent() != null && getIntent().getExtras() != null)
{
str_Name=cc_Extras.getExtras();
}
Toast.makeText(getApplicationContext(), "Name: "+str_Name, Toast.LENGTH_SHORT).show();
}
}
Extras class
public class Extras { //remove "extends Activity" because it is a class not a activity
String str_Name;
Intent intent;
Extras(Intent i)
{
this.intent=i;
}
public void putExtras(String str) {
// TODO Auto-generated method stub
str_Name=str;
intent.putExtra("KEY_Name", str_Name);
}
public String getExtras() {
// TODO Auto-generated method stub
str_Name = intent.getExtras().getString("KEY_Name");
return str_Name;
}
}
Above code will work just on String. You can extend the functionality if you want.
I hope this must work to get your code working!

How to close PereferenceActivity

i'm trying to close the preference activity after i click the back button..but when i press it then click the multi tasking button i see two activities opened for my app the one i'm currently on and the preferenceActvivty which i was on before i pressed back
this is my code
public class List extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new SetFrag()).commit();
}
public static class SetFrag extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings_main);
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
List.this.finish ();
}
Thanks for help.
I got the solution, Usually we need to code before super.onBackPressed() to be called.
So change your code in to this
public class List extends PreferenceActivity {
// do some stuff
#Override
public void onBackPressed() {
List.this.finish ();
}
Edit :
So here is my final answer
paste this custom exit activity in your package
public class ExitActivity extends Activity
{
#SuppressLint("NewApi")
#Override protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if(android.os.Build.VERSION.SDK_INT >= 21)
{
finishAndRemoveTask();
}
else
{
finish();
}
}
public static void exitApplication(Context context)
{
Intent intent = new Intent(context, ExitActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
context.startActivity(intent);
}
}
add in manifest
<activity
android:name=".ExitActivity"
android:autoRemoveFromRecents="true"
android:theme="#android:style/Theme.NoDisplay" />
And call it with
#Override
public void onBackPressed() {
ExitActivity.exitApplication(getApplicationContext());
}
Good luck
Problem solved!!
step 1:In the MainActivity, add flag "FLAG_ACTIVITY_NO_HISTORY" to the Intent, then start the SettingsActivity.
step 2: Override the onBuildStartFragmentIntent() method of SettingsActivity(PreferenceActivity) for adding flag FLAG_ACTIVITY_FORWARD_RESULT,so that the activityresult can return to the MainActivity.
Like below:
#Override
public Intent onBuildStartFragmentIntent (String fragmentName,
Bundle args,
int titleRes,
int shortTitleRes)
{
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClass(this, getClass());
intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
intent.putExtra(EXTRA_SHOW_FRAGMENT_TITLE, titleRes);
intent.putExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, shortTitleRes);
intent.putExtra(EXTRA_NO_HEADERS, true);
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);//the new statement
return intent;
}

how to override onBackPressed inside an if statement?

My aim is to override the code of my onBackPressed method..
I have overridden the onBackPressed inside my activity
#Override
public void onBackPressed() {
this.finish();
}
The code below is inside onCreate(), how can i override the onBackPressed to do something like go to another intent instead,
if(mode.equals("edit")){
//onBackPressed();
}
EDIT!!
sorry for unclear question,
What i want to know is, is there a way to override the method inside to onCreate method's if statement?
Just do this:
#Override
public void onBackPressed() {
// Check your mode in onBackPressed
if(mode.equals("edit")){
// Launch the intent
Intent editIntent = new Intent(MyActivity.this, EditActivity.class);
startActivity(editIntent);
// else call to the super class method, for default behavior
}else{
super.onBackPressed();
}
}
There is nothing stopping you from making an onBackPressed call from any method in your Activity class:
public class MainActivity extends AppCompatActivity {
private int editMode = 1;
private String mode = "edit";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// This is totally legal to do
if(editMode == 1){
onBackPressed();
}
}
}
Since the method onBackPressed() is a public method You can do this:
inside onCreate(){
if(mode.equals("edit")){
onBackPressed();
}
else
Log.d("dj","something else");
}
in onBackPressed, i did this for testing:
#Override
public void onBackPressed() {
Log.d("dj", "Yeah! on back pressed");
//super.onBackPressed();
}
I think you want to perform some operation based on the calling location,
for that I think you can follow the given below method:
onCreate(){
if(Edit){
performOperation(EDIT_OPERATION);
}
if(View){
performOperation(VIEW_OPERATION);
}
}
onBackPressed(){
performOperation(BACKP_RESSED);
}
performOperation(int operationType){
/*
* do operation
*/
}
I hope this is what you want

What is wrong with this use of Application context in Android?

I abstract my model like this:first there is a class UserInfo which holds user information:
public class UserInfo extends Application{
private int userid;
public void setUserId(int id)
{
userid=id;
}
public int getUserId()
{
return userid;
}
}
Then in MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
userinfo=(UserInfo)getApplication();
userinfo.setUserId(1354);
....
Intent intent=new Intent(MainActivity.this,VoteActivity.class);
startActivity(intent);
}
public
#Override void onResume()
{
super.onResume();
TextView text=(TextView)MainActivity.this.findViewById(R.id.usernameText);
text.setText(userinfo.getUserId()+" ");
}
And in VoteActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vote);
userinfo=(UserInfo)getApplication();
Button back=(Button)findViewById(R.id.backButton);
back.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
userinfo.setUserId(-100);
Intent intent=new Intent(VoteActivity.this,MainActivity.class);
startActivity(intent);
}});
}
The result is: when MainActivity first run, userid in UserInfo is 1354 ; And when VoteActivity first run, userid in UserInfo is 1354 too.However when back to MainActivity from VoteAcitivy userid remains 1354 which should be -100.What is wrong with this use of Application context?
You're starting a new activity in your onClick method :
Intent intent=new Intent(VoteActivity.this,MainActivity.class);
startActivity(intent);
And you direct set your id in the MainActivity :
userinfo.setUserId(1354);
That's why you get (1354). You should call finish in your on click (instead of starting the MainActivity).
The activity's stack look like this : MainActivity - VoteActivity - MainActivity and I think you want it to look like this : MainActivity after pressed on your Button
#Override
public void onClick(View arg0) {
userinfo.setUserId(-100);
finish();
}});
How you do you get back for your MainActivity? Pressing the device's back button or clicking on your button? If you press the device's back button your onClickListener won't be called, so that's why id remains the same.
#Override
public void onClick(View arg0) {
userinfo.setUserId(-100);
Intent intent=new Intent(VoteActivity.this,MainActivity.class);
startActivity(intent);
}});
when you click on your back button you restart MainActivity. The MainActivity onCreate will be excuted again. Is MainActivity flagged as singleInstance?

Categories

Resources