Zadbaj o dobrą organizację dzięki kolekcji
Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.
Najczęściej spotykane na urządzeniach z Androidem siłowniki wibracyjne to siłowniki rezonansowe liniowe (LRA). LRAs symulują wrażenie kliknięcia przycisku na powierzchni szklanej, która normalnie nie reaguje na dotyk. Jasny i czysty sygnał kliknięcia trwa zwykle od 10 do 20 milisekund. Dzięki temu interakcje z użytkownikiem wydają się bardziej naturalne. W przypadku klawiatur wirtualnych ta funkcja może zwiększyć szybkość pisania i zmniejszyć liczbę błędów.
Niektóre LRAs miały częstotliwości rezonansowe w zakresie 200–300 Hz, co zbiega się z częstotliwością, przy której ludzka skóra jest najbardziej wrażliwa na wibracje. Wrażenia z wibracji w tym zakresie częstotliwości są zwykle opisywane jako płynne, ostre i przenikliwe.
Inne modele LRAs mają niższe częstotliwości rezonansowe, około 150 Hz. Wrażenie jest jakościowo bardziej miękkie i pełniejsze (w wymiarach).
Elementy liniowego aktuatora rezonansowego (LRA).
Przy tym samym napięciu wejściowym o 2 różnych częstotliwościach amplitudy drgań wyjściowych mogą być różne. Im większa odległość częstotliwości od częstotliwości rezonansowej LRA, tym mniejsza amplituda drgań.
Efekty haptyczne danego urządzenia korzystają zarówno z silnika wibracyjnego, jak i z sterownika.
Sterowniki haptyczne, które obejmują funkcje overdrive i aktywnego hamowania, mogą skrócić czas narastania i dzwonienia w przypadku LRAs, co prowadzi do bardziej responsywnej i jasnej wibracji.
Przyspieszenie wyjścia wibratora
Mapowanie częstotliwości na przyspieszenie wyjściowe (FOAM) opisuje maksymalne możliwe przyspieszenie wyjściowe (w G szczyt) przy danej częstotliwości wibracji (w hercach). Od Androida 16 (poziom interfejsu API 36) platforma zapewnia wbudowane wsparcie dla tego mapowania za pomocą VibratorFrequencyProfile. Za pomocą tej klasy oraz interfejsów API kopert podstawowych i zaawansowanych możesz tworzyć efekty haptyczne.
Większość silników LRA ma jeden szczyt w krzywej FOAM, zwykle w pobliżu częstotliwości rezonansowej. Przyspieszenie zwykle maleje wykładniczo, gdy częstotliwość odbiega od tego zakresu. Krzywa może nie być symetryczna i może zawierać plateau wokół częstotliwości rezonansowej, aby chronić silnik przed uszkodzeniem.
Na sąsiednim wykresie pokazano przykładową piankę dla silnika LRA.
Przykładowy FOAM dla silnika LRA.
Próg wykrywania ludzkiego postrzegania
Próg wykrywania przez człowieka odnosi się do minimalnego przyspieszenia wibracji, które człowiek może niezawodnie wykryć. Ten poziom zależy od częstotliwości wibracji.
Na sąsiednim wykresie widać próg wykrywania haptycznego odbioru przez człowieka w przyspieszeniu jako funkcję częstotliwości czasowej. Dane progowe są przekształcane z progu przemieszczenia w Rysunku 1 w artykule Bolanowski Jr., S. J., et
al., 1988, „Cztery kanały pośredniczą w mechanicznych aspektach dotyku”.
Android automatycznie obsługuje ten próg w BasicEnvelopeBuilder, który sprawdza, czy wszystkie efekty używają zakresu częstotliwości, który generuje amplitudy wibracji, których amplitudy wykrywania przez człowieka przekraczają próg wykrywania o co najmniej 10 dB.
Odbieranie przez człowieka intensywności wibracji, czyli odczucia, nie wzrasta w prosto proporcjonalnie do amplitudy wibracji, czyli parametru fizycznego. Odbierana intensywność jest charakteryzowana przez poziom wrażenia (SL), który jest zdefiniowany jako wartość w dB powyżej progu wykrywania na tej samej częstotliwości.
Odpowiednią amplitudę przyspieszenia drgań (w G szczytowych) można obliczyć w ten sposób:
$$
Amplitude(G) = 10^{Amplitude(db)/20}
$$
...gdzie dB amplitudy jest sumą SL i progresu wykrywania – wartości na osi pionowej na sąsiednim wykresie – przy danej częstotliwości.
Na sąsiednim wykresie pokazano poziomy przyspieszenia wibracji na poziomie 10, 20, 30, 40 i 50 dB SL oraz próg wykrywania wibracji przez człowieka (0 dB SL) jako funkcję częstotliwości czasowej. Dane są oszacowane na podstawie rysunku 8 w Verrillo, R. T., et al., 1969, „Sensation magnitude of vibrotactile
stimuli."
Poziomy przyspieszenia wibracji.
Android automatycznie obsługuje tę konwersję w funkcji BasicEnvelopeBuilder, która przyjmuje wartości jako skończone natężenia w przestrzeni sensation level (dBSL) i przekształca je w przyspieszenie wyjściowe. Z drugiej strony WaveformEnvelopeBuilder nie stosuje tej konwersji i zamiast tego przyjmuje wartości jako skończone wartości wyjściowe przyspieszenia w przestrzeni przyspieszenia (Gs). Interfejs API envelope zakłada, że gdy projektant lub deweloper myśli o zmianach siły wibracji, oczekuje, że wyczuwalna intensywność będzie się zmieniać w sposób schodkowy.
Domyślne wygładzanie krzywej na urządzeniach
Dla przykładu zobacz, jak niestandardowy wzór fali zachowuje się na urządzeniu ogólnym:
Na wykresach poniżej widać sygnał wejściowy i przyspieszenie wyjściowe odpowiadające poprzedzającym fragmentom kodu. Pamiętaj, że przyspieszenie wzrasta stopniowo, a nie gwałtownie, gdy w wzorze występuje zmiana amplitudy o krok – czyli w 0 ms, 150 ms, 200 ms, 250 ms i 700 ms. Występuje też przeregulowanie przy każdej zmianie amplitudy, a także widoczne zjawisko zniekształceń, które trwa co najmniej 50 ms, gdy amplituda wejścia nagle spada do 0.
Wykres fali wejściowej funkcji krokowej.
Wykres rzeczywistej zmierzonej fali, pokazujący bardziej naturalne przejścia między poziomami.
Ulepszona reakcja haptyczna
Aby uniknąć przesterowania i zredukować czas dzwonienia, zmień amplitudy w bardziej stopniowy sposób. Poniżej pokazano wykresy fali i przyspieszenia w zmienionej wersji:
Kotlin
valtimings:LongArray=longArrayOf(25,25,50,25,25,25,25,25,25,25,75,25,25,300,25,25,150,25,25,25)valamplitudes:IntArray=intArrayOf(38,77,79,84,92,99,121,143,180,217,255,170,85,0,85,170,255,170,85,0)valrepeatIndex=-1// Do not repeat.vibrator.vibrate(VibrationEffect.createWaveform(timings,amplitudes,repeatIndex))
Java
long[]timings=newlong[]{25,25,50,25,25,25,25,25,25,25,75,25,25,300,25,25,150,25,25,25};int[]amplitudes=newint[]{38,77,79,84,92,99,121,143,180,217,255,170,85,0,85,170,255,170,85,0};intrepeatIndex=-1;// Do not repeat.vibrator.vibrate(VibrationEffect.createWaveform(timings,amplitudes,repeatIndex));
Inne elementy wystarczającej odpowiedzi na kliknięcie są bardziej złożone i wymagają pewnej wiedzy o używanych na urządzeniu funkcjach LRA. Aby uzyskać najlepsze wyniki, użyj gotowych przebiegów sygnału na urządzeniu i konstant udostępnionych przez platformę, które umożliwiają wykonywanie tych czynności:
Te wstępnie zdefiniowane statyczne i proste elementy haptyczne mogą znacznie przyspieszyć pracę przy tworzeniu wysokiej jakości efektów haptycznych.
Treść strony i umieszczone na niej fragmenty kodu podlegają licencjom opisanym w Licencji na treści. Java i OpenJDK są znakami towarowymi lub zastrzeżonymi znakami towarowymi należącymi do firmy Oracle lub jej podmiotów stowarzyszonych.
Ostatnia aktualizacja: 2025-07-27 UTC.
[null,null,["Ostatnia aktualizacja: 2025-07-27 UTC."],[],[],null,["# Analyze vibration waveforms\n\nThe most common vibration actuators on Android devices are [linear resonant\nactuators (LRAs)](https://medium.com/@SomaticLabs/what-is-a-linear-resonant-actuator-81cc25f85779). LRAs simulate the feeling of a button click\non what is otherwise an unresponsive glass surface. A clear and crisp click\nfeedback signal typically lasts between 10 and 20 milliseconds in duration. This\nsensation makes user interactions feel more natural. For virtual keyboards, this\nclick feedback can increase typing speed and reduce errors.\n\nLRAs have a few common [resonant frequencies](https://en.wikipedia.org/wiki/Resonance#Examples):\n\n- Some LRAs had resonant frequencies in the 200 to 300 Hz range, which coincides with the frequency at which human skin is most sensitive to vibration. The sensation of vibrations at this frequency range are usually described as smooth, sharp, and penetrating.\n- Other models of LRAs have lower resonance frequencies, at around 150 Hz. The sensation is qualitatively softer and fuller (in dimension). \nComponents of a linear resonant actuator (LRA).\n\n\u003cbr /\u003e\n\nGiven the same input voltage at two different frequencies, the vibration output\namplitudes can be different. The further away the frequency is from the LRA's\nresonant frequency, the lower its vibration amplitude.\n\nA given device's haptic effects use both the vibration actuator and its driver.\nHaptic drivers that include overdrive and active braking features can reduce the\nrise time and ringing of LRAs, leading to a more responsive and clear vibration.\n\nVibrator output acceleration\n----------------------------\n\n\nThe frequency-to-output-acceleration mapping (FOAM) describes the maximum\nachievable output acceleration (in G peak) at a given vibration frequency (in\nHertz). Starting in Android 16 (API level 36), the platform provides built-in\nsupport for this mapping through the `VibratorFrequencyProfile`. You can use\nthis class, along with the [basic](/reference/android/os/VibrationEffect.BasicEnvelopeBuilder) and [advanced](/reference/android/os/VibrationEffect.WaveformEnvelopeBuilder) envelope APIs, to create\nhaptic effects.\n\nMost LRA motors have a single peak in their FOAM, typically near their resonant\nfrequency. Acceleration generally decreases exponentially as frequency deviates\nfrom this range. The curve may not be symmetrical and might feature a plateau\naround the resonant frequency to protect the motor from damage.\n\nThe adjacent plot shows an example FOAM for an LRA motor. \nExample FOAM for an LRA motor.\n\n\u003cbr /\u003e\n\n### Human perception detection threshold\n\n\nThe *human perception detection threshold* refers to the minimum acceleration of\na vibration that a person can reliably detect. This level varies based on the\nvibration frequency.\n\nThe adjacent plot shows the human haptic perception detection threshold, in\nacceleration, as a function of temporal frequency. The threshold data is\nconverted from displacement threshold in Figure 1 of Bolanowski Jr., S. J., et\nal.'s 1988 article,\n[\"Four channels mediate the mechanical aspects of touch.\"](https://pubmed.ncbi.nlm.nih.gov/3209773/).\n\nAndroid automatically handles this threshold in the `BasicEnvelopeBuilder`,\nwhich verifies that all effects use a frequency range that prodcues vibration\namplitudes that exceed the human perception detection threshold by at least\n10 dB. \nHuman haptic perception detection threshold.\n\n\u003cbr /\u003e\n\nAn online tutorial further explains the [conversion between acceleration\namplitude and displacement amplitude](https://www.tangerinex.com/tutorial-1).\n\n### Vibration acceleration levels\n\n\nHuman perception of vibration intensity, a *perception* measure, doesn't grow\nlinearly with vibration amplitude, a *physical* parameter. Perceived intensity\nis characterized by sensation level (SL), which is defined as a dB amount above\nthe detection threshold at the same frequency.\n\nThe corresponding vibration acceleration amplitude (in G peak) can be calculated\nas follows: \n$$ Amplitude(G) = 10\\^{Amplitude(db)/20} $$\n\n...where the amplitude dB is the sum of SL and detection threshold---the value\nalong the vertical axis in the adjacent plot---at a particular frequency.\n\nThe adjacent plot shows the vibration acceleration levels at 10, 20, 30, 40 and\n50 dB SL, along with the human haptic perception detection threshold (0 dB SL),\nas a function of temporal frequency. The data is estimated from Figure 8 in\nVerrillo, R. T., et al.'s 1969 article, [\"Sensation magnitude of vibrotactile\nstimuli.\"](https://link.springer.com/article/10.3758/BF03212793). \nVibration acceleration levels.\n\n\u003cbr /\u003e\n\nAndroid automatically handles this conversion in the `BasicEnvelopeBuilder`,\nwhich takes values as normalized intensities in the sensation level space (dB\nSL) and converts them to output acceleration. The `WaveformEnvelopeBuilder`, on\nthe other hand, doesn't apply this conversion and takes values as normalized\noutput acceleration amplitudes in the acceleration space (Gs) instead. The\nenvelope API assumes that, when a designer or developer thinks about changes in\nvibration strength, they expect the perceived intensity to follow a piecewise\nlinear envelope.\n\nDefault waveform smoothing on devices\n-------------------------------------\n\nFor illustration, consider how a custom waveform pattern behaves on a generic\ndevice: \n\n### Kotlin\n\n val timings: LongArray = longArrayOf(50, 50, 50, 50, 50, 100, 350, 250)\n val amplitudes: IntArray = intArrayOf(77, 79, 84, 99, 143, 255, 0, 255)\n val repeatIndex = -1 // Don't repeat.\n\n vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex))\n\n### Java\n\n long[] timings = new long[] { 50, 50, 50, 50, 50, 100, 350, 250 };\n int[] amplitudes = new int[] { 77, 79, 84, 99, 143, 255, 0, 255 };\n int repeatIndex = -1 // Don't repeat.\n\n vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex));\n\nThe following plots show the input waveform and output acceleration\ncorresponding to the preceding code snippets. Note that the acceleration\nincreases gradually, not suddenly, whenever there is a step change of amplitude\nin the pattern---that is, at 0ms, 150ms, 200ms, 250ms, and 700ms. There is also an\novershoot at each step change of amplitude, and there is visible ringing that\nlasts at least 50ms when the input amplitude suddenly drops to 0.\n\n\nPlot of step function input waveform. \nPlot of actual measured waveform, showing more organic transitions between levels.\n\n\u003cbr /\u003e\n\nImproved haptic pattern\n-----------------------\n\nTo avoid overshoot and reduce ringing time, change the amplitudes more\ngradually. The following shows the waveform and acceleration plots of the\nrevised version: \n\n### Kotlin\n\n val timings: LongArray = longArrayOf(\n 25, 25, 50, 25, 25, 25, 25, 25, 25, 25, 75, 25, 25,\n 300, 25, 25, 150, 25, 25, 25\n )\n val amplitudes: IntArray = intArrayOf(\n 38, 77, 79, 84, 92, 99, 121, 143, 180, 217, 255, 170, 85,\n 0, 85, 170, 255, 170, 85, 0\n )\n val repeatIndex = -1 // Do not repeat.\n\n vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex))\n\n### Java\n\n long[] timings = new long[] {\n 25, 25, 50, 25, 25, 25, 25, 25, 25, 25, 75, 25, 25,\n 300, 25, 25, 150, 25, 25, 25\n };\n int[] amplitudes = new int[] {\n 38, 77, 79, 84, 92, 99, 121, 143, 180, 217, 255, 170, 85,\n 0, 85, 170, 255, 170, 85, 0\n };\n int repeatIndex = -1; // Do not repeat.\n\n vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex));\n\n\nPlot of input waveform with additional steps. \nPlot of measured waveform, showing smoother transitions.\n\n\u003cbr /\u003e\n\nCreate more complex haptic effects\n----------------------------------\n\nOther elements in a satisfying click response are more intricate, requiring some\nknowledge of the LRA used in a device. For best results, use the device's\npre-fabricated waveforms and platform-provided constants, which let you do the\nfollowing:\n\n- Perform clear effects and [primitives](/develop/ui/views/haptics/custom-haptic-effects#primitives).\n- Concatenate them to compose new haptic effects.\n\nThese predefined haptic constants and primitives can greatly speed up your work\nwhile creating high-quality haptic effects."]]