Android小项目之音乐播放器简易版
来源:互联网 发布:sql修复工具 编辑:程序博客网 时间:2024/06/09 06:01
V1.0-最简单的一种,只有MediaPlay
activity.xml
<Button android:id="@+id/btn_play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="播放" /><Button android:id="@+id/btn_pause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="播放" />
manifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
MainActivity.java
package com.xks.musicplayer;import android.media.MediaPlayer;import android.os.Bundle;import android.os.Environment;import android.support.v7.app.AppCompatActivity;import android.view.View;import java.io.IOException;public class MainActivity extends AppCompatActivity implements View.OnClickListener { private MediaPlayer mediaPlayer = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mediaPlayer = new MediaPlayer(); //这里通过getExternalStoragePublicDirectory方法获取到了sd卡中的公共路径中的Music目录,同理我们还可以获取其他的公共目录 String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath() + "/许巍 - 那一年.mp3"; try { //这里设置了mediaPlayer要播放的资源所在路径 mediaPlayer.setDataSource(path); //如果不准备就进行play会报state 0错误,如果多次准备会报state 1错误 这里mediaPlayer的使用流程请参照下图 不需要prepare操作的情况是当pause后重新start mediaPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } } @Override public void onClick(View view) { switch (view.getId()) { case R.id.btn_play: mediaPlayer.start(); break; case R.id.btn_pause: mediaPlayer.pause(); break; } }}
V2.0-加入服务和播放列表
总结:
- 因为在manifest.xml文件中忘记对服务进行注册导致出错
- 使用MediaPlayer特别需要了解下面的流程,否则容易出现state 0,1,8等错误
- 不要忘记权限,特别是如果手机是6.0我们还要动态权限
- 使用mediaPlayer类必须要对下图的使用流程有较深的理解
- 为什么会有prepareAsync呢?因为有些要播放的文件可能很大,所以需要进行异步准备,以免ANR(application not responding)
- 我们可以为mediaPlayer注册一个监听器setOnPreparedListener,在其中重写onPrepare方法,当监听到已经准备好了后就调用mediaPlayer.start()方法
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); isPause = false; }});
代码的目录结构
MyMusicAdapter>这是一个很简单的播放列表的适配器
public class MyMusicAdapter extends BaseAdapter { @Override public int getCount() { return MyApp.musicBeanList == null ? 0 : MyApp.musicBeanList.size(); } @Override public MusicBean getItem(int position) { return MyApp.musicBeanList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; MusicBean musicBean = MyApp.musicBeanList.get(position); if (convertView == null) { convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_music, null); viewHolder = new ViewHolder(); viewHolder.mTextView = (TextView) convertView.findViewById(R.id.tv_music); viewHolder.mTextView.setText(musicBean.getMusicName()); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); viewHolder.mTextView.setText(musicBean.getMusicName()); } return convertView; } class ViewHolder { private TextView mTextView; }}
MusicBean>歌曲实体类,存放了歌曲名称和路径以及getter/setter/toString方法
public class MusicBean { private String musicName; private String musicPath; public MusicBean() { } public MusicBean(String musicName, String musicPath) { this.musicName = musicName; this.musicPath = musicPath; } public String getMusicName() { return musicName; } public void setMusicName(String musicName) { this.musicName = musicName; } public String getMusicPath() { return musicPath; } public void setMusicPath(String musicPath) { this.musicPath = musicPath; } @Override public String toString() { return "MusicBean{" + "musicName='" + musicName + '\'' + ", musicPath='" + musicPath + '\'' + '}'; }}
MyApp extends Application 特别注意需要在manifest.xml文件中声明:
android:name=”MyApp”
里面存放的是歌曲集合,由于本类继承自application,因此歌曲集合是一个全局变量,只需要在服务中对目标文件夹进行遍历将以.mp3结尾的歌曲加入集合即可
public class MyApp extends Application { //播放列表音乐集合,MusicBean实体类中着存放歌曲名称和歌曲所在目录 public static List<MusicBean> musicBeanList; @Override public void onCreate() { super.onCreate(); musicBeanList = new ArrayList<MusicBean>(); }}
MusicService>音乐服务类,使用绑定服务的方式打开后再使用startService方法,使得播放器可以在用户打开activity的时候与服务进行交互,在用户关闭了activity的时候在onDestroy方法中解除绑定,使服务可以后台运行播放音乐
public class MusicService extends Service { MediaPlayer mediaPlayer;//播放歌曲的类 private int currentPlaying = 0;//正在播放的歌曲 private static final String TAG = "MusicService"; public static boolean isPlaying = false;//是否处于播放状态 public static boolean isPause = false;//是否处于暂停状态 /** * 服务Create,此时应当生成播放列表并初始化MediaPlay类 */ @Override public void onCreate() { super.onCreate(); if (mediaPlayer == null) { mediaPlayer = new MediaPlayer(); } } @Override public IBinder onBind(Intent intent) { Log.e(TAG, "方法名>>onBind()"); final MyBinder myBinder = new MyBinder(); if (MyApp.musicBeanList.size() == 0) { myBinder.createPlayList(); Log.e(TAG, "方法名>>onBind()" + MyApp.musicBeanList.toString()); } return myBinder; } /** * 服务与activity进行交互的方法 */ public class MyBinder extends Binder { /** * 播放指定位置的歌曲 * * @param music */ public void playMusic(MusicBean music, int position) { try { /* * Resets the MediaPlayer to its uninitialized state. After calling this method, * you will have to initialize it again by setting the data source and calling prepare(). */ if (isPlaying&&isPause) {//播放状态但是被暂停了 if (currentPlaying != position) {//正在播放的与点击的歌不是同一首 setMusic(music); } else if (currentPlaying == position) {//是同一首歌 mediaPlayer.start();//=>无需prepare,直接start就行 isPause = false; } }else{//没有播放 setMusic(music); } currentPlaying = position; } catch (IOException e) { e.printStackTrace(); } } private void setMusic(MusicBean music) throws IOException { mediaPlayer.reset();//reset后需要重新确定要播放的音乐所在路径 mediaPlayer.setDataSource(music.getMusicPath()); mediaPlayer.prepareAsync(); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); isPause = false; isPlaying = true; } }); } /** * 暂停播放 */ public void pauseMusic() { if (mediaPlayer.isPlaying()) {//正在播放时 mediaPlayer.pause(); isPlaying = true; isPause = true; } } /** * 子线程中扫描歌曲>生成播放列表 * 遍历SD卡下的Music文件夹(mnt>shell>emulated>0>MUSIC),获取以.mp3结尾的文件并装入集合 */ public void createPlayList() { new Thread() { @Override public void run() { MyApp.musicBeanList.clear(); File musicDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC); File[] files = musicDirectory.listFiles(); for (File file : files) { if (file.getName().endsWith(".mp3")) { MusicBean musicBean = new MusicBean(); musicBean.setMusicName(file.getName()); musicBean.setMusicPath(file.getAbsolutePath()); MyApp.musicBeanList.add(musicBean); } } } }.start(); } } @Override public void onDestroy() { //在服务中的onDestroy方法中对mediaPlayer资源进行释放 mediaPlayer.release(); //将mediaPlayer赋空便于垃圾回收器进行回收 mediaPlayer = null; super.onDestroy(); }}
MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener ,AdapterView.OnItemClickListener { private static final String TAG = "MainActivity"; private Button playButton; private Button pauseButton; private ListView mListView; private MyMusicAdapter myMusicAdapter; private MusicService.MyBinder myBinder;//Binder对象 private MyServiceConnected myServiceConnected; private int currentPlaying = 0;//正在播放的是第几首歌 private Button mRefreshPlayList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); playButton = (Button) findViewById(R.id.btn_play); pauseButton = (Button) findViewById(R.id.btn_pause); mRefreshPlayList = (Button) findViewById(R.id.btn_flush_playlist); mListView = (ListView) findViewById(R.id.lv_listview); //通过绑定的方式开启服务,该方式可以使activity与服务进行通信 Intent intent = new Intent(this,MusicService.class); myServiceConnected = new MyServiceConnected(); bindService(intent, myServiceConnected,BIND_AUTO_CREATE); startService(intent); playButton.setOnClickListener(this); pauseButton.setOnClickListener(this); mRefreshPlayList.setOnClickListener(this); mListView.setOnItemClickListener(this); } /** * 退出activity时要解除与服务的绑定 */ @Override protected void onDestroy() { unbindService(myServiceConnected); super.onDestroy(); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.btn_play://播放音乐 Log.d(TAG, "myBinder ==null? " + (myBinder == null)); myBinder.playMusic(MyApp.musicBeanList.get(currentPlaying),currentPlaying); break; case R.id.btn_pause://暂停音乐 myBinder.pauseMusic(); break; case R.id.btn_flush_playlist: myBinder.createPlayList(); myMusicAdapter.notifyDataSetChanged(); break; } } private class MyServiceConnected implements ServiceConnection{ /** * 绑定服务成功回调 * @param componentName * @param service */ @Override public void onServiceConnected(ComponentName componentName, IBinder service) { Log.e(TAG, "类名>>MainActivity>>方法名>>onServiceConnected()"); myBinder = (MusicService.MyBinder) service; myMusicAdapter = new MyMusicAdapter(); mListView.setAdapter(myMusicAdapter); } /** * 服务意外挂掉回调 * @param name */ @Override public void onServiceDisconnected(ComponentName name) { } } @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { MusicBean musicBean = myMusicAdapter.getItem(position); currentPlaying = position; Log.e(TAG, "类名>>MainActivity>>方法名>>onItemClick()"+musicBean.getMusicName()); myBinder.playMusic(musicBean,position); }}
activity_main.xml
<Button android:id="@+id/btn_play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="播放" /> <Button android:id="@+id/btn_pause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/btn_play" android:text="暂停" /> <Button android:id="@+id/btn_flush_playlist" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="刷新播放列表" android:layout_toRightOf="@+id/btn_pause"/> <ListView android:id="@+id/lv_listview" android:scrollbars="none" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/btn_play" />
item_music
<TextView android:id="@+id/tv_music" android:textSize="25sp" android:layout_gravity="center" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="5dp" />
GitHub 源代码下载:https://github.com/a1265137718/AndroidProjectRepository.git
0 0
- Android小项目之音乐播放器简易版
- Android 小项目之--Mini音乐播放器【简单版】
- android之service音乐简易版播放器
- android小项目之音乐播放器一
- android小项目之音乐播放器二
- android简易音乐播放器
- Android 小项目之--Mini音乐播放器【简单版】(附源码)
- Android 小项目之--Mini音乐播放器【简单版】(附源码)
- Android 小项目之--Mini音乐播放器【简单版】(附源码)
- Android 小项目之--Mini音乐播放器【简单版】(附源码)
- Android 小项目之--Mini音乐播放器【简单版】(附源码)
- Android 小项目之--Mini音乐播放器【简单版】(附源码)
- Android 小项目之--Mini音乐播放器【简单版】(附源码)
- Android 小项目之--Mini音乐播放器【简单版】(附源码)
- appWidget小应用----简易音乐播放器
- 最简单、简易的android音乐播放器,android开发应用之(音乐播放)
- Android开发笔记之简易音乐播放器
- Android 项目之--Mini音乐播放器
- 赏罚有序
- Gray Code
- 获取父类的类名
- Android Studio 和 Unity3D 交互
- 第二周项目2--程序的多文件组织
- Android小项目之音乐播放器简易版
- stl中双向队列用法
- RIME-使用小心得
- 最小生成树算法——Kruskal算法
- A+B
- sscanf函数基本用法
- win10+ubuntu 14.04双系统安装 (UEFI)
- codeforces基础题——#362(div2)C
- numpy中mat和python的list转换