android 小型音乐播放器(实现播放、下一首、上一首、自动播放、随机播放按钮、当前播放歌曲界面)
16lz
2021-01-26
该文章主要针对 android 的音乐播放器软件进行简单的功能添加:播放、断点播放、停止、上一曲、下一曲、随机播放、显示当前播放歌曲(后续会为当前显示的播放添加动画);
软件开发流程:
1、先向内存卡导入音乐文件(文件的导入方法可以自己查找,文章类较多);
2、获取内存卡中的音乐文件;
3、将音乐文件存入集合中,便于调用,并将需要播放的文件显示在 ListView 中(点击 ListView 中的文件也可播放);
4、运用 MediaPlayer的方法实现播放、暂停、断点播放、连续播放文件;
5、通过调用写好的方法实现手动的下一曲、上一曲、随机播放、显示当前播放的音乐名;
package com.wangban.yzbbanban.v10;import android.content.Context;import android.content.Intent;import android.database.Cursor;import android.media.MediaPlayer;import android.os.Environment;import android.provider.MediaStore;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.AdapterView;import android.widget.ImageButton;import android.widget.ListView;import android.widget.RadioButton;import android.widget.TextView;import android.widget.Toast;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.List;import java.util.Locale;import java.util.Random;public class MainActivity extends AppCompatActivity { //声明各个组件,集合 private List musics; private ListView lvMusicList; private ImageButton ibtnPlayOrPause; private ImageButton ibtnNext; private ImageButton ibtnprevious; private ImageButton ibtnGetPosition; private RadioButton rbtnPlayRandown; private RadioButton rbtnPlaySequence; private RadioButton rbtnPlaySingle; private MusicAdapter adapter; private TextView tvTip; private Context context; //声明 MediaPla private MediaPlayer player; // 记录的暂停时的播放位置 private int pausePosition; // 当前播放的歌曲的索引 private int currentMusicIndex; @Override //主函数 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //设置布局为 activity_main setContentView(R.layout.activity_main); //初始化控件 initView(); //获取歌曲列表 loadData(); //列出列表 initListView(); //配置监听器 setListener(); //重置(设置 MediaPlayer必须步骤) player.reset(); } //设置各种监听器 private void setListener() { InnerOnclickListener listener = new InnerOnclickListener(); //暂停播放 ibtnPlayOrPause.setOnClickListener(listener); //下一首 ibtnNext.setOnClickListener(listener); //上一首 ibtnprevious.setOnClickListener(listener); //获取当前播放音乐 ibtnGetPosition.setOnClickListener(listener); InnerItemOnCLickListener listener2 = new InnerItemOnCLickListener(); //给 ListView 添加点击(点击音乐即可播放) lvMusicList.setOnItemClickListener(listener2); // MediaPlay 自动播放(因为就一条,无需加变量) player.setOnCompletionListener(new InnerOnCompletionListener()); } //播放ListView 点击的音乐 private class InnerItemOnCLickListener implements AdapterView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //获取点击的列表的中音乐的位置,赋值给当前播放音乐 currentMusicIndex = position; //令暂停的进度为0(即为从头播放) pausePosition = 0; //播放 play(); } } //主要按钮的播放监听器 private class InnerOnclickListener implements View.OnClickListener { @Override public void onClick(View v) { switch (v.getId()) { // 播放/暂停按钮即执行的方法 case R.id.ibtn_playorpause: //当音乐在播放时 if (player.isPlaying()) { //暂停 pause(); } else { //不在播放,则播放 play(); } break; //下一首按钮即执行方法 case R.id.ibtn_next: next(); break; //上一首按钮即执行方法 case R.id.ibtn_previous: previous(); break; //获取当前播放音乐即执行方法 case R.id.ibtn_getposition: getPosition(); break; } } } //单曲循环 private void single() { currentMusicIndex++; currentMusicIndex--; pausePosition = 0; play(); } //随机播放方法 private void randown() { currentMusicIndex = new Random().nextInt(musics.size()); Toast.makeText(MainActivity.this, "随机", Toast.LENGTH_SHORT).show(); pausePosition = 0; play(); } //列表循环 private void sequence() { currentMusicIndex++; if (currentMusicIndex >= musics.size()) { currentMusicIndex = 0; } pausePosition = 0; play(); } //获取当前播放的音乐文件的名字,必先是在另一个布局中; private void getPosition() { //声明一个意图,用来切换布局和传递数据 Intent intent = new Intent(); //定义要传递的数据 String extra = musics.get(currentMusicIndex).getName() + ""; //传递数据 intent.putExtra("currentMusic", extra); //切换布局 intent.setClass(MainActivity.this, Main2Activity.class); //执行此系列活动 MainActivity.this.startActivity(intent); } //暂停 private void pause() { //直接调用MediaPlay 中的暂停方法 player.pause(); //获取暂停的位置(音乐进度) pausePosition = player.getCurrentPosition(); //切换为播放的按钮(按钮为android系统自带的按钮,可直接用) ibtnPlayOrPause.setImageResource(android.R.drawable.ic_media_play); } //播放上一曲 private void previous() { //判断是否为第一首歌曲,若为第一首歌曲,则播放最后一首 if (rbtnPlaySingle.isChecked()) { single(); } else { //当前音乐播放位置--(上一曲) currentMusicIndex--; if (currentMusicIndex <= 0) { Toast.makeText(MainActivity.this, "已经是第一首了", Toast.LENGTH_SHORT).show(); return; } else { //音乐进度置为0 pausePosition = 0; //播放 play(); } } } //播放下一曲(与上一曲类似) private void next() { if (rbtnPlayRandown.isChecked()) { randown(); } else if (rbtnPlaySingle.isChecked()) { single(); } else if (rbtnPlaySequence.isChecked()) { sequence(); } else { currentMusicIndex++; if (currentMusicIndex >= musics.size()) { Toast.makeText(MainActivity.this, "已经是最后一首了", Toast.LENGTH_SHORT).show(); return; } else { pausePosition = 0; play(); } } } //播放音乐 private void play() { //重置 player.reset(); try { //设置音乐文件来源 player.setDataSource(musics.get(currentMusicIndex).getPath()); //准备(缓冲文件) player.prepare(); //将进度设置到“音乐进度” player.seekTo(pausePosition); //获取音乐进度 player.getCurrentPosition(); //播放开始 player.start(); //用当前界面的 TextView显示当前播放的音乐 tvTip.setText(musics.get(currentMusicIndex).getName() + ""); //设置按钮图片为暂停图标 ibtnPlayOrPause.setImageResource(android.R.drawable.ic_media_pause); } catch (IOException e) { e.printStackTrace(); } } private final class InnerOnCompletionListener implements MediaPlayer.OnCompletionListener { @Override public void onCompletion(MediaPlayer mp) { next(); } } private void initListView() { adapter = new MusicAdapter(getApplicationContext(), musics); lvMusicList.setAdapter(adapter); } private void loadData() { //获取音乐文件的内容 Cursor cursor = context.getContentResolver().query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER); // 获取歌曲列表 musics = new ArrayList<>(); // 1. 检查sdcard是否可用 if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { // 2. 获取sdcard下Music文件夹的File对象 File musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC); // 3. 检查Music文件夹是否存在 if (musicDir.exists()) { // 4. 通过File类的listFiles()方法,获取Music文件夹下所有子级File对象 File[] files = musicDir.listFiles(); // 5. 检查获取到的File列表是否有效(数组是否为null,或数组长度是否为0) if (files != null && files.length > 0) { // 6. 遍历File列表 for (int i = 0; i < files.length; i++) { //下一个文件 cursor.moveToNext(); //获取艺术家内容 String artist = cursor.getString(cursor .getColumnIndex(MediaStore.Audio.Media.ARTIST)); // 6.1. 通过File类的isFile()方法,检查是否是文件 if (files[i].isFile()) { // 6.2. 通过File类的getName()方法获取文件名, // 结合String类的endsWith()方法,检查是否是mp3文件 String fileName = files[i].getName(); if (fileName.toUpperCase(Locale.CHINA).endsWith(".MP3")) { // 6.3. 创建Music对象,并封装必要的属性 Music music = new Music(); music.setName(fileName.substring(0, fileName.length() - 4)); music.setArtist(artist); music.setPath(files[i].getAbsolutePath()); // 6.4. 将新创建的Music对象添加到集合中 musics.add(music); } } } } } } } //初始化控件级布局文件等 private void initView() { player = new MediaPlayer(); lvMusicList = (ListView) findViewById(R.id.lv_musiclist); ibtnPlayOrPause = (ImageButton) findViewById(R.id.ibtn_playorpause); ibtnNext = (ImageButton) findViewById(R.id.ibtn_next); ibtnprevious = (ImageButton) findViewById(R.id.ibtn_previous); ibtnGetPosition = (ImageButton) findViewById(R.id.ibtn_getposition); rbtnPlayRandown = (RadioButton) findViewById(R.id.rbtn_playrandowm); rbtnPlaySequence = (RadioButton) findViewById(R.id.rbtn_playsequence); rbtnPlaySingle = (RadioButton) findViewById(R.id.rbtn_playsingle); tvTip = (TextView) findViewById(R.id.tv_musictip); context = MainActivity.this; }}
package com.wangban.yzbbanban.v10;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.TextView;//实现显示当前播放的音乐public class Main2Activity extends AppCompatActivity { private TextView tvCurrentMusic; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //设置当前布局为activity_main2 setContentView(R.layout.activity_main2); //声明 TextView 控件 tvCurrentMusic = (TextView) findViewById(R.id.tv_current_music); //获取主程序传出的“当前播放文件名字”的值 Intent intent= this.getIntent(); String stringValue=intent.getStringExtra("currentMusic"); tvCurrentMusic.setText(stringValue); }}
package com.wangban.yzbbanban.v10;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;import java.util.List;//集合:显示音乐文件的名称、路径,显示在 ListView 中public class MusicAdapter extends BaseAdapter{ private Context context; private List musics; public MusicAdapter(Context context, List musics) { this.context = context; this.musics = musics; } @Override public int getCount() { return musics.size(); } @Override public View getView(int position, View convertView, ViewGroup parent) { //获取当个文件的位置 Music music=musics.get(position); //将文件布置在模板中 if (convertView==null){ LayoutInflater inflater=LayoutInflater.from(context); convertView=inflater.inflate(R.layout.music_item,null); } //初始化控件 TextView tvName= (TextView) convertView.findViewById(R.id.tv_music_title); TextView tvArtist= (TextView) convertView.findViewById(R.id.tv_music_path); //TextView tvPath= (TextView) convertView.findViewById(R.id.tv_music_path); //显示文件内容 //显示歌曲名 tvName.setText(music.getName()); //tvPath.setText(music.getPath()); //显示艺术家名字 tvArtist.setText(music.getArtist()); return convertView; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; }}
package com.wangban.yzbbanban.v10;//Music 类型文件,用于集合musics,声明一个类型,获取集合中的名字、路径public class Music { //name 类型 private String name; //path 类型 private String path; //获取艺术家 private String artist; public String getArtist() { return artist; } public void setArtist(String artist) { this.artist = artist; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Music{" + "name='" + name + '\'' + ", path='" + path + '\'' + '}'; }}
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
//随机图标的选择 <?xml version="1.0" encoding="utf-8"?>
//顺序播放的图标的选择
<?xml version="1.0" encoding="utf-8"?>
//单曲循环的图标的选择
<?xml version="1.0" encoding="utf-8"?>
更多相关文章
- Android(安卓)Q分区存储权限变更及适配
- Android中利用ZipEntry漏洞实现免root写恶意文件到应用的沙盒中
- Android之使用SoundPool播放一小段音频,实现猜歌的功能
- iOS /Android多渠道打包方案、重签名方案
- Android笔记之开发中处理异常并写入本地log文件
- 基于Android的小巫新闻客户端开发---显示新闻详细内容业务逻辑实
- Android(安卓)Studio初使用之百度地图初使用(一)--配置
- 【Android7.1.2源码解析系列】Android编译系统翻译------Android
- Android(安卓)Studio中布局文件(如activity_main.xml)设计视图&代