diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.kt index a4e5d3600a..7d32f8b56a 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.kt @@ -103,11 +103,6 @@ class MainActivity : AppCompatActivity(), MainView, OnRefreshListener, ThemeProv presenter.onResume() } - override fun onStart() { - super.onStart() - StartupHandler.checkSessionReset(this) - } - override fun onStop() { super.onStop() if (isChangingConfigurations) { @@ -116,8 +111,6 @@ class MainActivity : AppCompatActivity(), MainView, OnRefreshListener, ThemeProv // If the currently selected platform tab changed, save it to disk NativeConfig.save(NativeConfig.LAYER_BASE) } - - StartupHandler.setSessionTime(this) } override fun onCreateOptionsMenu(menu: Menu): Boolean { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt index 9beec74fc3..6a0542d483 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt @@ -76,17 +76,11 @@ class TvMainActivity : FragmentActivity(), MainView, OnRefreshListener { presenter.onResume() } - override fun onStart() { - super.onStart() - StartupHandler.checkSessionReset(this) - } - override fun onStop() { super.onStop() if (isChangingConfigurations) { MainPresenter.skipRescanningLibrary() } - StartupHandler.setSessionTime(this) } private fun setupUI() { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ActivityTracker.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ActivityTracker.kt index b3a6a5d91a..83a34e3e8c 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ActivityTracker.kt +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ActivityTracker.kt @@ -3,14 +3,29 @@ package org.dolphinemu.dolphinemu.utils import android.app.Activity import android.app.Application.ActivityLifecycleCallbacks import android.os.Bundle +import org.dolphinemu.dolphinemu.ui.main.MainView class ActivityTracker : ActivityLifecycleCallbacks { - val resumedActivities = HashSet() - var backgroundExecutionAllowed = false + private val resumedActivities = HashSet() + private var backgroundExecutionAllowed = false + private var firstStart = true - override fun onActivityCreated(activity: Activity, bundle: Bundle?) {} + private fun isMainActivity(activity: Activity): Boolean { + return activity is MainView + } - override fun onActivityStarted(activity: Activity) {} + override fun onActivityCreated(activity: Activity, bundle: Bundle?) { + if (isMainActivity(activity)) { + firstStart = bundle == null + } + } + + override fun onActivityStarted(activity: Activity) { + if (isMainActivity(activity)) { + StartupHandler.reportStartToAnalytics(activity.applicationContext, firstStart) + firstStart = false + } + } override fun onActivityResumed(activity: Activity) { resumedActivities.add(activity) @@ -28,7 +43,11 @@ class ActivityTracker : ActivityLifecycleCallbacks { } } - override fun onActivityStopped(activity: Activity) {} + override fun onActivityStopped(activity: Activity) { + if (isMainActivity(activity)) { + StartupHandler.updateSessionTimestamp(activity.applicationContext) + } + } override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) {} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java index 1d7342372f..2942bfe29f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java @@ -84,7 +84,6 @@ public final class DirectoryInitialization extractSysDirectory(context); NativeLibrary.Initialize(); - NativeLibrary.ReportStartToAnalytics(); areDirectoriesAvailable = true; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java index 63b8657f83..db003b82b2 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java @@ -2,6 +2,7 @@ package org.dolphinemu.dolphinemu.utils; +import android.app.Activity; import android.content.ClipData; import android.content.Context; import android.content.Intent; @@ -11,6 +12,7 @@ import android.os.Bundle; import android.text.TextUtils; import androidx.fragment.app.FragmentActivity; +import androidx.lifecycle.LifecycleOwner; import androidx.preference.PreferenceManager; import org.dolphinemu.dolphinemu.NativeLibrary; @@ -22,7 +24,7 @@ import java.util.Objects; public final class StartupHandler { - public static final String LAST_CLOSED = "LAST_CLOSED"; + private static final String SESSION_TIMESTAMP = "SESSION_TIMESTAMP"; public static void HandleInit(FragmentActivity parent) { @@ -88,29 +90,38 @@ public final class StartupHandler return null; } + private static Instant getSessionTimestamp(Context context) + { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + long timestamp = preferences.getLong(SESSION_TIMESTAMP, 0); + return Instant.ofEpochMilli(timestamp); + } + /** - * There isn't a good way to determine a new session. setSessionTime is called if the main - * activity goes into the background. + * Called on activity stop / to set timestamp to "now". */ - public static void setSessionTime(Context context) + public static void updateSessionTimestamp(Context context) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences.Editor sPrefsEditor = preferences.edit(); - sPrefsEditor.putLong(LAST_CLOSED, System.currentTimeMillis()); + sPrefsEditor.putLong(SESSION_TIMESTAMP, Instant.now().toEpochMilli()); sPrefsEditor.apply(); } /** - * Called to determine if we treat this activity start as a new session. + * Called on activity start. Generates analytics start event if it's a fresh start of the app, or + * if it's a start after a long period of the app not being used (during which time the process + * may be restarted for power/memory saving reasons, although app state persists). */ - public static void checkSessionReset(Context context) + public static void reportStartToAnalytics(Context context, boolean firstStart) { - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - long lastOpen = preferences.getLong(LAST_CLOSED, 0); - final Instant current = Instant.now(); - final Instant lastOpened = Instant.ofEpochMilli(lastOpen); - if (current.isAfter(lastOpened.plus(6, ChronoUnit.HOURS))) + final Instant sessionTimestamp = getSessionTimestamp(context); + final Instant now = Instant.now(); + if (firstStart || now.isAfter(sessionTimestamp.plus(6, ChronoUnit.HOURS))) { + // Just in case: ensure start event won't be accidentally sent too often. + updateSessionTimestamp(context); + new AfterDirectoryInitializationRunner().runWithoutLifecycle( NativeLibrary::ReportStartToAnalytics); }