Android练习项目 Mp3播放器实现(二)
2016-04-19 15:50
661 查看
在经过几天的折腾之后,迎来了Mp3播放器的第二篇博客,这篇文章主要将如何实现播放器的播放,下一首,上一首,顺序播放,循环播放,随机播放,单曲循环等操作。
其实操作的过程中主要是通过参数的传递来实现功能的。
在activity里面互相传参有很多中方法,但对于activity和service进行交互有些方法并不适合,通过对Broadcast和BroadcastReceiver等操作,来控制播放的实现。
我们先设定好广播,然后通过发送信号来进行传递数据。
主要在activity里面动态注册广播,通过传递播放的顺序选择,Mp3的url,Mp3播放的位置到service里面,service里面接受传来的广播,获得参数,在进行对应的操作。
还有一个要解决的问题就是,如何通过service将播放的时间和歌曲信息反馈到activity里面,然后更新标题,时间,所以就是参数在service和activity之间进行传递,在程序中通过handle来处理程序的更新数据,通过handle来和activity交互,但由于没有开启线程,所以十分耗时的操作可能不适合,在下一个版本可能需要着手解决这个问题。
所以对于广播的处理就显得比较重要了。
先将作出的效果粘贴出来,目前还没有歌词等处理。
对于里面流程的处理十分重要,需要不断的调试,这是最为花费功夫的。
activity_main.xml布局文件
主要功能通过展示listview来显示内容。
自定义子部局:
listmusic.xml
MainActivity.java
主要获取mp3文件,对于里面出现的Mp3infos这个类,参考我上篇文章,这篇文章没有修改。
musicplay.xml,播放界面的布局
接下来就是MusicActivity.java
这里面有个东西我觉得非常好,就是用了static变量,来共享mp3infos文件信息,通过MainActivity函数来赋值进来,相当于不再需要另一块内存来存储数据了,service也是这样实现的,这样每次我们只需要将位置position传进去就能够解决问题了。
这里面有许多细节,处理的过程就是不断调试。
最为重要的就是写service了,这个里面主要涉及到MP3的播放,暂停,切换,上一首,进行操作的主要是接受MusicActivity里面传过来的广播,然后进行判断,然后处理对应的函数。说的就是这么简单,但处理起来,并不是很好解决。
MusicService.java
这些函数里面有个标识,其实有时候,我们并不想通过new一个类来处理信息,这个就是个很好的表示来解决问题。
PlayerMSG.java
主要的内容就这么多,现在还未完成歌词显示,还有需要解决地问题,就是需要在子线程里面更新UI,这个需要重新考虑。
这篇博客,改变了上一篇博客里面的设计思路,让我掌握了广播的使用。
参考这篇文章,我就是参考大神之后修改的,站在巨人的肩膀上看世界
源码下载
其实操作的过程中主要是通过参数的传递来实现功能的。
在activity里面互相传参有很多中方法,但对于activity和service进行交互有些方法并不适合,通过对Broadcast和BroadcastReceiver等操作,来控制播放的实现。
我们先设定好广播,然后通过发送信号来进行传递数据。
主要在activity里面动态注册广播,通过传递播放的顺序选择,Mp3的url,Mp3播放的位置到service里面,service里面接受传来的广播,获得参数,在进行对应的操作。
还有一个要解决的问题就是,如何通过service将播放的时间和歌曲信息反馈到activity里面,然后更新标题,时间,所以就是参数在service和activity之间进行传递,在程序中通过handle来处理程序的更新数据,通过handle来和activity交互,但由于没有开启线程,所以十分耗时的操作可能不适合,在下一个版本可能需要着手解决这个问题。
所以对于广播的处理就显得比较重要了。
先将作出的效果粘贴出来,目前还没有歌词等处理。
对于里面流程的处理十分重要,需要不断的调试,这是最为花费功夫的。
activity_main.xml布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/listviewmusic"> </ListView> </LinearLayout>
主要功能通过展示listview来显示内容。
自定义子部局:
listmusic.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="60dp" android:orientation="vertical"> <TextView android:layout_width="70dp" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" android:text="Small Text" android:id="@+id/MusicID" android:gravity="center" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentBottom="true" android:layout_alignParentTop="true"/> <TextView android:layout_width="200dp" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" android:text="Small Text" android:id="@+id/Musictitle" android:textStyle="bold" android:layout_alignParentTop="true" android:layout_toRightOf="@+id/MusicID" android:layout_toEndOf="@+id/MusicID" android:layout_marginLeft="20dp" android:layout_marginTop="10dp" android:textSize="15dp" android:singleLine="true" android:ellipsize="end"/> <TextView android:layout_width="220dp" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" android:text="Small Text" android:id="@+id/MusicArtist" android:textColor="#878383" android:layout_toRightOf="@+id/MusicID" android:layout_toEndOf="@+id/MusicID" android:layout_marginLeft="20dp" android:layout_below="@+id/Musictitle" android:layout_marginTop="7dp" android:textSize="12dp" android:ellipsize="end" android:singleLine="true"/> <ImageView android:layout_width="25dp" android:layout_height="25dp" android:id="@+id/MusicIcon" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:layout_marginRight="30dp" /> </RelativeLayout>
MainActivity.java
主要获取mp3文件,对于里面出现的Mp3infos这个类,参考我上篇文章,这篇文章没有修改。
package com.flashmusic; import android.app.Activity; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.provider.MediaStore; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import android.widget.SimpleAdapter; import com.flashmusic.tool.Mp3Info; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class MainActivity extends Activity implements AdapterView.OnItemClickListener { //Music的listview控件 private ListView MusicList; // 存储数据的数组列表 ArrayList<HashMap<String, Object>> MusiclistData = new ArrayList<HashMap<String, Object>>(); // 适配器 private SimpleAdapter MusicListAdapter; //存放mp3信息 static List<Mp3Info> mp3Infos; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MusicList = (ListView) findViewById(R.id.listviewmusic); mp3Infos = getMp3Infos(); GetData(mp3Infos); MusicListAdapter = new SimpleAdapter( this, MusiclistData, R.layout.listmusic, new String[]{"ID", "Title", "Artist", "Icon"}, new int[]{R.id.MusicID, R.id.Musictitle, R.id.MusicArtist, R.id.MusicIcon} ); //赋予数据 MusicList.setAdapter(MusicListAdapter); MusicList.setOnItemClickListener(MusiclistListen); } AdapterView.OnItemClickListener MusiclistListen = new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { // //Toast.makeText(MainActivity.this, String.valueOf(l), Toast.LENGTH_SHORT).show(); // // //判断当前服务是否已经开启 // if(isServiceRunning(getBaseContext(),"com.flashmusic.MusicService")){ // stopService(new Intent(MainActivity.this, MusicService.class)); // } // Intent intent = new Intent(); // intent.putExtra("url", mp3Infos.get(i).getUrl()); // intent.putExtra("position",String.valueOf(i)); // intent.setClass(MainActivity.this, MusicService.class); // //启动服务 // startService(intent); Intent musicintent = new Intent(MainActivity.this, MusicActivity.class); //当前播放的位置 musicintent.putExtra("position", String.valueOf(i)); MusicActivity.mp3Infos = mp3Infos; // MusicActivity.musicserviceintent = intent; //启动音乐播放界面 startActivity(musicintent); } }; //判断服务是否存在 public static boolean isServiceRunning(Context mContext,String className) { boolean isRunning = false; ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningServiceInfo> serviceList= activityManager.getRunningServices(50); if (!(serviceList.size()>0)) { return false; } for (int i=0; i<serviceList.size(); i++) { String a =serviceList.get(i).service.getClassName(); if (serviceList.get(i).service.getClassName().equals(className) == true) { isRunning = true; break; } } return isRunning; } public void GetData(List<Mp3Info> mp3Infos) { for (int i = 0; i < mp3Infos.size(); i++) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put("ID",mp3Infos.get(i).getID()); map.put("Title", mp3Infos.get(i).getTitle()); map.put("Artist", mp3Infos.get(i).getArtist()); map.put("Icon", R.drawable.musicicon); MusiclistData.add(map); } } public List<Mp3Info> getMp3Infos() { Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER); int ID = 0; List<Mp3Info> mp3Infos = new ArrayList<Mp3Info>(); for (int i = 0; i < cursor.getCount(); i++) { Mp3Info mp3Info = new Mp3Info(); cursor.moveToNext(); long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID)); //音乐id,音乐ID不是播放的顺序 String title = cursor.getString((cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)));//音乐标题 String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));//艺术家 long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));//时长 long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE)); //文件大小 String url = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)); //文件路径 int isMusic = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));//是否为音乐 if (isMusic != 0) { //只把音乐添加到集合当中 ID++; mp3Info.setID(ID); mp3Info.setTitle(title); mp3Info.setArtist(artist); mp3Info.setDuration(duration); mp3Info.setSize(size); mp3Info.setUrl(url); mp3Infos.add(mp3Info); } } return mp3Infos; } @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { } }
musicplay.xml,播放界面的布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:focusable="false" android:orientation="horizontal" android:background="@drawable/background"> <TextView android:id="@+id/musictitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:textColor="#ffffff" android:textSize="20dp" android:textStyle="bold" android:layout_marginTop="15dp"/> <TextView android:id="@+id/musicartist" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/musictitle" android:layout_centerHorizontal="true" android:layout_marginTop="5dp" android:textColor="#c6bbbb"/> <LinearLayout android:id="@+id/linearLayout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_marginBottom="10dp"> <ImageView android:id="@+id/musicplaymode" android:layout_width="40dp" android:layout_height="40dp" android:layout_margin="10dp" android:layout_weight="1" android:src="@drawable/orderplay"/> <ImageView android:id="@+id/musicprevious" android:layout_width="40dp" android:layout_height="40dp" android:layout_margin="10dp" android:layout_weight="1" android:src="@drawable/musicprevious"/> <ImageView android:id="@+id/musicplay" android:layout_width="40dp" android:layout_height="40dp" android:layout_margin="10dp" android:layout_weight="1" android:src="@drawable/musicpause"/> <ImageView android:id="@+id/musicnext" android:layout_width="40dp" android:layout_height="40dp" android:layout_margin="10dp" android:layout_weight="1" android:src="@drawable/musicnext"/> <ImageView android:id="@+id/musicplaymenu" android:layout_width="40dp" android:layout_height="40dp" android:layout_margin="10dp" android:layout_weight="1" android:src="@drawable/menuplay"/> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="60dp" android:layout_above="@+id/linearLayout" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:id="@+id/playcurrenttime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/MusicProgress" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:text="00:00" android:textAppearance="?android:attr/textAppearanceSmall"/> <SeekBar android:id="@+id/MusicProgress" android:layout_width="184dp" android:layout_height="wrap_content" android:layout_above="@+id/linearLayout" android:layout_toRightOf="@+id/playcurrenttime" android:layout_weight="0.16" android:indeterminate="false" android:max="100"/> <TextView android:id="@+id/playtime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="00:00" android:textAppearance="?android:attr/textAppearanceSmall"/> </LinearLayout> </RelativeLayout>
接下来就是MusicActivity.java
这里面有个东西我觉得非常好,就是用了static变量,来共享mp3infos文件信息,通过MainActivity函数来赋值进来,相当于不再需要另一块内存来存储数据了,service也是这样实现的,这样每次我们只需要将位置position传进去就能够解决问题了。
package com.flashmusic; import com.flashmusic.tool.PlayerMSG; import android.annotation.TargetApi; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.view.Menu; import android.view.View; import android.widget.ImageView; import android.widget.SeekBar; import android.widget.TextView; import android.widget.ThemedSpinnerAdapter; import android.widget.Toast; import com.flashmusic.tool.Mp3Info; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Random; import java.util.TimeZone; public class MusicActivity extends Activity implements View.OnClickListener { //mp3需要播放的数据 static List<Mp3Info> mp3Infos; static Intent musicserviceintent; //播放按钮 private ImageView MusicPlay; //下一首 private ImageView MusicNext; //上一首 private ImageView MusicPrevious; //播放方式选择 private ImageView MusicMOde; //播放菜单 private ImageView MusicMenu; //显示总时间 private TextView MusicTime; //显示当前时间 private TextView MusicCurrentTime; //显示歌曲名 private TextView MusicTitle; //显示歌曲艺术家 private TextView MusicArtist; //进度条 SeekBar seekBar; //广播 MusicPlayerReceiver musicPlayerReceiver; private final int isorderplay = 0;//顺序播放 private final int islistloop = 1;//表示列表循环 private final int isrepeatone = 2;//单曲循环 private final int israndomplay = 3;//随机 public static final String UPDATE_ACTION = "com.flashmusic.action.UPDATE_ACTION"; //更新动作 public static final String CTL_ACTION = "com.flashmusic.action.CTL_ACTION"; //控制动作 public static final String MUSIC_CURRENT = "com.flashmusic.action.MUSIC_CURRENT"; //音乐当前时间改变动作 public static final String MUSIC_DURATION = "com.flashmusic.action.MUSIC_DURATION";//音乐播放长度改变动作 public static final String MUSIC_PLAYING = "com.flashmusic.action.MUSIC_PLAYING"; //音乐正在播放动作 public static final String REPEAT_ACTION = "com.flashmusic.action.REPEAT_ACTION"; //音乐重复播放动作 public static final String SHUFFLE_ACTION = "com.flashmusic.action.RANDOM_ACTION";//音乐随机播放动作 public static final String PLAY_STATUE = "com.flashmusic.action.PLAY_STATUE"; //更新播放状态 //是否绑定了对应的service Boolean mBound = false; //播放方式表识0表示顺序播放,1表示列表循环,2表示单曲循环,3表示随机,初始为顺序播放 int playmodeflag = 0; //歌曲播放的位置,就能够获取位置 int position; int currentTime; int duration;//总时间 //记录鼠标点击了几次,播放和暂停状态 boolean playorpauseflag = false; //播放服务 MusicService mService; // 正在播放 private boolean isPlaying; // 暂停 private boolean isPause; //多线程,后台更新UI Thread myThread; //控制后台线程退出 boolean playStatus = true; //转换毫秒数为时间模式,一般都是分钟数,音乐文件 public static String formatDuring(long mss) { long days = mss / (1000 * 60 * 60 * 24); long hours = (mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60); long minutes = (mss % (1000 * 60 * 60)) / (1000 * 60); long seconds = (mss % (1000 * 60)) / 1000; return String.format("%02d", minutes) + ":" + String.format("%02d", seconds); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.musicplay); //初始化控件 InitView(); //获得传过来的值 Intent intent = getIntent(); position = Integer.parseInt(intent.getStringExtra("position")); MusicArtist.setText(mp3Infos.get(position).getArtist()); MusicTitle.setText(mp3Infos.get(position).getTitle()); //注册广播 musicPlayerReceiver = new MusicPlayerReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(UPDATE_ACTION); filter.addAction(MUSIC_CURRENT); filter.addAction(MUSIC_DURATION); filter.addAction(PLAY_STATUE); registerReceiver(musicPlayerReceiver, filter); //设置响应事件 MusicNext.setOnClickListener(this); MusicPrevious.setOnClickListener(this); MusicMenu.setOnClickListener(this); MusicMOde.setOnClickListener(this); MusicPlay.setOnClickListener(this); seekBar.setOnSeekBarChangeListener(seekBarChangeListener); PlayMusic(); } //初始化控件 void InitView() { MusicPlay = (ImageView) findViewById(R.id.musicplay); MusicNext = (ImageView) findViewById(R.id.musicnext); MusicPrevious = (ImageView) findViewById(R.id.musicprevious); MusicMenu = (ImageView) findViewById(R.id.musicplaymenu); MusicMOde = (ImageView) findViewById(R.id.musicplaymode); MusicTime = (TextView) findViewById(R.id.playtime); MusicCurrentTime = (TextView) findViewById(R.id.playcurrenttime); MusicTitle = (TextView) findViewById(R.id.musictitle); MusicArtist = (TextView) findViewById(R.id.musicartist); seekBar = (SeekBar) findViewById(R.id.MusicProgress); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void onClick(View v) { Intent intent = new Intent(); switch (v.getId()) { case R.id.musicplay: if (isPlaying) { MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicpause, null)); intent.setClass(MusicActivity.this, MusicService.class); intent.putExtra("MSG", PlayerMSG.MSG.PAUSE_MSG); startService(intent); isPlaying = false; } else { MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null)); intent.setClass(MusicActivity.this, MusicService.class); intent.putExtra("MSG", PlayerMSG.MSG.CONTINUE_MSG); startService(intent); isPlaying = true; } break; case R.id.musicplaymode: setPlayMOde(); break; case R.id.musicnext: PlayNextMusic(); break; case R.id.musicprevious: PlayPreviousMusic(); break; case R.id.musicplaymenu: break; default: break; } } @TargetApi(Build.VERSION_CODES.LOLLIPOP) void setPlayMOde() { playmodeflag++; Intent intent = new Intent(CTL_ACTION); intent.putExtra("control", playmodeflag); sendBroadcast(intent); switch (playmodeflag) { case isorderplay: MusicMOde.setImageDrawable(getResources().getDrawable(R.drawable.orderplay, null)); break; case islistloop: MusicMOde.setImageDrawable(getResources().getDrawable(R.drawable.repeatplay, null)); break; case isrepeatone: MusicMOde.setImageDrawable(getResources().getDrawable(R.drawable.repeatoneplay, null)); break; case israndomplay: MusicMOde.setImageDrawable(getResources().getDrawable(R.drawable.randomplay, null)); playmodeflag = -1; break; default: break; } } SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() { //停止拖动事件 @Override public void onStopTrackingTouch(SeekBar seekBar) { //手动调节进度 // TODO Auto-generated method stub //seekbar的拖动位置 int progress = seekBar.getProgress(); ChangeProgress(progress); //调用service调节播放进度 // mService.setProgress(max, dest); } //数值改变事件 @Override public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) { // TODO Auto-generated method stub } //开始拖动事件 @Override public void onStartTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub } }; public void ChangeProgress(int progress) { Intent intent = new Intent(); intent.setClass(MusicActivity.this, MusicService.class); intent.putExtra("url", mp3Infos.get(position).getUrl()); intent.putExtra("position", position); intent.putExtra("MSG", PlayerMSG.MSG.PROGRESS_CHANGE); intent.putExtra("progress", progress); startService(intent); } //播放音乐 @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void PlayMusic() { isPlaying = true; MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null)); // 开始播放的时候为顺序播放 Intent intent = new Intent(); intent.setClass(MusicActivity.this, MusicService.class); intent.putExtra("url", mp3Infos.get(position).getUrl()); intent.putExtra("position", position); intent.putExtra("MSG", PlayerMSG.MSG.PLAY_MSG); MusicService.mp3Infos = mp3Infos; startService(intent); } //播放上一首音乐 @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void PlayPreviousMusic() { position = position - 1; // MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicpause,null)); if (position < 0) { position = mp3Infos.size() - 1; } Mp3Info mp3Info = mp3Infos.get(position); MusicTitle.setText(mp3Info.getTitle()); MusicArtist.setText(mp3Info.getArtist()); Intent intent = new Intent(); intent.setClass(MusicActivity.this, MusicService.class); intent.putExtra("url", mp3Info.getUrl()); intent.putExtra("position", position); intent.putExtra("MSG", PlayerMSG.MSG.PRIVIOUS_MSG); startService(intent); isPlaying = true; MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null)); } //播放下一首音乐 @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void PlayNextMusic() { //判断是否是随机播放,因为随机播放设置后,playmodeflag变为-1了 if (playmodeflag == -1) { Random random = new Random(); position = random.nextInt(mp3Infos.size()); } else position = position + 1; if (position >= mp3Infos.size()) position = 0; Mp3Info mp3Info = mp3Infos.get(position); MusicTitle.setText(mp3Info.getTitle()); MusicArtist.setText(mp3Info.getArtist()); Intent intent = new Intent(); intent.setClass(MusicActivity.this, MusicService.class); intent.putExtra("url", mp3Info.getUrl()); intent.putExtra("position", position); intent.putExtra("MSG", PlayerMSG.MSG.NEXT_MSG); startService(intent); MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null)); isPlaying = true; } public class MusicPlayerReceiver extends BroadcastReceiver { @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); //当前时间更新 if (action.equals(MUSIC_CURRENT)) { currentTime = intent.getIntExtra("currentTime", -1); seekBar.setProgress(currentTime); MusicCurrentTime.setText(formatDuring(currentTime)); } else if (action.equals(MUSIC_DURATION)) { //总时间更新 duration = intent.getIntExtra("duration", -1); seekBar.setMax(duration); MusicTime.setText(formatDuring(duration)); } else if (action.equals(UPDATE_ACTION)) { position = intent.getIntExtra("position", -1); String url = mp3Infos.get(position).getUrl(); MusicTitle.setText(mp3Infos.get(position).getTitle()); MusicArtist.setText(mp3Infos.get(position).getArtist()); MusicTime.setText(formatDuring(mp3Infos.get(position).getDuration())); } else if (action.equals(PLAY_STATUE)) { boolean playstatue = intent.getBooleanExtra("playstatue", true); if (playstatue) { MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicplay, null)); isPlaying = true; } else { MusicPlay.setImageDrawable(getResources().getDrawable(R.drawable.musicpause, null)); isPlaying = false; } } } } public void onDestroy() { //销毁activity时,要记得销毁线程 playStatus = false; super.onDestroy(); } }
这里面有许多细节,处理的过程就是不断调试。
最为重要的就是写service了,这个里面主要涉及到MP3的播放,暂停,切换,上一首,进行操作的主要是接受MusicActivity里面传过来的广播,然后进行判断,然后处理对应的函数。说的就是这么简单,但处理起来,并不是很好解决。
MusicService.java
package com.flashmusic; import com.flashmusic.tool.PlayerMSG; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.util.Log; import android.widget.Toast; import com.flashmusic.tool.Mp3Info; import java.util.ArrayList; import java.util.List; public class MusicService extends Service { // mp3的绝对路径 private String path; //当前播放位置 private int position; //当前播放进度 private int currentTime; private int msg; //播放信息 private boolean isPause; static List<Mp3Info> mp3Infos; //存放Mp3Info对象的集合 private int duration; //播放长度 int palyflag = 0; //服务要发送的一些Action public static final String UPDATE_ACTION = "com.flashmusic.action.UPDATE_ACTION"; //更新音乐播放曲目 public static final String CTL_ACTION = "com.flashmusic.action.CTL_ACTION"; //控制播放模式 public static final String MUSIC_CURRENT = "com.flashmusic.action.MUSIC_CURRENT"; //当前音乐播放时间更新 public static final String MUSIC_DURATION = "com.flashmusic.action.MUSIC_DURATION";//播放音乐长度更新 public static final String PLAY_STATUE = "com.flashmusic.action.PLAY_STATUE"; //更新播放状态 //播放音乐的媒体类 MediaPlayer mediaPlayer; //广播接收器,接收来自MusicActivity的广播 private MusicReceiver musicReceiver; IBinder musicBinder = new MyBinder(); //handler用来接收消息,来发送广播更新播放时间 private Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case 1: if (mediaPlayer != null) { currentTime = mediaPlayer.getCurrentPosition(); Intent intent = new Intent(); intent.setAction(MUSIC_CURRENT); intent.putExtra("currentTime", currentTime); sendBroadcast(intent); // 给PlayerActivity发送广播 mHandler.sendEmptyMessageDelayed(1, 1000); } break; default: break; } } ; }; class MyBinder extends Binder { public Service getService() { return MusicService.this; } } @Override public void onCreate() { super.onCreate(); mediaPlayer = new MediaPlayer(); /** * 设置音乐播放完成时的监听器 */ mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { Intent intent = new Intent(PLAY_STATUE); // 发送播放完毕的信号,更新播放状态 intent.putExtra("playstatue", false); sendBroadcast(intent); // Toast.makeText(getApplicationContext(),"服务完成了",Toast.LENGTH_SHORT).show(); if (palyflag == 2) { Intent loopintent = new Intent(PLAY_STATUE); // 发送播放完毕的信号,更新播放状态 intent.putExtra("playstatue", true); sendBroadcast(loopintent); // 单曲循环 mediaPlayer.start(); } else if (palyflag == 1) { // 列表循环 position++; if (position > mp3Infos.size() - 1) { //变为第一首的位置继续播放 position = 0; } Intent sendIntent = new Intent(UPDATE_ACTION); sendIntent.putExtra("position", position); // 发送广播,将被Activity组件中的BroadcastReceiver接收到 sendBroadcast(sendIntent); path = mp3Infos.get(position).getUrl(); play(0); } else if (palyflag == 0) { // 顺序播放 position++; //下一首位置 if (position <= mp3Infos.size() - 1) { Intent sendIntent = new Intent(UPDATE_ACTION); sendIntent.putExtra("position", position); // 发送广播,将被Activity组件中的BroadcastReceiver接收到 sendBroadcast(sendIntent); path = mp3Infos.get(position).getUrl(); play(0); } else { mediaPlayer.seekTo(0); position = 0; Intent sendIntent = new Intent(UPDATE_ACTION); sendIntent.putExtra("position", position); // 发送广播,将被Activity组件中的BroadcastReceiver接收到 sendBroadcast(sendIntent); } } else if (palyflag == 3) { //随机播放 position = getRandomIndex(mp3Infos.size() - 1); Intent sendIntent = new Intent(UPDATE_ACTION); sendIntent.putExtra("position", position); // 发送广播,将被Activity组件中的BroadcastReceiver接收到 sendBroadcast(sendIntent); path = mp3Infos.get(position).getUrl(); play(0); } } }); musicReceiver = new MusicReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(CTL_ACTION); // filter.addAction(SHOW_LRC); registerReceiver(musicReceiver, filter); } @Override public int onStartCommand(Intent intent, int flags, int startId) { path = intent.getStringExtra("url"); //歌曲路径 position = intent.getIntExtra("position", -1); //当前播放歌曲的在mp3Infos的位置 msg = intent.getIntExtra("MSG", 0); //播放信息 if (msg == PlayerMSG.MSG.PLAY_MSG) { //直接播放音乐 play(0); } else if (msg == PlayerMSG.MSG.PAUSE_MSG) { //暂停 pause(); } else if (msg == PlayerMSG.MSG.STOP_MSG) { //停止 stop(); } else if (msg == PlayerMSG.MSG.CONTINUE_MSG) { //继续播放 resume(); } else if (msg == PlayerMSG.MSG.PRIVIOUS_MSG) { //上一首 previous(); } else if (msg == PlayerMSG.MSG.NEXT_MSG) { //下一首 next(); } else if (msg == PlayerMSG.MSG.PROGRESS_CHANGE) { //进度更新 currentTime = intent.getIntExtra("progress", -1); play(currentTime); } else if (msg == PlayerMSG.MSG.PLAYING_MSG) { mHandler.sendEmptyMessage(1); } return super.onStartCommand(intent, flags, startId); } private void play(int currentTime) { try { mediaPlayer.reset();// 把各项参数恢复到初始状态 mediaPlayer.setDataSource(path); mediaPlayer.prepare(); // 进行缓冲 mediaPlayer.setOnPreparedListener(new PreparedListener(currentTime));// 注册一个监听器 //更新播放状态 Intent intent = new Intent(PLAY_STATUE); // 发送播放完毕的信号,更新播放状态 intent.putExtra("playstatue", true); sendBroadcast(intent); mHandler.sendEmptyMessage(1); } catch (Exception e) { e.printStackTrace(); } } //继续播放 private void resume() { if (isPause) { mediaPlayer.start(); isPause = false; } } /** * 上一首 */ private void previous() { Intent sendIntent = new Intent(UPDATE_ACTION); sendIntent.putExtra("position", position); // 发送广播,将被Activity组件中的BroadcastReceiver接收到 sendBroadcast(sendIntent); play(0); } /** * 下一首 */ private void next() { Intent sendIntent = new Intent(UPDATE_ACTION); sendIntent.putExtra("position", position); // 发送广播,将被Activity组件中的BroadcastReceiver接收到 sendBroadcast(sendIntent); play(0); } private void pause() { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.pause(); isPause = true; } } private void stop() { if (mediaPlayer != null) { mediaPlayer.stop(); try { mediaPlayer.prepare(); // 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数 } catch (Exception e) { e.printStackTrace(); } } } /** * 实现一个OnPrepareLister接口,当音乐准备好的时候开始播放 */ private final class PreparedListener implements MediaPlayer.OnPreparedListener { private int currentTime; public PreparedListener(int currentTime) { this.currentTime = currentTime; } @Override public void onPrepared(MediaPlayer mp) { mediaPlayer.start(); // 开始播放 if (currentTime > 0) { // 如果音乐不是从头播放 mediaPlayer.seekTo(currentTime); } Intent intent = new Intent(); intent.setAction(MUSIC_DURATION); duration = mediaPlayer.getDuration(); intent.putExtra("duration", duration); //通过Intent来传递歌曲的总长度 sendBroadcast(intent); } } protected int getRandomIndex(int end) { int index = (int) (Math.random() * end); return index; } public class MusicReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { int control = intent.getIntExtra("control", -1); switch (control) { case 0: palyflag = 0; // 顺序播放 break; case 1: palyflag = 1; //列表循环 break; case 2: palyflag = 2; //单曲循环 break; case 3: palyflag = 3; //随机 break; default: break; // if(action.equals(SHOW_LRC)){ // current = intent.getIntExtra("listPosition", -1); // initLrc(); } } } @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub //当绑定后,返回一个musicBinder return musicBinder; } @Override public void onDestroy() { if (mediaPlayer != null) { mediaPlayer.stop(); mediaPlayer.release(); mediaPlayer = null; } } }
这些函数里面有个标识,其实有时候,我们并不想通过new一个类来处理信息,这个就是个很好的表示来解决问题。
PlayerMSG.java
package com.flashmusic.tool; /** * Created by zhouchenglin on 2016/4/18. */ public class PlayerMSG { public class MSG{ public static final int PLAY_MSG = 1; //播放 public static final int PAUSE_MSG = 2; //暂停 public static final int STOP_MSG = 3; //停止 public static final int CONTINUE_MSG = 4; //继续 public static final int PRIVIOUS_MSG = 5; //上一首 public static final int NEXT_MSG = 6; //下一首 public static final int PROGRESS_CHANGE = 7;//进度改变 public static final int PLAYING_MSG = 8; //正在播放 } }
主要的内容就这么多,现在还未完成歌词显示,还有需要解决地问题,就是需要在子线程里面更新UI,这个需要重新考虑。
这篇博客,改变了上一篇博客里面的设计思路,让我掌握了广播的使用。
参考这篇文章,我就是参考大神之后修改的,站在巨人的肩膀上看世界
源码下载
相关文章推荐
- Android 环境下编译FFmpeg
- 【Android】输入框控件EditText
- android加载大量图片内存溢出的三种解决办法
- Android中判断SD卡状态
- Android访问WEBAPI,传递json
- Android studio 百度地图开发(7)overlayManager、overlayutil应用
- Android Studio制作library(图解)
- Android中启动第三方程序的代码
- android 菜单
- android 动态设置listview gridview高度
- Android 悬浮视图
- android 关于全局变量的使用
- Android获取系统相关的信息
- Android 子activity关闭 向父activity传值
- Android App中实现图片异步加载的实例分享
- Android-Xml绘图
- Android 消息机制
- Android Window创建应用窗口
- Android学习笔记 — ShapeDrawable
- 给RecycleView定制个分割线吧。