使用 snow 助您快速打造一个 Android 音乐播放器

2,251 阅读4分钟

要开发一个 Android 音乐播放器,相信各位 Android 开发者首先想到的是 MediaSession 框架。但 MediaSession 框架仅对基础功能进行了封装,要使用它开发一个音乐播放器,开发者还需要编写大量的代码。例如,响应媒体按钮、请求和管理音频焦点、在输出设备改变时暂停播放。此外,由于音乐播放器需要在后台运行,因此还得维护一个 Notification,以便在后台运行时,用户可以通过这个 Notification 对播放器进行控制。如果你的播放器还需要支持播放列表、线控播放、音质切换、睡眠定时器等一系列功能,那么接下来就有的忙了。不过不用担心,snow 框架已经为您做好了其中的大部分工作。

snow 框架简介

snow 是一个 Android 音乐播放器框架,基于 MediaSession 框架构建,并提供了对 MediaSession 框架的兼容snow 框架已经为开发者处理好了大部分繁琐的事情,例如,响应媒体按钮、请求和管理音频焦点、在输出设备改变时暂停播放、播放列表,线控播放等...

仓库地址https://github.com/jrfeng/snow

支持的功能:

  • 自定义播放器(MediaPlayer, ExoPlayer)
  • 自定义通知栏控制器
  • 自定义音频特效引擎
  • 仅 WiFi 网络播放
  • 切换音质/动态 URL
  • 线控播放
  • 睡眠定时器
  • 记录播放历史
  • 播放器状态持久化

快速上手

项目配置

  1. 将以下代码添加到项目根目录中的 build.gradle 文件中:
allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
  1. 将以下代码添加到模块的依赖中:
dependencies {
    implementation 'com.github.jrfeng.snow:player:1.0.9'
}
  1. 申请权限:
<!-- 用于启动前台 Service -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<!-- 用于后台播放 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

<!-- 用于播放本地音乐 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

<!-- 用于播放网络音乐 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

注意!从 Android 6.0(API Level 23) 开始,需要在运行时动态申请存储器访问权限:"android.permission.READ_EXTERNAL_STORAGE"

  1. 创建 PlayerService

创建一个类并让其继承 snow.player.PlayerService 类,并且使用 @PersistenceId 注解对其进行标注。你不需要重写这个类的任何方法

例:

@PersistenId("MyPlayerService")
public MyPlayerService extends PlayerService {
}

@PersistenceId 注解用于为当前 PlayerService 设置一个持久化 ID(请保证该 ID 值的唯一性),该 ID 将用于 PlayerService 状态的持久化。如果你没有使用 @PersistenceId 注解设置持久化 ID,则持久化 ID 默认为你的 PlayerService 的完整类名(例如 snow.demo.MyPlayerService)。建议为你的 PlayerService 设置一个持久化 ID,这样即使重命名类也不会导致状态丢失。

  1. 注册 PlayerService
<service android:name="snow.demo.MyPlayerService">
    <intent-filter>
        <action android:name="android.media.browse.MediaBrowserService" />
    </intent-filter>
</service>

<receiver android:name="androidx.media.session.MediaButtonReceiver" >
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>

简单使用

  1. 连接到 PlayerService
// 创建一个 PlayerClient 对象
PlayerClient playerClient = PlayerClient.newInstance(context, MyPlayerService.class);

// 连接到 PlayerService
playerClient.connect(new PlayerClient.OnConnectCallback() {
    @Override
    public void onConnected(boolean success) {
        // DEBUG
        Log.d("App", "connect: " + success);
    }
});
  1. 创建一个播放列表
private Playlist createPlaylist() {
    MusicItem song1 = new MusicItem.Builder()
            .setTitle("太阳照常升起")
            .setArtist("久石让")
            .setAlbum("太阳照常升起 电影原声大碟")
            .setDuration(224013)
            .setUri("http://music.163.com/song/media/outer/url?id=441722")
            .setIconUri("http://p2.music.126.net/drqGdK7zgW7B7IFl4lWpoQ==/109951163369835547.jpg")
            .build();

    MusicItem song2 = new MusicItem.Builder()
            .setTitle("钢铁洪流进行曲")
            .setArtist("李旭昊")
            .setAlbum("国庆70周年阅兵BGM")
            .setDuration(186154)
            .setUri("http://music.163.com/song/media/outer/url?id=1394369908")
            .setIconUri("http://p2.music.126.net/KnC_YJjnRTNvCF82_2leCg==/109951164930615683.jpg")
            .build();

    MusicItem song3 = new MusicItem.Builder()
            .setTitle("国际歌-钢琴")
            .setArtist("曹伟健")
            .setAlbum("音迹")
            .setDuration(141369)
            .setUri("http://music.163.com/song/media/outer/url?id=1857796913")
            .build();

    MusicItem song4 = new MusicItem.Builder()
            .setTitle("我爱你中国[Forbid Seek]")
            .setDuration(136000)
            // cross-protocol redirects
            .setUri("https://music.163.com/song/media/outer/url?id=174451")
            .setIconUri("http://p2.music.126.net/x6pVwc6ysKZ9S01jYlYiAw==/97856534887060.jpg")
            // forbid seek
            .setForbidSeek(true)
            .build();

    return new Playlist.Builder()
            .append(song1)
            .append(song2)
            .append(song3)
            .append(song4)
            .build();
}
  1. 设置播放列表并播放音乐
// 创建播放列表
Playlist playlist = createPlaylist();

// 设置播放列表,并播放音乐
playerClient.setPlaylist(playlist, true);

示例程序

为了演示 snow 框架的部分功能,我们特意开发了一个示例程序,如下图所示(网盘下载,提取码:7mye):

提示:示例程序是一个本地音乐播放器,可以在项目的 app 模块中找到该示例程序的源代码。

文档

如果您对 snow 框架感兴趣,并且希望深入了解,可以查看项目的 Wiki:

End