Android之多媒体MediaPlayer(一个简单的音乐播放器)
2015-09-09 20:13
507 查看
音乐播放器
MediaPlayer:利用Environment.getExternalStorageDirectory()方法得到sdcard路径,然后用new File(得到的sdcard父路径,子路径)得到音乐存放路径。用File[]型的数组存放得到的所有音乐文件,接着就可以播放。
用MediaPlay需要在manifests中申请权限android.permission.READ_EXTERNAL_STORAGE。
本实例用于实现一个简单的音乐播放器,用ListView来显示音乐清单。
代码:
public class MainActivity extends Activity { private Button mButtonStart; private File[] mMusics; private ListView mMusicList; private MusicAdapter mAdapter; private LayoutInflater mInflater; private SeekBar mMusicSeekBar; private TextView mTimeText; private MusicReceiver mReceiver; private int duration; private int currentTime; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButtonStart = (Button) findViewById(R.id.button_start_music); mMusicList = (ListView) findViewById(R.id.list_view_musics); mMusicSeekBar = (SeekBar) findViewById(R.id.music_seek_bar); mTimeText = (TextView) findViewById(R.id.text_time); initMusicData(); mInflater = getLayoutInflater(); mAdapter = new MusicAdapter(mMusics,mInflater); mMusicList.setAdapter(mAdapter); mReceiver = new MusicReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction("com.music.play"); registerReceiver(mReceiver, filter); mMusicList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { changeMusic(mMusics[position]); } }); mMusicSeekBar.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) { changeProgress(); } }); } //当拖动SeekBar进度条时调用此方法,向MusicService服务发送进度条的进度,服务器收到消息后会作出让当前播放音频进度同步于进度条的操作 private void changeProgress() { Intent intent = new Intent(getApplicationContext(),MusicService.class); int progress = mMusicSeekBar.getProgress(); intent.putExtra("type", Config.CHANGE_PROGRESS); intent.putExtra("progress",progress); startService(intent); } //当点击ListView时调用该方法,向MusicService发出要更换曲目的消息 private void changeMusic(File mMusic) { Intent intent = new Intent(getApplicationContext(), MusicService.class); intent.putExtra("type", Config.CHANGE_MUSIC); intent.putExtra("musicName", mMusic.getAbsolutePath()); startService(intent); } private void initMusicData(){ //得到外部存储中音频文件存储的路径 File musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC); mMusics = musicDir.listFiles(); } //此广播***用于接收来自音乐服务的信息,并作出响应 private class MusicReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { int type = intent.getIntExtra("type",0); switch (type){ case 0: duration = intent.getIntExtra("duration",0); mMusicSeekBar.setMax(duration); //将seekBar进度条的进度容量设定为音频的长度 break; case 1: currentTime = intent.getIntExtra("time",0); mMusicSeekBar.setProgress(currentTime); mTimeText.setText(myTimeFormat(currentTime)+"/"+myTimeFormat(duration));//将seekbar的进度大小设定为当前音乐播放的进度 break; default: break; } } } @Override protected void onDestroy() { unregisterReceiver(mReceiver); } //当要将得到的音乐进度和总长度转换为XX(分):XX(秒)形式时调用该函数 public String myTimeFormat(long time){ long miao = time/1000; long fen = miao/60; long yumiao = miao%60; String backTime = ""; if(miao>0){ backTime = fen+":"+yumiao; }else{ backTime = ""+yumiao; } return backTime; } //点击后退键不停止活动 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode==KeyEvent.KEYCODE_BACK){ moveTaskToBack(false); return true; } return super.onKeyDown(keyCode, event); } }
建立一个服务Service
public class MusicService extends Service { private MediaPlayer mPlayer; @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(final Intent intent, int flags, int startId) { int type = intent.getIntExtra("type", 1 ); //判断type以完成不同的操作 switch (type) { case 0: startNewMusic(intent); break; case 1: if (mPlayer != null) { int progress = intent.getIntExtra("progress", 0); mPlayer.seekTo(progress);//设置曲目进度 } break; default: break; } return super.onStartCommand(intent, flags, startId); } //此方法用于得到被点击的音频的绝对路径并播放 private void startNewMusic(Intent intent) { String musicPath = intent.getStringExtra("musicName"); if (mPlayer == null) { mPlayer = new MediaPlayer(); } mPlayer.reset(); try { mPlayer.setDataSource(musicPath); mPlayer.prepare(); mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); int duration = mPlayer.getDuration();//得到总的播放的时间 Intent intent = new Intent("com.music.play"); intent.putExtra("type", 0); intent.putExtra("duration", duration); sendBroadcast(intent); MusicPlayThread musicPlayThread = new MusicPlayThread(); musicPlayThread.start(); } }); } catch (IOException e) { e.printStackTrace(); } } //这个线程用于发送音乐播放的进度,理论上每1秒发送一次 class MusicPlayThread extends Thread { @Override public void run() { while (mPlayer.isPlaying()) { int time = mPlayer.getCurrentPosition();//得到当前播放的时间 Intent intent = new Intent("com.music.play"); intent.putExtra("type", 1); intent.putExtra("time", time); sendBroadcast(intent); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } @Override public void onDestroy() { super.onDestroy(); } }
MusicListView的adapter
public class MusicAdapter extends BaseAdapter { private File[] mMusics; private LayoutInflater mInflater; public MusicAdapter(File[] mMusics, LayoutInflater mInflater) { this.mMusics = mMusics; this.mInflater = mInflater; } @Override public int getCount() { return mMusics.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 vh = null; if(convertView==null){ convertView = mInflater.inflate(R.layout.music_item,null); vh = new ViewHolder(); vh.musicName = (TextView) convertView.findViewById(R.id.text_music_name); vh.artistImage = (ImageView)convertView.findViewById(R.id.image_artist); vh.artistName = (TextView) convertView.findViewById(R.id.text_artist_name); convertView.setTag(vh); }else{ vh = (ViewHolder) convertView.getTag(); } String musicName = mMusics[position].getName(); vh.musicName.setText(musicName); //MediaMetadataRetriever用于得到音乐文件的一些信息,如图片,艺术家等 MediaMetadataRetriever mmr = new MediaMetadataRetriever(); //MediaMetadataRetriever不能加载非音频文件,否则会出错 mmr.setDataSource(mMusics[position].getAbsolutePath()); //得到歌手名 String author = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST); if(author!=null){ vh.artistName.setText(author); }else{ vh.artistName.setText("<未知>"); } //得到音乐的图片,但很多音频文件不含图片 byte[] image = mmr.getEmbeddedPicture(); if(image!=null){ Bitmap bitmap = BitmapFactory.decodeByteArray(image,0,image.length); vh.artistImage.setImageBitmap(bitmap); }else{ vh.artistImage.setImageResource(R.mipmap.photo_nomal); } return convertView; } class ViewHolder{ ImageView artistImage; TextView musicName; TextView artistName; } }
布局
<LinearLayout <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"> <ListView android:id="@+id/list_view_musics" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:layout_marginRight="15dp"> </ListView> <Button android:id="@+id/button_start_music" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" android:text="开始音乐"/> <SeekBar style="?android:attr/seekBarStyle" android:id="@+id/music_seek_bar" android:layout_width="match_parent" android:layout_height="wrap_content"/> <TextView android:id="@+id/text_time" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingRight="15dp" android:gravity="right"/> </LinearLayout>
music_item
<?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:gravity="center_vertical" android:padding="15dp"> <ImageView android:id="@+id/image_artist" android:layout_width="30dp" android:layout_height="30dp"/> <TextView android:id="@+id/text_music_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" android:layout_marginLeft="20dp"/> <TextView android:id="@+id/text_artist_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp"/> </LinearLayout>
结果展示:
相关文章推荐
- Android新闻阅读器(数据抓取)
- Android之Bundle传递数据详解与实例及Bundle与SharedPreferences的区别
- Android的进程Hnadler与AsyncTask
- Android0908<十三>(部分Service、 ContentProvider、 BroadcastReceiver)
- Android经常使用的布局类整理(一)
- Android使用XLog打印与收集程序运行详细日志
- android-------截屏的两种方法
- Android的AsyncTask和数据存储
- android 运行时找不到id异常
- Service IntentService Android中的线程 MediaPlayer
- adt环境下,手机连接电脑测试android,logcat输出停不下来
- 解决Android使用SurfaceView播放视频结束后黑屏问题
- Android视觉规范-间距规范与文字规范单位换算(dip、sp与px)
- Android InsetDrawable
- Android Service——活动和服务进行通信
- Android JSON(Fastjson,Gson)
- 15_09_18 Android 程序结构图
- Android中自定义组合控件
- Android进程间通信之使用Messenger
- Android客户端支付宝支付