MusicLibrary-丰富的音频播放SDK.

电脑杂谈  发布时间:2020-06-08 21:41:58  来源:网络整理

播放器build_放碟片的播放丨器_高达build fighters

GitHub地址: github.com/lizixian18/…

在日常开发中,如果需要在项目中添加音频播放功能,那是一件非常麻烦的事情. 需要处理的一般事项是音频服务包装,播放器包装,通知栏管理,链接系统媒体中心,音频焦点获取,播放列表维护,各种API方法编写等. 如果进行了改进,IPC也需要将要执行. 可以看出,有很多事情要处理.

MusicLibrary的写法是这样的,其目的是帮助您实现所有与音频有关的事情,以便您可以专注于其他事情.

实施基于IPC的音频服务,减少应用程序内存高峰,并避免OOM. 集成和调用API非常简单,音频功能几乎可以用一句话集成. 提供丰富的API方法以轻松实现各种功能. 将通知栏集成到一句话中,您可以自定义通知栏的控件. 内部集成了两个播放器,即ExoPlayer和MediaPlayer. 默认情况下使用ExoPlayer播放器build,可以随意切换. 还有其他...

为了反映MusicLibrary的实际应用,编写了一个简单的音乐播放器NiceMusic.

GitHub地址: github.com/lizixian18/…

MusicLibrary的基本用法可以参考该项目中的实现.

在NiceMusic中,您可以了解以下内容:

更好的MVP结构封装,与RxJava结合使用,生命周期与Activity绑定在一起,并且Presenter通过注释实例化,而注释则更加分离. 改造框架封装以及如何使用向所有接口添加通用参数和头信息. 其他等等...

放置一些屏幕截图:

不再讨论IPC和AIDL的用法和原理. 如果您听不懂,请亲自咨询信息.

如您所见,PlayControl实际上是连接客户端和服务器的活页夹.

QueueManager是播放列表管理类,用于维护当前的播放列表和当前的音频索引.

播放列表存储在ArrayList中,默认情况下,音频索引为0:

放碟片的播放丨器_高达build fighters_播放器build

public QueueManager(MetadataUpdateListener listener, PlayMode playMode) {
    mPlayingQueue = Collections.synchronizedList(new ArrayList<SongInfo>());
    mCurrentIndex = 0;
    ...
}
复制代码

在调用与设置播放列表有关的API时,实际上会调用setCurrentQueue方法. 每次清除播放列表时,便会分配值:

public void setCurrentQueue(List<SongInfo> newQueue, int currentIndex) {
    int index = 0;
    if (currentIndex != -1) {
        index = currentIndex;
    }
    mCurrentIndex = Math.max(index, 0);
    mPlayingQueue.clear();
    mPlayingQueue.addAll(newQueue);
    //通知播放列表更新了
    List<MediaSessionCompat.QueueItem> queueItems = QueueHelper.getQueueItems(mPlayingQueue);
    if (mListener != null) {
        mListener.onQueueUpdated(queueItems, mPlayingQueue);
    }
}
复制代码

更新播放列表时,它将把播放列表封装到QueueItem列表中,并在锁定屏幕时回调MediaSessionManager进行与媒体相关的操作.

获取当前正在播放的音乐,播放指定的音乐等实际上是在操作音频索引mCurrentIndex,然后根据该索引提取列表中的相应音频信息.

上一个和下一个操作实际上称为skipQueuePosition方法,该方法使用剩余算法计算上一首和下一首歌曲的索引,

代替加或减一个,这样的好处是可以避免数组越界或计算更加方便:

public boolean skipQueuePosition(int amount) {
    int index = mCurrentIndex + amount;
    if (index < 0) {
        // 在第一首歌曲之前向后跳,让你在第一首歌曲上
        index = 0;
    } else {
        //当在最后一首歌时点下一首将返回第一首个
        index %= mPlayingQueue.size();
    }
    if (!QueueHelper.isIndexPlayable(index, mPlayingQueue)) {
        return false;
    }
    mCurrentIndex = index;
    return true;
}
复制代码

参数数量是尺寸的含义. 如您所见,如果通过1,则将获得下一首歌曲;如果通过-1,则将获得下一首歌曲. 实际上,您可以获得任何音频,

只要尺寸不同.

播放音乐时,首先调用setCurrentQueueIndex方法设置音频索引,然后将回调传递给PlaybackManager进行真正的播放处理.

private void setCurrentQueueIndex(int index, boolean isJustPlay, boolean isSwitchMusic) {
    if (index >= 0 && index < mPlayingQueue.size()) {
        mCurrentIndex = index;
        if (mListener != null) {
            mListener.onCurrentQueueIndexUpdated(mCurrentIndex, isJustPlay, isSwitchMusic);
        }
    }
}
复制代码

这是QueueManager需要解释的. 如果您有兴趣,可以克隆代码并仔细查看.

PlaybackManager是一个播放管理类,负责操作播放,暂停和其他播放控制操作.

播放器build_高达build fighters_放碟片的播放丨器

它实现了Playback.Callback接口,而Playback是定义播放器相关操作的接口.

特定的播放器ExoPlayer和MediaPlayer实现都实现了Playback接口,而PlaybackManager是通过Playback

以统一的方式管理播放器的相关操作. 因此,如果要添加其他播放器,只需实现Playback接口.

播放:

public void handlePlayRequest() {
    SongInfo currentMusic = mQueueManager.getCurrentMusic();
    if (currentMusic != null) {
        String mediaId = currentMusic.getSongId();
        boolean mediaHasChanged = !TextUtils.equals(mediaId, mCurrentMediaId);
        if (mediaHasChanged) {
            mCurrentMediaId = mediaId;
            notifyPlaybackSwitch(currentMusic);
        }
        //播放
        mPlayback.play(currentMusic);
        //更新媒体信息
        mQueueManager.updateMetadata();
        updatePlaybackState(null);
    }
}
复制代码

播放方法分几个步骤:

删除要播放的音频信息. 根据音频id的比较,判断是否回切歌曲的方法. 如果id不同,则表示歌曲需要剪切. 然后调用mPlayback.play(currentMusic)并将其提供给特定的播放器. 然后更新媒体操作(即屏幕锁定时的播放器)的音频信息. 回调播放状态.

暂停:

public void handlePauseRequest() {
    if (mPlayback.isPlaying()) {
        mPlayback.pause();
        updatePlaybackState(null);
    }
}
复制代码

暂停将直接移交给特定播放器以暂停,然后回放状态会被回调.

停止:

public void handleStopRequest(String withError) {
    mPlayback.stop(true);
    updatePlaybackState(withError);
}
复制代码

停止也是如此.

基本上,PlaybackManager中的操作围绕这三种方法,而其他方法则是一些封装和回调处理.

播放器build_放碟片的播放丨器_高达build fighters

具体的播放器实现是指Google的官方示例android-UniversalMusicPlayer. 这个项目真的很好.

该类主要用于管理媒体信息MediaSessionCompat,他的写作是相对固定的,可以参考本文链接系统媒体中心的介绍

您还可以参考Google的官方示例

此类封装了通知栏的相关操作. 自定义通知栏的情况可以认为非常复杂,远不止是新的通知. (也许我是菜鸟)

NotificationCompat.Builder中有两种setContentView方法,一种是setCustomContentView()

一个是setCustomBigContentView(). 您可以知道差异就是大小差异. 还有两个RemoteView: RemoteView和BigRemoteView

不同的手机,某些通知栏背景为白色,某些通知栏背景为透明或黑色(例如魅族,小米等),那么您需要根据不同背景显示不同的样式(除非您在布局中显示为死背景)颜色,但这确实很难看)

通知栏需要四种布局:

在白色背景下的ContentView在黑色背景下的BigContentView在黑色背景下的ContentView在黑色背景下的ContentView

按如下所示设置ContentView:

...
if (Build.VERSION.SDK_INT >= 24) {
    notificationBuilder.setCustomContentView(mRemoteView);
    if (mBigRemoteView != null) {
        notificationBuilder.setCustomBigContentView(mBigRemoteView);
    }
}
...
Notification notification;
if (Build.VERSION.SDK_INT >= 16) {
    notification = notificationBuilder.build();
} else {
    notification = notificationBuilder.getNotification();
}
if (Build.VERSION.SDK_INT < 24) {
    notification.contentView = mRemoteView;
    if (Build.VERSION.SDK_INT >= 16 && mBigRemoteView != null) {
        notification.bigContentView = mBigRemoteView;
    }
}
...
复制代码


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/bofangqi/article-238684-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    • 宋延博
      宋延博

      如果再配合降【】17%至7%

    热点图片
    拼命载入中...