首页 > 其他分享 >使用MediaPlayer开发简单的在线音乐播放器

使用MediaPlayer开发简单的在线音乐播放器

时间:2023-10-24 22:32:28浏览次数:46  
标签:播放器 Toast 在线音乐 Service MediaPlayer void mediaPlayer 播放 public

由于工作内容的局限性,Service组件在平时并不经常用得上,本篇以一个简单的音乐播放器为例,记录开发过程,以熟悉Service组件的使用,以免生疏。
本篇中所用到的音乐数据及音乐播放地址皆以爬虫实时获取,只用于学习交流所用。

本篇核心在于温习Service组件的使用,爬取音乐数据及列表展示不在此赘述,详情可查看篇尾项目地址

定义Service用于编写所有的音乐播放控制及监听逻辑

首先我们定义一个MusicPlayService

public class MusicPlayerService extends Service {
    private MusicInfo currentMusic = null;
    private int playState = 0; //0stop 1playing 2paused -1加载中

    @Override
    public IBinder onBind(Intent intent) {
        return new MusicBinder();
    }

    public class MusicBinder extends Binder {
        public void start(MusicInfo musicInfo) {
            currentMusic = musicInfo;
            Toast.makeText(MusicPlayerService.this, "play", Toast.LENGTH_SHORT).show();
        }
        public void pauseOrPlay(){
            Toast.makeText(MusicPlayerService.this, "pauseOrPlay", Toast.LENGTH_SHORT).show();
        }
        public void stop(){
            Toast.makeText(MusicPlayerService.this, "play", Toast.LENGTH_SHORT).show();
        }
    }
}

在Service中定义一个内部类继承自Binder用于onBind方法返回,因为是内部类,所以该类的方法可以与Service交互操作。 onBind方法在多次调用bindService时只会调用一次,除第一次外,再次调用bindService时会从缓存中获取第一次获取到的binder,也就是说我们不用担心在onBind方法中直接new对象会造成多次bind操作new多个binder的情况。

在Activity中开启Service并BindService

我们定义一个Activity来模拟音乐播放界面或其他可操作的音乐播放界面

public class MusicPlayActivity extends AppCompatActivity {
    private ServiceConnection serviceConnection;
    private MusicPlayerService.MusicBinder musicBinder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_music_play);
        startService(new Intent(this, MusicPlayerService.class));
        serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                musicBinder = (MusicPlayerService.MusicBinder) service;
            }
            @Override
            public void onServiceDisconnected(ComponentName name) { }
        };
        bindService(new Intent(this, MusicPlayerService.class), serviceConnection, AppCompatActivity.BIND_AUTO_CREATE);
    }

    public void start(View view) {
        musicBinder.start(null);
    }
    public void pauseOrPlay(View view) {
        musicBinder.pauseOrPlay();
    }
    public void stop(View view) {
       musicBinder.stop();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(serviceConnection);
    }
}

这里我们首先调用了startService来激活Service,接下来使用bindService和unbindService来进行Service的绑定和解绑 如果在不使用startService的情况下只是用bind和unbind来操作Service的话,Service会在所有bind都被unbind的情况下自动销毁的,所以在这里先使用了startService。 使用了StartService激活的Service只有在调用stopService或者service自身stopself的情况下才会被正常结束,这样就能实现结束Activity之后仍能在后台播放音乐了。

通过bindservice我们在onServiceConnected回调方法中能够拿到在service的onbind方法中放回的Ibinder,由于我们返回的是MusicBinder内部类,所以可以直接强转得到musicbinder对象, 通过此对象我们就可以和musicService进行通信了,也就是说我们可以通过调用musicBinder的播放暂停停止方法来通知Service进行相应的音乐控制操作。

在Service中通过MediaPlayer实现音乐的播放控制操作

我们需要在Service初始化的时候同时创建一个Mediaplayer对象让Service在运行期间播放音乐时使用,所以在oncreate中加入以下代码

@Override
    public void onCreate() {
        super.onCreate();
        createMediaPlayer();
    }

    private void createMediaPlayer() {
        if (mediaPlayer == null) {
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mp.start();
                }
            });
        }
    }

接下来在MusicBinder中用MediaPlayer实现对音乐播放控制

public class MusicBinder extends Binder {
        public void start(MusicInfo musicInfo) {
            currentMusic = musicInfo;
            if (mediaPlayer == null) {
                createMediaPlayer();
            }
            mediaPlayer.reset();
            try {
                mediaPlayer.setDataSource(musicInfo.url);
                mediaPlayer.prepareAsync();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void pauseOrPlay() {
            Toast.makeText(MusicPlayerService.this, "pauseOrPlay", Toast.LENGTH_SHORT).show();
            if (mediaPlayer==null){
                createMediaPlayer();
            }
            mediaPlayer.pause();
//       or     mediaPlayer.start();
        }

        public void stop() {
            Toast.makeText(MusicPlayerService.this, "play", Toast.LENGTH_SHORT).show();
            if (mediaPlayer==null){
                createMediaPlayer();
            }
            mediaPlayer.stop();
        }
    }

上面代码只是大致示意了音乐播放暂停停止的操作,篇幅限制,这里不再赘述 到此为止对音乐的简单播放停止控制已经完成了。

新增播放进度监听

MediaPlayer并没有为我们提供监听播放进度的api,所以我们要实现进度监听只能通过定时查询播放进度的方式来进行。 我们使用RXJava来定义一个定时器,当然你也可以使用Thread或者其他方式

override fun onCreate() {
        super.onCreate()
        Observable.interval(1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    if (!(mediaPlayer?.isPlaying ?: false)) return@subscribe
                    val duration = mediaPlayer?.duration ?: 0
                    val currentPosition = mediaPlayer?.currentPosition ?: 0
                    if (binder.currentPosition != currentPosition || binder.duration != duration) {
                        binder.currentPosition = currentPosition
                        binder.duration = duration
                        if (binder.isBinderAlive) {
                            for (callBack in binder.callBackList) {
                                callBack.onProgress(currentPosition, duration)
                            }
                        }
                    }
                };

这个示例项目其实是用kotlin来写的,上面几段代码都是从kotlin又翻译回java的,这段实在不想用java来表示了,因为又长又丑 简单说一下吧,这里定义了一个1秒触发一次的定时器,并在主线程中回调,判断mediaplayer的播放状态,若是正在播放,则从mediaplayer中获取正在播放的音乐的最大长度和当前播放位置。 binder是维护的另外一个容器,用来存储播放器的进度以及注册的所有回调函数,然后遍历binder中注册的回调进行invoke。

完工。

完整项目代码地址:https://github.com/NightFarmer/MusicPlayer

标签:播放器,Toast,在线音乐,Service,MediaPlayer,void,mediaPlayer,播放,public
From: https://blog.51cto.com/NightFarmer/8010769

相关文章

  • FFMPEG+SDL简单视频播放器——人脸检测
    前言最近突发奇想,给播放器加上一个人脸检测的功能(事情似乎朝着奇怪的方向发展了,谁家的播放器会需要去检测人脸啊......
  • 循环语法之编程模拟音乐播放器
    以音乐播放器软件的界面作为导入提问学生:如果需要自己生成一个歌单,在歌单中有哪些较为重要的组成部分?提取关键元素:歌曲名;歌手;歌曲顺序编程实现一:利用顺序结构实现一个简单的歌单回顾字符串类型与print()函数,实现下列代码songname1="画"songname2="借我"songname3="......
  • 关于流媒体播放器EasyPlayer和EasyPlayerPro的介绍以及其区别
    EasyPlayer是一款流媒体播放器系列项目,它支持多种流媒体协议的播放,包括但不限于RTSP、RTMP、HTTP、HLS、UDP、RTP、File等。除此之外,EasyPlayer还支持本地文件播放和多种功能特性,包括本地抓拍、本地录像、播放旋转、多屏播放、倍数播放等。EasyPlayer核心基于ffmpeg,稳定、......
  • 使用开源播放器VLC media player进行视频格式转换
    VLC是一款自由、开源的跨平台多媒体播放器及框架,可播放大多数多媒体文件,以及DVD、音频CD、VCD及各类流媒体协议。---摘自官网一般用它来播放视频,但其实它也可以转换视频.虽然官网没有明说,我估计转换功能是调用了大佬程序员 法布里斯•贝拉(FabriceBellard)的开源项目FFmpe......
  • IINA Mac:免费的视频播放器
    IINAMac是一款免费的视频播放器,适用于Mac平台。它的外观和设计都遵循了现代MacOS的风格,优雅而简洁。IINAMac的开发者使用Swift编程语言进行开发,使得这款播放器拥有强大的性能和兼容性,可以流畅播放几乎所有主流的视频格式以及进行网络播放。→→↓↓载IINAMac版IINAMac不仅......
  • 基于.Net 的 AvaloniUI 多媒体播放器方案汇总
    基于.Net的AvaloniUI多媒体播放器方案汇总摘要随着国产化的推进,相信.Net的桌面端的小伙伴的可能已经有感受到了。为了让.Net的桌面框架能够跨桌面平台,首选的就是Avalona-UI。为了让AvaloniaUI能够跨多个平台播放视频,这里测试主要播放视频形式是使用RTSP。所以,在这篇博文中......
  • FFMPEG+SDL简单视频播放器——视频快进
    之前写过一篇关于视频播放器的文章。播放器只简单实现了视频播放的功能,在此功能的基础上,给它加上一个视频快进的功能。实现添加参数//videoplaycontrolbooldo_seek=false;//播放状态int64_tseek_length=5;//快进秒数int64_tseek_pos;//视频跳转......
  • 如何搭建一个dash播放器
    1.安装宝塔面板为什么安装宝塔面板,因为宝塔面板的图形化界面使操作更加方便简洁,不需要手动去终端输入路径一个一个打开文件内容查看。安装入口:https://www.bt.cn/new/index.html这里我使用了自己购买的云服务器,直接在云服务器上安装即可。查看面板是否安装成功:(输入14,进入面板)......
  • 音乐播放器 Foobar2000 / Foobox 安装使用
    1、安装可以参考Foobox作者项目地址教程安装:https://gitee.com/dream7180/foobox-cn2、配置MusicTag作者博客:https://www.cnblogs.com/vinlxc/p/11347744.html......
  • 推荐一款好用的开源视频播放器(免费无广告)
    mpv是一个自由开源的媒体播放器,它支持多种音频和视频格式,并且具有高度可定制性。mpv的设计理念是简洁、高效和功能强大。软件特点:1.开源、跨平台。可以在Windows\Linux\MacOS\BSD等系统上使用,完全免费无广告。Windows版解压即用,绿色便携。2.兼容性好。支持绝大多数视频、音频、......