1 实验名称

       音乐播放器

2 实验目的

       掌握使用Service启动服务的方法,掌握BroadcastReceiver广播传递机制的实现,利用Activity、Service和BroadcastReceiver实现一个音乐播放器APP。

3 实验源代码

布局文件代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="@drawable/bg"
    tools:context=".MainActivity">

    <ImageButton
        android:id="@+id/stopImageBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/stop"
        />

    <ImageButton
        android:id="@+id/playImageBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/play"
        />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >

        <TextView
            android:id="@+id/songNameTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ffffff"
            android:textSize="24sp"
            android:text="歌曲名"
            android:layout_weight="2"
            />

        <TextView
            android:id="@+id/singerNameTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ffffff"
            android:textSize="20sp"
            android:text="歌手名"
            android:layout_weight="1"
            />

    </LinearLayout>

</LinearLayout>

java代码:

(1)MainActivity

package com.example.musicplayertest;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

public class MainActivity extends AppCompatActivity {
    private ImageButton stopImageBtn = null;
    private ImageButton playImageBtn = null;
    private TextView songNameTV = null;
    private TextView singerNameTV = null;

    private ServiceReceiver serviceReceiver = null;
    private IntentFilter intentFilter= null;

    private boolean isPlaying = false;//定义一个反映MusicService播放状态的变量

    //定义存放歌曲名的数组
    private String []songNames = new String[]{"若思念便思念","就在江湖之上","山外"};

    //定义存放歌手名的数组
    private String []singerNames = new String[]{"周深","刘宇宁","张远"};


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        stopImageBtn = findViewById(R.id.stopImageBtn);
        playImageBtn = findViewById(R.id.playImageBtn);
        songNameTV = findViewById(R.id.songNameTV);
        singerNameTV = findViewById(R.id.singerNameTV);

        init();

        playImageBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("cn.edu.nuc.mainactivity");
                //控制指令:1表示播放指令,2表示暂停指令,3表示停止指令
                if (isPlaying){//如果isPlaying为真,说明后台正在播放音乐
                    intent.putExtra("control",2);//封装暂停指令
                    playImageBtn.setImageResource(R.drawable.play);//更新为播放按钮图片
                    isPlaying = false;
                }else {//后台播放状态是暂停或停止状态
                    intent.putExtra("control",1);//封装播放指令
                    playImageBtn.setImageResource(R.drawable.pause);
                    isPlaying = true;
                }
                sendBroadcast(intent);//发送带有过滤条件和控制指令的广播
            }
        });

        stopImageBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("cn.edu.nuc.mainactivity");
                intent.putExtra("control",3);//封装停止指令
                playImageBtn.setImageResource(R.drawable.play);//更新为播放按钮图片
                isPlaying = false;
                sendBroadcast(intent);
            }
        });

    }

    private void init(){
        //启动MusicService
        Intent intent = new Intent(MainActivity.this, MusicService.class);
        startService(intent);//启动MusicService
        //创建广播接收器对象
        serviceReceiver = new ServiceReceiver();
        intentFilter = new IntentFilter("cn.edu.nuc.musicservice");
        //动态注册广播接收器
        registerReceiver(serviceReceiver,intentFilter);
    }

    //定义用于接受MusicService发送的广播接收器类
    private class ServiceReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            int status = intent.getIntExtra("status",-1);
            int current = intent.getIntExtra("current",-1);
            //根据后台播放状态更新播放按钮的图片
            switch (status){
                //定义当前音乐播放状态的变量,0x11表示停止状态,0x12表示正在播放状态,0x13表示暂停状态
                case 0x11:
                    playImageBtn.setImageResource(R.drawable.play);
                    break;
                case 0x12:
                    playImageBtn.setImageResource(R.drawable.pause);
                    break;
                case 0x13:
                    playImageBtn.setImageResource(R.drawable.play);
                    break;
                default:break;
            }

            //在播放器界面对应的文本框中更新当前正在播放的歌曲信息
            if (current>=0){
                songNameTV.setText(songNames[current]);
                singerNameTV.setText(singerNames[current]);
            }
        }
    }
}

(2)MusicService

package com.example.musicplayertest;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.media.MediaPlayer;
import android.os.IBinder;

import java.io.IOException;

public class MusicService extends Service {

    //定义一个媒体播放器
    private MediaPlayer mediaPlayer = null;

    //定义一个广播接收器
    private ActivityReceiver activityReceiver = null;
    //定义广播过滤器
    private IntentFilter intentFilter = null;

    //定义资源管理器
    private AssetManager assetManager = null;

    //将歌曲文件信息存放到数组中
    String []musics = new String[]{"life.mp3","road.mp3","star.mp3"};

    //定义一个存放当前正在播放的音乐的索引值变量
    int current = 0;
    //定义当前音乐播放状态的变量,0x11表示停止状态,0x12表示正在播放状态,0x13表示暂停状态
    int status = 0x11;

    public MusicService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        activityReceiver =new ActivityReceiver();//创建广播接收器对象
        intentFilter = new IntentFilter("cn.edu.nuc.mainactivity");
        registerReceiver(activityReceiver,intentFilter);//动态注册广播接收器
        mediaPlayer = new MediaPlayer();
        //给mediaPlayer添加播放完一首歌后的事件监听处理,实现自动播放下一首
        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                current++;
                if (current>=3){
                    current = 0;
                }
                Intent sendIntent = new Intent("cn.edu.nuc.musicservice");
                sendIntent.putExtra("current",current);
                sendBroadcast(sendIntent);
                prepareAndPlay(musics[current]);
            }
        });
        assetManager = getAssets();//创建资源管理器对象
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    //定义用于接受MainActivity发送的广播的广播接收器类
    private class ActivityReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            //从MainActivity发送过来的广播中解析出控制指令
            int control = intent.getIntExtra("control",-1);
            //控制指令:1表示播放指令,2表示暂停指令,3表示停止指令
            //定义当前音乐播放状态的变量,0x11表示停止状态,0x12表示正在播放状态,0x13表示暂停状态
            switch (control){
                case 1:
                    if (status == 0x11){
                        prepareAndPlay(musics[current]);
                        status = 0x12;
                    } else if (status == 0x12) {
                        mediaPlayer.pause();
                        status = 0x13;
                    } else if (status == 0x13) {
                        mediaPlayer.start();
                        status = 0x12;
                    }
                    break;
                case 2:
                    //暂停音乐播放
                    mediaPlayer.pause();
                    status = 0x13;
                    break;
                case 3:
                    //停止音乐播放
                    mediaPlayer.stop();
                    status = 0x11;
                    break;
                default:break;
            }

            //向MainActivity发送含有当前播放状态和歌曲索引值的广播
            Intent sendIntent = new Intent("cn.edu.nuc.musicservice");
            sendIntent.putExtra("status",status);
            sendIntent.putExtra("current",current);
            sendBroadcast(sendIntent);
        }
    }

    //定义初始化音乐播放的方法
    private void prepareAndPlay(String music){
        try {
            //创建音乐文件的一个资源文件描述符
            AssetFileDescriptor assetFileDescriptor = assetManager.openFd(music);
            mediaPlayer.reset();//重置媒体播放器
            mediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(),
                    assetFileDescriptor.getStartOffset(),
                    assetFileDescriptor.getLength());//将要播放的音乐文件设置为媒体播放器的播放资源
            mediaPlayer.prepare();//准备声音
            mediaPlayer.start();//播放音乐
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

4 实验运行结果图

5 实验总结

       第一步,写布局文件。主要是两个图片按钮和两个文本框,图像按钮分别是暂停和播放;文本框分别是歌曲名和歌手名。

       写完布局文件开始写Java代码。设置控制指令,1表示播放指令,2表示暂停指令,3表示停止指令;再定义当前音乐播放状态的变量,0x11表示停止状态,0x12表示正在播放状态,0x13表示暂停状态;再分别定义存放歌曲名和歌手名的数组,将歌曲文件信息存放到数组中。

       分别定义一个媒体播放器、广播接收器、广播过滤器、资源管理器和一个存放当前正在播放的音乐的索引值变量。关于广播接收器,先创建广播接收器对象,动态注册广播接收器,给媒体播放器添加播放完一首歌后的事件监听处理,实现自动播放下一首。关于广播接收器,定义用于接收发送过来的广播的广播接收器类,从发送过来的广播中解析出指令,向其发送含有当前播放状态和歌曲索引值的广播。关于音乐播放,定义一个初始化音乐播放的方法,创建音乐文件的一个资源文件描述符,重置媒体播放器,将要播放的音乐文件设置位媒体播放器的播放资源,准备声音播放音乐。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部