android 本地 播放器,Android 本地播放器

一、先看效果图

931e3dc5e8a9baafe3f33270d62683a3.png

52f24828566a4aaa7b9f7174f88332f3.png

38d3813b0408efa1ede6990a5d64c577.png

24b872f45f001647613e70ef0bacc664.png

0e4ee46d2ce37234fe923550730afd16.png

656f54cacf7642da56719b9cb710873b.png

a170312e254be74e7d4f2ce64201570d.png

二、项目的播放流程简要介绍

1.首先我们需要一个常驻在后台的播放服务,在播放服务中绑定一个播放广播,我们在打开播放器的时候就启动这个播放服务。public class MusicPlayerService extends Service {

private static final String TAG = MusicPlayerService.class.getName();

public static final String PLAYER_MANAGER_ACTION = "com.lijunyan.blackmusic.service.MusicPlayerService.player.action";

private PlayerManagerReceiver mReceiver;

public MusicPlayerService() {

}

@Override

public IBinder onBind(Intent intent) {

throw new UnsupportedOperationException("Not yet implemented");

}

@Override

public void onCreate() {

super.onCreate();

Log.e(TAG, "onCreate: ");

register();

}

@Override

public void onDestroy() {

super.onDestroy();

Log.e(TAG, "onDestroy: ");

unRegister();

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

Log.e(TAG, "onStartCommand: ");

return super.onStartCommand(intent, flags, startId);

}

private void register() {

mReceiver = new PlayerManagerReceiver(MusicPlayerService.this);

IntentFilter intentFilter = new IntentFilter();

intentFilter.addAction(PLAYER_MANAGER_ACTION);

registerReceiver(mReceiver, intentFilter);

}

private void unRegister() {

if (mReceiver != null) {

unregisterReceiver(mReceiver);

}

}

}

2.播放服务中的广播可以接受各种音频控制操作,包括播放、暂停、切歌等。程序在响应用户的音频控制操作时向这个播放广播发送对应的播放、暂停、停止等指令。广播收到不同的指令做不同的功能实现。public class PlayerManagerReceiver extends BroadcastReceiver {

private static final String TAG = PlayerManagerReceiver.class.getName();

public static final String ACTION_UPDATE_UI_ADAPTER = "com.lijunyan.blackmusic.receiver.PlayerManagerReceiver:action_update_ui_adapter_broad_cast";

private MediaPlayer mediaPlayer;

private DBManager dbManager;

public static int status = Constant.STATUS_STOP;

private int playMode;

private int threadNumber;

private Context context;

public PlayerManagerReceiver() {

}

public PlayerManagerReceiver(Context context) {

super();

this.context = context;

dbManager = DBManager.getInstance(context);

mediaPlayer = new MediaPlayer();

Log.d(TAG, "create");

initMediaPlayer();

}

@Override

public void onReceive(Context context, Intent intent) {

int cmd = intent.getIntExtra(Constant.COMMAND,Constant.COMMAND_INIT);

Log.d(TAG, "cmd = " + cmd);

switch (cmd) {

case Constant.COMMAND_INIT:

Log.d(TAG, "COMMAND_INIT");

break;

case Constant.COMMAND_PLAY:

Log.d(TAG, "COMMAND_PLAY");

status = Constant.STATUS_PLAY;

String musicPath = intent.getStringExtra(Constant.KEY_PATH);

if (musicPath!=null) {

playMusic(musicPath);

}else {

mediaPlayer.start();

}

break;

case Constant.COMMAND_PAUSE:

mediaPlayer.pause();

status = Constant.STATUS_PAUSE;

break;

case Constant.COMMAND_STOP:

NumberRandom();

status = Constant.STATUS_STOP;

if(mediaPlayer!=null) {

mediaPlayer.stop();

}

initStopOperate();

break;

case Constant.COMMAND_PROGRESS://拖动进度

int curProgress = intent.getIntExtra(Constant.KEY_CURRENT, 0);

//异步的,可以设置完成监听来获取真正定位完成的时候

mediaPlayer.seekTo(curProgress);

break;

case Constant.COMMAND_RELEASE:

NumberRandom();

status = Constant.STATUS_STOP;

if(mediaPlayer!=null) {

mediaPlayer.stop();

mediaPlayer.release();

}

break;

}

UpdateUI();

}

private void initStopOperate(){

MyMusicUtil.setShared(Constant.KEY_ID,dbManager.getFirstId(Constant.LIST_ALLMUSIC));

}

private void playMusic(String musicPath) {

NumberRandom();

if (mediaPlayer!=null) {

mediaPlayer.release();

}

mediaPlayer = new MediaPlayer();

mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

@Override

public void onCompletion(MediaPlayer mp) {

Log.d(TAG, "playMusic onCompletion: ");

NumberRandom();             //切换线程

onComplete();     //调用音乐切换模块,进行相应操作

UpdateUI();             //更新界面

}

});

try {

File file = new File(musicPath);

if(!file.exists()){

Toast.makeText(context,"歌曲文件不存在,请重新扫描",Toast.LENGTH_SHORT).show();

MyMusicUtil.playNextMusic(context);

return;

}

mediaPlayer.setDataSource(musicPath);   //设置MediaPlayer数据源

mediaPlayer.prepare();

mediaPlayer.start();

new UpdateUIThread(this, context, threadNumber).start();

} catch (Exception e) {

e.printStackTrace();

}

}

//取一个(0,100)之间的不一样的随机数

private void NumberRandom() {

int count;

do {

count =(int)(Math.random()*100);

} while (count == threadNumber);

threadNumber = count;

}

private void onComplete() {

MyMusicUtil.playNextMusic(context);

}

private void UpdateUI() {

Intent playBarintent = new Intent(PlayBarFragment.ACTION_UPDATE_UI_PlayBar);    //接收广播为MusicUpdateMain

playBarintent.putExtra(Constant.STATUS, status);

context.sendBroadcast(playBarintent);

Intent intent = new Intent(ACTION_UPDATE_UI_ADAPTER);    //接收广播为所有歌曲列表的adapter

context.sendBroadcast(intent);

}

private void initMediaPlayer() {

NumberRandom(); // 改变线程号,使旧的播放线程停止

int musicId = MyMusicUtil.getIntShared(Constant.KEY_ID);

int current = MyMusicUtil.getIntShared(Constant.KEY_CURRENT);

Log.d(TAG, "initMediaPlayer musicId = " + musicId);

// 如果是没取到当前正在播放的音乐ID,则从数据库中获取第一首音乐的播放信息初始化

if (musicId == -1) {

return;

}

String path = dbManager.getMusicPath(musicId);

if (path == null) {

Log.e(TAG, "initMediaPlayer: path == null");

return;

}

if (current == 0) {

status = Constant.STATUS_STOP; // 设置播放状态为停止

}else {

status = Constant.STATUS_PAUSE; // 设置播放状态为暂停

}

Log.d(TAG, "initMediaPlayer status = " + status);

MyMusicUtil.setShared(Constant.KEY_ID,musicId);

MyMusicUtil.setShared(Constant.KEY_PATH,path);

UpdateUI();

}

public MediaPlayer getMediaPlayer() {

return mediaPlayer;

}

public int getThreadNumber() {

return threadNumber;

}

}

3.项目在播放一个音频的同时维护了一个线程实时去通知界面刷新,该线程从MediaPlayer中获取当前的播放进度、总时间等信息发送给播放界面,播放界面拿到数据就可以刷新播放显示信息了。public class UpdateUIThread extends Thread {

private static final String TAG = UpdateUIThread.class.getName();

private int threadNumber;

private Context context;

private PlayerManagerReceiver playerManagerReceiver;

private int duration;

private int curPosition;

public UpdateUIThread(PlayerManagerReceiver playerManagerReceiver, Context context, int threadNumber) {

Log.i(TAG, "UpdateUIThread: " );

this.playerManagerReceiver = playerManagerReceiver;

this.context = context;

this.threadNumber = threadNumber;

}

@Override

public void run() {

try {

while (playerManagerReceiver.getThreadNumber() == this.threadNumber) {

if (playerManagerReceiver.status == Constant.STATUS_STOP) {

Log.e(TAG, "run: Constant.STATUS_STOP");

break;

}

if (playerManagerReceiver.status == Constant.STATUS_PLAY ||

playerManagerReceiver.status == Constant.STATUS_PAUSE) {

if (!playerManagerReceiver.getMediaPlayer().isPlaying()) {

Log.i(TAG, "run: getMediaPlayer().isPlaying() = " + playerManagerReceiver.getMediaPlayer().isPlaying());

break;

}

duration = playerManagerReceiver.getMediaPlayer().getDuration();

curPosition = playerManagerReceiver.getMediaPlayer().getCurrentPosition();

Intent intent = new Intent(PlayBarFragment.ACTION_UPDATE_UI_PlayBar);

intent.putExtra(Constant.STATUS, Constant.STATUS_RUN);

intent.putExtra(Constant.KEY_DURATION, duration);

intent.putExtra(Constant.KEY_CURRENT, curPosition);

context.sendBroadcast(intent);

}

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}catch (Exception e){

e.printStackTrace();

}

}

}

三、项目文件结构

f7a9950273507132f145ce7ffd325bcf.png

四、其他

如果对你有帮助的话,可以给我github个star,谢谢。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值