Support vibration magnitude on Android 8.0 (thanks Rachel!)
authorSam Lantinga <slouken@libsdl.org>
Tue, 16 Oct 2018 08:29:27 -0700
changeset 12332c80f702e4b8b
parent 12331 43d46306c3ba
child 12333 898f03b00670
Support vibration magnitude on Android 8.0 (thanks Rachel!)
android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java
src/core/android/SDL_android.c
src/core/android/SDL_android.h
src/haptic/android/SDL_syshaptic.c
     1.1 --- a/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java	Mon Oct 15 11:01:00 2018 +0300
     1.2 +++ b/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java	Tue Oct 16 08:29:27 2018 -0700
     1.3 @@ -1,5 +1,6 @@
     1.4  package org.libsdl.app;
     1.5  
     1.6 +import java.lang.reflect.Method;
     1.7  import java.util.ArrayList;
     1.8  import java.util.Collections;
     1.9  import java.util.Comparator;
    1.10 @@ -77,8 +78,8 @@
    1.11      /**
    1.12       * This method is called by SDL using JNI.
    1.13       */
    1.14 -    public static void hapticRun(int device_id, int length) {
    1.15 -        mHapticHandler.run(device_id, length);
    1.16 +    public static void hapticRun(int device_id, float intensity, int length) {
    1.17 +        mHapticHandler.run(device_id, intensity, length);
    1.18      }
    1.19  
    1.20      /**
    1.21 @@ -423,10 +424,50 @@
    1.22          mHaptics = new ArrayList<SDLHaptic>();
    1.23      }
    1.24  
    1.25 -    public void run(int device_id, int length) {
    1.26 +    public void run(int device_id, float intensity, int length) {
    1.27          SDLHaptic haptic = getHaptic(device_id);
    1.28          if (haptic != null) {
    1.29 -            haptic.vib.vibrate (length);
    1.30 +
    1.31 +            Log.d("SDL", "Rtest: Vibe with intensity " + intensity + " for " + length);
    1.32 +            if (intensity == 0.0f) {
    1.33 +                stop(device_id);
    1.34 +                return;
    1.35 +            }
    1.36 +
    1.37 +            if (Build.VERSION.SDK_INT >= 26) {
    1.38 +                // We have to do this dynamically to avoid issues on earlier SDKs.
    1.39 +                // But we want to use the VibrationEffect so we can set amplitude.
    1.40 +
    1.41 +                try {
    1.42 +                    int vibeValue = Math.round(intensity * 255);
    1.43 +
    1.44 +                    if (vibeValue > 255) {
    1.45 +                        vibeValue = 255;
    1.46 +                    }
    1.47 +                    if (vibeValue < 1) {
    1.48 +                        stop(device_id);
    1.49 +                        return;
    1.50 +                    }
    1.51 +
    1.52 +                    long longLength = length;
    1.53 +                    Class vibrationEffectClass = Class.forName("android.os.VibrationEffect");
    1.54 +                    Method oneShotMethod = vibrationEffectClass.getMethod("createOneShot", long.class, int.class);
    1.55 +                    Object effect = oneShotMethod.invoke(null, longLength, vibeValue);
    1.56 +                    Method vibeEffect = android.os.Vibrator.class.getMethod("vibrate", vibrationEffectClass);
    1.57 +                    vibeEffect.invoke(haptic.vib, vibrationEffectClass.cast(effect));
    1.58 +                }
    1.59 +                catch (Exception e) {
    1.60 +                    // Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but works even if
    1.61 +                    // something went horribly wrong with the Android 8.0 APIs.
    1.62 +                    haptic.vib.vibrate(length);
    1.63 +                }
    1.64 +            }
    1.65 +            else {
    1.66 +                // Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but exists
    1.67 +                // on earlier SDKs.
    1.68 +
    1.69 +                haptic.vib.vibrate (length);
    1.70 +            }
    1.71          }
    1.72      }
    1.73  
     2.1 --- a/src/core/android/SDL_android.c	Mon Oct 15 11:01:00 2018 +0300
     2.2 +++ b/src/core/android/SDL_android.c	Tue Oct 16 08:29:27 2018 -0700
     2.3 @@ -445,7 +445,7 @@
     2.4      midPollHapticDevices = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
     2.5                                  "pollHapticDevices", "()V");
     2.6      midHapticRun = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
     2.7 -                                "hapticRun", "(II)V");
     2.8 +                                "hapticRun", "(IFI)V");
     2.9      midHapticStop = (*mEnv)->GetStaticMethodID(mEnv, mControllerManagerClass,
    2.10                                  "hapticStop", "(I)V");
    2.11  
    2.12 @@ -2005,10 +2005,10 @@
    2.13      (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midPollHapticDevices);
    2.14  }
    2.15  
    2.16 -void Android_JNI_HapticRun(int device_id, int length)
    2.17 +void Android_JNI_HapticRun(int device_id, float intensity, int length)
    2.18  {
    2.19      JNIEnv *env = Android_JNI_GetEnv();
    2.20 -    (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, length);
    2.21 +    (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, intensity, length);
    2.22  }
    2.23  
    2.24  void Android_JNI_HapticStop(int device_id)
     3.1 --- a/src/core/android/SDL_android.h	Mon Oct 15 11:01:00 2018 +0300
     3.2 +++ b/src/core/android/SDL_android.h	Tue Oct 16 08:29:27 2018 -0700
     3.3 @@ -84,7 +84,7 @@
     3.4  
     3.5  /* Haptic support */
     3.6  void Android_JNI_PollHapticDevices(void);
     3.7 -void Android_JNI_HapticRun(int device_id, int length);
     3.8 +void Android_JNI_HapticRun(int device_id, float intensity, int length);
     3.9  void Android_JNI_HapticStop(int device_id);
    3.10  
    3.11  /* Video */
     4.1 --- a/src/haptic/android/SDL_syshaptic.c	Mon Oct 15 11:01:00 2018 +0300
     4.2 +++ b/src/haptic/android/SDL_syshaptic.c	Tue Oct 16 08:29:27 2018 -0700
     4.3 @@ -235,7 +235,12 @@
     4.4  SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
     4.5                          Uint32 iterations)
     4.6  {
     4.7 -    Android_JNI_HapticRun (((SDL_hapticlist_item *)haptic->hwdata)->device_id, effect->effect.leftright.length);
     4.8 +    float large = effect->effect.leftright.large_magnitude / 32767.0f;
     4.9 +    float small = effect->effect.leftright.small_magnitude / 32767.0f;
    4.10 +
    4.11 +    float total = (large * 0.6f) + (small * 0.4f);
    4.12 +
    4.13 +    Android_JNI_HapticRun (((SDL_hapticlist_item *)haptic->hwdata)->device_id, total, effect->effect.leftright.length);
    4.14      return 0;
    4.15  }
    4.16