diff --git a/Source/Android/app/src/main/AndroidManifest.xml b/Source/Android/app/src/main/AndroidManifest.xml
index 975a493860..147b658ad3 100644
--- a/Source/Android/app/src/main/AndroidManifest.xml
+++ b/Source/Android/app/src/main/AndroidManifest.xml
@@ -18,6 +18,7 @@
+
= Build.VERSION_CODES.O)
+ {
+ vibrator.vibrate(VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
+ }
+ else
+ {
+ vibrator.vibrate(100);
+ }
+ }
+ }
+ }
+
public static native String GetUserSetting(String gameID, String Section, String Key);
public static native void SetUserSetting(String gameID, String Section, String Key, String Value);
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 221d3ee399..7eb8430935 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
@@ -124,6 +124,7 @@ public final class EmulationActivity extends AppCompatActivity
public static final int MENU_ACTION_EXIT = 22;
public static final int MENU_ACTION_CHANGE_DISC = 23;
public static final int MENU_ACTION_JOYSTICK_REL_CENTER = 24;
+ public static final int MENU_ACTION_RUMBLE = 25;
private static SparseIntArray buttonsActionsMap = new SparseIntArray();
@@ -163,6 +164,7 @@ public final class EmulationActivity extends AppCompatActivity
buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT);
buttonsActionsMap.append(R.id.menu_emulation_joystick_rel_center,
EmulationActivity.MENU_ACTION_JOYSTICK_REL_CENTER);
+ buttonsActionsMap.append(R.id.menu_emulation_rumble, EmulationActivity.MENU_ACTION_RUMBLE);
}
public static void launch(FragmentActivity activity, GameFile gameFile, int position,
@@ -473,6 +475,8 @@ public final class EmulationActivity extends AppCompatActivity
// Populate the checkbox value for joystick center on touch
menu.findItem(R.id.menu_emulation_joystick_rel_center)
.setChecked(mPreferences.getBoolean("joystickRelCenter", true));
+ menu.findItem(R.id.menu_emulation_rumble)
+ .setChecked(mPreferences.getBoolean("phoneRumble", true));
return true;
}
@@ -504,7 +508,11 @@ public final class EmulationActivity extends AppCompatActivity
case MENU_ACTION_JOYSTICK_REL_CENTER:
item.setChecked(!item.isChecked());
toggleJoystickRelCenter(item.isChecked());
- return;
+ break;
+ case MENU_ACTION_RUMBLE:
+ item.setChecked(!item.isChecked());
+ toggleRumble(item.isChecked());
+ break;
}
}
@@ -636,6 +644,13 @@ public final class EmulationActivity extends AppCompatActivity
editor.commit();
}
+ private void toggleRumble(boolean state)
+ {
+ final SharedPreferences.Editor editor = mPreferences.edit();
+ editor.putBoolean("phoneRumble", state);
+ editor.apply();
+ }
+
private void editControlsPlacement()
{
diff --git a/Source/Android/app/src/main/res/menu/menu_emulation.xml b/Source/Android/app/src/main/res/menu/menu_emulation.xml
index bbb418018c..0a9ccfd25d 100644
--- a/Source/Android/app/src/main/res/menu/menu_emulation.xml
+++ b/Source/Android/app/src/main/res/menu/menu_emulation.xml
@@ -98,6 +98,10 @@
android:id="@+id/menu_emulation_joystick_rel_center"
android:checkable="true"
android:title="@string/emulation_control_joystick_rel_center"/>
+
diff --git a/Source/Android/app/src/main/res/menu/menu_emulation_wii.xml b/Source/Android/app/src/main/res/menu/menu_emulation_wii.xml
index 87c61eefc0..f0cbc6024a 100644
--- a/Source/Android/app/src/main/res/menu/menu_emulation_wii.xml
+++ b/Source/Android/app/src/main/res/menu/menu_emulation_wii.xml
@@ -98,11 +98,16 @@
android:id="@+id/menu_emulation_joystick_rel_center"
android:checkable="true"
android:title="@string/emulation_control_joystick_rel_center"/>
+
+
diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml
index 52627892cb..c1bf44b837 100644
--- a/Source/Android/app/src/main/res/values/strings.xml
+++ b/Source/Android/app/src/main/res/values/strings.xml
@@ -271,6 +271,7 @@
Toggle All
Adjust Scale
Relative Stick Center
+ Rumble
Choose Controller
You may have to reload the game after changing extensions.
To change the button layout, open the menu -> Configure Controls -> Edit Layout
diff --git a/Source/Android/jni/ButtonManager.cpp b/Source/Android/jni/ButtonManager.cpp
index 6f6b812494..8490561c0f 100644
--- a/Source/Android/jni/ButtonManager.cpp
+++ b/Source/Android/jni/ButtonManager.cpp
@@ -52,6 +52,8 @@ std::vector configStrings = {
"TurntableEuphoria", "TurntableLeftTLeft", "TurntableLeftTRight", "TurntableRightTLeft",
"TurntableRightTRight", "TurntableUp", "TurntableDown", "TurntableLeft", "TurntableRight",
"TurntableEffDial", "TurntableCrossLeft", "TurntableCrossRight",
+ // Rumble
+ "Rumble",
};
std::vector configTypes = {
// GC
@@ -95,6 +97,8 @@ std::vector configTypes = {
TURNTABLE_TABLE_RIGHT_RIGHT, TURNTABLE_STICK_UP, TURNTABLE_STICK_DOWN, TURNTABLE_STICK_LEFT,
TURNTABLE_STICK_RIGHT, TURNTABLE_EFFECT_DIAL, TURNTABLE_CROSSFADE_LEFT,
TURNTABLE_CROSSFADE_RIGHT,
+ // Rumble
+ RUMBLE,
};
static void AddBind(const std::string& dev, sBind* bind)
@@ -462,4 +466,5 @@ float InputDevice::AxisValue(int padID, ButtonType axis)
else
return _buttons[binding->second->_buttontype] == BUTTON_PRESSED ? 1.0f : 0.0f;
}
+
}
diff --git a/Source/Android/jni/ButtonManager.h b/Source/Android/jni/ButtonManager.h
index c65d8180f0..b9744f516c 100644
--- a/Source/Android/jni/ButtonManager.h
+++ b/Source/Android/jni/ButtonManager.h
@@ -176,6 +176,8 @@ enum ButtonType
TURNTABLE_CROSSFADE = 622, // To Be Used on Java Side
TURNTABLE_CROSSFADE_LEFT = 623,
TURNTABLE_CROSSFADE_RIGHT = 624,
+ // Rumble
+ RUMBLE = 700,
};
enum ButtonState
{
diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp
index 983108f356..b5faf422de 100644
--- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp
@@ -3,7 +3,9 @@
// Refer to the license.txt file included.
#include "InputCommon/ControllerInterface/Android/Android.h"
+#include
#include
+#include
#include "InputCommon/ControllerInterface/ControllerInterface.h"
namespace ciface
@@ -190,6 +192,8 @@ Touchscreen::Touchscreen(int padID) : _padID(padID)
new Axis(_padID, ButtonManager::TURNTABLE_CROSSFADE_RIGHT));
AddAnalogInputs(new Axis(_padID, ButtonManager::TURNTABLE_EFFECT_DIAL),
new Axis(_padID, ButtonManager::TURNTABLE_EFFECT_DIAL));
+ // Rumble
+ AddOutput(new Motor(_padID, ButtonManager::RUMBLE));
}
// Buttons and stuff
@@ -215,5 +219,34 @@ ControlState Touchscreen::Axis::GetState() const
{
return ButtonManager::GetAxisValue(_padID, _index) * _neg;
}
+
+Touchscreen::Motor::~Motor()
+{
+}
+
+std::string Touchscreen::Motor::GetName() const
+{
+ std::ostringstream ss;
+ ss << "Rumble " << (int)_index;
+ return ss.str();
+}
+
+void Touchscreen::Motor::SetState(ControlState state)
+{
+ if (state > 0)
+ {
+ std::thread(Rumble, _padID, state).detach();
+ }
+}
+
+void Touchscreen::Motor::Rumble(int padID, double state)
+{
+ JNIEnv* env;
+ IDCache::GetJavaVM()->AttachCurrentThread(&env, nullptr);
+ jmethodID rumbleMethod =
+ env->GetStaticMethodID(IDCache::GetNativeLibraryClass(), "rumble", "(ID)V");
+ env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), rumbleMethod, padID, state);
+ IDCache::GetJavaVM()->DetachCurrentThread();
+}
}
}
diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.h b/Source/Core/InputCommon/ControllerInterface/Android/Android.h
index bf588719c2..deb23539ce 100644
--- a/Source/Core/InputCommon/ControllerInterface/Android/Android.h
+++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.h
@@ -41,6 +41,19 @@ private:
const ButtonManager::ButtonType _index;
const float _neg;
};
+ class Motor : public Core::Device::Output
+ {
+ public:
+ Motor(int padID, ButtonManager::ButtonType index) : _padID(padID), _index(index) {}
+ ~Motor();
+ std::string GetName() const override;
+ void SetState(ControlState state) override;
+
+ private:
+ const int _padID;
+ const ButtonManager::ButtonType _index;
+ static void Rumble(int padID, double state);
+ };
public:
Touchscreen(int padID);