Support vibration magnitude on Android 8.0 (thanks Rachel!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java b/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java
index a631c3e..c6a33e8 100644
--- a/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java
+++ b/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java
@@ -1,5 +1,6 @@
package org.libsdl.app;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -77,8 +78,8 @@ public class SDLControllerManager
/**
* This method is called by SDL using JNI.
*/
- public static void hapticRun(int device_id, int length) {
- mHapticHandler.run(device_id, length);
+ public static void hapticRun(int device_id, float intensity, int length) {
+ mHapticHandler.run(device_id, intensity, length);
}
/**
@@ -423,10 +424,50 @@ class SDLHapticHandler {
mHaptics = new ArrayList<SDLHaptic>();
}
- public void run(int device_id, int length) {
+ public void run(int device_id, float intensity, int length) {
SDLHaptic haptic = getHaptic(device_id);
if (haptic != null) {
- haptic.vib.vibrate (length);
+
+ Log.d("SDL", "Rtest: Vibe with intensity " + intensity + " for " + length);
+ if (intensity == 0.0f) {
+ stop(device_id);
+ return;
+ }
+
+ if (Build.VERSION.SDK_INT >= 26) {
+ // We have to do this dynamically to avoid issues on earlier SDKs.
+ // But we want to use the VibrationEffect so we can set amplitude.
+
+ try {
+ int vibeValue = Math.round(intensity * 255);
+
+ if (vibeValue > 255) {
+ vibeValue = 255;
+ }
+ if (vibeValue < 1) {
+ stop(device_id);
+ return;
+ }
+
+ long longLength = length;
+ Class vibrationEffectClass = Class.forName("android.os.VibrationEffect");
+ Method oneShotMethod = vibrationEffectClass.getMethod("createOneShot", long.class, int.class);
+ Object effect = oneShotMethod.invoke(null, longLength, vibeValue);
+ Method vibeEffect = android.os.Vibrator.class.getMethod("vibrate", vibrationEffectClass);
+ vibeEffect.invoke(haptic.vib, vibrationEffectClass.cast(effect));
+ }
+ catch (Exception e) {
+ // Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but works even if
+ // something went horribly wrong with the Android 8.0 APIs.
+ haptic.vib.vibrate(length);
+ }
+ }
+ else {
+ // Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but exists
+ // on earlier SDKs.
+
+ haptic.vib.vibrate (length);
+ }
}
}
diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c
index 37f328b..a56575e 100644
--- a/src/core/android/SDL_android.c
+++ b/src/core/android/SDL_android.c
@@ -445,7 +445,7 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv* mEn
midPollHapticDevices = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
"pollHapticDevices", "()V");
midHapticRun = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
- "hapticRun", "(II)V");
+ "hapticRun", "(IFI)V");
midHapticStop = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
"hapticStop", "(I)V");
@@ -2005,10 +2005,10 @@ void Android_JNI_PollHapticDevices(void)
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollHapticDevices);
}
-void Android_JNI_HapticRun(int device_id, int length)
+void Android_JNI_HapticRun(int device_id, float intensity, int length)
{
JNIEnv *env = Android_JNI_GetEnv();
- (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, length);
+ (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, intensity, length);
}
void Android_JNI_HapticStop(int device_id)
diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h
index 006f5fd..b2ff32e 100644
--- a/src/core/android/SDL_android.h
+++ b/src/core/android/SDL_android.h
@@ -84,7 +84,7 @@ void Android_JNI_PollInputDevices(void);
/* Haptic support */
void Android_JNI_PollHapticDevices(void);
-void Android_JNI_HapticRun(int device_id, int length);
+void Android_JNI_HapticRun(int device_id, float intensity, int length);
void Android_JNI_HapticStop(int device_id);
/* Video */
diff --git a/src/haptic/android/SDL_syshaptic.c b/src/haptic/android/SDL_syshaptic.c
index 391b7b5..7cb289b 100644
--- a/src/haptic/android/SDL_syshaptic.c
+++ b/src/haptic/android/SDL_syshaptic.c
@@ -235,7 +235,12 @@ int
SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
Uint32 iterations)
{
- Android_JNI_HapticRun (((SDL_hapticlist_item *)haptic->hwdata)->device_id, effect->effect.leftright.length);
+ float large = effect->effect.leftright.large_magnitude / 32767.0f;
+ float small = effect->effect.leftright.small_magnitude / 32767.0f;
+
+ float total = (large * 0.6f) + (small * 0.4f);
+
+ Android_JNI_HapticRun (((SDL_hapticlist_item *)haptic->hwdata)->device_id, total, effect->effect.leftright.length);
return 0;
}