I've been studying Google IO 2012 code
In one of the activities (HomeActivity.java) they're doing as follows:
void onCreate(Bundle savedInstance)
{
if(someCondition) {
// start some other activity here
finish(); // finish this activity
}
if(isFinishing()) return;
// More code here
}
I wonder why they do not put return right after finish() but instead checking isFinishing() ?
An Activity can be finished in a number of ways.
finishActivity from an activity that has called startActivityForResult
finishAffinity and finishFromChild
So isfinishing is used to account for such cases.
Related
In my project i move from main activity to activity A and from activity A to activity B. From activity B using home menu on toolbar i jump back to main activity. Now when i press back button application should exit but it opens the activity A again.
You should make use of the launch flags to manage your activities in the back stack. As far as I understood your scenario, I think you need to use FLAG_ACTIVITY_CLEAR_TOP for starting your main/home activity.
Read more about launch flags: https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_CLEAR_TOP.
Also, take a look this for more details on managing activity back stack on Android: https://developer.android.com/guide/components/activities/tasks-and-back-stack#ManagingTasks
Call the finish() method before starting the next activity to have it removed from the activity. Find more details and options here.
For Kotlin write this in your MainActivity :
override fun onBackPressed() {
moveTaskToBack(true)
exitProcess(-1)
}
For Java write this in your MainActivity :
#Override
void onBackPressed() {
moveTaskToBack(true)
exitProcess(-1)
}
Hope to it will work for you as good as for me
hey i write some code for you
Variables:
boolean backactivity = true;
CODE:
public boolean onOptionsItemSelected(MenuItem item){
if(backactivity==true)
{
finishActivity(1);
backactivity=false;
}else
{
Intent homeIntent = new Intent(Intent.ACTION_MAIN);
homeIntent.addCategory( Intent.CATEGORY_HOME );
homeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(homeIntent);
}
return true;
}
MainActivity has an attribute android:launchMode="singleInstance" in AndroidManifest.xml
Here's the onCreate method from MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "onCreate() from MainActivity");
session = new TempSession(this);
// check if logged in. If not, take the user back to login activity.
session.checkLogin(); // <---- HERE
Toast.makeText(this, "logged in as " + session.getUsername(), Toast.LENGTH_SHORT).show();
// Prevents screen from turning off when in this Activity.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
....
and the TempSession, it checks if user is logged in, and if not, it will take the user to the LoginActivity.
This is the checkLogin() method
public void checkLogin(){
// Check login status
if(!this.isLoggedIn() || getUsername() == null) {
// user is not logged in redirect him to Login Activity
Intent i = new Intent(context, LoginActivity.class);
// Closing all the Activities
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
// Add new Flag to start new Activity
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
// Staring Login Activity
context.startActivity(i);
}
}
From my understanding, where I marked <---- HERE from MainActivity, when it calls checkLogin(), shouldn't it finish all task before it proceeds?
Currently, my app would open up LoginActivity, but still proceeds to the next instructions (e.g. makes a Toast saying "logged in as null", and keeps going on in background) and calls onPause() -> onStop() .
Is there any way to stop the MainActivity from keep going at that point?
This situation causes pressing back from LoginActivity bypasses to MainActivity.
Let me know if you need more information.
Thank you in advance.
Is there any way to stop the MainActivity from keep going at that point?
Yes. Have checkLogin() return some value that indicates MainActivity#onCreate(...) should return instead of proceeding.
Calling startActivity(...) does not start an activity. Think of it as asking the Android framework to start an activity. It places this job at the end of the UI thread's work queue. That means that before it starts the new activity, it will finish any other jobs that are already in the work queue, including the rest of the current method and possibly other lifecycle methods of the current activity.
The reason that your toast still shows up is because merely starting a new activity does not destroy your old activity. It's merely pushed to the backstack. Of course you can change this using the android:launchMode attribute in your manifest. A simple strategy in your cause might be to simply return true from your checkLogin() method when the user is logged in and change your onCreate as follows:
if( session.checkLogin() ) {
Toast.makeText(this, "logged in as " + session.getUsername(), Toast.LENGTH_SHORT).show();
// Prevents screen from turning off when in this Activity.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
....
}
I want to refresh fragments from an Actvitiy. (Let's call the activity A)
Activity A contains the fragments.
When I finish Activity B then Activity A should refresh the fragments.
I was thinking this would be done in onResume? I tried simply restarting the activity through an intent but that's not usability friendly.
So how do I refresh fragments when I resume an activity?
Just put this code inside
onResume()
For example you want to update your listview when u return to your fregment.
#Override
public void onResume() {
super.onResume();
if (allowRefresh)
{
allowRefresh = false;
lst_applist = db.load_apps();
getFragmentManager().beginTransaction().detach(this).attach(this).commit();
}
}
Here getFragmentManager().beginTransaction().detach(this).attach(this).commit();
This line detach and re-attach the fragment so your content will be updated.
The onResume() get called always before the fragment is displayed. Even when the fragment is created for the first time . So you can simply move your from onViewCreated() to onResume.
#Override
public void onResume() {
super.onResume();
//move your code from onViewCreated() here
}
I agree with Mehul But u can alse do it this way .if you want to replace your fragment you could just say
#Override
public void onResume() {
super.onResume();
if (allowRefresh)
{
allowRefresh = false;
lst_applist = db.load_apps();
getFragmentManager().beginTransaction().replace(Fragment_Container,fragment).commit();
}
}
I'm pretty new to Android/java, and have come up against my first head-scratcher.
I'm trying to conditionally change the starting view based on if a user is logged in (I've set is_logged_in already, here, to more simply illustrate the problem).
Many thanks.
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean is_logged_in = false;
if(is_logged_in) {
setContentView(R.layout.activity_main);
} else {
menu_sign_up(); // How would I pass the View?
}
}
// Doesn't work, at least when called inside of MainActivity's onCreate
public void menu_sign_up(/* View view */) {
Intent intent = new Intent(this, SignUp.class);
startActivity(intent);
}
// Example of a working method, at least when called from android:onClick in XML
public void menu_sign_in(View view) {
Intent intent = new Intent(this, SignIn.class);
startActivity(intent);
overridePendingTransition(0,0);
}
}
public class SignUp extends MainActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sign_up);
}
// ...
}
***** Truncated Stack Trace Below ******* (adb logcat *:W)
W/ActivityManager(19583): Activity idle timeout for HistoryRecord{40953fd8 com.example.digitalkarmaeclipse/.SignUp}
W/ActivityManager(): Activity idle timeout for HistoryRecord{}
W/ActivityManager(21900): Launch timeout has expired, giving up wake lock!
W/ActivityManager(21900): Activity idle timeout for HistoryRecord{40a23580 com.example.digitalkarmaeclipse/.MainActivity}
W/ActivityManager(21900): Activity idle timeout for HistoryRecord{40a2c6f8 com.example.digitalkarmaeclipse/.SignUp}
W/ActivityManager(21900): Activity idle timeout for HistoryRecord{40a30100 com.example.digitalkarmaeclipse/.SignUp}
W/ActivityManager(21900): Activity idle timeout for HistoryRecord{40a338e8 com.example.digitalkarmaeclipse/.SignUp}
W/ActivityManager(21900): Activity idle timeout for HistoryRecord{40a376e0 com.example.digitalkarmaeclipse/.SignUp}
Your current app structure doesn't make a lot of sense. Does SignUp have to be an Activity as well? You could use an AlertDialog to do something similar. If it does need to be an Activity then have it extend Activity, it doesn't make much sense to extend HomeActivity in this context.
I also don't like the idea of putting setContentView() in a logical statement. onCreate() is only called when the Activity is created. So if you start your SignUp Activity and then press the back button, there won't be a layout for your HomeActivity.
edit: And like Shark said it doesn't look like you have a way to pass the data from SignUp back to HomeActivity. You should try to use startActivityForResult() and then use setResult() in SignUp to say whether it was successful or not.
You need to let onCreate() finish, then move your new Activity to onResume() or onStart(); those get called as your activity is shown to the user instead of it still initializing (itself).
Also, it looks like you need to set up a
onLoginFinished(int result);
callback... either try running your login with startActivityForResult() and catching the result in onActivityResult()
OR ...
you make your own interface and once the other activity finishes it, it invokes the onLoginFinished(isOK) callback where you determine which screen to use.
I want to check to see if an activity is running or finished. Is there any method through which I can check the status of activity?
I found activity.isFinishing() but I am not sure about it.
If you want to perform any step before Activity is going to become invisible.
Their are several choices here.
onDestroy() - for final cleanup.
isFinishing() - right after act.finish() is called it will return true.
onStop() - when the Activity is killed by framework process. (not destroyed)
onPause() - when the Activity is covered by any other Activity
onBackPressed() - capturing the event of hardware Back key triggered by user.
Call isFinishing in the onPause method before the activity is destroyed:
#Override
protected void onPause() {
super.onPause();
if (isFinishing()) {
// Here you can be sure the Activity will be destroyed eventually
}
}
I realize this is very old, but for anyone using Kotlin:
We can check within a Fragment:
// FRAGMENT
override fun onPause() {
super.onPause()
// Log.v(TAG, "onPause");
if(requireActivity().isChangingConfigurations) {
// Config change
} else {
if(requireActivity().isFinishing) {
// deal with activity ending (finish up viewModel etc)
}
// deal with rotate or other config changes as required
}
}
Of course, we can also just do this directly inside an activity (just remove the requireActivity() parts).