音乐播放器实验 一、实验内容 1.使用Service实现一个简单的播放器功能,具有开始/暂停,跳转到下/上一首歌功能。实现通过一个Activity远程绑定和打开该Service. 2. 加入拖拽进度条功能,通过拖拽控制播放进度。 3.添加一个历史轨迹功能。历史轨迹包括以下数据:a.上次打开播放器的时刻;b.上次关闭播放器的时刻(以Service被关闭为准);c.上次关闭Service时,所播放的歌曲曲目以及该曲目已播放时间。请使用SharedPreference进行保存。 二、实验主要代码 1.Service实现播放器功能 …… private IBinder stub = new IMusicPlayerService.Stub() { @Override public void pause() throws RemoteException { mPlayer.pause(); }
@Override
public void resume() throws RemoteException {
mPlayer.start();
}
@Override
public void stop() throws RemoteException {
mPlayer.stop();
}
@Override
public int getDuration() throws RemoteException {
return mPlayer.getDuration();
}
@Override
public int getCurrentPosition() throws RemoteException {
return mPlayer.getCurrentPosition();
}
@Override
public void seekTo(int current) throws RemoteException {
mPlayer.seekTo(current);
}
@Override
public boolean setLoop(boolean loop) throws RemoteException {
return false;
}
@Override
public String setToNext(){
Log.i("INFO", "onClick: 切歌按钮被点击!");
currentPlaying++;
if(currentPlaying==playList.size())
currentPlaying=0;
prepareMedia();
isPausing = false;
isPlaying = true;
return nameList.get(currentPlaying);
}
@Override
public String setToPrev(){
// 重播、上切
Log.i("INFO", "onClick: 重播按钮被点击!");
if (!mPlayer.isPlaying()) { //如果没有被暂停,就不切歌
currentPlaying = --currentPlaying % playList.size();
currentPlaying--;
if(currentPlaying==-1)
currentPlaying=playList.size()-1;
}
prepareMedia();
isPausing = false;
isPlaying = true;
return nameList.get(currentPlaying);
}
@Override
public int playOrPause(){
int flag=0;
// 开始暂停
Log.i("INFO", "onClick: 开始暂停按钮被点击!");
if (!isPausing && !isPlaying) { // 暂停状态,且从未被播放
// 开始播放
prepareMedia();
isPlaying = true;
flag= 1;
} else if (isPausing && isPlaying) { // 暂停状态,且被播放过一次
// 继续播放
mPlayer.start();
flag= 2;
} else { // 播放状态
// 暂停播放
mPlayer.pause();
flag=3;
}
isPausing = !isPausing; // 切换状态
return flag;
}
@Override
public String getSongName() throws RemoteException {
return nameList.get(currentPlaying);
}
};
@Override
public void onCreate() {
Log.i(tag, "MusicService onCreate()");
//mPlayer =new MediaPlayer();
preparePlaylist();
}
@Override
public IBinder onBind(Intent intent) {
if(stub!=null)
Log.e("wocao*******","*********************************");
return stub;
}
@Override
public void onDestroy() {
if (mPlayer != null) {
mPlayer.release();
}
super.onDestroy();
}
private void preparePlaylist() {
Field[] fields = R.raw.class.getFields();
for (int count = 0; count < fields.length; count++) {
Log.i("Raw Asset", fields[count].getName());
try {
int resId = fields[count].getInt(fields[count]);
String resName=fields[count].getName();
nameList.add(resName);
playList.add(resId);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
private void prepareMedia() {
if (isPlaying) {
mPlayer.stop();
mPlayer.reset();
}
mPlayer = MediaPlayer.create(getApplicationContext(), playList.get(currentPlaying));
mPlayer.start();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i("TAG","service onUnbind");
return super.onUnbind(intent);
}
} 2.实现远程服务的aidl文件 // IMusicPlayerService.aidl package com.example.remote;
// Declare any non-default types here with import statements
interface IMusicPlayerService { String setToNext(); String setToPrev(); int playOrPause(); String getSongName(); void pause(); void resume(); void stop(); int getDuration(); int getCurrentPosition(); void seekTo(int current); boolean setLoop(boolean loop); }
3.Activity中的代码 ①实现音乐的播放 …… class OnClick implements View.OnClickListener{
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_prev:
if(control!=null){
try {
btn_play_pause.setImageResource(R.drawable.control_pause_dark); // 切换成暂停键
tv_song_name.setText(control.setToPrev());
} catch (RemoteException e) {
e.printStackTrace();
}
}
else
Log.e("TAGGGG","play");
//播放音乐
timer=null;
// timer.cancel();
addTimer();
break;
case R.id.btn_play_pause:
try {
tv_song_name.setText(control.getSongName());
} catch (RemoteException e) {
e.printStackTrace();
}
// 暂停音乐
try {
Log.i("INFO", "onClick: 开始暂停按钮被点击!");
int flag= control.playOrPause();
if(flag==1 || flag==2){
btn_play_pause.setImageResource(R.drawable.control_pause_dark); // 切换成暂停键
}
else if(flag==3){
btn_play_pause.setImageResource(R.drawable.control_play_dark); // 切换成播放键
}
else {
Log.e("TAGGGG","flag error");
}
} catch (RemoteException e) {
e.printStackTrace();
}
addTimer();
break;
case R.id.btn_next:
// 继续播放
try {
Log.i("INFO", "onClick: 切歌按钮被点击!");
btn_play_pause.setImageResource(R.drawable.control_pause_dark); // 切换成暂停键
tv_song_name.setText(control.setToNext());
} catch (RemoteException e) {
e.printStackTrace();
}
timer=null;
// timer.cancel();
addTimer();
break;
}
}
}
…… ②进度条拖拽 …… private static SeekBar sb;//进度条 //进度条拖动事件 sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if(fromUser){ try { control.seekTo(progress); } catch (RemoteException e) { e.printStackTrace(); } } }
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
try{
control.pause();
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
try{
control.resume();
}catch (Exception e){
e.printStackTrace();
}
}
});
…… ③SharedPreference保存数据与读取 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initGUI(); mSpf = super.getSharedPreferences("musicInfo",MODE_PRIVATE); SharedPreferences.Editor editor = mSpf.edit();
out.setText("上次打开时间:"+mSpf.getString("lastOpen","")
+"\n上次关闭时间:"+mSpf.getString("lastClose","")
+"\n上次曲目:"+mSpf.getString("songName","")
+"\n已播放时长:"+mSpf.getString("tv_already",""));
SimpleDateFormat sdf = new SimpleDateFormat();// 格式化时间
sdf.applyPattern("yyyy-MM-dd HH:mm:ss");// a为am/pm的标记
Date date = new Date();// 获取当前时间
// System.out.println("现在时间:" + sdf.format(date)); // 输出已经格式化的现在时间(24小时制) editor.putString("lastOpen",sdf.format(date)); editor.commit(); }
@Override protected void onDestroy() { mSpf = super.getSharedPreferences("musicInfo",MODE_PRIVATE); SharedPreferences.Editor editor = mSpf.edit();
SimpleDateFormat sdf = new SimpleDateFormat();// 格式化时间
sdf.applyPattern("yyyy-MM-dd HH:mm:ss");// a为am/pm的标记
Date date = new Date();// 获取当前时间
editor.putString("lastClose",sdf.format(date));
editor.putString("songName",tv_song_name.getText().toString());
editor.putString("tv_already",tv_already.getText().toString());
editor.commit();
timer=null;
unbindService(conn);
super.onDestroy();
}
三、实验收获 1、学习了AIDL的使用,它是用于进程间的通信的一种语言,需要先在服务端定义.aidl文件,编译后会在gen目录下生成对应的java文件。然后需要把服务端的aidl文件复制到客户端名字相同的包下面,编译器会根据AIDL文件为我们生成一个与AIDL文件同名的 .java 文件。基本的操作流程就是:在服务端实现AIDL中定义的方法接口的具体逻辑,然后在客户端调用这些方法接口,从而达到跨进程通信的目的。 2、学习了Android MediaPlayer的使用方法,这是一个是一个流媒体操作类,提供了相应的方法来直接操作流媒体,例如void statr():开始或恢复播放,void stop():停止播放,void pause():暂停播放。本次实验还用到了int getDuration()和int getCurrentPosition()来制作进度条。 3、学习了SharedPreference的使用,这是一种轻量级的数据存储方式,以键值对的方式存储,通过Activity自带的getSharedPreferences方法,得到SharedPreferences对象,然后用putString()方法把相关的信息存进去,还要调用commit()方法。用getString()取出存储的信息。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。