6#if !ENABLE_METAQUEST && !ENABLE_OPENXR && UNITY_ANDROID && !UNITY_EDITOR
9using System.Collections;
10using System.Collections.Generic;
12namespace Interhaptics.Platforms.Android
14 public sealed class AndroidProvider : IHapticProvider
16#region HAPTIC CHARACTERISTICS FIELDS
17 private const string DISPLAY_NAME =
"Android";
18 private const string DESCRIPTION =
"Android device";
19 private const string MANUFACTURER =
"Google";
20 private const string VERSION =
"1.0";
21 private const int SAMPLERATE = 100;
22 private const int AMPLITUDE_DISTANCE = 5;
23 private ulong lastBufferStartingTime = 0;
24 private bool hapticPlaying=
false;
25 private float? expectedEndTimestamp =
null;
29#region HAPTIC CHARACTERISTICS GETTERS
30 [UnityEngine.Scripting.Preserve]
31 public string DisplayName()
36 [UnityEngine.Scripting.Preserve]
37 public string Description()
42 [UnityEngine.Scripting.Preserve]
43 public string Manufacturer()
48 [UnityEngine.Scripting.Preserve]
49 public string Version()
57 [UnityEngine.Scripting.Preserve]
60#if !ENABLE_IL2CPP && UNITY_ANDROID && !UNITY_EDITOR
61 UnityEngine.Debug.LogError(
"Interhaptics requires IL2CPP scripting backend for Android. Please change it in Player Settings. Haptics will not play on the Mono scripting backend on the Android platform." +
"Source: Android Provider");
62 HapticManager.MonoScriptingBackend =
true;
66#if !UNITY_EDITOR && UNITY_ANDROID && !ENABLE_METAQUEST && !ENABLE_OPENXR
68 AndroidJavaClass UnityPlayer =
new AndroidJavaClass(
"com.unity3d.player.UnityPlayer");
69 AndroidJavaObject currentActivity = UnityPlayer.GetStatic<AndroidJavaObject>(
"currentActivity");
70 AndroidJavaObject vibrator = currentActivity.Call<AndroidJavaObject>(
"getSystemService",
"vibrator");
71 bool hasVibrator = vibrator.Call<
bool>(
"hasVibrator");
74 Debug.Log(
"Haptic capabilities supported on Android.");
78 Debug.Log(
"Haptic capabilities not supported on this Android device.");
80 if (!SystemInfo.supportsVibration)
82 UnityEngine.Debug.LogError(
"The device does not have haptic capabilities. Haptics will not play on this device. ");
85 using (var version =
new AndroidJavaClass(
"android.os.Build$VERSION"))
87 string androidVersion = version.GetStatic<
string>(
"RELEASE");
88 int apiLevel = version.GetStatic<
int>(
"SDK_INT");
89 using (var build =
new AndroidJavaClass(
"android.os.Build"))
91 string deviceModel = build.GetStatic<
string>(
"MODEL");
92 Debug.LogError($
"Android version: {androidVersion} API: {apiLevel} Device model: {deviceModel}");
100 Core.HAR.AddBodyPart(
Perception.Vibration, Hand, 1, 1, 1, SAMPLERATE,
false,
false,
false,
false);
101 if (HapticManager.DebugSwitch)
103 using (var version =
new AndroidJavaClass(
"android.os.Build$VERSION"))
105 string androidVersion = version.GetStatic<
string>(
"RELEASE");
106 int apiLevel = version.GetStatic<
int>(
"SDK_INT");
107 using (var build =
new AndroidJavaClass(
"android.os.Build"))
109 string deviceModel = build.GetStatic<
string>(
"MODEL");
110 Debug.Log($
"Android haptic provider started. Android version: {androidVersion} API: {apiLevel} Device model: {deviceModel}");
117 [UnityEngine.Scripting.Preserve]
118 public bool IsPresent()
123 [UnityEngine.Scripting.Preserve]
129 private bool IsEqual(
int _amplitudeA,
int _amplitudeB,
int _distance = 0)
131 return Mathf.Abs(_amplitudeA - _amplitudeB) <= _distance;
134 [UnityEngine.Scripting.Preserve]
135 public void RenderHaptics()
137 ulong startingTime = Core.HAR.GetVectorStartingTime(
Perception.Vibration, Hand, 0, 0, 0);
139 if (startingTime!= lastBufferStartingTime)
141 lastBufferStartingTime = startingTime;
145 double[] outputBuffer =
new double[size];
148 List<int> AndroidOutputBuffer =
new List<int>();
149 List<long> timeBuffer =
new List<long>();
150 long step = Mathf.RoundToInt(1000.0f / SAMPLERATE);
151 int lastAmplitude = -1;
152 int currentAmplitude = -1;
153 long currentTiming = 0;
155 for (
int i = 0; i < size; i++)
157 currentAmplitude = Mathf.RoundToInt((
float)(outputBuffer[i] * 255));
158 if (i != 0 && IsEqual(currentAmplitude, lastAmplitude, AMPLITUDE_DISTANCE))
160 currentTiming += step;
165 AndroidOutputBuffer.Add(currentAmplitude);
166 lastAmplitude = currentAmplitude;
169 timeBuffer.Add(currentTiming + step);
174 timeBuffer.Add(currentTiming + step);
178 hapticPlaying =
true;
179 expectedEndTimestamp = UnityEngine.Time.realtimeSinceStartup+((float)size / (
float)SAMPLERATE);
184 if (hapticPlaying && UnityEngine.Time.realtimeSinceStartup> expectedEndTimestamp)
188 hapticPlaying =
false;
BufferDataType
Enumeration for types of haptic buffer data.
BodyPartID
Enumeration for identifying different body parts for haptic effects.
Perception
Enumeration for different types of haptic perceptions.