Flutter 蓝牙耳机控制暂停播放

542 阅读2分钟

最近在做一个Flutter的音乐播放器,遇到了需要蓝牙耳机控制的需求,查了一下网上的相关资料,并没有针对没有安卓开发经验的开发者的文档,大部分文章都未一针见血的提出解决方案。其实在从 Android 4.0(API 级别 14)开始,系统可以访问媒体会话的播放状态和元数据。此功能可让锁定屏幕显示媒体控件和海报图片。原生安卓中使用MediaSeesion实现类似耳机控制的功能。 那么话不多说,我们直接上代码。 本次使用到了audio_service这个插件。不选择使用just_audio_background是因为适用度不够高,虽然其相对简单。audio_service支持与其他的音乐播放插件兼容,因此不用对代码进行大量的删改,比较简单。

插件链接:https://pub.dev/packages/audio_service
安装:flutter pub add audio_service

首先先初始化,并且实现相应的回调方法

    
class MyAudioHandler extends BaseAudioHandler
    with QueueHandler, // mix in default queue callback implementations
    SeekHandler { // 混合使用默认的查找回调实现
  
  // The most common callbacks:
  Future<void> play() async {
    // 所有“播放”都来源于此. 记得实现此方法
    // 此回调方法会开始播放您的音频
  }
  Future<void> pause() async {}
  Future<void> stop() async {}
  Future<void> seek(Duration position) async {}
  Future<void> skipToQueueItem(int i) async {}
}
//注:代码来源于https://pub.dev/packages/audio_service

第二步,在Main函数中注册

    
Future<void> main() async {
  // 将其存储在单例中
  _audioHandler = await AudioService.init(
    builder: () => MyAudioHandler(),
    config: AudioServiceConfig(
      androidNotificationChannelId: 'com.mycompany.myapp.channel.audio',
      androidNotificationChannelName: 'Music playback',
    ),
  );
  runApp(new MyApp());
}

然后设置音源

var item = MediaItem(
  id: 'https://example.com/audio.mp3',
  album: 'Album name',
  title: 'Track title',
  artist: 'Artist name',
  duration: const Duration(milliseconds: 123456),
  artUri: Uri.parse('https://example.com/album.jpg'),
);

_audioHandler.playMediaItem(item);
_audioHandler.playFromSearch(queryString);
_audioHandler.playFromUri(uri);//从URI中播放
_audioHandler.playFromMediaId(id);//根据ID播放音乐

基础的控制

_audioHandler.play();
_audioHandler.seek(Duration(seconds: 10));
_audioHandler.setSpeed(1.5);
_audioHandler.pause();
_audioHandler.stop();

最后修改配置文件

<manifest xmlns:tools="http://schemas.android.com/tools" ...>
  <!-- 添加这两个权限 -->
  <uses-permission android:name="android.permission.WAKE_LOCK"/>
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
  
  <application ...>
    
    ...
    
    <!-- 编辑现有“Activity”元素中的android:name属性 -->
    <activity android:name="com.ryanheise.audioservice.AudioServiceActivity" ...>
      ...
    </activity>
    
    <!-- 添加这个service -->
    <service android:name="com.ryanheise.audioservice.AudioService"
        android:foregroundServiceType="mediaPlayback"
        android:exported="true" tools:ignore="Instantiatable">
      <intent-filter>
        <action android:name="android.media.browse.MediaBrowserService" />
      </intent-filter>
    </service>

    <!-- 添加这个receiver -->
    <receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver"
        android:exported="true" tools:ignore="Instantiatable">
      <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
      </intent-filter>
    </receiver> 
  </application>
</manifest>