> 技术文档 > Android实现手机振动(附带源码)_android震动代码

Android实现手机振动(附带源码)_android震动代码


一、项目介绍

在移动应用中,手机振动(Haptic Feedback) 是一种常见且重要的用户体验增强方式。不同场景下的振动反馈能让用户获得更直观、更沉浸的交互提示,例如:

  • 按钮点击反馈:输入框聚焦、按钮按下时轻微震动,让用户感知操作已生效。

  • 重要提醒:闹钟、计时器、来电或消息通知时的持续振动,确保用户不会错过。

  • 复杂游戏震动:游戏中爆炸、碰撞等重击感,通过不同强度与节奏的振动提升沉浸感。

  • 导航指引:使用导航时,转弯提示或危险路况提醒通过短促振动提示驾驶者。

我们希望搭建一个通用的、可扩展的振动管理框架,满足以下需求:

  1. 多种振动效果支持

    • 简单的单次振动

    • 持续振动

    • 自定义节奏(pattern)

    • 强度(amplitude)控制

  2. 兼容多 Android 版本

    • API 级别差异(Vibrator vs VibrationEffect)

    • Android 12+ 平台 Haptic API 新特性

  3. 易于集成

    • 只需在 ApplicationActivity 中初始化一次

    • 对外暴露简单的振动接口,可在业务层随时调用

  4. 可扩展高级能力

    • 混合式振动:结合音频、灯光,形成更丰富的感官反馈

    • 远程配置振动资源 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_CLICKEFFECT_TICKEFFECT_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+ 预定义触觉效果。

具体流程:

  1. 初始化:在 Application.onCreate() 中调用 VibrationManager.init(context),获取系统 Vibrator。

  2. 调用:业务层调用 VibrationManager 的方法,无需关心 API 差异与权限。

  3. 执行VibrationManager 根据当前 SDK 版本选择相应 Helper,并调用对应接口。

  4. 扩展:如需支持远程配置,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 差异。


六、基础篇小结

  1. 核心功能:单次振动、Pattern 振动、取消振动、API 兼容处理、Android 12+ 预定义触觉。

  2. 模块化设计VibrationManager 统一入口,PatternHelper/PredefinedHelper 拆分业务。

  3. 扩展思考

    • 可在 PatternHelper 中加载远程配置 JSON,动态下发节奏。

    • 可为不同 UI 组件封装 haptic-click 类,自动调用预定义 EFFECT_TICK

    • 在 Jetpack Compose 中,使用 remember + LaunchedEffect 在状态变化时触发振动。