音乐盒设计
1.1 环境配置
- Android Studio 4.1.2
- Gradle 6.5
- JDK 12
- Android 7.0
1.2 需求描述
1、掌握BroadCast广播机制的使用
2、使用广播进行歌曲的播放暂停、上一首、下一首功能。
1.3 演示效果
二、操作步骤
2.1 设计界面
然后准备歌曲,放置在assets文件夹下,供AssetFileDescriptor
进行读取。
2.2 编写Service和Activity
Service的onCreate()中需要创建一个BroadcastReceiver
和创建IntentFilter
,在代码里进行动态绑定。另外也可以选择在AndroidManifest.xml
中进行静态绑定,但是静态绑定优先级会低于动态绑定。然后开启线程以发送广播的方式传递消息。
我们还需要添加一个监听器mPlayer.setOnCompletionListener()
监听音乐是否已经播放完成,如果完成则自动切换到下一首。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| @Override public void onCreate() { super.onCreate(); am = getAssets();
serviceReceiver = new MyReceiver();
IntentFilter filter = new IntentFilter(); filter.addAction(MainActivity.CTL_ACTION); registerReceiver(serviceReceiver, filter);
mPlayer = new MediaPlayer();
mPlayer.setOnCompletionListener(mp -> { Log.d("musicService", "播放完成"); current++; if (current >= 3) { current = 0; }
prepareAndPlay(musics[current]); Intent sendIntent = new Intent(MainActivity.UPDATE_ACTION); sendIntent.putExtra("current", current); sendIntent.putExtra("currentTime", mPlayer.getCurrentPosition()); sendIntent.putExtra("totalTime", mPlayer.getDuration()); sendBroadcast(sendIntent);
}); Intent sendIntent = new Intent(MainActivity.UPDATE_ACTION); sendIntent.putExtra("current", current); sendBroadcast(sendIntent);
processThread = new Thread(() -> { while (true) { if (status == 0x12) { try { Thread.sleep(1000); Intent sendIntent1 = new Intent(MainActivity.UPDATE_ACTION); sendIntent1.putExtra("current", current); sendIntent1.putExtra("currentTime", mPlayer.getCurrentPosition()); sendIntent1.putExtra("totalTime", mPlayer.getDuration()); sendBroadcast(sendIntent1); } catch (InterruptedException e) { e.printStackTrace(); } } } }); processThread.start(); }
|
Service中还需要添加一个Receiver
进行广播消息的接收处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(final Context context, Intent intent) { int control = intent.getIntExtra("control", -1); Log.d("musicReceiver", "收到广播, control=" + control); switch (control) { case 1: if (status == 0x11) { prepareAndPlay(musics[current]); status = 0x12; } else if (status == 0x12) { mPlayer.pause(); status = 0x13; } else if (status == 0x13) { mPlayer.start(); status = 0x12; } break; case 2: if (status == 0x12 || status == 0x13) { mPlayer.stop(); if (current + 1 >= musics.length) { current = 0; } else { current++; } prepareAndPlay(musics[current]); status = 0x12; break; } case 3: if (status == 0x12 || status == 0x13) { mPlayer.stop(); if (current - 1 < 0) { current = musics.length - 1; } else { current--; } prepareAndPlay(musics[current]); status = 0x12; }
}
Intent sendIntent = new Intent(MainActivity.UPDATE_ACTION); sendIntent.putExtra("update", status); sendIntent.putExtra("current", current); sendBroadcast(sendIntent); } }
|
在MainActivity
中,我们也需要创建一个BroadcastReceiver
来接收Service传递的广播并进行处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public class ActivityReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { int update = intent.getIntExtra("update", -1); int current = intent.getIntExtra("current", -1); int totalPosition = intent.getIntExtra("totalTime", -1); int currentPosition = intent.getIntExtra("currentTime", -1); Log.d("activityReceiver", "收到广播"); Log.d("activityReceiver", "current:" + current + " totalPosition:" + totalPosition + " currentPosition:" + currentPosition + " update:" + update); if (current >= 0) { title.setText(titleStrs[current]); author.setText(authorStrs[current]); }
if (totalPosition >= 0) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("mm:ss", Locale.CHINA); Date date = new Date(totalPosition); String formatTime = simpleDateFormat.format(date); totalTime.setText(formatTime); }
if (currentPosition >= 0) { double process = ((double)currentPosition / totalPosition)*100; Log.d("activityReceiver", "当前进度:" + (double)currentPosition/totalPosition); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("mm:ss", Locale.CHINA); Date date = new Date(currentPosition); String formatTime = simpleDateFormat.format(date); progressBar.setProgress((int) process); currentTime.setText(formatTime); }
switch (update) { case 0x11: play.setImageResource(R.drawable.play); status = 0x11; break; case 0x12: play.setImageResource(R.drawable.pause); status = 0x12; break; case 0x13: play.setImageResource(R.drawable.play); status = 0x13; break; } } }
|
最后是Activity
中监听点击事件,每次点击事件都会发送广播。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Override public void onClick(View source) { Intent intent = new Intent("org.xr.action.CTL_ACTION"); switch (source.getId()) { case R.id.play: intent.putExtra("control", 1); break; case R.id.lastMusic: intent.putExtra("control", 3); case R.id.nextMusic: intent.putExtra("control", 2); } sendBroadcast(intent); }
|
核心功能到此就基本介绍完毕。
项目代码地址:https://gitee.com/retain990/musicbox