实验一 音乐播放器
一、实验目的
1、掌握Activity工作机制。
2、掌握ListView、MediaPlayer等用法。
二、实验内容
设计一个音乐播放器,用ListView显示手机中MP3格式音乐,支持播放、暂停、继续、上一首、下一首等功能。
三、工作流程图
四、程序源代码
1、布局页面
在res的layout的activity_music.xml中
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.lenovo.myapplication.MusicActivity">
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_below="@+id/btn_test"
android:layout_marginTop="20dp">
</ListView>
<SeekBar
android:id="@+id/seekBar"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@android:color/background_light"
android:backgroundTint="@android:color/background_light"
android:progressBackgroundTint="@color/bg" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<ImageButton
android:id="@+id/previous"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:background="@android:color/background_light"
android:src="@drawable/rewind" />
<ImageButton
android:id="@+id/btn_pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_marginLeft="100dp"
android:layout_marginRight="100dp" android:layout_weight="1" android:background="@android:color/background_light" android:src="@drawable/pause11" /> <ImageButton android:id="@+id/next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:layout_weight="1" android:background="@android:color/background_light" android:src="@drawable/forward" /> </LinearLayout> </LinearLayout>
2、MusicActivity代码
A、添加SD卡访问权限
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE">
</uses-permission>
权限请求和兼容性
if (ActivityCompat.checkSelfPermission(MusicActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MusicActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 123);
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
}
B、获取mp3音乐文件路径代码
final ArrayList<String> list = new ArrayList<String>(); //音乐列表File sdpath = Environment.getExternalStorageDirectory(); //获得手机SD卡路径
File path = new File(sdpath + "//mp3//" ); //获得SD卡的mp3文件夹
//返回以.mp3结尾的文件 (自定义文件过滤)
File[] songFiles = path.listFiles(new MyFilter(".mp3"));
for (File file : songFiles) {
list.add(file.getAbsolutePath());//获取文件的绝对路径
}
其中MyFilter:自定义的文件过滤器类
MyFilter代码:
package com.example.lenovo.myapplication;
import java.io.File;
import java.io.FilenameFilter;
/**
* Created by lenovo on 2018/4/12.
*/
public class MyFilter implements FilenameFilter {
private String type;
public MyFilter(String type) {
//构造函数
this.type = type;
}
@Override //实现FilenameFilter接口accept()方法
public boolean accept(File dir, String name) {
//dir当前目录, name文件名
return name.endsWith(type);
//返回true的文件则合格
}
}
C、ListView适配器数据填充
ArrayAdapter<String> adapter =new ArrayAdapter<String>(
MusicActivity.this,
android.R.layout.simple_list_item_single_choice,
list );
ListViewli=(ListView)findViewById(R.id.listView);
li.setAdapter(adapter);
li.setChoiceMode(ListView.CHOICE_MODE_SINGLE); //单选
D、音乐播放
定义类成员
MediaPlayer mp=new MediaPlayer();
String song_path = "";
int id;
private int currentposition;//当前音乐播放的位置
private boolean isChanging=false;//歌曲改变
private SeekBar seekBar;//进度条
private Timer timer;
private TimerTask timerTask;//定时器
ListView li;//ListView选取元素
//音乐播放
li.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
currentposition=position;
TextView music_url=(TextView)view.findViewById(R.id.music_url);
try{
mp.reset(); //重置
mp.setDataSource( music_url.getText().toString());
mp.prepare(); //准备
mp.start(); //播放
}catch (Exception e){ }
}
});
E、音乐停止播放
//音乐停止播放
@Override
protected void onDestroy() {
super.onDestroy();
if(mp!=null ){
mp.stop();
mp.release();
}
Toast.makeText(getApplicationContext(), "退出啦", Toast.LENGTH_SHORT).show();
}
F、音乐的暂停和播放以及进度条的实现
//音乐暂停和继续
seekBar=(SeekBar)findViewById(R.id.seekBar);
seekBar.setOnSeekBarChangeListener(new Myseekbar());//拖动的事件监
seekBar=(SeekBar)findViewById(R.id.seekBar);
seekBar.setOnSeekBarChangeListener(new Myseekbar());//拖动的事件监
听
final ImageButton btnpause=(ImageButton)findViewById(R.id.btn_pause);
btnpause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if( song_path.isEmpty() )
Toast.makeText(getApplicationContext(), "先选收歌曲先听听", Toast.LENGTH_SHORT).show();
if( mp.isPlaying() ){
mp.pause();
btnpause.setImageResource(R.drawable.play11);
}else if( !song_path.isEmpty() ){
mp.start();
btnpause.setImageResource(R.drawable.pause11);
seekBar.setMax(mp.getDuration());//设置seekbar最大值为音乐文件持续时间
//Time线程实现和执行一个任务,实现TimeTask的子类,
timer=new Timer();
timerTask=new TimerTask() {
@Override
public void run() {
if(isChanging)
{
return;
}
seekBar.setProgress(mp.getCurrentPosition());//更新进度条
}
};
timer.schedule(timerTask,0,10);
//从0毫秒以后,每隔10毫秒执行一次。
}
} });
class Myseekbar implements SeekBar.OnSeekBarChangeListener{
//当进度条改变后用于通知客户端的回调函数
public void onProgressChanged(SeekBarseekbar,int progress,boolean formUser){}
@Override
public void onStartTrackingTouch(SeekBarseekBar) {
public void onProgressChanged(SeekBarseekbar,int progress,boolean formUser){}
@Override
public void onStartTrackingTouch(SeekBarseekBar) {
isChanging=true; } @Override public void onStopTrackingTouch(SeekBar seekBar) { mp.seekTo(seekBar.getProgress());//seekbar确认位置后调到指定位置 isChanging=false; } }
G、实现上一首、下一首
//实现上一首,下一首
ImageButtonprevious=(ImageButton)findViewById(R.id.previous);
previous.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
if(currentposition
ImageButtonprevious=(ImageButton)findViewById(R.id.previous);
previous.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
if(currentposition