安卓第一阶段实训项目:基于存储卡音乐播放器V0.2----实训报告(二)

安卓第一阶段实训项目:基于存储卡音乐播放器V0.2----实训报告(二)

(一)功能要求

添加一个进度条,动态显示音乐的播放进度。----已完成
添加一个标签显示音乐播放的当前位置(格式——mm:ss)。----已完成
添加一个标签显示音乐的播放时长(格式——mm:ss)。----已完成

(二)运行效果

在这里插入图片描述

(三)涉及知识点

线性布局(LinearLayout)
标签(TextView)
按钮(Button)
媒体播放器(MediaPlayer)
读取存储卡指定目录里的文件
控件背景选择器
进度条(ProgressBar)
线程(Thread)
消息处理器(Handler)

(四)实现步骤

  1. 创建安卓应用【SDCardMusicPlayerV0.2】
  2. 创建按钮背景图片选择器
  3. 播放按钮背景图片选择器 - play_button_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/play_button_pressed" android:state_pressed="true" />
    <item android:drawable="@drawable/play_button" android:state_pressed="false" />
</selector>

暂停按钮背景图片选择器 - pause_button_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/pause_button_pressed" android:state_pressed="true" />
    <item android:drawable="@drawable/pause_button" android:state_pressed="false" />
</selector>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background"
    android:orientation="vertical"
    android:padding="20dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tvMusicName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#0000ff"
        android:textSize="20sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/tvCurrentPosition"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textColor="#ff0000" />

        <ProgressBar
            android:id="@+id/pbMusicProgress"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="6" />

        <TextView
            android:id="@+id/tvDuration"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textColor="#ff00ff" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnPlayOrPause"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/play_button_selector"
            android:onClick="doPlayOrPause" />
    </LinearLayout>
</LinearLayout>

  1. 创建ui子包,将MainActivity拖进ui子包
    在这里插入图片描述

  2. 创建util子包,在里面创建常用工具类CommonUtils

package net.yq.sdcardmusicplayerv02.util;

import java.text.SimpleDateFormat;

public class CommonUtils {
    private static SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");

    /**
     * 获取格式化时间
     *
     * @param time
     * @return
     */
    public static String getFormatTime(int time){
        return sdf.format(time);
    }
}

  1. 在项目清单文件里授权访问外置存储卡
    在这里插入图片描述
  2. 主界面完整源代码
package net.yq.sdcardmusicplayerv02.ui;

import android.Manifest;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import net.yq.sdcardmusicplayerv02.R;
import net.yq.sdcardmusicplayerv02.util.CommonUtils;

import java.io.File;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
    private MediaPlayer mp; // 媒体播放器
    private File musicDir; // 音乐存放目录
    private String musicName; // 音乐文件名
    private TextView tvMusicName; // 音乐名标签
    private Button btnPlayOrPause; // 播放|暂停按钮
    private int currentPosition; // 音乐当前播放位置
    private TextView tvCurrentPosition;//显示当前播放位置的标签
    private TextView tvDuration;//显示音乐播放时长的标签
    private ProgressBar pbMusicProgress;//音乐播放进度条
    private Thread thread;//线程
    private Handler handler;//异步消息处理器
    private boolean isRunning;//线程循环控制变量


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 通过资源标识符获取控件实例
        tvMusicName = findViewById(R.id.tvMusicName);
        btnPlayOrPause = findViewById(R.id.btnPlayOrPause);
        tvCurrentPosition = findViewById(R.id.tvCurrentPosition);
        tvDuration = findViewById(R.id.tvDuration);
        pbMusicProgress = findViewById(R.id.pbMusicProgress);
        // 定义存储读写权限数组
        String[] PERMISSIONS_STORAGE = {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
        // 检查是否有读权限
        int permission = ActivityCompat.checkSelfPermission(this, PERMISSIONS_STORAGE[0]);
        // 如果没有授权,那么就请求读权限
        if (permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, 0);
        }

        // 获取音乐文件存放目录
        musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);

        try {
            // 获取音乐文件存放目录里的第一首音乐文件名
            musicName = musicDir.list()[0];
            // 设置音乐名标签,要去掉扩展名
            tvMusicName.setText("音乐名:" + musicName.substring(0, musicName.lastIndexOf(".")));
        } catch (Exception e) {
            Toast.makeText(this, "存储卡Music目录里没有音乐文件!", Toast.LENGTH_SHORT).show();
        }
        //初始化播放器
        mp = new MediaPlayer();
        try {
            // 设置播放源(完整音乐名 = 音乐目录 + 音乐名)
            mp.setDataSource(musicDir.getAbsolutePath() + "/" + musicName);
            Toast.makeText(MainActivity.this,musicDir.getAbsolutePath() + "/" + musicName,Toast.LENGTH_SHORT).show();
            // 缓冲播放源(从存储卡加载到内存)
            mp.prepare();
            //设置当前播放位置标签
            tvCurrentPosition.setText(CommonUtils.getFormatTime(mp.getCurrentPosition()));
            //设置音乐播放时常标签
            tvDuration.setText(CommonUtils.getFormatTime(mp.getDuration()));
            //数字化音乐播放进度条最大值
            pbMusicProgress.setMax(mp.getDuration());
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 给媒体播放器注册完成监听器
        mp.setOnCompletionListener(mp -> {
            // 提示用户当前音乐播放完毕
            Toast.makeText(MainActivity.this, "当前音乐播放完毕!", Toast.LENGTH_SHORT).show();
            // 当前播放位置清零
            currentPosition = 0;
            // 按钮图标由【暂停】图标切换到【播放】图标
            btnPlayOrPause.setBackgroundResource(R.drawable.play_button_selector);
        });
        isRunning = true;
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (isRunning) {
                    handler.sendEmptyMessage(0x001);
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        //启动子线程
        thread.start();
        //创建消息处理器,接受子线程发送的消息
        handler = new Handler() {
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
                if (msg.what == 0x001) {
                    if (mp.isPlaying()) {
                        currentPosition = mp.getCurrentPosition();
                        pbMusicProgress.setProgress(currentPosition);
                        tvCurrentPosition.setText(CommonUtils.getFormatTime(currentPosition));
                    }
                }
            }
        };
    }
    /**
     * 播放方法
     */
    private void play() throws IOException {
        // 重置媒体播放器
        mp.reset();
        // 设置播放源(完整音乐名 = 音乐目录 + 音乐名)
        mp.setDataSource(musicDir.getAbsolutePath() + "/" + musicName);
        // 缓冲播放源(从存储卡加载到内存)
        mp.prepare();
        // 定位到暂停时的播放位置
        mp.seekTo(currentPosition);
        // 启动音乐的播放
        mp.start();
        // 按钮图标由【播放】图标切换到【暂停】图标
        btnPlayOrPause.setBackgroundResource(R.drawable.pause_button_selector);
    }

    /**
     * 暂停方法
     */
    private void pause() {
        // 暂停播放
        mp.pause();
        // 保存音乐播放的当前位置
        currentPosition = mp.getCurrentPosition();
        // 按钮图标由【暂停】图标切换到【播放】图标
        btnPlayOrPause.setBackgroundResource(R.drawable.play_button_selector);
    }

    /**
     * 播放|暂停按钮单击事件处理方法
     *
     * @param view
     */
    public void doPlayOrPause(View view) throws IOException {
        // 判断音乐是否在播放
        if (mp.isPlaying()) {
            // 暂停音乐
            pause();
        } else {
            // 播放音乐
            play();
        }
    }

    /**
     * 销毁回调方法,释放资源
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        isRunning = false;
        thread = null;
        // 判断音乐是否在播放
        if (mp.isPlaying()) {
            mp.stop();
        }
        // 释放媒体播放器
        mp.release();
        // 销毁媒体播放器
        mp = null;
    }

}
课 程 名: 软件工程综合实践 实践项目: 基于Android的手机音乐播放器 一、课程设计题目 基于Android的手机音乐播放器 、课程设计内容(含技术指标) 本程序是基于Android开源系统技术,利用Java语言和Eclipse编辑工具对播放器进行编 写。程序功能如下: 用户可以按照以下规则进行操作: 1.音乐播放:界面对歌曲操作有播放、暂停、停止、音量控制、上一首/下一首 播放模式:随机播放、顺序播放、单曲循环。 2. 音乐管理:音乐列表、专辑:显示全部音乐文件,能直接选择播 放歌曲。 艺术家:归类艺术家的音乐文件。 最近播放:记录用户最近播放的音乐文件,方便用户再次使用。 3.显示歌词:能显示播放歌曲的歌词。 4.添加音乐:在文件夹中添加音乐进播放列表。 5.删除音乐:删除播放列表的歌曲。 三、进度安排 1.第四周分组分工,5人。并选择题目 2.第五~九周独立完成各自内容及相关文档。 3.第十周周整合,联调。 4.第十一周答辩。 四、基本要求 1.各组指定组长一名,组长负责分工,分工要求要明确,不得重叠。组长有加分。 各个成员独立完成各自的部分,不得抄袭。 2.答辩要求每个人讲清楚自己做的部分。 课程负责人签名: 年 月 日 目录 第一章 引言 6 1.1 目的及范围 6 第章 需求说明 7 2.1 系统参与者 7 2.2 系统用例 7 2.3领域模型分析 8 第三章 架构设计说明 11 3.1 逻辑视图 11 3.2 进程视图 11 3.3 开发视图 12 3.4 物理视图 13 3.5 用例视图 14 第四章 用例设计 15 4.1 播放音乐用例设计 15 4.2暂停音乐用例设计 16 4.3 切换音乐用例设计 16 4.4 显示音乐列表用例设计 17 4.5 删除音乐用例设计 18 4.6 显示艺术家用例设计 19 4.7 显示专辑用例设计 20 4.8 显示最近播放用例设计 21 4.9 启动随机播放用例设计 22 4.10 启动单曲循环播放用例设计 23 4.11 播放进度调节用例设计 24 第五章 设计类说明 26 5.1 设计类字典 26 第六章 测试 28 6.1 测试需求 28 6.2 测试用例 28 6.3 缺陷 35 参考文献 37 心得体会 38 第一章 引言 1.1 目的及范围 随着科技的进步,手机的功能也不断的得到丰富,从最早的"大哥大"到现在的商务手机 ,只能手机,音乐手机等等,功能也从单纯的打电话发展到了发短信,听歌,上网……手 机和我们生活的联系越来越紧密,手机的功能也是很多人们关注的焦点。 目前手机的音乐播放器已经是大家比较关注的一个部分,不少人在购买手机的时候都 会关心手机的音乐播放的能力,这也足以看出目前大家对音乐播放功能的重视,所以一 款性能良好的手机音乐播放器软件一定会受到欢迎。和传统的音乐播放器相比,手机播 放音乐更加的容易携带,其他方面也不输于传统的音乐播放器,而且还具有网上听音乐 动能,所以开发一款受欢迎的手机音乐播放器软件是具有良好的市场和应用前景。 一款专业的音乐播放器软件是手机中必不可少的要素,几乎市场上所有的手机都拥有 一个自带的音乐播放器软件,通过软件可以对音乐欣赏中一些必要的元素进行人性化的 设置,同时在操作的时候也能得到一定的便利,但是不能满足用户的所有要求,所以网 上就出现了各种各样的手机音乐播放器软件,来满足不用用户的不同要求。不同手机平 台的手机,所支持的音乐播放软件也是各不相同,而现在最流行的手机平台就是google 的android手机平台,所以本课题就致力于开发出一款基于android手机平台的音乐播放 器,来满足用户的使用需求。 1.2 术语 Android:一种以Linux为基础的开放源码操作系统,主要使用于便携设备。 SDK:Software Development Kit,即软件开发工具包,是一些被软件工程师用于为特定的软件包、软件框架、硬件平 台、操纵系统等建立应用软件的开发工具的集合。 AVD:Android Virtual Device,即Android运行的虚拟设备。 DDMS:Dalvik Debug Monitor Service,是Android开发环境中的Dalvik虚拟机调试监控服务。 Activity:Android组件中最基本的组件,在一个Android应用中,一个Activity通常就 是一个单独的屏幕。 Intent是Android中的重要组件,可以被认为是不同组件之间通信的"媒介"或者"信使" 。使用它可以启动Activity,Service还可以发起一个广播(Broadcast)。Intent对象 由Action、Data、Category、Component和Extra组成。 Service:一种
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值