0 实验环境
在Android Studio中进行有关代码的编写和界面效果展示
1 界面展示
2 功能说明
(1)使用Service服务来注册音乐服务;
(2)利用BroadcastReceiver广播组件来启动音乐播放。
3 设计原理
- Service是Android的四大组件之一,用来编写没有工作界面的服务程序;
- Service必须在清单文件里service标签注册(配置);
- Service根据使用方式,可分为显式启动和隐式启动;
- 服务类的设计,与其启动方式有关。启动方式分为startService(非绑定方式)和bindService(绑定方式)两种; 绑定服务:
被绑定的service是当其他组件(一个客户)调用bindService()来创建的。客户可以通过一个IBinder接口和service进行通信。客户可以通过unbindService()方法来关闭这种连接。一个service可以同时和多个客户绑定,当多个客户都解除绑定之后,系统会销毁service。Service的onCreate方法只会执行一次,当建立连接后,Service会一直运行,除非调用unbindService来接触绑定、断开连接或调用该Service的Context不存在了(如Activity被Finish——即通过bindService启动的Service的生命周期依附于启动它的Context),系统在这时会自动停止该Service。 - 当Service与Activity处于同一进程时,Activity对Service的调用属于本地服务调用;
4 核心代码
4.1 普通方式启动服务进行音乐播放与停止
Service是编写服务的抽象基类。
onCreate()和onDestroy()是Service的2个重要生命周期方法,通常需要我们在其内写代码。
以非绑定方式启动服务时,不需要我们在生命周期方法onBind()内写代码,反之不然。
(1)添加音乐文件:
右键res→New→Directory,输入文件夹名raw→复制某个音乐文件名至该文件夹,并重命名。
(2)设计UI界面,需设计两点击按钮,用于启动和停止音乐服务:
<Button
android:id="@+id/btn_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="调用播放音乐的服务程序"
android:textSize="20sp"/>
<Button
android:id="@+id/btn_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="停止播放音乐的服务程序"
android:textSize="20sp"/>
(3)添加音乐Music服务:
右键模块里程序的包名→New→Service→Service,输入Service组件名MyMusicService,此方法将自动清单文件中生成服务组件的配置代码
<service
android:name=".MyMusicService"
android:enabled="true"
android:exported="true">
</service>
然后在MyMusicService.java中重写了onCreate、onDestroy、onBind方法
@Override
public void onCreate() {
//在开始服务时调用
super.onCreate();
mp = MediaPlayer.create(getApplicationContext(), R.raw.mojito);
//打印日志信息
Log.d(TAG, "play...");
mp.start();
}
@Override
public void onDestroy() {
//在停止服务时调用
super.onDestroy();
//打印日志信息
Log.d(TAG, "stop...");
mp.stop();
if(mp!=null)
mp=null;
}
@Override
public IBinder onBind(Intent intent) {
//不可省略的生命周期方法
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
(4)最后编写MainActivity.java程序:
在其中重写onCreate、onClick、onDestroy方法,用于视图的创建及监听点击事件和音乐服务的开启与停止的功能
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//播放按钮
btn_play = findViewById(R.id.btn_play);btn_play.setOnClickListener(this);
//停止按钮
btn_stop=findViewById(R.id.btn_stop);btn_stop.setOnClickListener(this);
}
@Override
public void onClick(View v) {
//显式调用服务意图
intent=new Intent(this, MyMusicService.class);
//获取视图id
int id=v.getId();
switch (id){
case R.id.btn_play:
startService(intent);
Toast.makeText(this, "音乐播放服务进行中...", Toast.LENGTH_SHORT).show();
btn_stop.setEnabled(true);btn_play.setEnabled(false);
break;
case R.id.btn_stop:
stopService(intent);
btn_stop.setEnabled(false);btn_play.setEnabled(true);
}
}
@Override
protected void onDestroy() {
//考虑播放时按返回键
super.onDestroy();
if(intent!=null)
//停止服务
stopService(intent);
//打印日志信息
Log.d(TAG, "MainActivity调用stopService()停止服务...");
//关闭活动
finish();
//打印日志信息
Log.d(TAG, "MainActivity调用finish()关闭服务...");
}
(5)运行程序,查看效果
4.2 广播组件,启动音乐播放与停止
(1)将音乐文件mp3存放在assets目录下,存放三个mp3文件:
调用其中的音乐文件需要使用到AssetManager对象,调用getAssets()方法获取文件
(2)设计UI界面,添加五个音乐按钮和有关音乐信息
(3)添加音乐Music服务:
和上述非绑定式服务程序一样,右键模块里程序的New→Service→Service,输入Service组件名MyMusicService,此方法将自动清单文件中生成服务组件的配置代码
<service
android:name=".MusicService"
android:enabled="true"
android:exported="true">
</service>
然后在MyMusicService.java中重写了onCreate、onBind方法,并且编写MyReceiver类继承广播BroadcastReceiver类,最后定义prepareAndPlay()方法打开音乐文件并准备播放
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//打印日志信息
Log.d(TAG, "MusicService调用onReceive()...");
int control = intent.getIntExtra("control", -1);
switch (control) {
//判断播放状态,选择有关操作
//.......
}
//广播通知Activity更改图标、文本框
Intent sendIntent = new Intent(MainActivity.UPDATE_ACTION);
sendIntent.putExtra("update", status);
sendIntent.putExtra("current", current);
//发送广播,将被Activity组件中的BroadcastReceiver接收
sendBroadcast(sendIntent);
}
}
private void prepareAndPlay(String music) {
//打印日志信息
Log.d(TAG, "MusicService调用prepareAndPlay()...");
try {
//打开指定音乐文件
AssetFileDescriptor afd = am.openFd(music);
mPlayer.reset();
//使用MediaPlayer加载指定的音乐文件
mPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
//准备声音
mPlayer.prepare();
//播放
mPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
(4)最后编写MainActivity.java程序:
在其中重写onCreate、onClick、onDestroy方法,用于视图的创建及监听点击事件和音乐服务的开启与停止的功能,并且自定义的BroadcastReceiver,负责监听从Service传回来的广播
public class ActivityReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 获取Intent中的update消息,update代表播放状态
int update = intent.getIntExtra("update", -1);
// 获取Intent中的current消息,current代表当前正在播放的歌曲
int current = intent.getIntExtra("current", -1);
if (current >= 0) {
song_pic.setImageResource(song_pics[current]);
song.setText(songs[current]);
singer.setText(singers[current]);
}
//根据点击情况切换状态
switch (update) {
// 控制系统进入停止状态
case 1:
play.setImageResource(R.drawable.play);
status = 1;
break;
// 控制系统进入播放状态
case 2:
// 播放状态下设置使用暂停图标
play.setImageResource(R.drawable.pause);
// 设置当前状态
status = 2;
break;
// 控制系统进入暂停状态
case 3:
// 暂停状态下设置使用播放图标
play.setImageResource(R.drawable.play);
// 设置当前状态
status = 3;
break;
}
//打印日志信息
Log.d(TAG, "MainActivity调用onReceive()...");
}
}
//销毁广播
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(activityReceiver);
//打印日志信息
Log.d(TAG, "MainActivity调用onDestroy()...");
}
(5)运行程序,查看效果:
5 代码仓库
具体代码已上传至代码仓库gitee:
第一个案例
第二个案例
6 总结
学习了Android的四大组件中的两个:
(1)使用Service服务来注册音乐服务;
(2)利用BroadcastReceiver广播组件来启动音乐播放。
后续会继续更新有关Android设计的内容!
(注:第20次发文,如有错误和疑问,欢迎在评论区指出!)
——2021.11.15