19 private static UnityEngine.AndroidJavaObject vibrator =
null;
20 private static UnityEngine.AndroidJavaClass vibrationEffectClass =
null;
21 private static int defaultAmplitude = 255;
24 private static int ApiLevel = 1;
25 private static bool doesSupportVibrationEffect() => ApiLevel >= 26;
26 private static bool doesSupportPredefinedEffect() => ApiLevel >= 29;
28 #region Initialization
29 private static bool isInitialized =
false;
34 if (isInitialized ==
false && UnityEngine.Application.platform == UnityEngine.RuntimePlatform.Android)
38 if (UnityEngine.Application.isConsolePlatform)
40 UnityEngine.Handheld.Vibrate();
44 using (UnityEngine.AndroidJavaClass androidVersionClass =
new UnityEngine.AndroidJavaClass(
"android.os.Build$VERSION"))
46 ApiLevel = androidVersionClass.GetStatic<
int>(
"SDK_INT");
50 using (UnityEngine.AndroidJavaClass unityPlayer =
new UnityEngine.AndroidJavaClass(
"com.unity3d.player.UnityPlayer"))
51 using (UnityEngine.AndroidJavaObject currentActivity = unityPlayer.GetStatic<UnityEngine.AndroidJavaObject>(
"currentActivity"))
53 if (currentActivity !=
null)
55 vibrator = currentActivity.Call<UnityEngine.AndroidJavaObject>(
"getSystemService",
"vibrator");
58 if (doesSupportVibrationEffect())
60 vibrationEffectClass =
new UnityEngine.AndroidJavaClass(
"android.os.VibrationEffect");
61 defaultAmplitude = UnityEngine.Mathf.Clamp(vibrationEffectClass.GetStatic<
int>(
"DEFAULT_AMPLITUDE"), -1, 255);
65 if (doesSupportPredefinedEffect())
67 PredefinedEffect.EFFECT_CLICK = vibrationEffectClass.GetStatic<
int>(
"EFFECT_CLICK");
68 PredefinedEffect.EFFECT_DOUBLE_CLICK = vibrationEffectClass.GetStatic<
int>(
"EFFECT_DOUBLE_CLICK");
69 PredefinedEffect.EFFECT_HEAVY_CLICK = vibrationEffectClass.GetStatic<
int>(
"EFFECT_HEAVY_CLICK");
70 PredefinedEffect.EFFECT_TICK = vibrationEffectClass.GetStatic<
int>(
"EFFECT_TICK");
75 logAuto(
"Vibration component initialized",
logLevel.Info);
81 #region Vibrate Public
87 public static void Vibrate(
long milliseconds,
int amplitude = -1,
bool cancel =
false)
89 string funcToStr() =>
string.Format(
"Vibrate ({0}, {1}, {2})", milliseconds, amplitude, cancel);
91 if (isInitialized ==
false)
93 logAuto(funcToStr() +
": Not initialized",
logLevel.Warning);
97 logAuto(funcToStr() +
": Device doesn't have Vibrator",
logLevel.Warning);
105 if (doesSupportVibrationEffect())
108 amplitude = UnityEngine.Mathf.Clamp(amplitude, -1, 255);
115 logAuto(funcToStr() +
": Device doesn't have Amplitude Control, but Amplitude was set",
logLevel.Warning);
121 vibrateEffect(milliseconds, amplitude);
122 logAuto(funcToStr() +
": Effect called",
logLevel.Info);
126 vibrateLegacy(milliseconds);
127 logAuto(funcToStr() +
": Legacy called",
logLevel.Info);
138 public static void Vibrate(
long[] pattern,
int[] amplitudes =
null,
int repeat = -1,
bool cancel =
false)
140 string funcToStr() =>
string.Format(
"Vibrate (pattern, amplitudes, repeat, cancel)");
143 if (isInitialized ==
false)
145 logAuto(funcToStr() +
": Not initialized",
logLevel.Warning);
149 logAuto(funcToStr() +
": Device doesn't have Vibrator",
logLevel.Warning);
154 if (amplitudes !=
null && amplitudes.Length != pattern.Length)
156 logAuto(funcToStr() +
": Length of Amplitudes array is not equal to Pattern array. Amplitudes will be ignored.",
logLevel.Warning);
160 if (amplitudes !=
null)
162 clampAmplitudesArray(amplitudes);
170 if (doesSupportVibrationEffect())
175 vibrateEffect(pattern, amplitudes, repeat);
176 logAuto(funcToStr() +
": Effect with amplitudes called",
logLevel.Info);
181 logAuto(funcToStr() +
": called but device has no amplitude control",
logLevel.Warning);
193 string funcToStr() =>
string.Format(
"VibratePredefined ({0})", effectId);
196 if (isInitialized ==
false)
198 logAuto(funcToStr() +
": Not initialized",
logLevel.Warning);
202 logAuto(funcToStr() +
": Device doesn't have Vibrator",
logLevel.Warning);
204 else if (doesSupportPredefinedEffect() ==
false)
206 logAuto(funcToStr() +
": Device doesn't support Predefined Effects (Api Level >= 29)",
logLevel.Warning);
214 vibrateEffectPredefined(effectId);
215 logAuto(funcToStr() +
": Predefined effect called",
logLevel.Info);
220 #region Public Properties & Controls
223 if (_buffer.Length > 0)
226 for (
int i = 0; i < _buffer.Length; i++)
228 result += _buffer[i];
231 return UnityEngine.Mathf.Clamp(result / _buffer.Length, 0, 255);
243 pattern = pattern.Trim();
244 string[] split = pattern.Split(
',');
246 long[] timings =
new long[split.Length];
247 for (
int i = 0; i < split.Length; i++)
249 if (
int.TryParse(split[i].Trim(), out
int duration))
251 timings[i] = duration < 0 ? 0 : duration;
264 if (amplitudes ==
null)
266 return new long[] { 0, 0 };
269 System.Collections.Generic.List<
long> timings =
new System.Collections.Generic.List<
long>();
271 int currentAmplitudeIndex = 0;
272 long currentTimingValue = 0;
274 while (currentAmplitudeIndex < amplitudes.Length)
277 currentTimingValue = 0;
278 while (currentAmplitudeIndex < amplitudes.Length && amplitudes[currentAmplitudeIndex] <
AmplitudeThreshold)
280 currentTimingValue += amplitudeDuration;
281 currentAmplitudeIndex++;
283 timings.Add(currentTimingValue);
286 currentTimingValue = 0;
287 while (currentAmplitudeIndex < amplitudes.Length && amplitudes[currentAmplitudeIndex] >=
AmplitudeThreshold)
289 currentTimingValue += amplitudeDuration;
290 currentAmplitudeIndex++;
292 timings.Add(currentTimingValue);
295 return timings.ToArray();
312 return vibrator !=
null && vibrator.Call<
bool>(
"hasVibrator");
322 return vibrator.Call<
bool>(
"hasAmplitudeControl");
337 vibrator.Call(
"cancel");
338 logAuto(
"Cancel (): Called",
logLevel.Info);
343 #region Vibrate Internal
344 #region Vibration Callers
345 private static void vibrateEffect(
long milliseconds,
int amplitude)
347 using (UnityEngine.AndroidJavaObject effect = createEffect_OneShot(milliseconds, amplitude))
349 vibrator.Call(
"vibrate", effect);
353 private static void vibrateLegacy(
long milliseconds)
355 vibrator.Call(
"vibrate", milliseconds);
358 private static void vibrateEffect(
long[] pattern,
int repeat)
360 using (UnityEngine.AndroidJavaObject effect = createEffect_Waveform(pattern, repeat))
362 vibrator.Call(
"vibrate", effect);
366 private static void vibrateLegacy(
long[] pattern,
int repeat)
368 vibrator.Call(
"vibrate", pattern, repeat);
371 private static void vibrateEffect(
long[] pattern,
int[] amplitudes,
int repeat)
373 using (UnityEngine.AndroidJavaObject effect = createEffect_Waveform(pattern, amplitudes, repeat))
375 vibrator.Call(
"vibrate", effect);
379 private static void vibrateEffectPredefined(
int effectId)
381 using (UnityEngine.AndroidJavaObject effect = createEffect_Predefined(effectId))
383 vibrator.Call(
"vibrate", effect);
388 #region Vibration Effect
392 private static UnityEngine.AndroidJavaObject createEffect_OneShot(
long milliseconds,
int amplitude)
394 return vibrationEffectClass.CallStatic<UnityEngine.AndroidJavaObject>(
"createOneShot", milliseconds, amplitude);
400 private static UnityEngine.AndroidJavaObject createEffect_Predefined(
int effectId)
402 return vibrationEffectClass.CallStatic<UnityEngine.AndroidJavaObject>(
"createPredefined", effectId);
408 private static UnityEngine.AndroidJavaObject createEffect_Waveform(
long[] timings,
int[] amplitudes,
int repeat)
410 return vibrationEffectClass.CallStatic<UnityEngine.AndroidJavaObject>(
"createWaveform", timings, amplitudes, repeat);
416 private static UnityEngine.AndroidJavaObject createEffect_Waveform(
long[] timings,
int repeat)
418 return vibrationEffectClass.CallStatic<UnityEngine.AndroidJavaObject>(
"createWaveform", timings, repeat);
424 private static void logAuto(
string text,
logLevel level)
435 UnityEngine.Debug.LogWarning(text);
439 UnityEngine.Debug.Log(text);
444 private static string arrToStr(
long[] array) => array ==
null ?
"null" :
string.Join(
", ", array);
445 private static string arrToStr(
int[] array) => array ==
null ?
"null" :
string.Join(
", ", array);
447 private static void clampAmplitudesArray(
int[] amplitudes)
449 for (
int i = 0; i < amplitudes.Length; i++)
451 amplitudes[i] = UnityEngine.Mathf.Clamp(amplitudes[i], 0, 255);
456 public static class PredefinedEffect
458 public static int EFFECT_CLICK;
459 public static int EFFECT_DOUBLE_CLICK;
460 public static int EFFECT_HEAVY_CLICK;
461 public static int EFFECT_TICK;