Reputation: 9010
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>
Upvotes: 3
Views: 4414
Reputation: 13441
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.
Upvotes: 5
Reputation: 2121
You can wrap your activity and the normal launcher in fragments. Then, create another activity with a fragmentmanager in its onCreate and make that your launcher at all times. Check for the preference before putting the right fragment on the screen in that activity.
Upvotes: 1
Reputation: 28168
You could create a splash activity and from its onCreate method check which activity to run next, wait a few seconds, launch the activity and then immediately finish the splash.
If you don't want to create a splash, then create a fake splash activity with no GUI content and translucent theme, and do the routing in the onCreate, then finish immediately. This will be so fast the user won't notice.
Upvotes: 3