Android多媒体——播放音频
2015-09-09 21:00
711 查看
在Android中播放音频文件一般使用MediaPlayer类来实现,它对多种格式的音频文件提供了非常全面的控制方法,从而使得播放音乐的工作变得简单
setDataSource():设置要播放的音频文件的位置
prepare():在开始播放之前调用这个方法完成准备工作
start():开始或继续播放
pause():暂停播放
reset():将MediaPlayer对象重置到刚刚创建的状态
seekTo():从指定位置开始播放
stop():停止播放音频,调用之后MediaPlayer对象无法再播放音频
release():释放掉与MediaPlayer对象相关的资源
isPlaying():判断当前MediaPlayer是否正在播放
getDuration():获取载入的音频文件的时长
但是要实现一个功能比较齐全的仅仅靠在主活动上加点击事件是不可能的,因为还要实现音乐可以后台播放,并可以将播放过程用进度条显示在主活动上,通过拖拉进度条可以是音乐从所拖动的位置继续播放。要实现这么些功能,就需要用到Android中的服务和广播接收器。
首先搭建一个音乐播放器的主界面
ListView中的布局为
在主活动中添加三个点击事件,分别是ListView、开始暂停按钮、SeekBar进度条,还有一个广播接收器,用来接收广播并对UI上的空间进行处理。
然后既然有ListView,就需要一个Adapter类
中间获取歌曲的作者和图片的代码其实放在这里不是很合适,但是比较简单,不需要来回传递信息。
然后就需要一个后台服务类来进行后台操作,在后台中对活动中传回来的信息做相应的后台服务
setDataSource():设置要播放的音频文件的位置
prepare():在开始播放之前调用这个方法完成准备工作
start():开始或继续播放
pause():暂停播放
reset():将MediaPlayer对象重置到刚刚创建的状态
seekTo():从指定位置开始播放
stop():停止播放音频,调用之后MediaPlayer对象无法再播放音频
release():释放掉与MediaPlayer对象相关的资源
isPlaying():判断当前MediaPlayer是否正在播放
getDuration():获取载入的音频文件的时长
播放
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button mButton; private MediaPlayer player=new MediaPlayer(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton= (Button) findViewById(R.id.button_musicplay); mButton.setOnClickListener(this); mButtonPause= (Button) findViewById(R.id.button_musicpause); mButtonPause.setOnClickListener(this); player.reset(); File path= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC); File[]files=path.listFiles(); try { player.setDataSource(files[0].getAbsolutePath()); player.prepare(); player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); } }); } catch (IOException e) { e.printStackTrace(); } } }
但是要实现一个功能比较齐全的仅仅靠在主活动上加点击事件是不可能的,因为还要实现音乐可以后台播放,并可以将播放过程用进度条显示在主活动上,通过拖拉进度条可以是音乐从所拖动的位置继续播放。要实现这么些功能,就需要用到Android中的服务和广播接收器。
首先搭建一个音乐播放器的主界面
<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:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context=".MainActivity"> <ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"> </ListView> <SeekBar android:id="@+id/seekBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/textview_currenttime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="当前时间"/> <TextView android:id="@+id/textview_alltime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="总时间"/> </RelativeLayout> <Button android:id="@+id/button_musicpause" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="暂停/播放"/> </LinearLayout>
ListView中的布局为
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/imageview" android:layout_width="50dp" android:layout_height="50dp" android:src="@mipmap/ic_launcher"/> <TextView android:id="@+id/textview_artist" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="艺术家"/> <TextView android:id="@+id/textview_line" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="——"/> <TextView android:id="@+id/textview_musicname" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="歌曲名"/> </LinearLayout>
在主活动中添加三个点击事件,分别是ListView、开始暂停按钮、SeekBar进度条,还有一个广播接收器,用来接收广播并对UI上的空间进行处理。
package com.example.administrator.mymediaplayer; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.MediaPlayer; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.ListView; import android.widget.SeekBar; import android.widget.TextView; import com.example.administrator.mymediaplayer.adapter.MusicAdapter; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.logging.SimpleFormatter; public class MainActivity extends AppCompatActivity{ private Button mButton; private Button mButtonPause; private ListView mListView; private TextView mTextviewAll; private TextView mTextviewCurrent; private SeekBar mSeekBar; private File[]musics; private MediaPlayer player=new MediaPlayer(); private MusicReceiver musicReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextviewAll= (TextView) findViewById(R.id.textview_alltime); mTextviewCurrent= (TextView) findViewById(R.id.textview_currenttime); //开始暂停按钮的点击事件 mButtonPause= (Button) findViewById(R.id.button_musicpause); mButtonPause.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(getApplicationContext(),MusicService.class); intent.putExtra("type",Config.STOP_MUSIC); startService(intent); } }); //SeekBar的点击事件,将进度信息传送给后台服务 mSeekBar= (SeekBar) findViewById(R.id.seekBar); 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(),MusicService.class); intent.putExtra("type",Config.START_SEEK_TO); intent.putExtra("progress",seekBar.getProgress()); startService(intent); } }); //找到sdCard File sdCard=Environment.getExternalStorageDirectory(); //找到sdCard下的存放音乐的文件夹 File musicFiles = new File(sdCard,"Music"); //得到音乐文件夹下的所有歌曲 musics=musicFiles.listFiles(); //通过点击放置歌曲的ListView中的某一条信息使得音乐可以在后台播放 mListView= (ListView) findViewById(R.id.listview); mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent=new Intent(getApplicationContext(),MusicService.class); intent.putExtra("type",Config.START_MUSIC); //把某一首歌的路径传送给服务类 intent.putExtra("musicname",musics[position].getAbsolutePath()); //启动服务 startService(intent); } }); //定义ListView的适配器 MusicAdapter adapter=new MusicAdapter(getLayoutInflater(),musics); //将适配器加载到ListView中 mListView.setAdapter(adapter); //广播接收器的注册 musicReceiver=new MusicReceiver(); IntentFilter filter=new IntentFilter("com.music"); registerReceiver(musicReceiver,filter); } //广播接收器的取消注册 @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(musicReceiver); } //广播接收器类 class MusicReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { //接收到的广播的格式,通过不同的格式执行不同的操作 int type=intent.getIntExtra("type", Config.ALL_TIME); //定义显示歌曲播放和总时间的格式 SimpleDateFormat format=new SimpleDateFormat("mm:ss"); switch (type){ //得到歌曲的总时间,并设置进度条总的长度,作为给播放时间进度条的位置的参考 case Config.ALL_TIME: int alltime=intent.getIntExtra("alltime",Config.ALL_TIME); mSeekBar.setMax(alltime); String timeall=format.format(alltime); mTextviewAll.setText(timeall); break; //得到当前播放时间,并将其设置在进度条上 case Config.CURRENT_TIME: int time=intent.getIntExtra("time",Config.CURRENT_TIME); mSeekBar.setProgress(time); String timecurrent=format.format(time); mTextviewCurrent.setText(timecurrent); break; default: break; } } } }
然后既然有ListView,就需要一个Adapter类
package com.example.administrator.mymediaplayer.adapter; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.MediaMetadata; import android.media.MediaMetadataRetriever; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import com.example.administrator.mymediaplayer.R; import java.io.File; /** * Created by Administrator on 2015/9/10. */ 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.activity_music,null); viewHolder=new ViewHolder(); viewHolder.textView= (TextView) convertView.findViewById(R.id.textview_musicname); viewHolder.textViewArtist= (TextView) convertView.findViewById(R.id.textview_artist); viewHolder.textViewLine= (TextView) convertView.findViewById(R.id.textview_line); viewHolder.imageView= (ImageView) convertView.findViewById(R.id.imageview); convertView.setTag(viewHolder); }else { viewHolder= (ViewHolder) convertView.getTag(); } MediaMetadataRetriever metadata=new MediaMetadataRetriever(); metadata.setDataSource(musics[position].getAbsolutePath()); String artist=metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST); if (artist==null){ viewHolder.textViewArtist.setText("UnKnow"); }else { viewHolder.textViewArtist.setText(artist); } byte[]image=metadata.getEmbeddedPicture(); if (image==null){ viewHolder.imageView.setImageResource(R.mipmap.ic_launcher); }else { Bitmap bitmap= BitmapFactory.decodeByteArray(image,0,image.length); viewHolder.imageView.setImageBitmap(bitmap); } viewHolder.textView.setText(musics[position].getName()); return convertView; } class ViewHolder{ TextView textView; TextView textViewArtist; TextView textViewLine; ImageView imageView; } }
中间获取歌曲的作者和图片的代码其实放在这里不是很合适,但是比较简单,不需要来回传递信息。
然后就需要一个后台服务类来进行后台操作,在后台中对活动中传回来的信息做相应的后台服务
package com.example.administrator.mymediaplayer; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; import java.io.IOException; /** * Created by Administrator on 2015/9/10. */ public class MusicService 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_MUSIC); switch (type){ case Config.START_MUSIC: startMusic(intent); break; case Config.START_SEEK_TO: int progress=intent.getIntExtra("progress",0); player.seekTo(progress); break; case Config.STOP_MUSIC: if (player.isPlaying()){ player.pause(); }else{ player.start(); } new MusicPlayThread().start(); default: break; } return super.onStartCommand(intent, flags, startId); } private void startMusic(Intent intent) { String musicpath=intent.getStringExtra("musicname"); if (player==null){ player=new MediaPlayer(); } player.reset(); try { player.setDataSource(musicpath); player.prepare(); player.start(); } catch (IOException e) { e.printStackTrace(); } int time=player.getDuration(); Intent intent2=new Intent("com.music"); intent2.putExtra("type",Config.ALL_TIME); intent2.putExtra("alltime",time); sendBroadcast(intent2); new MusicPlayThread().start(); } //用来发送当前广播信息的线程 class MusicPlayThread extends Thread{ @Override public void run() { while (player.isPlaying()){ int currenttime=player.getCurrentPosition(); Intent intent=new Intent("com.music"); intent.putExtra("type",Config.CURRENT_TIME); intent.putExtra("time",currenttime); sendBroadcast(intent); //由于Android对时间是一毫秒计算,所以需要休眠一段时间,降低发送频率,不至于广播积压 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
相关文章推荐
- android AsyncTask详解
- Android四大组件---Service
- Android之VideoView播放视频
- android studio命令大全
- Android开发:在onTouchEvent中处理任意时间的长按事件
- Android视频播放手动切换和自动切换横竖屏冲突问题
- android待机添加电量小部件,点击位置信息图标,模式切换需要改为四种
- Android之SharedPreferences详解
- android学习笔记(20)数据流操作/文本的保存与查看
- Android 学习第6课,循环功能
- Android开发之_Menu_菜单的使用
- Android动态换肤开源库Colorful发布
- Android中的多线程
- Android Fragment 真正解析(上)
- Android用Gson解析JSON字符串
- Android用Gson解析JSON字符串
- Android多线程、Handler和AsyncTask的用法
- Android之多媒体MediaPlayer(一个简单的音乐播放器)
- Android新闻阅读器(数据抓取)
- Android之Bundle传递数据详解与实例及Bundle与SharedPreferences的区别