1

I have 4 activities, when i press home button, it goes in background and when i open it from background, it starts from the activity from where i resume, but i want to open Launcher activity always because in my first activity password is set and i want the user to type password every time when the app is open

        android:clearTaskOnLaunch="true"
        android:finishOnTaskLaunch="true"
        android:launchMode="singleInstance" 

` I have tried this code in Manifest,but it is also not working.

I have also tried this but unfortunately result is same

 @Override
protected void onStop() {
    sliderShow.stopAutoCycle();
    super.onStop();
   GalleryBrowserActivity.this.finish();
    Log.d("value","value on Stop"+("position"));
}
laraib
  • 43
  • 7
  • try playing with android:noHistory="true" in activity tags in manifest – Adeel Turk Sep 07 '17 at 06:17
  • @AdeelTurk I know that. All I'm saying is that your desire to restart app is against accepted flow. What you should be doing, is have a full screen lock dialog float on top when user returns. Now how to detect that, see https://stackoverflow.com/questions/4414171/how-to-detect-when-an-android-app-goes-to-the-background-and-come-back-to-the-fo – lionscribe Sep 07 '17 at 12:25

5 Answers5

0

You should change your app design! Users do not want the app restarted every time they step out. They may lose some work.
You should rather use a sign-in dialog, or fragment, that is displayed above the current activity, every time user returns after app goes to background.

lionscribe
  • 3,413
  • 1
  • 16
  • 21
0

you should just follow life cycle of android,

  • when user press back button >> onStop() and onDestroy() called
  • when use press Home button >> onStop() called
  • when user again back to open application without more waiting and clean from stack(clear background data) >> called onRestart() called
  • and if user close the application and also remove application from background then it call >> onCreate()

Now just you find your point while following the life cycle of Android :-)


Solution One: apply code in onStop()

Intent intent = new Intent(this, A.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 
startActivity(intent);
finish();

OR

Solution Two: In AndroidManifest.xml file put android:launchMode="singleTask" in to all Activity

like above

 <activity
       android:name=".Activity.BookingConfirmClass"
       android:label="@string/string_confrim_booking"
       android:launchMode="singleTask"
       android:parentActivityName=".Activity.HotelDetailsClass"
       android:screenOrientation="portrait" />
ND1010_
  • 3,743
  • 24
  • 41
  • Thankyou, i know all this life cycle and have used all that but still not able to launch the launcher activity – laraib Sep 07 '17 at 06:20
  • did you mean that after close application just u want to open a Launcher activity? – ND1010_ Sep 07 '17 at 06:21
  • @ND10101_ yes whether onDestroy is called or onStop, i always want to open Launcher Activity – laraib Sep 07 '17 at 06:24
  • see my answer and back to me i also add some more in this wait for some time – ND1010_ Sep 07 '17 at 06:27
  • This code works, but i got errors sometimes.. Actually i am using different intents for different purpose, and if i use this Intent, i got this error "Attempt to invoke virtual method 'char[] java.lang.String.toCharArray()' on a null object reference" – laraib Sep 07 '17 at 07:24
  • and if my blog is use full to you then should have to up mark me and give right mark to me :) – ND1010_ Sep 07 '17 at 07:26
0

If you call the method:

finish();

In your life cycle methods it will work but It will have a disadvantage too:

The advantage is that when the user clicks "back" the activity will be destroyed and the user will have to put the password again.

The disadvantage is that when the user go to another app may be due to a click in the notification. After finishing using that other app, when the user clicks "back" he wont find your activity! He will have to go to a launcher and click your app icon again. This is not good for users for because they will have to click your app from launcher each time they leave the app.

BEST WAY

Declare a boolean in your Activity call it for example:

    private boolean hasUserReturned=false;

Then in your onPause() method:

    @Override
    protected void onPause() {
       super.onPause();
       hasUserReturned=true;
    }

Then in your onResume() nethod:

    @Override
    protected void onResume() {
       super.onResume();
       if(hasUserReturned){
            recreate();
       }
    }

This will recreate your activity each time the user revisit your app. It handles "back button" clicks without removing your activity from backstack!

Xenolion
  • 12,035
  • 7
  • 33
  • 48
  • I have to add this code in all the activities? because i have 4 activities – laraib Sep 07 '17 at 06:29
  • If all those activity needs a password then of course you have to do it its easy! Otherwise you may need to make one Super Class that will be a parent for all those 4 Activity Classes! And extend it, power of inheritance! – Xenolion Sep 07 '17 at 15:39
0

I could suggest you one approach, Make all your activities extend from one BaseActivity

Add a variable in BaseActivity

public static boolean HAS_RESUMED_FROM_ACTIVITY=false;

and then override startActivity in your BaseActivity like

@Override
startActivity(Intent intent){
HAS_RESUMED_FROM_ACTIVITY=true;
super.startActivity(intent);
}

Now in onResume of your activities you

@Override
protected void onResume(){
if(!BaseActivity.HAS_RESUMED_FROM_ACTIVITY){
//show your lock screen
}
super.onResume();
}
Ashish Kumar
  • 374
  • 4
  • 11
0

UPDATE

Hi, I tried to solve this issue so that it can be useful for future too. May be my attempt will not suit in each and every application requirement but it can be helpful in many situations. This is a demo I tried using fragments and I assume this is the only possible way to achieve this requirement. Correct me if I am wrong anywhere. Here is the code:

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private Fragment mCurrentFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        addFragment(MainFragment.newInstance());
    }

    public void replaceFragment(Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        String backStackTag = fragment.getClass().getName();
        boolean fragmentPoped = fragmentManager.popBackStackImmediate(backStackTag, 0);
        if (!fragmentPoped) {
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.frame, fragment, backStackTag);
            if (backStackTag != null) {
                fragmentTransaction.addToBackStack(backStackTag);
            }
            fragmentTransaction.commitAllowingStateLoss();
        }
    }

    public void addFragment(Fragment fragment) {
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        if (mCurrentFragment != null) {
            Fragment f = getSupportFragmentManager().findFragmentByTag(mCurrentFragment.getClass().getName());
            if (f != null) {
                fragmentTransaction.remove(f);
            }
        }
        fragmentTransaction.add(R.id.frame, fragment, fragment.getClass().getName());
        fragmentTransaction.commit();
        mCurrentFragment = fragment;
    }

    public void replaceInMainFragment(Fragment fragment) {
        if (mCurrentFragment != null && mCurrentFragment instanceof MainFragment) {
            ((MainFragment) mCurrentFragment).replaceFragment(fragment);
        }
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></FrameLayout>

</RelativeLayout>

MainFragment.java

public class MainFragment extends Fragment {

    private View mView;
    private Fragment mCurrentFragment;

    public static MainFragment newInstance() {
        MainFragment loginFragment = new MainFragment();
        return loginFragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mView = inflater.inflate(R.layout.fragment_main, container, false);
        Log.e("MainFragment", "onCreateView");
        return mView;
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.e("MainFragment", "onStart");
        addFragment(LoginFragment.newInstance());
    }

    public void replaceFragment(Fragment fragment) {
        FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
        String backStackTag = fragment.getClass().getName();
        boolean fragmentPoped = fragmentManager.popBackStackImmediate(backStackTag, 0);
        if (!fragmentPoped) {
            FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.frame_main, fragment, backStackTag);
            if (backStackTag != null) {
                fragmentTransaction.addToBackStack(backStackTag);
            }
            fragmentTransaction.commitAllowingStateLoss();
        }
    }

    public void addFragment(Fragment fragment) {
        removeAllFragmentFromBackstack();
        FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
        if (mCurrentFragment != null) {
            Fragment f = getActivity().getSupportFragmentManager().findFragmentByTag(mCurrentFragment.getClass().getName());
            if (f != null) {
                fragmentTransaction.remove(f);
            }
        }
        fragmentTransaction.add(R.id.frame_main, fragment, fragment.getClass().getName());
        fragmentTransaction.commit();
        mCurrentFragment = fragment;
    }

    private void removeAllFragmentFromBackstack() {
        FragmentManager fm = getActivity().getSupportFragmentManager();
        for (int i = 0; i < fm.getBackStackEntryCount(); ++i) {
            fm.popBackStack();
        }
    }
}

fragment_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/frame_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></FrameLayout>

</RelativeLayout>

LoginFragment.java

public class LoginFragment extends Fragment {

    private View mView;

    public static LoginFragment newInstance() {
        LoginFragment loginFragment = new LoginFragment();
        return loginFragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mView = inflater.inflate(R.layout.fragment_login, container, false);
        Log.e("LoginFragment", "onCreateView");
        mView.findViewById(R.id.btnLogin).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((MainActivity) getActivity()).replaceInMainFragment(Fragment1.newInstance());
            }
        });
        return mView;
    }
}

fragment_login.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btnLogin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Login" />

</RelativeLayout>

Fragment1.java

public class Fragment1 extends Fragment {

    private View mView;

    public static Fragment1 newInstance() {
        Fragment1 fragment1 = new Fragment1();
        return fragment1;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mView = inflater.inflate(R.layout.fragment_1, container, false);
        mView.findViewById(R.id.btnFrag1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((MainActivity) getActivity()).replaceInMainFragment(Fragment2.newInstance());
            }
        });
        return mView;
    }

}

fragment_1.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btnFrag1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="This is Fragment 1" />

</RelativeLayout>

Fragment2.java

public class Fragment2 extends Fragment {

    private View mView;

    public static Fragment2 newInstance() {
        Fragment2 fragment1 = new Fragment2();
        return fragment1;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mView = inflater.inflate(R.layout.fragment_2, container, false);
        mView.findViewById(R.id.btnFrag2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            }
        });
        return mView;
    }

}

fragment_2.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btnFrag2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="This is fragment 2" />

</RelativeLayout>

Hope it helps someone.

OLD

Then I think you need some hack. It will not directly accessible. Try calling 2nd activity when user press back button or any other option to go to the 2nd activity from 3rd activity. Hope it suits your app's requirement.

ThirdActivity.java

public class ThirdActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_third);
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        startActivity(new Intent(getBaseContext(), SecondActivity.class));
    }
}

SecondActivity.java

public class SecondActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        findViewById(R.id.btnJumpToThirdScreen).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(getBaseContext(), ThirdActivity.class));
            }
        });
    }
}

OLD

Here is the demo I made just now. For this you need to define android:noHistory="true" in your manifest. Here is the sample code:

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.btnJump).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(getBaseContext(), SecondActivity.class));
            }
        });

    }
}

SecondActivity.java

public class SecondActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }
}

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.ccc.stackoverflow">

    <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=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".SecondActivity"
            android:noHistory="true"></activity>
    </application>

</manifest>

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/btnJump"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="My Launcher Activity Main" />

</RelativeLayout>

Try this demo. Also check removing noHistory flag from your Manifest. You can see the difference. Hope it helps you.

AndiM
  • 2,196
  • 2
  • 21
  • 38
  • This works also, but if one issue solves then other issue appears, if i use android:noHistory="true", i can't be able to go back from activity 3 to activity 2.. If the user wants to go to activity back to activity 2, he can't – laraib Sep 07 '17 at 08:02
  • If it does not fulfill your requirement then I think you need to change the flow of your app. Because there is some limitations of OS and we must follow standard flow of our app. – AndiM Sep 07 '17 at 08:49
  • If your code is not bounded to activity only you can achieve this using fragments too with only a single activity. You can add your login fragment on create of your activity and this way by adding other fragments into backstack you can achieve your desire flow. – AndiM Sep 07 '17 at 09:39
  • Thankyou your this code works :) but when i go from 2 activity to 3 and, then came back from 3 to 2, it dosen't works – laraib Sep 08 '17 at 06:37
  • Why? You need to call 2nd activity onBackpressed of your 3rd activity. And more feasible approach will be using fragments. You can try it. – AndiM Sep 08 '17 at 07:28
  • if the user wants to go back to 2 activity from 3 activity, thats why.. but sure i will try to use Fragments – laraib Sep 08 '17 at 07:41
  • Hello All, Please take a look at updated answer and let me know if anyone has any query. Happy coding...! – AndiM Sep 11 '17 at 12:55
  • yes thanks this is a good way, But i have Implemented this problem in a different way, that is also working perfectly now :) – laraib Sep 12 '17 at 05:36