如何在 Expo 应用中实现声音和震动通知功能?

来源:编程学习作者:阿狸头衔:草根站长
导读:本期聚焦于阿狸创作的《如何在 Expo 应用中实现声音和震动通知功能?》,敬请观看详情。移动应用开发中,通知反馈是提升用户体验的关键环节。不少开发者在处理 Expo 项目的本地通知时,会遇到声音无法播放或震动不生效的问题。这通常源于对 Expo Notifications 模块配置方式的理解偏差。本文将系统讲解如何在 Expo 应用中正确集成声音和震动通知功能,涵盖 Android 与 iOS 双平台的权限配置、通知通道建立、自定义声音文件放置规则以及震动模式触发方法。通过具体代码示例演示从基础通知到自定义反馈音效的完整实现流程,并针对真机测试中常见的静音模式失效、通道优先级冲突等典型问题给出排查思路与解决方案。

在移动应用开发中,通知不仅仅是文字信息的传递,声音和震动反馈同样是用户体验的重要组成部分。Expo 作为 React Native 生态中广受欢迎的框架,提供了 expo-notifications 模块来简化通知功能的集成。然而,声音播放和震动触发的配置涉及平台权限、通知通道、音频文件格式等多个层面,稍有不慎就会导致功能在真机上表现异常。本文将从基础配置入手,逐步讲解如何在 Expo 应用中完整实现声音和震动通知。

如何在 Expo 应用中实现声音和震动通知功能?

一、Expo Notifications 模块安装与权限配置

要实现通知功能,首先需要在项目中安装 expo-notifications 包。这个模块封装了 Android 和 iOS 平台的原生通知能力,提供了统一的 JavaScript API。安装命令非常简单,在项目根目录下执行即可。安装完成后,还需要在 app.json 配置文件中声明相关插件,确保 Expo 在构建时能正确链接原生模块。

权限配置是通知功能能否正常工作的前提条件。iOS 平台要求在 app.jsonios.infoPlist 字段中声明 NSUserNotificationUsageDescription 等权限描述字符串,向用户说明为什么需要通知权限。Android 平台从 Android 13(API 33)开始也强制要求运行时申请通知权限,需要在 android.permissions 中声明 android.permission.POST_NOTIFICATIONS。如果遗漏这些配置,应用在真机上请求权限时会直接崩溃或静默失败。

下面是 app.json 中通知相关配置的完整示例,包含了插件声明和权限描述:

{
  "expo": {
    "name": "NotificationDemo",
    "plugins": [
      [
        "expo-notifications",
        {
          "color": "#ffffff",
          "sounds": ["./assets/sounds/notification.wav"]
        }
      ]
    ],
    "android": {
      "permissions": ["android.permission.POST_NOTIFICATIONS"]
    },
    "ios": {
      "infoPlist": {
        "NSUserNotificationUsageDescription": "我们需要发送通知来提醒您重要事项"
      }
    }
  }
}

上述配置中,plugins 数组里的 sounds 字段用于注册自定义通知声音文件,这个文件路径是相对于项目根目录的。需要注意的是,iOS 支持的音频格式主要是 wavaiffcaf,而 Android 则支持 mp3wavogg 等格式。为了保证双平台兼容,建议统一使用 wav 格式的音频文件,采样率建议为 44100Hz,时长控制在 30 秒以内。

配置完成后,在应用启动时还需要通过代码请求通知权限。expo-notifications 提供了 requestPermissionsAsync 方法来统一处理权限申请,该方法会根据当前平台自动弹出对应的系统权限对话框。开发者应该检查返回的权限状态,只有在用户授权后才执行后续的通知调度逻辑。

二、实现声音通知:默认提示音与自定义音频

声音通知的实现分为两个层次:使用系统默认提示音和使用自定义音频文件。系统默认提示音是最简单的方式,只需要在创建通知时设置 sound 参数为 true,设备就会在收到通知时播放系统默认的通知音效。这种方式无需额外配置音频文件,适合对声音没有特殊要求的应用场景。

然而,大多数应用希望使用独特的提示音来增强品牌识别度,这就需要配置自定义声音。在 Expo 中,自定义声音的实现依赖于通知通道(Android)和声音文件注册(iOS)两个机制。Android 平台通过通知通道的 sound 属性指定音频文件,iOS 平台则通过通知内容的 sound 属性引用在 app.json 中注册的声音文件名。

下面是创建带有自定义声音的本地通知的完整代码示例:

import * as Notifications from 'expo-notifications';
import { Platform } from 'react-native';

// 配置通知处理器,设置前台通知的显示行为
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: true,
  }),
});

// 创建带自定义声音的通知通道(Android专用)
async function createSoundChannel() {
  if (Platform.OS === 'android') {
    await Notifications.setNotificationChannelAsync('custom-sound-channel', {
      name: '自定义声音通知',
      importance: Notifications.AndroidImportance.HIGH,
      sound: 'notification.wav', // 对应app.json中注册的声音文件
      vibrationPattern: [0, 250, 250, 250], // 震动模式
      enableVibration: true,
    });
  }
}

// 发送本地通知
async function scheduleNotification() {
  await createSoundChannel();

  await Notifications.scheduleNotificationAsync({
    content: {
      title: '新消息提醒',
      body: '您有一条新的未读消息,请及时查看',
      sound: 'notification.wav', // iOS引用注册的声音文件名
    },
    trigger: {
      type: Notifications.SchedulableTriggerInputTypes.TimeInterval,
      seconds: 5,
      channelId: 'custom-sound-channel', // Android指定通道
    },
  });
}

上述代码中有几个关键点需要特别注意。首先,setNotificationHandler 中的 shouldPlaySound 控制的是应用在前台时收到通知是否播放声音,默认值为 false,如果不设置为 true,前台通知将不会有声音反馈。其次,Android 的通知通道一旦创建,其声音和震动配置就无法修改,用户只能在系统设置中关闭但无法通过代码更改。因此,如果需要更换声音,必须创建一个新的通道。

iOS 平台的自定义声音引用方式与 Android 不同。在 iOS 上,content.sound 字段直接填写在 app.jsonsounds 数组注册过的文件名(不含路径),系统会自动匹配。如果填写 true 则使用系统默认声音,填写 null 或不设置则静默。需要特别注意的是,iOS 设备在静音模式下不会播放任何通知声音,这是系统级行为,应用层面无法绕过。

三、震动反馈的实现与平台差异处理

震动反馈是通知功能的另一重要维度,它能在静音或嘈杂环境中为用户提供触觉层面的感知。在 Expo 中,震动通知的实现方式因平台而异。Android 平台的震动通过通知通道的 vibrationPatternenableVibration 属性控制,而 iOS 平台的通知震动则是系统自动触发的,开发者无法自定义震动模式。

Android 的震动模式通过一个整数数组定义,数组中的偶数索引元素表示静止时长(毫秒),奇数索引元素表示震动时长(毫秒)。例如 [0, 250, 250, 250] 表示立即开始震动 250 毫秒,然后静止 250 毫秒,再震动 250 毫秒。这种模式可以创建有节奏的震动序列,帮助用户区分不同类型的通知。需要注意的是,震动功能还需要 android.permission.VIBRATE 权限,不过这个权限在 Expo 中默认已经包含,无需额外声明。

如果需要在非通知场景下触发震动,比如按钮点击反馈或操作确认,可以使用 expo-haptics 模块。这个模块提供了更丰富的触觉反馈选项,包括轻触、中等力度、重击等不同强度的震动模式,并且支持 iOS 平台。下面是 expo-haptics 的使用示例:

import * as Haptics from 'expo-haptics';

// 触发通知型震动反馈
async function triggerHapticFeedback() {
  await Haptics.notificationAsync(
    Haptics.NotificationFeedbackType.Success
  );
}

// 触发冲击型震动
async function triggerImpactFeedback() {
  await Haptics.impactAsync(
    Haptics.ImpactFeedbackStyle.Medium
  );
}

// 触发选择型震动(用于滚动选择器等场景)
async function triggerSelectionFeedback() {
  await Haptics.selectionAsync();
}

expo-haptics 模块提供了三种震动类型:impactAsync 用于模拟物理碰撞的触感,支持 Light、Medium、Heavy 三种力度;notificationAsync 用于通知场景,提供 Success、Warning、Error 三种语义化震动模式;selectionAsync 则用于用户选择操作时的轻微反馈。在 iOS 上,这些震动利用的是 Taptic Engine 硬件,体验比传统马达震动更加细腻。在 Android 上,模块会自动降级为系统震动马达的震动效果。

在实际开发中,通知震动和 Haptics 震动各有适用场景。通知场景下,应通过通知通道配置震动模式,这样即使应用在后台或被杀死,通知到达时仍能触发震动。而交互场景下的即时反馈,则应使用 expo-haptics,因为它不依赖通知系统,响应更即时。两者结合使用,能为用户提供全方位的触觉反馈体验。

最后需要提醒的是,震动和声音的测试必须在真机上进行。模拟器无法模拟震动硬件,部分模拟器也无法播放通知声音。建议在 Android 和 iOS 真机上分别测试通知的到达、声音播放和震动触发,并检查不同系统版本和不同静音模式下的表现。特别是 Android 的通知通道行为在不同厂商定制系统上可能存在差异,建议在小米、华为、三星等主流品牌设备上进行兼容性测试,确保通知反馈在所有目标设备上都能正常工作。

Expo声音通知震动反馈修改时间:2026-08-30 11:05:53

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。