如何仅在应用程序首次启动时以特定 Activity 启动应用程序?

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

我只想在我的应用程序第一次启动时启动一个 Activity,从那时起,该应用程序每次都应该与另一个(启动器)一起启动 activity。所以我实现了一个基于this SO answer的解决方案。

解决方案围绕 boolean 首选项(在以下代码中以 startedBeforePreferenceKey 作为键)。在启动器 activity 的 onCreate() 中,我尝试使用键 startedBeforePreferenceKey 检索首选项并将其存储在变量 startedBefore 中。如果首选项不存在,则分配 startedBefore false

然后我检查 startedBefore 是否是 false,如果是,我创建提到的首选项,给它一个值 true 并将它存储在SharedPreferences,然后启动这个 activity,这应该是第一次启动该应用程序。这样,当下次执行 onCreate() 时执行此检查时,startedBefore 将被分配 true,因此此启动一次 activity 将不会启动。

问题是,当应用程序首次启动时,普通启动器会在 activity 之前短暂显示,只有在应用程序启动时才会启动应用程序首次启动 已启动

第一次启动应用程序时,正常的启动器根本不应该显示。直接,我想在应用程序第一次启动时显示的特殊activity应该显示。

我该怎么办?

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)); 
} 

编辑: @HammadTariqSahi

首先,摘录自 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);
    }
}

清单文件:

<?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>

您可以创建启动画面 activity 并从其 onCreate 方法检查接下来是 activity 到 运行,等待几秒钟,启动 activity 然后立即完成飞溅。

如果您不想创建启动画面,则创建一个没有 GUI 内容和半透明主题的假启动画面 activity,并在 onCreate 中进行路由,然后立即完成。这将是如此之快,用户不会注意到。

您可以将 activity 和普通启动器打包成片段。然后,在其 onCreate 中创建另一个带有 fragmentmanager 的 activity 并始终将其作为您的启动器。在 activity.

中将正确的片段放在屏幕上之前检查首选项

上面的答案也很好,但如果你需要不飞溅activity那么你可以使用下面的方法

第 1 步:创建一个新的 class 并从应用程序扩展并添加以下代码(不要忘记相应地更改您的 activity 名称)。其中最重要的部分是在开始任何活动之前设置适当的 Intent Flags。

这个 GlobalActivity 将在您的启动器之前被调用 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);
    }
}
}

第 2 步: 您的清单文件应如下所示

<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>

然后相应地更改任何 activity 中的 loggedIn 变量以供将来使用。