2

I need my app to check if it's running for first time or not. If it's the first time, then it should launch LoginActivity instead of MainActivity. And if it's not the first run, it should display MainActivity as usual.

I used SharedPreference value to check if it's available, then app decides its not running it's first run.

This is what I've tried so far

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Set default values into settings
        PreferenceManager.setDefaultValues(this, R.xml.preferences, false);

        // Check if the app is running on its first run
        SharedPreferences fRun = getPreferences(MODE_PRIVATE);

        if(fRun.getBoolean("firstrun", true)){

            SharedPreferences.Editor editX=fRun.edit();
            editX.putBoolean("firstrun", false);
            editX.apply();

            // Login activity stuff here
            // Goto login screen

            Intent loginIntent=new    Intent(getApplicationContext(),LoginActivity.class);
            startActivity(loginIntent);

            //finish();

        } else {
            setContentView(R.layout.activity_main);
        }
    }
}

My problem is, when I run my app, it suddenly crashes and displays message Unfortunately, the app has stopped.

Why does the app crash? Is it because code in my LoginActivity have errors or do I need to first load MainActivity then call LoginActivity?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vishwa
  • 801
  • 11
  • 26
  • When the app is crashed u get the logs post it here it will be easier to understand where is the problem – Ashish Aug 28 '16 at 09:33
  • I think that "setContentView(R.layout.activity_main); " should be anyway after "super.onCreate(savedInstanceState);". try to get it out of the if-else. – MorZa Aug 28 '16 at 09:40
  • Like @MorZa mentioned, you should set your layout outside of the `if`: right now, when you exit your `LoginActivity`, you return to a blank `MainActivity`. A frequent pattern for this use-case is to start your application on a transparent `RedirectActivity`, doing nothing but redirecting the user to the wanted activity (either `MainActivity` or `LoginActivity` in your case). – Marc Plano-Lesay Aug 28 '16 at 09:47
  • Possible duplicate of [How to launch activity only once when app is opened for first time?](http://stackoverflow.com/questions/7238532/how-to-launch-activity-only-once-when-app-is-opened-for-first-time) – Yogesh Rathi Aug 28 '16 at 09:51
  • @YogeshRathi this is different question – Vishwa May 18 '17 at 06:13

3 Answers3

4

You can use LoginActivity as LAUNCHER activty and check whether the user is logged in. If yes, start MainActivity.

The AndroidManifest.xml:

<activity
    android:name=".LoginActivity"
    android:label="@string/app_name">

    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

<activity android:name=".MainActivity"/>

And the LoginActivity:

public class LoginActivity extends ActionBarActivity {
    private static final String LOGIN_KEY = "LOGIN_KEY";

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

        SharedPreferences pref = getPreferences(Context.MODE_PRIVATE);
        if (pref.getBoolean(LOGIN_KEY, false)) {
            //has login
            startActivity(new Intent(this, MainActivity.class));
            //must finish this activity (the login activity will not be shown when click back in main activity)
            finish();
        }
        else {
            // Mark login
            pref.edit().putBoolean(LOGIN_KEY, true).apply();

            // Do something
        }
    }
}

The MainActivity:

public class MainActivity extends ActionBarActivity {

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

        // Do something
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
loic
  • 107
  • 1
  • 5
  • This adds about 150-200ms overhead on the app's launch. Is there a way to avoid creating and inflating a LoginActivity if it won't be used? – Prof Feb 14 '21 at 00:23
2
 <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"
        tools:ignore="GoogleAppIndexingWarning">


        <activity android:name=".Activity.MainActivity" />

        <activity android:name=".Activity.SignupActivity" />

        <activity android:name=".Activity.SigninActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
shreyash
  • 21
  • 4
  • Only put your "intent-filter" into SigningActivity or LoginActivity into your AndroidMenifest.xml as like this example. – shreyash Feb 13 '19 at 09:47
1

You need to rearrange your Activity classes a bit I think. It's very simple to decide if your application has run first time or not and launch some Activity based on this decision. I would like to suggest the following architecture.

You can set a LauncherActivity to decide whether you need to start LoginActivity or MainActivity like this:

public class LauncherActivity extends Activity {

    private boolean firstLaunch = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent i;

        SharedPreferences pref = getSharedPreferences(Constants.ApplicationTag, MODE_PRIVATE);
        firstLaunch = pref.getBoolean(Constants.FIRST_LAUNCH, true);

        if (firstLaunch) {
            i = new Intent(LauncherActivity.this, LoginActivity.class);
            startActivity(i);
        } else {
            i = new Intent(LauncherActivity.this, MainActivity.class);
            startActivity(i);
        }

        finish();
    }
}

You have another problem I need to sort out is calling setContentView inside an else statement which is erroneous. You need to put setContentView just after the super.onCreate(savedInstanceState); in any of your Activity.

When you're putting it inside an else statement, the content view may not be set which will cause an application crash.

So remove the checking for first run from MainActivity and move that portion to LauncherActivity which will solve the problem.

The AndroidManifest.xml of the LauncherActivity may look like this

<activity
    android:name=".Activities.LauncherActivity"
    android:label="@string/app_name"
    android:theme="@style/AppTheme.NoActionBar">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98