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/NativeLibrary.java23
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java15
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/MotionAlertDialog.java80
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputBindingSetting.java53
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/RumbleBindingSetting.java75
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.java1
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java18
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java15
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/RumbleBindingViewHolder.java53
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java2
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Rumble.java98
11 files changed, 335 insertions, 98 deletions
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 acfac1e0f4..3536a17776 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
@@ -7,15 +7,11 @@
package org.dolphinemu.dolphinemu;
import android.app.AlertDialog;
-import android.content.Context;
-import android.os.Build;
-import android.os.VibrationEffect;
-import android.os.Vibrator;
-import android.preference.PreferenceManager;
import android.view.Surface;
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import org.dolphinemu.dolphinemu.utils.Log;
+import org.dolphinemu.dolphinemu.utils.Rumble;
import java.lang.ref.WeakReference;
@@ -245,22 +241,7 @@ public final class NativeLibrary
return;
}
- if (PreferenceManager.getDefaultSharedPreferences(emulationActivity)
- .getBoolean("phoneRumble", true))
- {
- Vibrator vibrator = (Vibrator) emulationActivity.getSystemService(Context.VIBRATOR_SERVICE);
- if (vibrator != null && vibrator.hasVibrator())
- {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
- {
- vibrator.vibrate(VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
- }
- else
- {
- vibrator.vibrate(100);
- }
- }
- }
+ Rumble.checkRumble(padID, state);
}
public static native String GetUserSetting(String gameID, String Section, String Key);
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
index b4050dfd81..2aad63d365 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
@@ -50,6 +50,7 @@ import org.dolphinemu.dolphinemu.utils.ControllerMappingHelper;
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
import org.dolphinemu.dolphinemu.utils.Java_GCAdapter;
import org.dolphinemu.dolphinemu.utils.Java_WiimoteAdapter;
+import org.dolphinemu.dolphinemu.utils.Rumble;
import org.dolphinemu.dolphinemu.utils.TvUtil;
import java.lang.annotation.Retention;
@@ -277,6 +278,7 @@ public final class EmulationActivity extends AppCompatActivity
Java_GCAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
Java_WiimoteAdapter.manager = (UsbManager) getSystemService(Context.USB_SERVICE);
+ Rumble.initRumble(this);
setContentView(R.layout.activity_emulation);
@@ -362,6 +364,13 @@ public final class EmulationActivity extends AppCompatActivity
}
@Override
+ protected void onStop()
+ {
+ super.onStop();
+ Rumble.clear();
+ }
+
+ @Override
public void onBackPressed()
{
if (!mDeviceHasTouchScreen)
@@ -693,6 +702,7 @@ public final class EmulationActivity extends AppCompatActivity
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putBoolean("phoneRumble", state);
editor.apply();
+ Rumble.setPhoneVibrator(state, this);
}
@@ -950,6 +960,11 @@ public final class EmulationActivity extends AppCompatActivity
.commit();
}
+ public boolean deviceHasTouchScreen()
+ {
+ return mDeviceHasTouchScreen;
+ }
+
public String getSelectedTitle()
{
return mSelectedTitle;
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/MotionAlertDialog.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/MotionAlertDialog.java
index 56339bba3c..cb0564d06a 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/MotionAlertDialog.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/MotionAlertDialog.java
@@ -3,14 +3,18 @@ package org.dolphinemu.dolphinemu.dialogs;
import android.app.AlertDialog;
import android.content.Context;
import android.content.SharedPreferences;
+import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.model.view.InputBindingSetting;
+import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
import org.dolphinemu.dolphinemu.utils.ControllerMappingHelper;
import org.dolphinemu.dolphinemu.utils.Log;
+import org.dolphinemu.dolphinemu.utils.Rumble;
import org.dolphinemu.dolphinemu.utils.TvUtil;
import java.util.ArrayList;
@@ -49,7 +53,8 @@ public final class MotionAlertDialog extends AlertDialog
case KeyEvent.ACTION_UP:
if (!ControllerMappingHelper.shouldKeyBeIgnored(event.getDevice(), keyCode))
{
- saveKeyInput(event);
+ setting.onKeyInput(event);
+ dismiss();
}
// Even if we ignore the key, we still consume it. Thus return true regardless.
return true;
@@ -63,13 +68,11 @@ public final class MotionAlertDialog extends AlertDialog
public boolean onKeyLongPress(int keyCode, KeyEvent event)
{
// Option to clear by long back is only needed on the TV interface
- if (TvUtil.isLeanback(getContext()))
+ if (TvUtil.isLeanback(getContext()) && keyCode == KeyEvent.KEYCODE_BACK)
{
- if (keyCode == KeyEvent.KEYCODE_BACK)
- {
- clearBinding();
- return true;
- }
+ setting.clearValue();
+ dismiss();
+ return true;
}
return super.onKeyLongPress(keyCode, event);
}
@@ -162,69 +165,10 @@ public final class MotionAlertDialog extends AlertDialog
if (numMovedAxis == 1)
{
mWaitingForEvent = false;
- saveMotionInput(input, lastMovedRange, lastMovedDir);
+ setting.onMotionInput(input, lastMovedRange, lastMovedDir);
+ dismiss();
}
}
-
return true;
}
-
- /**
- * Saves the provided key input setting both to the INI file (so native code can use it) and as
- * an Android preference (so it persists correctly and is human-readable.)
- *
- * @param keyEvent KeyEvent of this key press.
- */
- private void saveKeyInput(KeyEvent keyEvent)
- {
- InputDevice device = keyEvent.getDevice();
- String bindStr = "Device '" + device.getDescriptor() + "'-Button " + keyEvent.getKeyCode();
- String uiString = device.getName() + ": Button " + keyEvent.getKeyCode();
-
- saveInput(bindStr, uiString);
- }
-
- /**
- * Saves the provided motion input setting both to the INI file (so native code can use it) and as
- * an Android preference (so it persists correctly and is human-readable.)
- *
- * @param device InputDevice from which the input event originated.
- * @param motionRange MotionRange of the movement
- * @param axisDir Either '-' or '+'
- */
- private void saveMotionInput(InputDevice device, InputDevice.MotionRange motionRange,
- char axisDir)
- {
- String bindStr =
- "Device '" + device.getDescriptor() + "'-Axis " + motionRange.getAxis() + axisDir;
- String uiString = device.getName() + ": Axis " + motionRange.getAxis() + axisDir;
-
- saveInput(bindStr, uiString);
- }
-
- /**
- * Save the input string to settings and SharedPreferences, then dismiss this Dialog.
- */
- private void saveInput(String bind, String ui)
- {
- setting.setValue(bind);
-
- SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
- SharedPreferences.Editor editor = preferences.edit();
-
- editor.putString(setting.getKey(), ui);
- editor.apply();
-
- dismiss();
- }
-
- private void clearBinding()
- {
- setting.setValue("");
- SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
- SharedPreferences.Editor editor = preferences.edit();
- editor.remove(setting.getKey());
- editor.apply();
- dismiss();
- }
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputBindingSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputBindingSetting.java
index 45cfd3c7e8..e3850cb447 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputBindingSetting.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputBindingSetting.java
@@ -1,9 +1,15 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+
+import org.dolphinemu.dolphinemu.DolphinApplication;
import org.dolphinemu.dolphinemu.features.settings.model.Setting;
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
-public final class InputBindingSetting extends SettingsItem
+public class InputBindingSetting extends SettingsItem
{
public InputBindingSetting(String key, String section, int titleId, Setting setting)
{
@@ -22,14 +28,52 @@ public final class InputBindingSetting extends SettingsItem
}
/**
+ * Saves the provided key input setting both to the INI file (so native code can use it) and as
+ * an Android preference (so it persists correctly and is human-readable.)
+ *
+ * @param keyEvent KeyEvent of this key press.
+ */
+ public void onKeyInput(KeyEvent keyEvent)
+ {
+ InputDevice device = keyEvent.getDevice();
+ String bindStr = "Device '" + device.getDescriptor() + "'-Button " + keyEvent.getKeyCode();
+ String uiString = device.getName() + ": Button " + keyEvent.getKeyCode();
+ setValue(bindStr, uiString);
+ }
+
+ /**
+ * Saves the provided motion input setting both to the INI file (so native code can use it) and as
+ * an Android preference (so it persists correctly and is human-readable.)
+ *
+ * @param device InputDevice from which the input event originated.
+ * @param motionRange MotionRange of the movement
+ * @param axisDir Either '-' or '+'
+ */
+ public void onMotionInput(InputDevice device, InputDevice.MotionRange motionRange,
+ char axisDir)
+ {
+ String bindStr =
+ "Device '" + device.getDescriptor() + "'-Axis " + motionRange.getAxis() + axisDir;
+ String uiString = device.getName() + ": Axis " + motionRange.getAxis() + axisDir;
+ setValue(bindStr, uiString);
+ }
+
+ /**
* Write a value to the backing string. If that string was previously null,
* initializes a new one and returns it, so it can be added to the Hashmap.
*
* @param bind The input that will be bound
* @return null if overwritten successfully; otherwise, a newly created StringSetting.
*/
- public StringSetting setValue(String bind)
+ public StringSetting setValue(String bind, String ui)
{
+ SharedPreferences
+ preferences =
+ PreferenceManager.getDefaultSharedPreferences(DolphinApplication.getAppContext());
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString(getKey(), ui);
+ editor.apply();
+
if (getSetting() == null)
{
StringSetting setting = new StringSetting(getKey(), getSection(), bind);
@@ -44,6 +88,11 @@ public final class InputBindingSetting extends SettingsItem
}
}
+ public void clearValue()
+ {
+ setValue("", "");
+ }
+
@Override
public int getType()
{
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/RumbleBindingSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/RumbleBindingSetting.java
new file mode 100644
index 0000000000..8dde9825d5
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/RumbleBindingSetting.java
@@ -0,0 +1,75 @@
+package org.dolphinemu.dolphinemu.features.settings.model.view;
+
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.os.Vibrator;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+
+import org.dolphinemu.dolphinemu.DolphinApplication;
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.features.settings.model.Setting;
+import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
+import org.dolphinemu.dolphinemu.utils.Rumble;
+
+public class RumbleBindingSetting extends InputBindingSetting
+{
+
+ public RumbleBindingSetting(String key, String section, int titleId, Setting setting)
+ {
+ super(key, section, titleId, setting);
+ }
+
+ @Override
+ public String getValue()
+ {
+ if (getSetting() == null)
+ {
+ return "";
+ }
+
+ StringSetting setting = (StringSetting) getSetting();
+ return setting.getValue();
+ }
+
+ /**
+ * Just need the device when saving rumble.
+ */
+ @Override
+ public void onKeyInput(KeyEvent keyEvent)
+ {
+ saveRumble(keyEvent.getDevice());
+ }
+
+ /**
+ * Just need the device when saving rumble.
+ */
+ @Override
+ public void onMotionInput(InputDevice device,
+ InputDevice.MotionRange motionRange,
+ char axisDir)
+ {
+ saveRumble(device);
+ }
+
+ private void saveRumble(InputDevice device)
+ {
+ Vibrator vibrator = device.getVibrator();
+ if (vibrator != null && vibrator.hasVibrator())
+ {
+ setValue(device.getDescriptor(), device.getName());
+ Rumble.doRumble(vibrator);
+ }
+ else
+ {
+ setValue("",
+ DolphinApplication.getAppContext().getString(R.string.rumble_not_found));
+ }
+ }
+
+ @Override
+ public int getType()
+ {
+ return TYPE_RUMBLE_BINDING;
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.java
index 1ab8ee06c5..e3c798521f 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.java
@@ -19,6 +19,7 @@ public abstract class SettingsItem
public static final int TYPE_SUBMENU = 4;
public static final int TYPE_INPUT_BINDING = 5;
public static final int TYPE_STRING_SINGLE_CHOICE = 6;
+ public static final int TYPE_RUMBLE_BINDING = 7;
private String mKey;
private String mSection;
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java
index cbf53060eb..a2392caefc 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java
@@ -21,6 +21,7 @@ import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.CheckBoxSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.InputBindingSetting;
+import org.dolphinemu.dolphinemu.features.settings.model.view.RumbleBindingSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.SliderSetting;
@@ -29,6 +30,7 @@ import org.dolphinemu.dolphinemu.features.settings.model.view.SubmenuSetting;
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.CheckBoxSettingViewHolder;
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.HeaderViewHolder;
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.InputBindingSettingViewHolder;
+import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.RumbleBindingViewHolder;
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SettingViewHolder;
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SingleChoiceViewHolder;
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SliderViewHolder;
@@ -90,6 +92,10 @@ public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolde
view = inflater.inflate(R.layout.list_item_setting, parent, false);
return new InputBindingSettingViewHolder(view, this, mContext);
+ case SettingsItem.TYPE_RUMBLE_BINDING:
+ view = inflater.inflate(R.layout.list_item_setting, parent, false);
+ return new RumbleBindingViewHolder(view, this, mContext);
+
default:
Log.error("[SettingsAdapter] Invalid view type: " + viewType);
return null;
@@ -216,19 +222,17 @@ public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolde
{
final MotionAlertDialog dialog = new MotionAlertDialog(mContext, item);
dialog.setTitle(R.string.input_binding);
- dialog.setMessage(String.format(mContext.getString(R.string.input_binding_description),
+ dialog.setMessage(String.format(mContext.getString(
+ item instanceof RumbleBindingSetting ?
+ R.string.input_rumble_description : R.string.input_binding_description),
mContext.getString(item.getNameId())));
dialog.setButton(AlertDialog.BUTTON_NEGATIVE, mContext.getString(R.string.cancel), this);
dialog.setButton(AlertDialog.BUTTON_NEUTRAL, mContext.getString(R.string.clear),
(dialogInterface, i) ->
{
- item.setValue("");
-
- SharedPreferences sharedPreferences =
+ SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(mContext);
- SharedPreferences.Editor editor = sharedPreferences.edit();
- editor.remove(item.getKey());
- editor.apply();
+ item.clearValue();
});
dialog.setOnDismissListener(dialog1 ->
{
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 03f6b9962a..a7759be7f3 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
@@ -14,6 +14,7 @@ import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.CheckBoxSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.HeaderSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.InputBindingSetting;
+import org.dolphinemu.dolphinemu.features.settings.model.view.RumbleBindingSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.SliderSetting;
@@ -632,6 +633,8 @@ public final class SettingsFragmentPresenter
bindingsSection.getSetting(SettingsFile.KEY_GCBIND_DPAD_LEFT + gcPadNumber);
Setting bindDPadRight =
bindingsSection.getSetting(SettingsFile.KEY_GCBIND_DPAD_RIGHT + gcPadNumber);
+ Setting gcEmuRumble =
+ bindingsSection.getSetting(SettingsFile.KEY_EMU_RUMBLE + gcPadNumber);
sl.add(new HeaderSetting(null, null, R.string.generic_buttons, 0));
sl.add(new InputBindingSetting(SettingsFile.KEY_GCBIND_A + gcPadNumber,
@@ -682,6 +685,11 @@ public final class SettingsFragmentPresenter
Settings.SECTION_BINDINGS, R.string.generic_left, bindDPadLeft));
sl.add(new InputBindingSetting(SettingsFile.KEY_GCBIND_DPAD_RIGHT + gcPadNumber,
Settings.SECTION_BINDINGS, R.string.generic_right, bindDPadRight));
+
+
+ sl.add(new HeaderSetting(null, null, R.string.emulation_control_rumble, 0));
+ sl.add(new RumbleBindingSetting(SettingsFile.KEY_EMU_RUMBLE + gcPadNumber,
+ Settings.SECTION_BINDINGS, R.string.emulation_control_rumble, gcEmuRumble));
}
else // Adapter
{
@@ -761,6 +769,8 @@ public final class SettingsFragmentPresenter
bindingsSection.getSetting(SettingsFile.KEY_WIIBIND_DPAD_LEFT + wiimoteNumber);
Setting bindDPadRight =
bindingsSection.getSetting(SettingsFile.KEY_WIIBIND_DPAD_RIGHT + wiimoteNumber);
+ Setting wiiEmuRumble =
+ bindingsSection.getSetting(SettingsFile.KEY_EMU_RUMBLE + wiimoteNumber);
sl.add(new SingleChoiceSetting(SettingsFile.KEY_WIIMOTE_EXTENSION,
Settings.SECTION_WIIMOTE + (wiimoteNumber - 3), R.string.wiimote_extensions,
@@ -843,6 +853,11 @@ public final class SettingsFragmentPresenter
Settings.SECTION_BINDINGS, R.string.generic_left, bindDPadLeft));
sl.add(new InputBindingSetting(SettingsFile.KEY_WIIBIND_DPAD_RIGHT + wiimoteNumber,
Settings.SECTION_BINDINGS, R.string.generic_right, bindDPadRight));
+
+
+ sl.add(new HeaderSetting(null, null, R.string.emulation_control_rumble, 0));
+ sl.add(new RumbleBindingSetting(SettingsFile.KEY_EMU_RUMBLE + wiimoteNumber,
+ Settings.SECTION_BINDINGS, R.string.emulation_control_rumble, wiiEmuRumble));
}
private void addExtensionTypeSettings(ArrayList<SettingsItem> sl, int wiimoteNumber,
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/RumbleBindingViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/RumbleBindingViewHolder.java
new file mode 100644
index 0000000000..9720a1b977
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/RumbleBindingViewHolder.java
@@ -0,0 +1,53 @@
+package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.view.View;
+import android.widget.TextView;
+
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.features.settings.model.view.RumbleBindingSetting;
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
+
+public class RumbleBindingViewHolder extends SettingViewHolder
+{
+ private RumbleBindingSetting mItem;
+
+ private TextView mTextSettingName;
+ private TextView mTextSettingDescription;
+
+ private Context mContext;
+
+ public RumbleBindingViewHolder(View itemView, SettingsAdapter adapter, Context context)
+ {
+ super(itemView, adapter);
+
+ mContext = context;
+ }
+
+ @Override
+ protected void findViews(View root)
+ {
+ mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
+ mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
+ }
+
+ @Override
+ public void bind(SettingsItem item)
+ {
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
+
+ mItem = (RumbleBindingSetting) item;
+
+ mTextSettingName.setText(item.getNameId());
+ mTextSettingDescription.setText(sharedPreferences.getString(mItem.getKey(), ""));
+ }
+
+ @Override
+ public void onClick(View clicked)
+ {
+ getAdapter().onInputBindingClick(mItem, getAdapterPosition());
+ }
+}
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 b1f6dc46f0..0ccf700b0e 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
@@ -115,6 +115,8 @@ public final class SettingsFile
public static final String KEY_GCADAPTER_RUMBLE = "AdapterRumble";
public static final String KEY_GCADAPTER_BONGOS = "SimulateKonga";
+ public static final String KEY_EMU_RUMBLE = "EmuRumble";
+
public static final String KEY_WIIMOTE_TYPE = "Source";
public static final String KEY_WIIMOTE_EXTENSION = "Extension";
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Rumble.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Rumble.java
new file mode 100644
index 0000000000..7acc7c4a94
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Rumble.java
@@ -0,0 +1,98 @@
+package org.dolphinemu.dolphinemu.utils;
+
+import android.content.Context;
+import android.os.Build;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.preference.PreferenceManager;
+import android.util.SparseArray;
+import android.view.InputDevice;
+
+import org.dolphinemu.dolphinemu.activities.EmulationActivity;
+import org.dolphinemu.dolphinemu.features.settings.model.Settings;
+import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
+import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
+
+import java.util.HashMap;
+
+public class Rumble
+{
+ private static Vibrator phoneVibrator;
+ private static SparseArray<Vibrator> emuVibrators;
+
+ public static void initRumble(EmulationActivity activity)
+ {
+ if (activity.deviceHasTouchScreen() &&
+ PreferenceManager.getDefaultSharedPreferences(activity)
+ .getBoolean("phoneRumble", true))
+ {
+ setPhoneVibrator(true, activity);
+ }
+
+ emuVibrators = new SparseArray<>();
+ for (int i = 0; i < 8; i++)
+ {
+ StringSetting deviceName =
+ (StringSetting) activity.getSettings().getSection(Settings.SECTION_BINDINGS)
+ .getSetting(SettingsFile.KEY_EMU_RUMBLE + i);
+ if (deviceName != null && !deviceName.getValue().isEmpty())
+ {
+ for (int id : InputDevice.getDeviceIds())
+ {
+ InputDevice device = InputDevice.getDevice(id);
+ if (deviceName.getValue().equals(device.getDescriptor()))
+ {
+ Vibrator vib = device.getVibrator();
+ if (vib != null && vib.hasVibrator())
+ emuVibrators.put(i, vib);
+ }
+ }
+ }
+ }
+ }
+
+ public static void setPhoneVibrator(boolean set, EmulationActivity activity)
+ {
+ if (set)
+ {
+ Vibrator vib = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE);
+ if (vib != null && vib.hasVibrator())
+ phoneVibrator = vib;
+ }
+ else
+ {
+ phoneVibrator = null;
+ }
+ }
+
+ public static void clear()
+ {
+ phoneVibrator = null;
+ emuVibrators.clear();
+ }
+
+ public static void checkRumble(int padId, double state)
+ {
+ if (phoneVibrator != null)
+ doRumble(phoneVibrator);
+
+ if (emuVibrators.get(padId) != null)
+ doRumble(emuVibrators.get(padId));
+ }
+
+ public static void doRumble(Vibrator vib)
+ {
+ // Check again that it exists and can vibrate
+ if (vib != null && vib.hasVibrator())
+ {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ {
+ vib.vibrate(VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
+ }
+ else
+ {
+ vib.vibrate(100);
+ }
+ }
+ }
+}