媒体播放之MediaPlayer|三种媒体源|音乐播放器源码|服务中使用|前台运行|处理音频|检索本地歌曲焦点
2017-09-04 11:00
696 查看
简介
详解传送门:http://blog.csdn.net/hejjunlin/article/details/52349221大家好我们今天研究的是Android中很重要也最为复杂的媒体播放器—MediaPlayer.Android的MediaPlayer包含了Audio和video的播放功能,
在Android的界面上,Music和Video两个应用程序都是调用MediaPlayer实现的。
官方原图
另外翻译了整张图,不敢独享,献给大家:
MediaPlayer类可用于控制音频/视频文件和流的播放或回放(playback)。 1.状态图: idle表示空闲的意思,音频/视频文件和流的播放控制是使用一个状态机进行管理。下图显示了生命周期,并支持播放控制操作驱动的MediaPlayer对象的状态。椭圆表示一个MediaPlayer对象可以驻留在的状态。所述弧线表示驱动对象的状态过渡的重放控制操作。有两种类型的弧线。具有单箭头头部的弧线表示同步方法调用,而那些与双箭头表示异步方法调用。
MediaPlayer播放三种媒体源的播放方式
注意如果你要访问网络就要添加网络的权限:<uses-permission android:name=”android.permission.INTERNET”/>
package com.example.kaifaceshi; import java.io.IOException; import android.R.string; import android.app.Activity; import android.media.MediaPlayer; import android.media.MediaPlayer.OnPreparedListener; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.view.View; public class mediapalyer extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.mediaplayer); } //播放本地资源文件 public void button1(View v) { MediaPlayer mp=MediaPlayer.create(this,R.raw.music2); mp.start(); } //播放系统资源文件 public void button2(View v) { MediaPlayer mp=new MediaPlayer(); String path=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)+"/music.mp3"; try { mp.setDataSource(this,Uri.parse(path)); mp.prepare(); mp.start(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //播放网络资源文件 public void button3(View v) { String s="http://sc1.111ttt.com:8282/2017/1/05/09/298092042172.mp3?tflag=1504463364&pin=2801bde72cb71934f7a67ea7b3049202"; MediaPlayer mp=new MediaPlayer(); try { mp.setDataSource(this,Uri.parse(s)); mp.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { // TODO Auto-generated method stub mp.start(); } }); mp.prepareAsync(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
简单的音乐播放器源码
效果图:package com.example.simplemediaplkay; import java.io.IOException; import java.util.ArrayList; import android.app.Activity; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; import android.media.MediaPlayer.OnPreparedListener; import android.os.Bundle; import androi 4000 d.os.Environment; import android.view.View; import android.view.View.OnClickListener; import android.view.animation.Animation; import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; /* * 此类实现了: * OnClickListener//当按钮点击后调用此监听 * OnPreparedListener//当异步解析完成后调用此监听 * OnErrorListener//当播放错误后掉用此监听 * OnCompletionListener//当播放完音乐后调用此监听 */ public class MainActivity extends Activity implements OnClickListener, OnPreparedListener,OnErrorListener,OnCompletionListener{ private ImageView iv; private Button button_play,button_pause,button_next,button_up; private MediaPlayer mp; //表示当前要播放音乐的索引 private int index=0; //控制当前的播放状态 true表示暂停状态 ,false表示播放状态 private boolean isPause=false; ArrayList<String> musicList=new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mp=new MediaPlayer(); initUI(); initMusecList(); mp.setOnPreparedListener(this); mp.setOnErrorListener(this); mp.setOnCompletionListener(this); //设置旋转动画 iv=(ImageView) findViewById(R.id.imageView1); //用Java code实现 RotateAnimation rotate = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); LinearInterpolator lin = new LinearInterpolator(); rotate.setInterpolator(lin); rotate.setDuration(1500);//设置动画持续时间 rotate.setRepeatCount(-1);//设置重复次数 rotate.setFillAfter(true);//动画执行完后是否停留在执行完的状态 rotate.setStartOffset(10);//执行前的等待时间 iv.setAnimation(rotate); } //初始化音乐添加到集合中去 private void initMusecList() { String musicPath=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getPath(); musicList.add(musicPath+"/"+"list1.mp3"); musicList.add(musicPath+"/"+"list2.mp3"); musicList.add(musicPath+"/"+"list3.mp3"); musicList.add(musicPath+"/"+"list4.mp3"); musicList.add(musicPath+"/"+"list5.mp3"); musicList.add(musicPath+"/"+"list6.mp3"); musicList.add(musicPath+"/"+"list7.mp3"); musicList.add(musicPath+"/"+"list8.mp3"); musicList.add(musicPath+"/"+"list9.mp3"); musicList.add(musicPath+"/"+"list10.mp3"); } //初始化音乐 private void initUI() { button_play=(Button) findViewById(R.id.play); button_pause=(Button) findViewById(R.id.pause); button_next=(Button) findViewById(R.id.next); button_up=(Button) findViewById(R.id.up); //注册按钮的事件 button_play.setOnClickListener(this); button_pause.setOnClickListener(this); button_next.setOnClickListener(this); button_up.setOnClickListener(this); } //*********************主按钮点击判断方法********************* @Override public void onClick(View v) { switch (v.getId()) { case R.id.play://点击播放按钮 //状态1(第一次播放状态) 状态2(播放暂停状态) paly(); Toast.makeText(getApplicationContext(), index+"", 1000).show(); break; case R.id.pause://点击暂停按钮 pause(); Toast.makeText(getApplicationContext(), index+"", 1000).show(); break; case R.id.next://点击下一首按钮 next(); Toast.makeText(getApplicationContext(), index+"", 1000).show(); break; case R.id.up://点击上一首按钮 up(); Toast.makeText(getApplicationContext(), index+"", 1000).show(); break; } } //*********************自己写的播放状态监测方法*************** //播放方法 private void paly() { if(isPause) { mp.start();//如果是暂停状态直接开始播放 isPause=false;//是否为暂停状态 }else { start();//调用start方法 } } //重头开始播放音乐 private void start() { if(index<musicList.size()) { if(mp.isPlaying())mp.stop();//如果现在正在播发,就先停止 mp.reset();//重置一下 String musicPath=musicList.get(index);//从集合中获取音乐播放路径 try { mp.setDataSource(musicPath); //异步加载 mp.prepareAsync(); isPause=false;//是否为暂停状态 } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } //暂停方法 private void pause() { if(mp.isPlaying()) { mp.pause(); isPause=true;//把是否为暂停状态设置为true; } } //下一首方法 private void next() { if(index+1<musicList.size()) { index++; }else { index=0; } start(); } //上一首方法 private void up() { if(index-1>=0) { index--; }else { index=musicList.size()-1; } start(); } //****************************************************** @Override public boolean onError(MediaPlayer mp, int what, int extra) { //如果播放错误了我们就直接调用重置的方法 mp.reset(); return true; } @Override public void onPrepared(MediaPlayer mp) { //当异步加载完成 mp.start(); } @Override public void onCompletion(MediaPlayer mp) { //如果播放完成了我们就直接调用播放下一首的方法 next(); } //当Activity销毁了我们释放资源 @Override protected void onDestroy() { super.onDestroy(); if(mp!=null) { if(mp.isPlaying())mp.stop(); mp.release();//释放资源 } } }
服务中使用MediaPlayer
MainActivity.javapackage com.example.sevicesmediaplayer; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void play(View v) { Intent intent=new Intent("com.music.ACTION_PLAY"); startService(intent); } public void pause(View v) { Intent intent=new Intent("com.music.ACTION_PAUSE"); startService(intent); } public void exit(View v) { Intent intent=new Intent("com.music.ACTION_EXIT"); startService(intent); } }
MusicService.java
package com.example.sevicesmediaplayer; import java.io.IOException; import android.app.Service; import android.content.Context; import android.content.Intent; import android.media.MediaPlayer; import android.media.MediaPlayer.OnPreparedListener; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.WifiLock; import android.os.Environment; import android.os.IBinder; import android.os.PowerManager; /* * 注意!!!如果你要给MediaPlayer加锁那么你要添加以下全限,不然会报错 * * <uses-permission android:name="android.permission.WAKE_LOCK"/> */ public class MusicService extends Service implements OnPreparedListener{ public static final String ACTION_PLAY="com.music.ACTION_PLAY"; public static final String ACTION_PAUSE="com.music.ACTION_PAUSE"; public static final String ACTION_EXIT="com.music.ACTION_EXIT"; private MediaPlayer mp; WifiLock lock; public MusicService() { } @Override public void onCreate() { super.onCreate(); mp=new MediaPlayer(); //给MediaPlayer加CPU锁 //保持CPU正常运转 mp.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);; //给MediaPlayer加WIFI锁 //保持WIFI不被休眠 WifiManager manager=(WifiManager) getSystemService(Context.WIFI_SERVICE); lock=manager.createWifiLock("mylock"); lock.acquire(); mp.setOnPreparedListener(this); } //再次方法中触发相应的事件 @Override public int onStartCommand(Intent intent, int flags, int startId) { String action=intent.getAction(); if(ACTION_PLAY.equals(action)) { mp.reset(); try { mp.setDataSource(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)+"/"+"list1.mp3"); mp.prepareAsync(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }else if(ACTION_PAUSE.equals(action)) { if(mp.isPlaying())mp.pause(); }else if(ACTION_EXIT.equals(action)) { if(mp.isPlaying())mp.stop(); mp.release(); } return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onPrepared(android.media.MediaPlayer mp) { mp.start(); } @Override public void onDestroy() { super.onDestroy(); //释放MediaPlayer的锁 lock.release(); } }
XML文件
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.sevicesmediaplayer.MainActivity" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/button1" android:layout_centerHorizontal="true" android:text="play" android:onClick="play"/> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@+id/button1" android:layout_below="@+id/button1" android:layout_marginTop="89dp" android:text="pause" android:onClick="pause"/> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/button2" android:layout_alignParentBottom="true" android:layout_marginBottom="102dp" android:text="exit" android:onClick="exit"/> </RelativeLayout>
注册服务
<service android:name=".MusicService" android:process=":music"> <intent-filter > <action android:name="com.music.ACTION_PLAY"/> <action android:name="com.music.ACTION_PAUSE"/> <action android:name="com.music.ACTION_EXIT"/> </intent-filter> </service>
添加加锁权限
<uses-permission android:name="android.permission.WAKE_LOCK"/>
作为前台运行
前台服务是哪些被认为用户知道的并且在内存低的时候不允许系统杀死的服务。前台服务必须给状态栏提供一个通知,他被放到了“正在进行中(Ongoing)”标题之下,这就意味着直到这个服务被终止或从前台删除通知才能被解除。例如,一个播放音乐的音乐播放器服务应该被设置在前台运行,因为用户明确的知道它们的操作。状态栏中的通知可能指明了当前的歌曲,并且用户启动一个跟这个音乐播放器交互的Activity。
//发送作为前台通知的方法 private void nitification() { //发送一个通知 Notification.Builder builder=new Notification.Builder(this); builder.setTicker("我的第一个音乐播放器"); builder.setSmallIcon(R.id.action_settings); builder.setContentInfo("正在播放"); builder.setContentTitle("音乐播放器"); Intent intent=new Intent(this,MainActivity.class); PendingIntent pi=PendingIntent.getActivity(this,0, intent,PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(pi); NotificationManager nm=(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); Notification notifi=builder.build(); //设置为前台通知!!! startForeground(0, notifi); //发送通知 nm.notify(0,notifi); }
处理音频焦点
简介
在给定的时间尽管只有一个活动可以运行,但Android是一个多任务环境。这对应用程序使用音频造成了一个特别大的难度,由于只有一个音频输出,可能会有好几个媒体服务争夺使用它。Android 2.2之前,没有内置机制来解决这个问题,这可能在某些情况下导致糟糕的用户体验。例如,一个用户正在听音乐,同时另一个应用程序有很重要的事需要通知用户,由于吵闹的音乐用户可能不会听到提示音。从Android 2.2开始,Android平台为应用程序提供了一个方式来协商设备的音频输出,这个机制被称为音频焦点。
当您的应用程序需要输出音频,如音乐或一个通知,这时你就必须请求音频焦点。一旦得到焦点,它就可以自由的使用声音输出设备,同时它会不断监听焦点的更改。如果它被通知已经失去了音频焦点,它会要么立即杀死音频或立即降低到一个安静的水平(被称为“ducking”——有一个标记,指示哪一个是适当的)当它再次接收焦点时,继续不断播放。
音频焦点是自然的合作,应用程序都期望(强烈鼓励)遵守音频焦点指南,但规则并不是系统强制执行的。如果应用程序失去音频焦点后想要播放嘈杂的音乐,在系统中没有什么会阻止他。然而,这样可能会让用户有更糟糕的体验,并可能卸载这运行不当的应用程序。
请求音频焦点,您必须从AudioManager调用requestAudioFocus()方法
使用ContentResolver检索本地歌曲
public void showMusiclist(View v){ ContentResolver cr=getContentResolver(); Cursor c=cr.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,null, null, null, null); if(c!=null) { while(c.moveToNext()) { String musicPath=c.getString(c.getColumnIndex(MediaStore.Audio.Media.DATA)); String musicName=c.getString(c.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME)); String artist=c.getString(c.getColumnIndex(MediaStore.Audio.Media.ARTIST)); String duration=c.getString(c.getColumnIndex(MediaStore.Audio.Media.DURATION)); System.out.println("路径"+musicPath); System.out.println("歌名"+musicName); System.out.println("歌手"+artist); System.out.println("时常/毫秒:"+artist); System.out.println("----------------------"); } } }
相关文章推荐
- MediaPlayer(媒体播放器) 示例,播放音频(内存、网络、本地)
- Android 本地音频播放 MediaPlayer使用方法
- 牛腩购物11:完善用户注册 onblur 失去焦点 jquery ajax post方式使用 一般处理程序 判断用户是否存在 前台js的应用
- [转载][重要]使用Vitamio打造自己的Android万能播放器(10)—— 本地播放 (缩略图、视频信息、视频扫描服务)
- [重要]使用Vitamio打造自己的Android万能播放器(10)—— 本地播放 (缩略图、视频信息、视频扫描服务)
- 使用startForeground让android服务前台运行
- MediaPlayer使用之一 音频播放
- 使用MediaPlayer播放音频
- IOS三种播放音频的方式:AVAudioPlayer、音频服务、音频队列。
- 使用MediaPlayer播放音频
- IOS中有三种播放音频的方式:AVAudioPlayer、音频服务、音频队列。
- 01.Android之多媒体--使用MediaPlayer播放音频02
- 一个使用WINDOWS媒体库的WAV音频文件播放的示例
- Android之多媒体使用——MediaPlayer播放音频
- Android开发:使用AudioTrack播放PCM音频数据【附源码】
- windows7添加打印机时,提示“本地打印机后台处理程序服务没有运行”
- windows7安装打印机提示“本地打印后台处理程序服务没有运行”
- 使用Vitamio打造自己的Android万能播放器(10)—— 本地播放 (缩略图、视频信息、视频扫描服务)
- 本地音乐播放器MediaPlayer获取所有歌曲信息,getContentResolver()
- android学习笔记---43_音乐播放器,音频采集,音乐播放,使用SoundPool播放音效