播放音频
在Android中播放音频文件一般都是使用MediaPlayer类来实现的,它对多种格式的音频文件提供了非常全面的控制方法,从而使得播放音乐的工作变得十分简单。
下面列出MediaPlayer类中一些较为常用的控制方法。
方法名 | 功能描述 |
---|---|
setDataSource() | 设置要播放的音频文件的位置。 |
prepare() | 在开始播放之前调用这个方法完成准备工作。 |
start() | 开始或继续播放音频。 |
pause() | 暂停播放音频。 |
reset() | 将MediaPlayer对象重置到刚刚创建的状态。 |
seekTo() | 从指定的位置开始播放音频。 |
stop() | 停止播放音频,调用这个方法后的MediaPlayer对象无法再播放音频。 |
release() | 释放掉与MediaPlayer对象相关的资源。 |
isPlaying() | 判断当前MediaPlayer是否正在播放音频。 |
getDuration() | 获取载入的音频文件的时长。 |
MediaPlayer的工作流程
>
首先要创建出一个MediaPlayer对象,然后调用setDataSource()方法来设置音频文件的路径,再调用prepare()方法是MediaPlayer进入到准备状态,接下来调用start()方法就可以开始播放音频,调用pause()方法就会暂停播放,调用reset()方法就会停止播放。
主函数
public class MainActivity extends AppCompatActivity {
private Button mButtonStartMusic;
private SeekBar mseekBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButtonStartMusic = (Button) findViewById(R.id.button_player);
mButtonStartMusic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaPlayer player = new MediaPlayer();
player.reset();
Log.d("music", "" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath());
File musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);//得到Music文件在外部存储卡中的位置,它是File类型
// File[] files=musicDir.listFiles();//用for-each循环来遍历一遍music中的音乐文件
// for (File file:files) {
// Log.d("music1",""+file.getAbsolutePath());
// }
File hongmeigui = new File(musicDir, "hongmeigui.mp3");
try {
// player.setDataSource(files[1].getAbsolutePath());
player.setDataSource(hongmeigui.getAbsolutePath());
player.prepare();//在准备状态以后设置一个监听事件来防止直接开始调用start()引起的错误
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
特别注意:要在manifests中加上权限——
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
布局
<Button
android:id="@+id/button_player"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="播放音乐"/>
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
这里SeekBar是用来显示播放进度的
随机播放音乐
#
public class MainActivity extends AppCompatActivity {
private Button mButtonStartMusic;
private ListView mlistView;
private File[] musics;
private Random random;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
random=new Random();
mButtonStartMusic = (Button) findViewById(R.id.button_player);
mlistView= (ListView) findViewById(R.id.listview);
File sdcard=Environment.getExternalStorageDirectory();//得到外部存储位置
File musicDir=new File(sdcard,"/aa");
Log.d("music", musicDir.getAbsolutePath());
musics=musicDir.listFiles();
for (File music:musics){
Log.d("music",music.getName()+" "+music.getAbsolutePath());
}
mButtonStartMusic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MediaPlayer player = new MediaPlayer();
player.reset();
Log.d("music", "" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath());
try {
player.setDataSource(musics[random.nextInt(musics.length)].getAbsolutePath());
player.prepare();//在准备状态以后设置一个监听事件来防止直接开始调用start()引起的错误
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
模仿天天动听的音乐播放界面
主函数
public class MainActivity extends AppCompatActivity {
private Button mButtonStartMusic;
private LayoutInflater mInflater;
private ListView mlistView;
private File[] musics;
private Random random;
private SeekBar mSeekBar;
private MyReceiver receiver;
private TextView mTextViewAll;
private TextView mTextViewCurrent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
receiver=new MyReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction("com.example.play.music");
registerReceiver(receiver, filter);
mButtonStartMusic = (Button) findViewById(R.id.button_player);
mTextViewAll= (TextView) findViewById(R.id.textview_all_time);
mTextViewCurrent= (TextView) findViewById(R.id.textview_current_time);
mlistView= (ListView) findViewById(R.id.listview);
mSeekBar= (SeekBar) findViewById(R.id.seekbar);
File sdcard=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);//得到外部存储位置
// File musicDir=new File(sdcard,"/Music");
Log.d("music", sdcard.getAbsolutePath());
musics=sdcard.listFiles();
// for (File music:musics){
// Log.d("music",music.getName()+" "+music.getAbsolutePath());
//
// }
mInflater=getLayoutInflater();
MusicAdapter adapter=new MusicAdapter(mInflater,musics);
mlistView.setAdapter(adapter);
mlistView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(getApplicationContext(), MyService.class);
intent.putExtra("type",Config.START_NEW_MUSIC);
intent.putExtra("musicName", musics[position].getAbsolutePath());
startService(intent);
}
});
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
Intent intent=new Intent(getApplicationContext(),MyService.class);
intent.putExtra("type",Config.MUSIC_SEEK_TO);
intent.putExtra("progress",seekBar.getProgress());
startService(intent);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
int type=intent.getIntExtra("type",0);
switch (type){
case 0:
int duration=intent.getIntExtra("duration",0);
mTextViewAll.setText(""+duration);
mSeekBar.setMax(duration);
break;
case 1:
int currentTime=intent.getIntExtra("duration",0);
mTextViewCurrent.setText(""+currentTime);
mSeekBar.setProgress(currentTime);
break;
}
}
}
}
MusicAdapter
public class MusicAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private File[] musics;
public MusicAdapter(LayoutInflater mInflater, File[] musics) {
this.mInflater = mInflater;
this.musics = musics;
}
@Override
public int getCount() {
return musics.length;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder=null;
if (convertView==null){
convertView=mInflater.inflate(R.layout.list_view,null);
viewHolder=new ViewHolder();
viewHolder.textviewName= (TextView) convertView.findViewById(R.id.textview);
viewHolder.imageview= (ImageView) convertView.findViewById(R.id.imageview);
viewHolder.textviewSinger= (TextView) convertView.findViewById(R.id.textview_sing);
convertView.setTag(viewHolder);
}
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.textviewName.setText(musics[position].getName());
MediaMetadataRetriever mnr=new MediaMetadataRetriever();
mnr.setDataSource(musics[position].getAbsolutePath());
String singer=mnr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
if (singer!=null){
viewHolder.textviewSinger.setText(singer);
}else{
viewHolder.textviewSinger.setText("<未知>");
}
byte [] image=mnr.getEmbeddedPicture();
if (image!=null){
Bitmap bitmap= BitmapFactory.decodeByteArray(image,0,image.length);
viewHolder.imageview.setImageBitmap(bitmap);
}
else{
viewHolder.imageview.setImageResource(R.mipmap.ic_launcher);
}
return convertView;
}
class ViewHolder{
TextView textviewName;
ImageView imageview;
TextView textviewSinger;
}
}
MyService
public class MyService extends Service {
private MediaPlayer player;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
int type=intent.getIntExtra("type",Config.START_NEW_MUSIC);
switch (type){
case Config.START_NEW_MUSIC:
StartNewMusic(intent);
break;
case Config.MUSIC_SEEK_TO:
if (player!=null){
int progress=intent.getIntExtra("progress",0);
// player.pause();
player.seekTo(progress);
player.start();
}
break;
}
return super.onStartCommand(intent, flags, startId);
}
private void StartNewMusic(Intent intent) {
String musicPath=intent.getStringExtra("musicName");
if (player==null){
player=new MediaPlayer();
}
else{
player.stop();
}
player.reset();
try {
player.setDataSource(musicPath);
player.prepare();
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
int duration=player.getDuration();//得到总时长
Intent intent=new Intent("com.example.play.music");
intent.putExtra("type",0);
intent.putExtra("duration", duration);
sendBroadcast(intent);
MusicPlayThread thread=new MusicPlayThread();
thread.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
class MusicPlayThread extends Thread{
@Override
public void run() {
while(player.isPlaying()){
int time=player.getCurrentPosition();
Intent intent=new Intent("com.example.play.music");
intent.putExtra("type",1);
intent.putExtra("duration",time);
sendBroadcast(intent);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
常量放置类Config
public class Config {
public static final int START_NEW_MUSIC=0;
public static final int MUSIC_SEEK_TO=1;
}
activity布局
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity">
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1">
</ListView>
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<Button
android:id="@+id/button_player"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="播放音乐"
android:layout_gravity="bottom"/>
<TextView
android:id="@+id/textview_all_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="总时长"/>
<TextView
android:id="@+id/textview_current_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="当前时间数"/>
</LinearLayout>
</LinearLayout>
list_view布局
<?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">
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:gravity="center"
android:textColor="#0000ff"
/>
<ImageView
android:id="@+id/imageview"
android:layout_width="50dp"
android:layout_height="50dp"
/>
<TextView
android:id="@+id/textview_sing"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="演唱者"/>
</LinearLayout>
特别注意:在manifests中要加权限
*<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
和<service android:name=".MyService"></service>
*