summaryrefslogtreecommitdiff
path: root/Source/Android/app/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Android/app/src/main/java')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java11
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java2
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java4
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java4
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java32
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java14
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java125
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java3
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/VolleyUtil.java22
9 files changed, 208 insertions, 9 deletions
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<String, List<String>> 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<SettingsItem> 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<String, SettingSection> 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<String, SettingSection> 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;
+ }
+}