Search code examples
androidandroid-activityoncreateonresumeandroid-launcher

How to launch the app with a specific Activity only when the app is launched for the first time?


I wanted to start an Activity only the first time my App is launched, and from that point on, the app should launch with another (the launcher) activity every time. So I implemented a solution based on this SO answer.

The solution revolves around a boolean preference (the one having startedBeforePreferenceKey as key in the following code). In the onCreate() of the launcher activity, I try to retrieve a preference with the key startedBeforePreferenceKey and store it in a variable startedBefore. If the preference does not exist, startedBefore is assigned false.

Then I check if startedBefore is false, and if so, I create the mentioned preference, give it a value of true and store it in the SharedPreferences, and start this activity which should launch the app for the first time. This way, when this check is executed next time the onCreate() is being executed, startedBefore will be assigned true and thus this launch-once activity won't start.

THE PROBLEM IS that when the app is launched for the first time, the normal launcher SHOWS MOMENTARILY before the activity which should launch the app only when the app is launched for the first time is started.

When the app is launched for the first time, the normal launcher should not show at all. Directly, the special activity which I want to show when app is launched for the first time, should show.

What should I do?

SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
boolean startedBefore = sharedPreferences.getBoolean(getString(R.string.startedBeforePreferenceKey), false);

if (!startedBefore) {
    SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit();
    sharedPreferencesEditor.putBoolean(getString(R.string.startedBeforePreferenceKey), true);
    sharedPreferencesEditor.commit();
    startActivity(new Intent(this, MainActivity.class)); 
} 

EDIT: @HammadTariqSahi

First, this excerpt from LogCat:

03-16 08:42:25.629: E/AndroidRuntime(1837): FATAL EXCEPTION: main
03-16 08:42:25.629: E/AndroidRuntime(1837): Process: tests.globalactivitytest, PID: 1837
03-16 08:42:25.629: E/AndroidRuntime(1837): java.lang.RuntimeException: Unable to instantiate application tests.globalactivitytest.activity.GlobalActivity: java.lang.ClassNotFoundException: Didn't find class "tests.globalactivitytest.activity.GlobalActivity" on path: DexPathList[[zip file "/data/app/tests.globalactivitytest-1/base.apk"],nativeLibraryDirectories=[/data/app/tests.globalactivitytest-1/lib/x86, /vendor/lib, /system/lib]]
03-16 08:42:25.629: E/AndroidRuntime(1837):     at android.app.LoadedApk.makeApplication(LoadedApk.java:578)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4680)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at android.app.ActivityThread.-wrap1(ActivityThread.java)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at android.os.Handler.dispatchMessage(Handler.java:102)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at android.os.Looper.loop(Looper.java:148)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at android.app.ActivityThread.main(ActivityThread.java:5417)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at java.lang.reflect.Method.invoke(Native Method)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
03-16 08:42:25.629: E/AndroidRuntime(1837): Caused by: java.lang.ClassNotFoundException: Didn't find class "tests.globalactivitytest.activity.GlobalActivity" on path: DexPathList[[zip file "/data/app/tests.globalactivitytest-1/base.apk"],nativeLibraryDirectories=[/data/app/tests.globalactivitytest-1/lib/x86, /vendor/lib, /system/lib]]
03-16 08:42:25.629: E/AndroidRuntime(1837):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at android.app.Instrumentation.newApplication(Instrumentation.java:981)
03-16 08:42:25.629: E/AndroidRuntime(1837):     at android.app.LoadedApk.makeApplication(LoadedApk.java:573)
03-16 08:42:25.629: E/AndroidRuntime(1837):     ... 9 more
03-16 08:42:25.629: E/AndroidRuntime(1837):     Suppressed: java.lang.ClassNotFoundException: tests.globalactivitytest.activity.GlobalActivity
03-16 08:42:25.629: E/AndroidRuntime(1837):         at java.lang.Class.classForName(Native Method)
03-16 08:42:25.629: E/AndroidRuntime(1837):         at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
03-16 08:42:25.629: E/AndroidRuntime(1837):         at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
03-16 08:42:25.629: E/AndroidRuntime(1837):         at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
03-16 08:42:25.629: E/AndroidRuntime(1837):         ... 12 more
03-16 08:42:25.629: E/AndroidRuntime(1837):     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available

GlobalActivity.java:

package tests.globalactivitytest;

import android.app.Application;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

public class GlobalActivity extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
        //SharedPreferences.Editor editor = sharedPreferences.edit(); 
        boolean launchedBefore = sharedPreferences.getBoolean("launchedBefore", false);
        if (launchedBefore) {
            Intent intent = new Intent(this, MainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        } else {
            Intent intent = new Intent(this, LaunchOnceActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
    }
}

MainActivity.java:

package tests.globalactivitytest;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends Activity {

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

LaunchOnceActivity.java:

package tests.globalactivitytest;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class LaunchOnceActivity extends Activity {

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

Manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="tests.globalactivitytest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="23" />

    <application
        android:name=".activity.GlobalActivity"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            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=".LaunchOnceActivity"
            android:label="@string/title_activity_launch_once" >
        </activity>
    </application>

</manifest>

Solution

  • Above answers are also fine but if you need to do it without splash activity then you can use below method

    Step 1:Create a new class and extends from Application and add below code (do not forget to change your activity name accordingly). The most important part of it is setting appropriate Intent Flags before starting any of the activities.

    This GlobalActivity will be called before your launcher Activity

    public class GlobalActivity extends Application {
    
    
    @Override
    public void onCreate() {
        super.onCreate();
      SharedPreferences userInfo = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
      SharedPreferences.Editor  editor = userInfo.edit();
      boolean logedIn =  userInfo.getBoolean("loggedIn", false);
        if (logedIn)
        {
            Intent intent = new Intent(this,MainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            startActivity(intent);
        }
        else {
            Intent intent = new Intent(this,LaunchOnceActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            startActivity(intent);
        }
    }
    }
    

    Step 2: Your manifest file should be like below

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.app.appid" >
    
    
    <application
    android:name=".GlobalActivity"
    android:allowBackup="true"
    android:icon="@drawable/launch"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        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=".LaunchOnceActivity"
        android:label="Launch Once" >
    </activity>
    </application>
    </manifest>
    

    And then change loggedIn varibale in any of the activity accordingly for future use.