From 82f82a6b7d727ff3dcc8b4e5a4d7fc9a214a8596 Mon Sep 17 00:00:00 2001 From: zackhow Date: Sun, 19 Aug 2018 17:38:29 -0400 Subject: Android: Add usage statistics to android. Added an option in General config to enable/disable usage statistics. Added a popup on first open if the user would like to engage in reporting. Clicking cancel or out of the box opts out. Only clicking 'Ok' will enable reporting. Also added a new android specific values to report. --- .../dolphinemu/dolphinemu/DolphinApplication.java | 11 ++ .../org/dolphinemu/dolphinemu/NativeLibrary.java | 2 +- .../features/settings/model/Settings.java | 4 +- .../settings/ui/SettingsFragmentPresenter.java | 4 + .../features/settings/utils/SettingsFile.java | 32 +++++- .../dolphinemu/fragments/EmulationFragment.java | 14 ++- .../org/dolphinemu/dolphinemu/utils/Analytics.java | 125 +++++++++++++++++++++ .../dolphinemu/utils/StartupHandler.java | 3 + .../dolphinemu/dolphinemu/utils/VolleyUtil.java | 22 ++++ 9 files changed, 208 insertions(+), 9 deletions(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/VolleyUtil.java (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java index 22ee55cb70..3fd6e2192b 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java @@ -1,17 +1,28 @@ package org.dolphinemu.dolphinemu; import android.app.Application; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; import org.dolphinemu.dolphinemu.utils.PermissionsHandler; +import org.dolphinemu.dolphinemu.utils.VolleyUtil; public class DolphinApplication extends Application { + public static final String FIRST_OPEN = "FIRST_OPEN"; @Override public void onCreate() { super.onCreate(); + // Passed at emulation start to trigger first open event. + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + SharedPreferences.Editor sPrefsEditor = preferences.edit(); + sPrefsEditor.putBoolean(FIRST_OPEN, true); + sPrefsEditor.apply(); + + VolleyUtil.init(getApplicationContext()); System.loadLibrary("main"); if (PermissionsHandler.hasWriteAccess(getApplicationContext())) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java index c986857e75..922c041a7b 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -322,7 +322,7 @@ public final class NativeLibrary /** * Begins emulation. */ - public static native void Run(String path); + public static native void Run(String path, boolean firstOpen); /** * Begins emulation from the specified savestate. diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java index 5d960a3b9f..599559030a 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java @@ -27,13 +27,15 @@ public class Settings public static final String SECTION_BINDINGS = "Android"; + public static final String SECTION_ANALYTICS = "Analytics"; + private String gameId; private static final Map> configFileSectionsMap = new HashMap<>(); static { - configFileSectionsMap.put(SettingsFile.FILE_NAME_DOLPHIN, Arrays.asList(SECTION_INI_CORE, SECTION_INI_INTERFACE, SECTION_BINDINGS)); + configFileSectionsMap.put(SettingsFile.FILE_NAME_DOLPHIN, Arrays.asList(SECTION_INI_CORE, SECTION_INI_INTERFACE, SECTION_BINDINGS, SECTION_ANALYTICS)); configFileSectionsMap.put(SettingsFile.FILE_NAME_GFX, Arrays.asList(SECTION_GFX_SETTINGS, SECTION_GFX_ENHANCEMENTS, SECTION_GFX_HACKS, SECTION_STEREOSCOPY)); configFileSectionsMap.put(SettingsFile.FILE_NAME_WIIMOTE, Arrays.asList(SECTION_WIIMOTE + 1, SECTION_WIIMOTE + 2, SECTION_WIIMOTE + 3, SECTION_WIIMOTE + 4)); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java index fbdaf8ad92..98d62ccfd1 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java @@ -210,14 +210,17 @@ public final class SettingsFragmentPresenter Setting overclock = null; Setting speedLimit = null; Setting audioStretch = null; + Setting analytics = null; SettingSection coreSection = mSettings.getSection(Settings.SECTION_INI_CORE); + SettingSection analyticsSection = mSettings.getSection(Settings.SECTION_ANALYTICS); cpuCore = coreSection.getSetting(SettingsFile.KEY_CPU_CORE); dualCore = coreSection.getSetting(SettingsFile.KEY_DUAL_CORE); overclockEnable = coreSection.getSetting(SettingsFile.KEY_OVERCLOCK_ENABLE); overclock = coreSection.getSetting(SettingsFile.KEY_OVERCLOCK_PERCENT); speedLimit = coreSection.getSetting(SettingsFile.KEY_SPEED_LIMIT); audioStretch = coreSection.getSetting(SettingsFile.KEY_AUDIO_STRETCH); + analytics = analyticsSection.getSetting(SettingsFile.KEY_ANALYTICS_ENABLED); // TODO: Having different emuCoresEntries/emuCoresValues for each architecture is annoying. // The proper solution would be to have one emuCoresEntries and one emuCoresValues @@ -246,6 +249,7 @@ public final class SettingsFragmentPresenter sl.add(new SliderSetting(SettingsFile.KEY_OVERCLOCK_PERCENT, Settings.SECTION_INI_CORE, R.string.overclock_title, R.string.overclock_title_description, 400, "%", 100, overclock)); sl.add(new SliderSetting(SettingsFile.KEY_SPEED_LIMIT, Settings.SECTION_INI_CORE, R.string.speed_limit, 0, 200, "%", 100, speedLimit)); sl.add(new CheckBoxSetting(SettingsFile.KEY_AUDIO_STRETCH, Settings.SECTION_INI_CORE, R.string.audio_stretch, R.string.audio_stretch_description, false, audioStretch)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_ANALYTICS_ENABLED, Settings.SECTION_ANALYTICS, R.string.analytics, 0, false, analytics)); } private void addInterfaceSettings(ArrayList sl) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java index 2260b413f7..b68c879716 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java @@ -50,6 +50,9 @@ public final class SettingsFile public static final String KEY_SLOT_A_DEVICE = "SlotA"; public static final String KEY_SLOT_B_DEVICE = "SlotB"; + public static final String KEY_ANALYTICS_ENABLED = "Enabled"; + public static final String KEY_ANALYTICS_PERMISSION_ASKED = "PermissionAsked"; + public static final String KEY_USE_PANIC_HANDLERS = "UsePanicHandlers"; public static final String KEY_OSD_MESSAGES = "OnScreenDisplayMessages"; @@ -294,12 +297,14 @@ public final class SettingsFile catch (FileNotFoundException e) { Log.error("[SettingsFile] File not found: " + ini.getAbsolutePath() + e.getMessage()); - view.onSettingsFileNotFound(); + if (view != null) + view.onSettingsFileNotFound(); } catch (IOException e) { Log.error("[SettingsFile] Error reading from: " + ini.getAbsolutePath()+ e.getMessage()); - view.onSettingsFileNotFound(); + if (view != null) + view.onSettingsFileNotFound(); } finally { @@ -384,12 +389,14 @@ public final class SettingsFile catch (FileNotFoundException e) { Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.getMessage()); - view.showToastMessage("Error saving " + fileName + ".ini: " + e.getMessage()); + if (view != null) + view.showToastMessage("Error saving " + fileName + ".ini: " + e.getMessage()); } catch (UnsupportedEncodingException e) { Log.error("[SettingsFile] Bad encoding; please file a bug report: " + fileName + ".ini: " + e.getMessage()); - view.showToastMessage("Error saving " + fileName + ".ini: " + e.getMessage()); + if (view != null) + view.showToastMessage("Error saving " + fileName + ".ini: " + e.getMessage()); } finally { @@ -489,6 +496,23 @@ public final class SettingsFile sections.put(Settings.SECTION_INI_CORE, coreSection); } + public static void firstAnalyticsAdd(boolean enabled) + { + HashMap dolphinSections = readFile(SettingsFile.FILE_NAME_DOLPHIN, null); + SettingSection analyticsSection = dolphinSections.get(Settings.SECTION_ANALYTICS); + + Setting analyticsEnabled = new StringSetting(KEY_ANALYTICS_ENABLED, Settings.SECTION_ANALYTICS, enabled ? "True" : "False"); + Setting analyticsFirstAsk = new StringSetting(KEY_ANALYTICS_PERMISSION_ASKED, Settings.SECTION_ANALYTICS, "True"); + + analyticsSection.putSetting(analyticsFirstAsk); + analyticsSection.putSetting(analyticsEnabled); + + dolphinSections.put(Settings.SECTION_ANALYTICS, analyticsSection); + + TreeMap saveSection = new TreeMap<>(dolphinSections); + saveFile(SettingsFile.FILE_NAME_DOLPHIN, saveSection, null); + } + /** * For a line of text, determines what type of data is being represented, and returns * a Setting object containing this data. diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index c7e13a9999..15e5980acc 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -16,6 +16,7 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.Toast; +import org.dolphinemu.dolphinemu.DolphinApplication; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.EmulationActivity; @@ -84,7 +85,12 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); String gamePath = getArguments().getString(KEY_GAMEPATH); - mEmulationState = new EmulationState(gamePath, getTemporaryStateFilePath()); + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); + boolean firstOpen = preferences.getBoolean(DolphinApplication.FIRST_OPEN, true); + SharedPreferences.Editor sPrefsEditor = preferences.edit(); + sPrefsEditor.putBoolean(DolphinApplication.FIRST_OPEN, false); + sPrefsEditor.apply(); + mEmulationState = new EmulationState(gamePath, getTemporaryStateFilePath(), firstOpen); } /** @@ -264,10 +270,12 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C private Surface mSurface; private boolean mRunWhenSurfaceIsValid; private boolean loadPreviousTemporaryState; + private boolean firstOpen; private final String temporaryStatePath; - EmulationState(String gamePath, String temporaryStatePath) + EmulationState(String gamePath, String temporaryStatePath, boolean firstOpen) { + this.firstOpen = firstOpen; mGamePath = gamePath; this.temporaryStatePath = temporaryStatePath; // Starting state is stopped. @@ -411,7 +419,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C else { Log.debug("[EmulationFragment] Starting emulation thread."); - NativeLibrary.Run(mGamePath); + NativeLibrary.Run(mGamePath, firstOpen); } }, "NativeEmulation"); mEmulationThread.start(); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java new file mode 100644 index 0000000000..158e7c2055 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java @@ -0,0 +1,125 @@ +package org.dolphinemu.dolphinemu.utils; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.os.Build; +import android.preference.PreferenceManager; +import android.support.v4.content.LocalBroadcastManager; + +import com.android.volley.Request; +import com.android.volley.toolbox.StringRequest; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.features.settings.model.Settings; +import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile; +import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; + +public class Analytics +{ + private static DirectoryStateReceiver directoryStateReceiver; + + private static final String analyticsAsked = Settings.SECTION_ANALYTICS + "_" + SettingsFile.KEY_ANALYTICS_PERMISSION_ASKED; + private static final String analyticsEnabled = Settings.SECTION_ANALYTICS + "_" + SettingsFile.KEY_ANALYTICS_ENABLED; + + private static final String DEVICE_MANUFACTURER = "DEVICE_MANUFACTURER"; + private static final String DEVICE_OS = "DEVICE_OS"; + private static final String DEVICE_MODEL = "DEVICE_MODEL"; + private static final String DEVICE_TYPE = "DEVICE_TYPE"; + + private static String deviceType; + + public static void checkAnalyticsInit(Context context) + { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + if (!preferences.getBoolean(analyticsAsked, false)) + { + if (!DirectoryInitializationService.areDolphinDirectoriesReady()) + { + // Wait for directories to get initialized + IntentFilter statusIntentFilter = new IntentFilter( + DirectoryInitializationService.BROADCAST_ACTION); + + directoryStateReceiver = new DirectoryStateReceiver(directoryInitializationState -> + { + if (directoryInitializationState == DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) + { + LocalBroadcastManager.getInstance(context).unregisterReceiver(directoryStateReceiver); + directoryStateReceiver = null; + showMessage(context, preferences); + } + }); + // Registers the DirectoryStateReceiver and its intent filters + LocalBroadcastManager.getInstance(context).registerReceiver( + directoryStateReceiver, + statusIntentFilter); + } + else + { + showMessage(context, preferences); + } + } + // Get device type now since we have a context + deviceType = TvUtil.isLeanback(context) ? "android-tv" : "android-mobile"; + } + + private static void showMessage(Context context, SharedPreferences preferences) + { + // We asked, set to true regardless of answer + SharedPreferences.Editor sPrefsEditor = preferences.edit(); + sPrefsEditor.putBoolean(analyticsAsked, true); + sPrefsEditor.apply(); + + new AlertDialog.Builder(context) + .setTitle(context.getString(R.string.analytics)) + .setMessage(context.getString(R.string.analytics_desc)) + .setPositiveButton(R.string.yes, (dialogInterface, i) -> + { + sPrefsEditor.putBoolean(analyticsEnabled, true); + sPrefsEditor.apply(); + SettingsFile.firstAnalyticsAdd(true); + }) + .setNegativeButton(R.string.no, (dialogInterface, i) -> + { + sPrefsEditor.putBoolean(analyticsEnabled, false); + sPrefsEditor.apply(); + SettingsFile.firstAnalyticsAdd(false); + }) + .create() + .show(); + } + + public static void sendReport(String endpoint, byte[] data) + { + StringRequest request = new StringRequest(Request.Method.POST, endpoint, + null, error -> Log.debug("Send Report Failure code: " + + error.networkResponse.statusCode)) + { + @Override + public byte[] getBody() + { + return data; + } + }; + + VolleyUtil.getQueue().add(request); + } + + public static String getValue(String key) + { + switch (key) + { + case DEVICE_MODEL: + return Build.MODEL; + case DEVICE_MANUFACTURER: + return Build.MANUFACTURER; + case DEVICE_OS: + return String.valueOf(Build.VERSION.SDK_INT); + case DEVICE_TYPE: + return deviceType; + default: + return ""; + } + } +} 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 1be60cd21f..232de7f347 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 @@ -14,6 +14,9 @@ public final class StartupHandler // Ask the user to grant write permission if it's not already granted PermissionsHandler.checkWritePermission(parent); + // Ask the user if he wants to enable analytics if we haven't yet. + Analytics.checkAnalyticsInit(parent); + String start_file = ""; Bundle extras = parent.getIntent().getExtras(); if (extras != null) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/VolleyUtil.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/VolleyUtil.java new file mode 100644 index 0000000000..1e523bb45f --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/VolleyUtil.java @@ -0,0 +1,22 @@ +package org.dolphinemu.dolphinemu.utils; + +import android.content.Context; + +import com.android.volley.RequestQueue; +import com.android.volley.toolbox.Volley; + +public class VolleyUtil +{ + private static RequestQueue queue; + + public static void init(Context context) + { + if (queue == null) + queue = Volley.newRequestQueue(context); + } + + public static RequestQueue getQueue() + { + return queue; + } +} -- cgit v1.2.3 From a26cf8febcaf8d8f8d44a44ae834614bf89de2a8 Mon Sep 17 00:00:00 2001 From: zackhow Date: Sat, 25 Aug 2018 16:57:07 -0400 Subject: Android: Analytics - Set new session after being closed for 6 hours --- .../dolphinemu/dolphinemu/DolphinApplication.java | 9 ----- .../dolphinemu/fragments/EmulationFragment.java | 8 ++--- .../dolphinemu/ui/main/MainActivity.java | 14 ++++++++ .../dolphinemu/ui/main/TvMainActivity.java | 14 ++++++++ .../dolphinemu/utils/StartupHandler.java | 38 ++++++++++++++++++++++ 5 files changed, 69 insertions(+), 14 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java index 3fd6e2192b..251df3b117 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java @@ -1,8 +1,6 @@ package org.dolphinemu.dolphinemu; import android.app.Application; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; import org.dolphinemu.dolphinemu.utils.PermissionsHandler; @@ -10,18 +8,11 @@ import org.dolphinemu.dolphinemu.utils.VolleyUtil; public class DolphinApplication extends Application { - public static final String FIRST_OPEN = "FIRST_OPEN"; @Override public void onCreate() { super.onCreate(); - // Passed at emulation start to trigger first open event. - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); - SharedPreferences.Editor sPrefsEditor = preferences.edit(); - sPrefsEditor.putBoolean(FIRST_OPEN, true); - sPrefsEditor.apply(); - VolleyUtil.init(getApplicationContext()); System.loadLibrary("main"); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index 15e5980acc..2fb4ad8440 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -16,7 +16,6 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.Toast; -import org.dolphinemu.dolphinemu.DolphinApplication; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.EmulationActivity; @@ -25,11 +24,10 @@ import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; import org.dolphinemu.dolphinemu.services.DirectoryInitializationService.DirectoryInitializationState; import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; import org.dolphinemu.dolphinemu.utils.Log; +import org.dolphinemu.dolphinemu.utils.StartupHandler; import java.io.File; -import rx.functions.Action1; - public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback { private static final String KEY_GAMEPATH = "gamepath"; @@ -86,9 +84,9 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C String gamePath = getArguments().getString(KEY_GAMEPATH); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); - boolean firstOpen = preferences.getBoolean(DolphinApplication.FIRST_OPEN, true); + boolean firstOpen = preferences.getBoolean(StartupHandler.NEW_SESSION, true); SharedPreferences.Editor sPrefsEditor = preferences.edit(); - sPrefsEditor.putBoolean(DolphinApplication.FIRST_OPEN, false); + sPrefsEditor.putBoolean(StartupHandler.NEW_SESSION, false); sPrefsEditor.apply(); mEmulationState = new EmulationState(gamePath, getTemporaryStateFilePath(), firstOpen); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java index a2d47444af..fe367276cf 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java @@ -89,6 +89,20 @@ public final class MainActivity extends AppCompatActivity implements MainView mPresenter.onDestroy(); } + @Override + protected void onStart() + { + super.onStart(); + StartupHandler.checkSessionReset(this); + } + + @Override + protected void onStop() + { + super.onStop(); + StartupHandler.setSessionTime(this); + } + // TODO: Replace with a ButterKnife injection. private void findViews() { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java index 1e3fb5ba8d..a6c25d67d3 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java @@ -72,6 +72,20 @@ public final class TvMainActivity extends FragmentActivity implements MainView mPresenter.onDestroy(); } + @Override + protected void onStart() + { + super.onStart(); + StartupHandler.checkSessionReset(this); + } + + @Override + protected void onStop() + { + super.onStop(); + StartupHandler.setSessionTime(this); + } + void setupUI() { final FragmentManager fragmentManager = getSupportFragmentManager(); mBrowseFragment = new BrowseSupportFragment(); 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 232de7f347..22456d20e5 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 @@ -1,14 +1,23 @@ package org.dolphinemu.dolphinemu.utils; +import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.v4.app.FragmentActivity; import android.text.TextUtils; import org.dolphinemu.dolphinemu.activities.EmulationActivity; +import java.util.Date; + public final class StartupHandler { + public static final String NEW_SESSION = "NEW_SESSION"; + public static final String LAST_CLOSED = "LAST_CLOSED"; + public static final Long SESSION_TIMEOUT = 21600000L; // 6 hours in milliseconds + public static void HandleInit(FragmentActivity parent) { // Ask the user to grant write permission if it's not already granted @@ -31,4 +40,33 @@ public final class StartupHandler parent.finish(); } } + + /** + * There isn't a good way to determine a new session. setSessionTime is called if the main + * activity goes into the background. + */ + public static void setSessionTime(Context context) + { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + SharedPreferences.Editor sPrefsEditor = preferences.edit(); + sPrefsEditor.putLong(LAST_CLOSED, new Date(System.currentTimeMillis()).getTime()); + sPrefsEditor.apply(); + } + + /** + * Called to determine if we treat this activity start as a new session. + */ + public static void checkSessionReset(Context context) + { + Long currentTime = new Date(System.currentTimeMillis()).getTime(); + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + Long lastOpen = preferences.getLong(LAST_CLOSED, 0); + if (currentTime > (lastOpen + SESSION_TIMEOUT)) + { + // Passed at emulation start to trigger first open event. + SharedPreferences.Editor sPrefsEditor = preferences.edit(); + sPrefsEditor.putBoolean(NEW_SESSION, true); + sPrefsEditor.apply(); + } + } } -- cgit v1.2.3