You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中如何监听并处理耳机的播放/暂停按钮事件

React Native 处理耳机播放/暂停按钮事件的可行方案

我之前帮不少开发者解决过这个问题,耳机播放/暂停按钮的处理确实比音量键麻烦——系统默认会把这个事件劫持给内置媒体服务,得针对iOS和Android分别做适配,下面是具体的实现方案:

iOS 端实现思路

iOS上耳机的播放/暂停属于远程控制事件,需要通过AVAudioSession激活并监听这类事件,具体步骤如下:

原生代码配置(Objective-C)

在你的AppDelegate.m文件中添加以下代码,用来激活音频会话并监听远程控制事件:

#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // 激活音频会话,这是接收远程控制事件的前提
  AVAudioSession *session = [AVAudioSession sharedInstance];
  NSError *error = nil;
  [session setCategory:AVAudioSessionCategoryPlayback error:&error];
  if (error) {
    NSLog(@"激活音频会话失败: %@", error);
  }
  [session activateWithOptions:AVAudioSessionActivateOptionNotifyOthersOnDeactivation error:&error];
  if (error) {
    NSLog(@"激活会话出错: %@", error);
  }

  // 开始接收远程控制事件
  [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
  [self becomeFirstResponder];

  // 保留原有项目代码...
}

// 处理远程控制事件
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
  if (event.type == UIEventTypeRemoteControl) {
    switch (event.subtype) {
      case UIEventSubtypeRemoteControlPlay:
      case UIEventSubtypeRemoteControlPause:
      case UIEventSubtypeRemoteControlTogglePlayPause:
        // 发送事件给React Native层
        [[NSNotificationCenter defaultCenter] postNotificationName:@"HeadsetPlayPausePressed" object:nil];
        break;
      default:
        break;
    }
  }
}

// 确保AppDelegate能成为第一响应者,才能接收远程控制事件
- (BOOL)canBecomeFirstResponder {
  return YES;
}

React Native 层监听事件

在JS代码中通过NativeEventEmitter监听原生发送的事件,执行你的自定义操作:

import { NativeEventEmitter, useEffect } from 'react-native';

const eventEmitter = new NativeEventEmitter();

useEffect(() => {
  const subscription = eventEmitter.addListener('HeadsetPlayPausePressed', () => {
    // 这里写你的自定义逻辑,比如触发播放/暂停
    console.log('耳机播放/暂停按钮被点击');
    // 示例:togglePlayPause();
  });

  // 组件卸载时移除监听
  return () => subscription.remove();
}, []);

注意:别忘了在Info.plist中添加音频相关权限,比如NSAudioUsageDescription,否则可能无法激活音频会话。

Android 端实现思路

Android上耳机播放/暂停属于媒体按键事件,可以通过广播接收器来拦截处理,具体步骤:

原生代码配置(Java)

在MainActivity.java中注册广播接收器,拦截媒体按键事件:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Bundle;
import android.view.KeyEvent;
import com.facebook.react.ReactActivity;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.ReactContext;

public class MainActivity extends ReactActivity {
  private BroadcastReceiver mediaButtonReceiver;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // 注册媒体按键广播,设置最高优先级确保先收到事件
    IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
    filter.setPriority(Integer.MAX_VALUE);
    
    mediaButtonReceiver = new BroadcastReceiver() {
      @Override
      public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (Intent.ACTION_MEDIA_BUTTON.equals(action)) {
          KeyEvent event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
          if (event != null && event.getAction() == KeyEvent.ACTION_DOWN) {
            int keyCode = event.getKeyCode();
            if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
              // 发送事件给React Native层
              ReactContext reactContext = getReactInstanceManager().getCurrentReactContext();
              if (reactContext != null) {
                reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                  .emit("HeadsetPlayPausePressed", null);
              }
              abortBroadcast(); // 阻止系统继续处理该事件,避免触发其他媒体APP
            }
          }
        }
      }
    };
    registerReceiver(mediaButtonReceiver, filter);
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    // 组件销毁时注销广播接收器
    if (mediaButtonReceiver != null) {
      unregisterReceiver(mediaButtonReceiver);
    }
  }
}

React Native 层监听事件

同样在JS代码中监听事件:

import { NativeEventEmitter, useEffect } from 'react-native';
import { DeviceEventManagerModule } from '@react-native-community/hooks';

const eventEmitter = new NativeEventEmitter(DeviceEventManagerModule);

useEffect(() => {
  const subscription = eventEmitter.addListener('HeadsetPlayPausePressed', () => {
    // 执行你的自定义操作
    console.log('耳机播放/暂停按钮触发');
  });

  return () => subscription.remove();
}, []);

注意:

  1. Android 12及以上需要在AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.MEDIA_CONTROL" />
  1. 如果你的应用在后台,可能无法收到广播事件——Android 10及以上对后台广播限制较严,建议将应用设为前台媒体应用,或者使用前台服务来保持事件监听。

简化方案:使用第三方库

如果不想写原生代码,可以选择社区维护的第三方库(比如专门处理媒体按键或耳机事件的库),这类库已经封装好了iOS和Android的原生逻辑,只需要调用JS API就能快速实现监听。记得选择维护活跃、兼容性好的库哦。

常见问题排查

  • iOS:如果收不到事件,先检查音频会话是否激活,以及AppDelegate是否成为了第一响应者。如果你的应用没有播放音频,也需要激活AVAudioSessionCategoryPlayback类别才能接收远程控制事件。
  • Android:如果其他媒体APP正在播放,它们会优先获取事件——这时候可以让你的应用成为前台媒体应用,或者确保广播接收器的优先级设置为最高。

内容的提问来源于stack exchange,提问作者deniz ba艧

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:08:06