Android初学四之使用Service服务和BroadcastReceiver广播组件实现音乐播放器的设计


0 实验环境

在Android Studio中进行有关代码的编写和界面效果展示


1 界面展示

在这里插入图片描述


2 功能说明

(1)使用Service服务来注册音乐服务;
(2)利用BroadcastReceiver广播组件来启动音乐播放。


3 设计原理

在这里插入图片描述

  1. Service是Android的四大组件之一,用来编写没有工作界面的服务程序;
  2. Service必须在清单文件里service标签注册(配置);
  3. Service根据使用方式,可分为显式启动和隐式启动;
  4. 服务类的设计,与其启动方式有关。启动方式分为startService(非绑定方式)和bindService(绑定方式)两种; 绑定服务:
    被绑定的service是当其他组件(一个客户)调用bindService()来创建的。客户可以通过一个IBinder接口和service进行通信。客户可以通过unbindService()方法来关闭这种连接。一个service可以同时和多个客户绑定,当多个客户都解除绑定之后,系统会销毁service。Service的onCreate方法只会执行一次,当建立连接后,Service会一直运行,除非调用unbindService来接触绑定、断开连接或调用该Service的Context不存在了(如Activity被Finish——即通过bindService启动的Service的生命周期依附于启动它的Context),系统在这时会自动停止该Service。
  5. 当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

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>