When I click on the back button, my MainActivity reopens. Why is this happening?
I integrated navigation-drawer in my MainActivity, and after this, when I click on the back button, the MainActivity is recreated. If I click again on the back button, the application gets closed.
This is my MainActivity code:
public class BuildingsActivity extends AppCompatActivity implements BuildingsNavigator,
BuildingItemNavigator, NavigationView.OnNavigationItemSelectedListener {
private ActivityBuildingsBinding binding;
private BuildingsViewModel viewModel;
private DrawerLayout drawerLayout;
private NavigationView navigationView;
private Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_buildings);
viewModel = new BuildingsViewModel(this);
viewModel.loadBuildings();
viewModel.dataLoading.set(true);
if (!AppUtils.isOnline()) {
startForResult();
}
binding.setViewModel(viewModel);
binding.recycler.setLayoutManager(new GridLayoutManager(getApplicationContext(), 2));
binding.recycler.setAdapter(new BuildingAdapter(new ArrayList<Building>(0), this, this));
drawerLayout = binding.drawer;
toolbar = binding.actionToolbar;
setSupportActionBar(toolbar);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawerLayout.setDrawerListener(toggle);
toggle.syncState();
navigationView = binding.buildingNavigation;
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.building_nav_item:
break;
case R.id.delivery_nav_item:
Intent deliveryIntent = new Intent(this, new DeliveryActivity().getClass());
startActivity(deliveryIntent);
item.setChecked(false);
break;
}
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
#Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
Any suggestions?
Try to add to manifest: android:noHistory="true"
<activity android:name=".MainActivity"
android:screenOrientation = "portrait"
android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
or you can write handler for this button
#Override
public void onBackPressed() {
//add what you need, for example if you want to start another activity:
Intent intent = new Intent(AnotherActivity.this, MainActivity.class);
//or if you want to close:
this.finish();
//or
finish();
}
or if you about button on ActionBar you can write it in menu
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.menu_item:
//something
return true;
case android.R.id.home:
//what you need
return true;
}
return super.onOptionsItemSelected(item);
}
the Previous Activity you are coming from Has a code that it sending it back to the current activity you are in, in its onstart() method. try finishing the previous activity before entering the current one
#Override
protected void onStart() {
mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();
if (mFirebaseUser != null) {
Intent mIntent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(mIntent);
}
super.onStart();
}
Try finishing the Activity after the Authentication
#Override
protected void onStart() {
FirebaseUser mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();
if (mFirebaseUser != null) {
Intent mIntent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(mIntent);
finish();
}
super.onStart();
}
Related
I have two activities,one is a MainActivity which has navigation drawer working.The Other is a testActivity which extends from the MainActivity.When I move from the MainActivity to the testActivity the navigation bar appears there but not working when i click there.
I have read too many posts on this like extending navigation drawer activity to other activities but I didnt understand them.
The following is my MainActivity
public class MainActivity extends AppCompatActivity {
private DrawerLayout dl;
private ActionBarDrawerToggle t;
private NavigationView nv;
Button nextBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dl = (DrawerLayout) findViewById(R.id.activity_main);
t = new ActionBarDrawerToggle(this, dl, R.string.Open, R.string.Close);
nextBtn = (Button)findViewById(R.id.nextAct);
nextBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,TestActivity.class);
startActivity(intent);
}
});
dl.addDrawerListener(t);
t.syncState();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
nv = (NavigationView) findViewById(R.id.nv);
nv.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.account:
Toast.makeText(MainActivity.this, "My Account", Toast.LENGTH_SHORT).show();
break;
case R.id.settings:
Toast.makeText(MainActivity.this, "Settings", Toast.LENGTH_SHORT).show();
break;
case R.id.mycart:
Toast.makeText(MainActivity.this, "My Cart", Toast.LENGTH_SHORT).show();
break;
default:
return true;
}
return true;
}
});
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(t.onOptionsItemSelected(item))
return true;
return super.onOptionsItemSelected(item);
}
}
The following is the testActivity.
public class TestActivity extends MainActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
}
}
The second activity gets the navigation bar as i have extended this from the MainActivity but that is not clickable in this new activity.Can any edit the code so that it will be clickable.
I think that the best way to do this is to use fragments. The navigation drawer + bar stays the same, and you change fragments in the rest of the screen. Hope it helps !
My MainActivity is not calling onActivityResult after coming back from another activity using the onSupportNavigateUp method. I know that onSupportNavigateUp is working cause I logged it.
But when the MainActivity is returning i do not get the Log("RESULT") test, so it's not even getting to the if statement.
look at my code below
UPDATE: I've noticed a weird behaviour when pressing back button while on MainActivity. There seems to be multiple instances of it (like 8 or 10) before getting out of the app.
UPDATE: Joined my Manifest
MainActivity
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
FragmentManager mManager = getSupportFragmentManager();
FirebaseUser mCurrentUser;
FirebaseAuth mAuth;
private TextView mEmailHeader;
private User mUser;
private DatabaseReference mDatabase;
private static final int REQUEST_CODE = 222;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDatabase = FirebaseDatabase.getInstance().getReference();
initializeViews();
mUser = new User();
mAuth = FirebaseAuth.getInstance();
if (mAuth != null) {
mCurrentUser = mAuth.getCurrentUser();
String email = mCurrentUser.getEmail();
mEmailHeader.setText(email);
mUser.setEmail(email);
writeNewUser(mCurrentUser.getUid(), mUser);
}
}
private void writeNewUser(String userId, User user) {
mDatabase.child("users").child(userId).setValue(user);
}
private void initializeViews() {
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
MyUtilty.showSnackbar(view, "Replace with your own action !");
}
});
DrawerLayout drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
View headerView = navigationView.getHeaderView(0);
mEmailHeader = headerView.findViewById(R.id.textViewEmailHeader);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
switch (id) {
case R.id.action_logout:
FirebaseAuth.getInstance().signOut();
finish();
return true;
case R.id.action_profile:
Intent intent = new Intent(this, ProfileActivity.class);
```startActivityForResult(intent, REQUEST_CODE);
return true;```
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_trips) {
MyUtilty.switchFragment(mManager, new TripsFragment());
} else if (id == R.id.nav_gallery) {
MyUtilty.switchFragment(mManager, new GalleryFragment());
} else if (id == R.id.nav_tips) {
} else if (id == R.id.nav_map) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("RESULT", "TEST");
if (requestCode == REQUEST_CODE) {
if (resultCode == RESULT_OK) {
if (data != null && data.hasExtra("name")) {
String[] array = data.getStringArrayExtra("name");
mUser.setFirstName(array[0]);
mUser.setLastName(array[1]);
writeNewUser(mCurrentUser.getUid(), mUser);
Log.d("TEST", "It's working");
}
}
}
}
}
ProfileActivity
public class ProfileActivity extends AppCompatActivity {
private EditText mFirstName;
private EditText mLastName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
initializeViews();
}
private void initializeViews() {
mFirstName = findViewById(R.id.editTextFirstName);
mLastName = findViewById(R.id.editTextLastName);
}
#Override
public boolean onSupportNavigateUp() {
Log.d("NAV_UP", "Nav up working");
String firstName = mFirstName.getText().toString();
String lastName = mLastName.getText().toString();
String[] array = {firstName,lastName};
Intent intent = new Intent();
intent.putExtra("name", array);
setResult(RESULT_OK,intent);
finish();
return super.onSupportNavigateUp();
}
}
Manifest
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".ProfileActivity"
android:parentActivityName=".MainActivity"
android:label="Profile"></activity>
<activity
android:name=".LoginActivity"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SignupActivity"
android:theme="#style/AppTheme.NoActionBar"></activity>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar" />
</application>
</manifest>
try to replace new Intent() with getIntent() - else there will be no REQUEST_CODE.
#Override
public boolean onKeyDown(int keyCode, #NonNull KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Intent intent = this.getIntent();
String firstName = mFirstName.getText().toString();
String lastName = mLastName.getText().toString();
if(firstName != null && lastName != null) {
intent.putExtra("name", new String[] {firstName, lastName});
this.setResult(RESULT_OK, intent);
} else {
this.setResult(RESULT_CANCELED, intent);
}
this.finish();
}
return super.onKeyDown(keyCode, event);
}
I moved my code to a button instead of using onSupportNavigateUp().
For some reason onSupportNavigateUp does not support carrying out intents
public void onSave(View view) {
String firstName = mFirstName.getText().toString();
String lastName = mLastName.getText().toString();
String[] array = {firstName,lastName};
Intent intent = this.getIntent();
intent.putExtra("name", array);
this.setResult(RESULT_OK, intent);
this.finish();
}
I am trying to launch new activity from intent but it is only working in one case, even though both the activities extend AppCompatActivity. I don't know what the issue is.
the launcher activities are working fine
<manifest>
<activity
android:name=".activities.home_page.HomePageNavActivity"
android:label="#string/title_activity_home_page_nav"
android:theme="#style/AppTheme"
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".activities.UserProfileActivity"
android:parentActivityName=".activities.home_page.HomePageNavActivity"
android:windowSoftInputMode="adjustResize" />
<activity android:name=".activities.ProductDescription"
android:parentActivityName=".activities.home_page.HomePageNavActivity"
android:windowSoftInputMode="adjustResize"/>
MainActivity (HomePageNavActivity)
public class HomePageNavActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_page_nav);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
navigation.setSelectedItemId(R.id.navigation_discover);
}
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment fragment;
switch (item.getItemId()) {
case R.id.navigation_discover:
fragment = new DiscoverFragment();
if(!Constant.currentBottomFragmentSelected.equals("discover") ) {
Constant.currentBottomFragmentSelected = "discover";
loadFragment(fragment);
}
return true;
case R.id.navigation_inbox:
Intent intent=new Intent(HomePageNavActivity.this,ProductDescription.class); //this intent is not working
HomePageNavActivity.this.startActivity(intent);
return true;
case R.id.navigation_profile:
Intent intent1 = new Intent(HomePageNavActivity.this, UserProfileActivity.class); //this intent is working
startActivity(intent1);
return true;
}
return false;
}
};
Activity1 (ProductDescription) (Not working)
public class ProductDescription extends AppCompatActivity {
FloatingActionButton fabLove,fabShare,fabCart;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_description);
}
}
Activity2 (UserProfileActivity) (working)
public class UserProfileActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_profile);
utoolbar = (Toolbar) findViewById(R.id.toolbarProfile);
setSupportActionBar(utoolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
imgBtn = findViewById(R.id.imgBtnSettings);
imgBtnLogout = findViewById(R.id.imgBtnLogout);
//remaining code consists of onClickListeners for different buttons
}
}
You have to remove HomePageNavActivity.this.startActivity(intent):
case R.id.navigation_inbox:
Intent intent = new Intent(HomePageNavActivity.this,ProductDescription.class);
startActivity(intent);
return true;
I have 2 activites:
- LoginActivity: it will handle the login stuff later
- MainActivity: the main app, all of the functions will be provided on fragments.
I want to properly use the back stack, but I can't.
What I want (but can't) achieve:
App starts with Login screen. I login (right now press the Start button), after that the main screen appears and the first fragment loads.
Now if I press the back button, the app closes, and that's how it should work, it must not go back to the login screen with a simple back button press.
But now if I click logout (and the Login screen appears), and I press the back button, the app takes me back to the main screen, what is really not ok. If I log out, from the login screen the back button should close the app.
And another problem, regarding also backstack, and fragments:
I have 3 fragments: first, second and third. If I open them after each other (within the main activity of course), and I press the back button, I want it to take me back to the previously opened fragment, or if there's no previous, close the app.
Now it makes it, opens the previous fragment, but at the same time it closes the complete app. (I can see that they are happening right after each other)
What's missing? What should be modified to achieve this (normal) behavior?
Thanks!
My code:
MainActivity:
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
public static final String SP_DATA = "SP_DATA";
public static final String FB_LOGIN_STATUS = "FB_LOGIN_STATUS";
public static final String FLRT = "FLRT";
public SharedPreferences sharedPreferences;
#Override
protected void onCreate(Bundle savedInstanceState) {
sharedPreferences = getSharedPreferences(SP_DATA, MODE_PRIVATE);
boolean bAlreadyLoggedIn = sharedPreferences.getBoolean(FB_LOGIN_STATUS, false);
if (bAlreadyLoggedIn) {
Log.d(FLRT, "Already logged in");
}
else {
Log.d(FLRT, "Not logged in");
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
showFragment(new FirstFragment(),"FirstFragment");
Button btnLogout = (Button) findViewById(R.id.btnLogout);
btnLogout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
logout();
showActivity(MainActivity.this, LoginActivity.class);
}
});
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
private void showActivity(Context context_fromActivity, Class<?> class_toActivty){
Intent intent = new Intent(context_fromActivity, class_toActivty);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
private void logout() {
Log.d(FLRT, "Logging out...");
sharedPreferences = getSharedPreferences(SP_DATA, MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean(FB_LOGIN_STATUS, false);
editor.commit();
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
if (getFragmentManager().getBackStackEntryCount() > 0 ){
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_first_layout) {
showFragment(new FirstFragment(), "FirstFragment");
}
else if (id == R.id.nav_second_layout) {
showFragment(new SecondFragment(), "SecondFragment");
}
else if (id == R.id.nav_third_layout) {
showFragment(new ThirdFragment(), "ThirdFragment");
}
else if (id == R.id.nav_share) {
}
else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
private void showFragment(Fragment fragment, String sFragmentTAG) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (fragmentManager.findFragmentByTag(sFragmentTAG) != null) {
Log.d(FLRT, "Fragment found, using existing one: " + sFragmentTAG);
fragment = fragmentManager.findFragmentByTag(sFragmentTAG);
}
fragmentTransaction.replace(R.id.fragmentContainer, fragment, sFragmentTAG);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
LoginActivity:
public class LoginActivity extends AppCompatActivity {
public static final String SP_DATA = "SP_DATA";
public static final String FB_LOGIN_STATUS = "FB_LOGIN_STATUS";
public static final String FLRT = "FLRT";
public SharedPreferences sharedPreferences;
private Button btn_start;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
btn_start = (Button) findViewById(R.id.btn_start);
btn_start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
login();
showActivity(LoginActivity.this, MainActivity.class);;
}
});
}
private void showActivity(Context context_fromActivity, Class<?> class_toActivty){
Intent intent = new Intent(context_fromActivity, class_toActivty);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
private void login() {
Log.d(FLRT, "Logging in...");
sharedPreferences = getSharedPreferences(SP_DATA, MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean(FB_LOGIN_STATUS, true);
editor.commit();
}
}
About switching between Activities.
One important thing.
In showActivity() use finish() to kill current Activity when going to another. If it doesn't help - see below.
Try to use also FLAG_ACTIVITY_NEW_TASK with your current flag, because FLAG_ACTIVITY_CLEAR_TOP will close only Activities in task above current Activity, but not below.
So, it would be this: intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Another option is to use: FLAG_ACTIVITY_CLEAR_TASK only - new Activity will clear the task and become root in it.
If both won't help - use android:launchMode = "singleInstance" in Manifest for each Actitivy.
About Fragments - I see a little mistake in your code: it calls super.onBackPressed(); before popping Fragment from BackStack
I would change like this:
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (getFragmentManager().getBackStackEntryCount() > 0 ){
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
!! Also you should test this line: getFragmentManager().getBackStackEntryCount() > 0 with 0 and 1 in condition (because in current implementation in my project FragmentContainer is considering as first, zero value in a BackStack). Just test 0 and 1 to see which works.
Thanks.
PS. Few more tips.
You can declare FragmentManager fragmentManager in your Activity in order to create it one time only in onCreate(). It would be better than get it each time.
Consider change this:
if (id == R.id.nav_first_layout) {
showFragment(new FirstFragment(), "FirstFragment");
}
else if (id == R.id.nav_second_layout) {
showFragment(new SecondFragment(), "SecondFragment");
}
else if (id == R.id.nav_third_layout) {
showFragment(new ThirdFragment(), "ThirdFragment");
}
else if (id == R.id.nav_share) {
}
else if (id == R.id.nav_send) {
}
To:
switch (item.getItemId()) {
case R.id.nav_first_layout:
showFragment(new FirstFragment(), "FirstFragment");
break;
case ...
}
and so on. The code would be more pretty :)
Something is not OK in my code. Normally the activity lifecycle is
- at starting app: onCreate --> onStart --> onResume
- at closing app: onPause --> onStop --> onDestroy
- pressing the home button or the task switch button: onPause --> onStop
- coming back to the already opened app from another app: onStart --> onResume
But for some reason my app also calls onDestroy when I press the home button or the task switch button, and it calls onCreate, when I go back to the already opened app.
My app has 2 Activites:
- LoginActivity, which should appear first, if nobody is logged on, or if the logout button is pressed
- MainActivity to handle the main functions.
Please help me identify what causes this not normal behavior of lifecycle.
Thanks!
MainActivity:
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
public Helper helper = new Helper(this);
public static final String SP_DATA = "SP_DATA";
public static final String FB_LOGIN_STATUS = "FB_LOGIN_STATUS";
public static final String FLRT = "FLRT";
public SharedPreferences sharedPreferences;
public FragmentManager fragmentManager = getFragmentManager();
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(FLRT, "onCreate");
helper.makeToast("onCreate");
sharedPreferences = getSharedPreferences(SP_DATA, MODE_PRIVATE);
boolean bAlreadyLoggedIn = sharedPreferences.getBoolean(FB_LOGIN_STATUS, false);
if (bAlreadyLoggedIn) {
Log.d(FLRT, "Already logged in");
}
else {
Log.d(FLRT, "Not logged in");
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
showFragment(new FirstFragment(),"FirstFragment");
Button btnLogout = (Button) findViewById(R.id.btnLogout);
btnLogout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
logout();
showActivity(MainActivity.this, LoginActivity.class);
}
});
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
private void showActivity(Context context_fromActivity, Class<?> class_toActivty){
Intent intent = new Intent(context_fromActivity, class_toActivty);
//intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
MainActivity.this.finish();
}
private void logout() {
Log.d(FLRT, "Logging out...");
sharedPreferences = getSharedPreferences(SP_DATA, MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean(FB_LOGIN_STATUS, false);
editor.commit();
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (getFragmentManager().getBackStackEntryCount() > 1 ){
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_first_layout:
showFragment(new FirstFragment(), "FirstFragment");
break;
case R.id.nav_second_layout:
showFragment(new SecondFragment(), "SecondFragment");
break;
case R.id.nav_third_layout:
showFragment(new ThirdFragment(), "ThirdFragment");
break;
case R.id.nav_share:
break;
case R.id.nav_send:
break;
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
private void showFragment(Fragment fragment, String sFragmentTAG) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (fragmentManager.findFragmentByTag(sFragmentTAG) != null) {
Log.d(FLRT, "Fragment found, using existing one: " + sFragmentTAG);
fragment = fragmentManager.findFragmentByTag(sFragmentTAG);
}
fragmentTransaction.replace(R.id.fragmentContainer, fragment, sFragmentTAG);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
#Override
protected void onStart() {
super.onStart();
Log.d(FLRT, "onStart");
helper.makeToast("onStart");
}
#Override
protected void onResume() {
super.onResume();
Log.d(FLRT, "onResume");
helper.makeToast("onResume");
}
#Override
protected void onPause() {
super.onPause();
Log.d(FLRT, "onPause");
helper.makeToast("onPause");
}
#Override
protected void onStop() {
super.onStop();
Log.d(FLRT, "onStop");
helper.makeToast("onStop");
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.d(FLRT, "onDestroy");
helper.makeToast("onDestroy");
}
}
LoginActivity:
public class LoginActivity extends AppCompatActivity {
public static final String SP_DATA = "SP_DATA";
public static final String FB_LOGIN_STATUS = "FB_LOGIN_STATUS";
public static final String FLRT = "FLRT";
public SharedPreferences sharedPreferences;
private Button btn_start;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
btn_start = (Button) findViewById(R.id.btn_start);
btn_start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
login();
showActivity(LoginActivity.this, MainActivity.class);;
}
});
}
private void showActivity(Context context_fromActivity, Class<?> class_toActivty){
Intent intent = new Intent(context_fromActivity, class_toActivty);
//intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
LoginActivity.this.finish();
}
private void login() {
Log.d(FLRT, "Logging in...");
sharedPreferences = getSharedPreferences(SP_DATA, MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean(FB_LOGIN_STATUS, true);
editor.commit();
}
}
Nothing surprising here,
The behavior of onDestroy() method is
In some situations System simply kill the activity's hosting process without calling this method. OR System can directly destroy your app If its getting into low memory situations even your app is in onStop() event, And another thing to notice is onStop() method also may not be called, in low memory situations.
See onDestroy() method in details.
Ok, when you call MainActivity.this.finish(); or LoginActivity.this.finish(); the activity is distroyed. try not call finish() if you don't want destroy needed activity
I found the problem: in the mainfest file android:noHistory="true"
was set for both activities. Now the activity lifecycle is working fine.
However now from the Login screen I can simply can go back to the Main screen with pressing the Back button... and that's not ok. :)