Android实现手机振动(附带源码)_android震动代码
一、项目介绍
在移动应用中,手机振动(Haptic Feedback) 是一种常见且重要的用户体验增强方式。不同场景下的振动反馈能让用户获得更直观、更沉浸的交互提示,例如:
-
按钮点击反馈:输入框聚焦、按钮按下时轻微震动,让用户感知操作已生效。
-
重要提醒:闹钟、计时器、来电或消息通知时的持续振动,确保用户不会错过。
-
复杂游戏震动:游戏中爆炸、碰撞等重击感,通过不同强度与节奏的振动提升沉浸感。
-
导航指引:使用导航时,转弯提示或危险路况提醒通过短促振动提示驾驶者。
我们希望搭建一个通用的、可扩展的振动管理框架,满足以下需求:
-
多种振动效果支持
-
简单的单次振动
-
持续振动
-
自定义节奏(pattern)
-
强度(amplitude)控制
-
-
兼容多 Android 版本
-
API 级别差异(Vibrator vs VibrationEffect)
-
Android 12+ 平台 Haptic API 新特性
-
-
易于集成
-
只需在
Application
或Activity
中初始化一次 -
对外暴露简单的振动接口,可在业务层随时调用
-
-
可扩展高级能力
-
混合式振动:结合音频、灯光,形成更丰富的感官反馈
-
远程配置振动资源 JSON 文件,动态下发节奏和强度
-
与 Jetpack Compose 结合的响应式振动触发
-
本文将深度剖析 Android 振动底层原理,全面展示从最基础单次振动,到复杂 Haptic Pattern,再到新版 HapticFeedback 兼容方案的完整实现,最终提供一个模块化、可扩展的振动管理框架示例,并附上完整整合代码、方法功能解读及项目总结,全文超过 10,000 字,适合作为博客或文档直接发布。
二、相关知识与术语
在动手编码之前,需要先了解振动在 Android 中的相关概念、API 演进及硬件支持细节。
2.1 振动驱动与硬件支持
-
Vibrator Service
-
Android 系统提供了
Vibrator
服务,底层通过 HAL(硬件抽象层)与设备真实的振动电机通信。 -
不同设备的振动器(ER: Eccentric Rotating Mass vs LRA: Linear Resonant Actuator)性能和特性各异:
-
ER 振动器:经典偏心轮式,振幅大、能耗高、响应慢。
-
LRA 振动器:线性谐振器,振幅相对小、能耗低、响应快,常用于触觉反馈。
-
-
-
Vibration HAL 与音频子系统
-
从 Android 8.0(O)起,振动信号被纳入音频接口,由
AudioFlinger
调度,更易与音频同步。 -
Vibrator HAL 通过
IVibrator
接口向上暴露perform()
、on()
、off()
、setAmplitude()
等方法。
-
2.2 Android 振动 API 演进
-
API ≤ 25
-
调用
Vibrator.vibrate(long milliseconds)
或Vibrator.vibrate(long[] pattern, int repeat)
。 -
无法控制振动强度,且 pattern 的精度与硬件响应有限。
-
-
API ≥ 26
-
引入
VibrationEffect
类:java
复制编辑
VibrationEffect.createOneShot(long milliseconds, int amplitude); VibrationEffect.createWaveform(long[] timings, int[] amplitudes, int repeat);
-
amplitude
范围 1–255,0 表示静音模式,可精细控制振动强度。
-
-
API ≥ 29 (Android 10)
-
支持触觉(Haptic)调用优先级控制,避免与媒体音频冲突。
-
-
API ≥ 31 (Android 12)
-
引入
FeedbackEffect
枚举,如EFFECT_CLICK
、EFFECT_TICK
、EFFECT_POP
,统一触觉体验。 -
通过
Vibrator.vibrate(VibrationEffect.createPredefined(...))
直接调用预定义触觉效果。
-
2.3 权限与兼容性
-
Permission
-
普通振动无需申请任何危险权限,
即可。
-
该权限在运行期不需动态申请。
-
-
兼容性注意
-
不同厂商对振动 amplitude 支持度不同,部分老设备 amplitude 参数会被忽略并退回到全强度。
-
某些系统(如 MIUI、Flyme)会对短促振动进行合并或限频,需要在业务层做延迟或 pattern 调整。
-
三、实现思路与架构设计
针对上述需求,我们设计一个 VibrationManager 模块,架构如下:
+-------------------+ 调用 +----------------+| Business Layer | ----------> | VibrationManager || (UI / ViewModel) | +----------------++-------------------+ | | | | | | +-----------+ | +--------------+ | | | +--------------+ +---------------+ +---------------+ | BaseHelper | | PatternHelper | | PredefinedHelper | +--------------+ +---------------+ +---------------+
-
Business Layer:Activity、Fragment 或 ViewModel,直接调用
VibrationManager.vibrateOneShot(...)
、vibratePattern(...)
、vibratePredefined(...)
。 -
VibrationManager:单例,负责初始化系统 Vibrator 服务、统一调度调用、处理 API 版本差异。
-
BaseHelper:封装最基础的振动调用,如单次、Waveform,无 amplitude 支持的降级。
-
PatternHelper:提供常用的 pattern 模式生成器,如 SOS、心跳、节奏节拍等。
-
PredefinedHelper:封装 Android 12+ 预定义触觉效果。
具体流程:
-
初始化:在
Application.onCreate()
中调用VibrationManager.init(context)
,获取系统 Vibrator。 -
调用:业务层调用
VibrationManager
的方法,无需关心 API 差异与权限。 -
执行:
VibrationManager
根据当前 SDK 版本选择相应 Helper,并调用对应接口。 -
扩展:如需支持远程配置,PatternHelper 可从 JSON 文件加载 timing/amplitude 数组并调用
createWaveform
。
四、完整项目代码(整合)
提示:以下代码已将所有类与 XML、资源整合到同一文件,通过注释分区。复制时请按实际包路径与文件拆分。
// =======================================================// 包名:com.example.vibrationdemo// 文件:VibrationExample.java(整合所有类与布局)// =======================================================package com.example.vibrationdemo;import android.app.Application;import android.content.Context;import android.os.*;import androidx.annotation.RequiresApi;import java.util.*;// =======================================================// Class: VibrationManager// 说明:振动管理单例,API 兼容调度// =======================================================public class VibrationManager { private static VibrationManager instance; private Vibrator vibrator; private Context ctx; /** 初始化,建议在 Application.onCreate() 调用 */ public static void init(Context context) { if (instance == null) { instance = new VibrationManager(context.getApplicationContext()); } } public static VibrationManager get() { if (instance == null) { throw new IllegalStateException(\"Must call init() first\"); } return instance; } private VibrationManager(Context context) { this.ctx = context; vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); } /** 单次振动 ms 毫秒,最大强度 */ public void vibrateOneShot(long ms) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { vibrator.vibrate(VibrationEffect.createOneShot(ms, VibrationEffect.DEFAULT_AMPLITUDE)); } else { vibrator.vibrate(ms); } } /** 持续振动,直到 cancel() */ public void vibrateLong(long ms) { vibrateOneShot(ms); } /** 按 pattern 执行振动,repeat=-1 不循环 */ public void vibratePattern(long[] pattern, int repeat) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { int[] amps = new int[pattern.length]; Arrays.fill(amps, VibrationEffect.DEFAULT_AMPLITUDE); vibrator.vibrate(VibrationEffect.createWaveform(pattern, amps, repeat)); } else { vibrator.vibrate(pattern, repeat); } } /** Android 12+ 预定义触觉效果 */ @RequiresApi(Build.VERSION_CODES.S) public void vibratePredefined(int effectId) { vibrator.vibrate(VibrationEffect.createPredefined(effectId)); } /** 取消所有振动 */ public void cancel() { vibrator.cancel(); }}// =======================================================// Class: PatternHelper// 说明:常用振动节奏生成器// =======================================================public class PatternHelper { /** 心跳节奏:200ms 休息 100ms 震动 200ms 休息 150ms 震动 */ public static long[] heartbeatPattern() { return new long[]{0, 100, 200, 150}; } /** SOS 节奏:... --- ... */ public static long[] sosPattern() { // S: dot dot dot, O: dash dash dash // dot: 200ms on / 200ms off; dash: 600ms on / 200ms off return new long[]{ 0, 200,200, 200,200, 200,600, 600,200, 600,200, 600,200, 200,200, 200,200, 200 }; }}// =======================================================// Class: PredefinedHelper (API 31+)// 说明:封装 Sdk31+ 预定义效果// =======================================================import android.os.VibrationEffect;@RequiresApi(Build.VERSION_CODES.S)public class PredefinedHelper { /** 点击反馈效果 */ public static int EFFECT_CLICK = VibrationEffect.EFFECT_CLICK; /** 弹簧效果 */ public static int EFFECT_TICK = VibrationEffect.EFFECT_TICK; /** 长按效果 */ public static int EFFECT_THUD = VibrationEffect.EFFECT_THUD;}// =======================================================// Application: MyApp// 说明:初始化 VibrationManager// =======================================================public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); VibrationManager.init(this); }}// =======================================================// Activity: MainActivity// 说明:演示各种振动调用// =======================================================import android.app.Activity;import android.os.Build;import android.os.Bundle;import android.view.View;import android.widget.*;public class MainActivity extends Activity { private Button btnOneShot, btnPattern, btnHeartbeat, btnSOS, btnCancel, btnPredef; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnOneShot = findViewById(R.id.btn_one_shot); btnPattern = findViewById(R.id.btn_pattern); btnHeartbeat= findViewById(R.id.btn_heartbeat); btnSOS = findViewById(R.id.btn_sos); btnCancel = findViewById(R.id.btn_cancel); btnPredef = findViewById(R.id.btn_predef); btnOneShot.setOnClickListener(v -> VibrationManager.get().vibrateOneShot(500)); btnPattern.setOnClickListener(v -> VibrationManager.get().vibratePattern(new long[]{0,300,150,300}, -1)); btnHeartbeat.setOnClickListener(v -> VibrationManager.get().vibratePattern(PatternHelper.heartbeatPattern(), 0)); btnSOS.setOnClickListener(v -> VibrationManager.get().vibratePattern(PatternHelper.sosPattern(), -1)); btnCancel.setOnClickListener(v -> VibrationManager.get().cancel()); btnPredef.setOnClickListener(v -> { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { VibrationManager.get() .vibratePredefined(PredefinedHelper.EFFECT_CLICK); } else { Toast.makeText(this, \"仅 Android 12+ 支持预定义效果\", Toast.LENGTH_SHORT).show(); } }); }}/*=======================================XML: res/layout/activity_main.xml======================================= */
五、代码解读(方法功能说明)
-
VibrationManager.init(Context)
-
在
Application.onCreate()
中调用,获取系统Vibrator
服务并缓存。
-
-
vibrateOneShot(long ms)
-
API 26+:
VibrationEffect.createOneShot(ms, DEFAULT_AMPLITUDE)
; -
API 25 及以下:退回
vibrator.vibrate(ms)
。
-
-
vibratePattern(long[] pattern, int repeat)
-
API 26+:使用
createWaveform(pattern, amplitudes, repeat)
,默认全强度; -
否则:调用
vibrator.vibrate(pattern, repeat)
。
-
-
vibratePredefined(int effectId)
-
API 31+:调用
createPredefined(effectId)
,支持系统预设触觉效果; -
通过
PredefinedHelper
封装常用效果常量。
-
-
cancel()
-
取消所有正在进行的振动。
-
-
PatternHelper.heartbeatPattern() / sosPattern()
-
提供常用振动节奏的
long[] timings
数组,便于业务层直接调用。
-
-
MainActivity 中的按钮点击
-
分别演示各种振动类型的调用,无需关心具体 API 差异。
-
六、基础篇小结
-
核心功能:单次振动、Pattern 振动、取消振动、API 兼容处理、Android 12+ 预定义触觉。
-
模块化设计:
VibrationManager
统一入口,PatternHelper
/PredefinedHelper
拆分业务。 -
扩展思考:
-
可在
PatternHelper
中加载远程配置 JSON,动态下发节奏。 -
可为不同 UI 组件封装 haptic-click 类,自动调用预定义
EFFECT_TICK
。 -
在 Jetpack Compose 中,使用
remember
+LaunchedEffect
在状态变化时触发振动。
-