移动技术开发:音乐播放器

1 实验名称

音乐播放器

2 实验目的

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

3 实验源代码

布局文件代码:

java 复制代码
<?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

java 复制代码
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

java 复制代码
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表示暂停状态;再分别定义存放歌曲名和歌手名的数组,将歌曲文件信息存放到数组中。

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

相关推荐
疯一样的码农14 分钟前
Spring Boot Starter Parent介绍
java·spring boot·后端
iQM7516 分钟前
Spring Boot集成RBloomFilter快速入门Demo
java·spring boot·spring
爱上语文19 分钟前
Springboot 阿里云对象存储OSS 工具类
java·开发语言·spring boot·后端·阿里云
某风吾起20 分钟前
阿里云物联网自有app创建之初始化SDK
android
代码代码快快显灵3 小时前
java之异常处理
java·开发语言
阳光男孩013 小时前
MySQL基础之约束
android·数据库·mysql
茶馆大橘3 小时前
Spring Validation —— 参数校验框架
java·后端·学习·spring
我的运维人生4 小时前
Android架构组件MVVM模式的实战应用与数据绑定技巧
android·架构·运维开发·技术共享
阿望要努力上研究生5 小时前
若依项目搭建(黑马经验)
java·redis·node.js·maven·管理系统
一只脑洞君5 小时前
Kubernetes(K8s)的简介
java·容器·kubernetes