2

我只想在我的應用第一次啓動時啓動一個活動,並且從那時起,應用應該每次都啓動另一個(啓動器)活動。所以我實施了基於this SO answer的解決方案。僅當應用第一次啓動時,如何使用特定的活動啓動應用?

該解決方案圍繞boolean首選項(具有startedBeforePreferenceKey作爲以下代碼中的鍵)進行優化。在啓動器活動的onCreate()中,我嘗試使用密鑰startedBeforePreferenceKey檢索首選項,並將其存儲在變量startedBefore中。如果該偏好不存在,則startedBefore被分配爲false

然後我檢查startedBeforefalse,如果是這樣,我創建提到的喜好,給它的true一個值,並將其存儲在SharedPreferences,並啓動這一活動應啓動應用程序的第一次。這樣,當下次執行onCreate()時執行此檢查時,startedBefore將被分配爲true,因此此啓動一次活動不會啓動。

的問題是,當應用程序被啓動的第一次,正常啓動時啓動活動應該只啓動時,應用程序啓動首次應用程序之前短暫表演。

當應用程序第一次啓動時,正常啓動程序根本不應該顯示。直接地,應該顯示我第一次啓動應用程序時要展示的特殊活動。

我該怎麼辦?

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

沒有某種「閃光燈」,你無法真正處理這個問題。我的建議是,啓動屏幕視圖充當您啓動的活動並處理來自那裏的重定向,這樣無論加載哪個活動,您都可以獲得持續的體驗。 – zgc7009

+1

你應該使用某種SplashScreen(如@ zgc7009所說的)以及應用程序版本的使用等等(共享偏好將是存儲數據的好地方)。 Android官方不提供你打算做的事,這是缺點。 – russellhoff

+0

@ zgc7009你見過Instagram嗎? Instagram,Quora,WhatsApp,他們都要求您在第一次啓動應用時註冊或登錄。他們是否使用這種黑客?我不認爲他們會使用hacky解決方案,因爲他們是科技巨頭並擁有最好的工程師。 :s – Solace

回答

2

以上的答案也很好,但如果你需要做的是不閃的活動,那麼你可以使用下面的方法

步驟1:創建一個新的類和應用擴展,並添加以下代碼(不要忘了相應地更改您的活動名稱)。其中最重要的部分是在開始任何活動之前設置適當的意圖標誌。

這GlobalActivity將你的發射活動

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> 

,然後更改的loggedIn varibale任何的該活動相應地供將來使用。

+0

是否有理由在'onCreate()'的第二個語句中使用'getApplicationContext()'而不是'this'?因爲在其他需要'Context'的地方(即在'startActivity()'語句)中使用過'this', – Solace

+0

我應該在哪裏添加啓動器意圖過濾器? – Solace

+1

啓動器意圖過濾器將與往常一樣,與它無關,只需添加您想要首先啓動的活動,上面的GlobalActivity的onCreate方法將在啓動器活動的onCreate之前調用。 –

3

您合作uld創建一個splash活動,並從onCreate方法中檢查下一個要運行的活動,等待幾秒鐘,啓動活動,然後立即完成初始化。

如果您不想創建飛濺,那麼創建一個沒有GUI內容和半透明主題的假飛濺活動,然後在onCreate中執行路由,然後立即完成。這將是如此之快,用戶不會注意到。

+0

我喜歡這個迴應,它提供了一個選項,不強制視覺啓動畫面,但仍然隱藏blip/flash。如果你有時間發佈一個例子,它會很棒,但仍然是一個很好的建議。 – zgc7009

+0

你見過Instagram嗎? Instagram,Quora,WhatsApp,他們都要求您在第一次啓動應用時註冊或登錄。他們是否使用這種黑客?我不認爲他們會使用hacky解決方案,因爲他們是科技巨頭。 :s – Solace

+0

@Solace可以處理這種情況。 – zgc7009

1

你可以將你的活動和普通的啓動器封裝成碎片。然後,在其onCreate中使用fragmentmanager創建另一個活動,並隨時製作啓動器。在將正確的片段放在該活動的屏幕上之前,檢查首選項。

相關問題