-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathVibration.cs
More file actions
117 lines (92 loc) · 4.28 KB
/
Vibration.cs
File metadata and controls
117 lines (92 loc) · 4.28 KB
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
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Effects
{
public static class Vibration
{
private static readonly int Sdk;
private static readonly AndroidJavaObject Vibrator;
private static readonly IntPtr VibratorPtr;
private static readonly IntPtr VibrateWithEffectMethodPtr;
private static readonly IntPtr VibrateMethodPtr;
private static readonly AndroidJavaClass VibrationEffectClass;
static Vibration()
{
// Trick Unity into giving the App vibration permission when it builds.
// This check will always be false, but the compiler doesn't know that.
if (Application.isEditor) Handheld.Vibrate();
if (!IsAndroid()) return;
using (var version = new AndroidJavaClass("android.os.Build$VERSION"))
{
Sdk = version.GetStatic<int>("SDK_INT");
}
Vibrator = new AndroidJavaClass("com.unity3d.player.UnityPlayer")// Get the Unity Player.
.GetStatic<AndroidJavaObject>("currentActivity")// Get the Current Activity from the Unity Player.
?.Call<AndroidJavaObject>("getSystemService", "vibrator");// Then get the Vibration Service from the Current Activity.
if (Vibrator != null)
{
VibratorPtr = Vibrator.GetRawObject();
VibrateWithEffectMethodPtr =
AndroidJNI.GetMethodID(Vibrator.GetRawClass(), "vibrate", "(Landroid/os/VibrationEffect;)V");
VibrateMethodPtr = AndroidJNI.GetMethodID(Vibrator.GetRawClass(), "vibrate", "(J)V");
}
if (Sdk >= MinSdkForVibrationEffect)
{
VibrationEffectClass = new AndroidJavaClass("android.os.VibrationEffect");
}
}
public static void Vibrate(long durationMs, int amplitude)
{
if (!IsAndroid()) return;
if (Sdk >= MinSdkForVibrationEffect)
{
VibrateWithEffect(durationMs, amplitude);
}
else
{
VibrateLegacy(durationMs);
}
}
private static void VibrateWithEffect(long durationMs, int amplitude)
{
var effect = CreateVibrationEffect(durationMs, amplitude);
AndroidJNI.CallVoidMethod(VibratorPtr, VibrateWithEffectMethodPtr, effect);
}
private static jvalue[] CreateVibrationEffect(long durationMs, int amplitude)
{
if (!IsAndroid()) return null;
if (!VibrateEffectArgsCache.TryGetValue((durationMs, amplitude), out var args))
{
var effect = VibrationEffectClass?.CallStatic<AndroidJavaObject>("createOneShot", durationMs, amplitude);
if (effect != null)
GlobalReferences.Add(effect);
args = new[] {new jvalue {l = effect?.GetRawObject() ?? IntPtr.Zero}};
VibrateEffectArgsCache[(durationMs, amplitude)] = args;
}
return args;
}
private static readonly IDictionary<(long duration, int amplitude), jvalue[]> VibrateEffectArgsCache = new Dictionary<(long duration, int amplitude), jvalue[]>();
private static readonly IDictionary<long, jvalue[]> VibrateArgsCache = new Dictionary<long, jvalue[]>();
private static readonly ISet<AndroidJavaObject> GlobalReferences = new HashSet<AndroidJavaObject>();
private static void VibrateLegacy(long duration)
{
if (!IsAndroid()) return;
if (!VibrateArgsCache.TryGetValue(duration, out var args))
{
args = new [] {new jvalue{j = duration}};
VibrateArgsCache[duration] = args;
}
AndroidJNI.CallVoidMethod(VibratorPtr, VibrateMethodPtr, args);
}
private static bool IsAndroid()
{
#if UNITY_ANDROID && !UNITY_EDITOR
return true;
#else
return false;
#endif
}
private const int MinSdkForVibrationEffect = 26;
}
}