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

ops/2024/10/19 16:57:54/

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"><ImageButtonandroid:id="@+id/stopImageBtn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/stop"/><ImageButtonandroid:id="@+id/playImageBtn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/play"/><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"><TextViewandroid: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"/><TextViewandroid: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[]{"周深","刘宇宁","张远"};@Overrideprotected 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() {@Overridepublic 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() {@Overridepublic 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(){//启动MusicServiceIntent 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{@Overridepublic 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() {}@Overridepublic 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() {@Overridepublic 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();//创建资源管理器对象}@Overridepublic IBinder onBind(Intent intent) {// TODO: Return the communication channel to the service.throw new UnsupportedOperationException("Not yet implemented");}//定义用于接受MainActivity发送的广播的广播接收器类private class ActivityReceiver extends BroadcastReceiver{@Overridepublic 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表示暂停状态;再分别定义存放歌曲名和歌手名的数组,将歌曲文件信息存放到数组中。

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


http://www.ppmy.cn/ops/122536.html

相关文章

爬虫案例——爬取情话网数据

需求&#xff1a; 1.爬取情话网站中表白里面的所有句子&#xff08;表白词_表白的话_表白句子情话大全_情话网&#xff09; 2.利用XPath来进行解析 3.使用面向对象形发请求——创建一个类 4.将爬取下来的数据保存在数据库中 写出对应解析语法 //div[class"box labelbo…

滚雪球学MySQL[4.3讲]:MySQL表设计与优化:正规化、表分区与性能调优详解

全文目录&#xff1a; 前言4.3 表设计与优化1. 正规化与反规范化1.1 正规化正规化的步骤&#xff1a;正规化的优点&#xff1a; 1.2 反规范化示例&#xff1a;反规范化提升性能反规范化的优点&#xff1a;反规范化的缺点&#xff1a; 2. 表的分区与分区策略2.1 分区的类型1. **…

<<机器学习实战>>12-14节笔记:机器学习模型可信度、逻辑回归模型及多分类问题处理

12机器学习模型可信度 是否检验模型的指标好就一定说明模型可用&#xff1f;不是&#xff0c;必须得保证训练的样本和整天基本满足同一分布。 统计学习和机器学习区别&#xff1a;统计学习是根据样本模拟总体规律进而去预测&#xff08;当然要比对样本和总体的统计量是否一致&…

C++读取大文件三种方法速度比较

目录 测试说明第一种方法&#xff1a;按块读&#xff0c;一次读8kb第二种方法&#xff1a;按行读&#xff0c;一次读一行第三种方法&#xff1a;多线程并行读取完整示例 测试说明 测试文件&#xff1a;100万行&#xff0c;每一行是两个小数&#xff0c;中间用逗号隔开&#xf…

高级java每日一道面试题-2024年10月2日-分布式篇-什么是FLP 不可能性定理?

如果有遗漏,评论区告诉我进行补充 面试官: 什么是FLP 不可能性定理&#xff1f; 我回答: 在Java高级面试中&#xff0c;FLP不可能性定理是一个可能涉及的重要分布式系统理论。以下是对FLP不可能性定理的详细解析&#xff1a; FLP 定理背景 在分布式计算领域&#xff0c;共…

Pycharm常用快捷键

代码编辑 注释/取消注释&#xff1a;ctrl / 折叠代码&#xff1a;ctrl - 展开代码&#xff1a;ctrl 导航 转到函数实现&#xff1a;ctrl b 或 ctrl 鼠标左键 向前导航&#xff1a;ctrl alt 左箭头 向后导航&#xff1a;ctrl alt 右箭头 查找与替换 在当前文件…

MySQL总结

先是数据库的基本介绍和库的操作&#xff1a;MySQL 库 基础操作-CSDN博客 再是MySQL表的操作&#xff1a;CRUD工程师必会&#xff1a;MySQL 表 的操作&#xff08;全&#xff09;-CSDN博客 MySQL事务&#xff1a;MySQL事务-CSDN博客 MySQL索引&#xff1a;MySQL索引-CSDN博客…

【QT Quick】C++交互:暴露 C++ 对象到 QML

【QT Quick】C交互&#xff1a;暴露 C 对象到 QML 在 Qt Quick 开发中&#xff0c;使用 Context Property 将 C 对象暴露给 QML 是一种直观有效的方式。这种方法允许我们直接在 QML 中访问 C 对象的属性和方法&#xff0c;而无需使用信号和槽。这篇文章将详细展开如何通过 Con…