一 功能实现:
1,播放服务器端音频文件
2,实现play,pause,next,previous,stop功能
3,实现退出Activity后,后台继续播放音乐功能。
二 代码主要分两部分,Activity和Service。
首先看Activity,Activity里面主要功能是初始化界面及按键,启动Service,绑定Service,实现播放,暂停等控制逻辑。
主要代码如下:
启动和绑定Service:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
conn=new Conn();
service=new MusicService();
initView();
Intent intent=new Intent(MainActivity.this,MusicService.class);
startService(intent);
intent.putExtra("url",url);
bindService(intent,conn,BIND_AUTO_CREATE);
}
介绍下主要代码。Conn类是一个内部类,绑定Service需要用到,这里Conn实现了一个ServiceConnection接口接口有两个回调方法,这里我们只用到了onServiceConnected 方法,服务绑定后会回调此方法,注意这个方法是Service 里面onBind方法执行后才会调用此方法。我们在这个方法里面Service里面的binder实例,以及Service实例,这个会在接下来用到,代码如下。
class Conn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder serviceBinder) {
binder= (MusicService.MyBinder) serviceBinder;
service=binder.getService();
Log.d(TAG,"conn on service connected");
}
@Override
public void onServiceDisconnected(ComponentName name) {}}
接下来是得到了一个Service实例,并且initview初始化界面的按键,再然后是start Service启动服务。到这里也许有人会问到,Conn类里面已经得到了一个Service实例,为什么在这里又要new一个Service。注意,这两个Service实例并不是同一个实例。conn里面的实例是返回MusicService里面的实例,可以控制MusicService里面的逻辑代码。而这个Service实例并不能控制服务里面的逻辑。他的作用是让onPostResume里面的代码不报错。
再往下看,intent里面传入一个url,这个url是服务器上音乐文件地址。然后是bindService,把参数传入即可,最后一个参数是自动创建bind的意思,照写就好了。
再往下看
protected void onPostResume() {
super.onPostResume();
Log.d(TAG,"on post resume");
if(service.player.isPlaying()){
btn_start.setText("Pause");
}else
btn_start.setText("Play");
handler.post(runnable);
}
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(runnable);
unbindService(conn);
Log.d(TAG,"activity on destroy");
}
public Runnablerunnable=new Runnable() {
@Override
public void run() {
if(service.player.isPlaying()){
btn_start.setText("Pause");
}else
btn_start.setText("Play");
handler.postDelayed(runnable,100);
}
};
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(runnable);
unbindService(conn);
Log.d(TAG,"activity on destroy");
}
onPostResume里面代码主要是实现播放暂停功能,这个Service需要能控制Service里面的逻辑,然后把runnable加入到handler队列,并且没100毫秒检查一次。注意destroy里面要remove runnable,解绑Service。
以上就是Activity注意代码。
我们再看一下Service里面的代码。
class MyBinderextends Binderimplements Operation{
public MusicService getService(){
Log.d(TAG,"service load attr");
return MusicService.this;
}
@Override
public void play() {
if(player.isPlaying())
player.pause();
else
player.start();
}
在Service里面创建binder内部类,在这个类里面实现音乐播放,暂停,下一首等逻辑。并得到一个本类的实例。
@Nullable
@Override
public IBinder onBind(Intent intent) {
getUrl=intent.getStringExtra("url");
Log.d(TAG,getUrl);
player.reset();
Log.d(TAG,"on bind");
try {
player.setDataSource(getUrl);
player.setLooping(false);
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
Log.d(TAG,"media player on prepared listener");}});
player.prepareAsync();
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Log.d(TAG,"media player complete listener");
}});
}catch (IOException e) {
e.printStackTrace();
}return new MyBinder();}
onbind方法里面,我们得到了绑定Service时传入的url地址,然后初始化mediaPlayer,准备播放。
@Override
public boolean onUnbind(Intent intent) {
// if(player.isPlaying()){
// player.release();
// }
// player=null;
Log.d(TAG,"service on unbind");
return super.onUnbind(intent);
}
解绑的时候不要释放player实例,否则不能后台播放了。主要代码就这些。
上完整代码。
Activity
package bourne.com.musicdemo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivityextends AppCompatActivityimplements View.OnClickListener{
final public StringTAG="MainActivity--";
public final Stringurl="http://**/upload/app/1.flac";
private MusicServiceservice;
private MusicService.MyBinderbinder;
private Connconn;
private Buttonbtn_start,btn_pause,btn_stop,btn_next,btn_previous;
public android.os.Handlerhandler=new android.os.Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
conn=new Conn();
service=new MusicService();
initView();
Intent intent=new Intent(MainActivity.this,MusicService.class);
startService(intent);
intent.putExtra("url",url);
bindService(intent,conn,BIND_AUTO_CREATE);
}
void initView(){
btn_start = findViewById(R.id.btn_play);
// btn_pause = findViewById(R.id.btn_pause);
btn_stop=findViewById(R.id.btn_stop);
btn_next = findViewById(R.id.btn_next);
btn_previous = findViewById(R.id.btn_previous);
// btn_pause.setOnClickListener(this);
btn_stop.setOnClickListener(this);
btn_previous.setOnClickListener(this);
btn_next.setOnClickListener(this);
btn_start.setOnClickListener(this);
}
@Override
protected void onPostResume() {
super.onPostResume();
Log.d(TAG,"on post resume");
if(service.player.isPlaying()){
btn_start.setText("Pause");
}else
btn_start.setText("Play");
handler.post(runnable);
}
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(runnable);
unbindService(conn);
Log.d(TAG,"activity on destroy");
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_play:
Log.d(TAG,"play");
binder.play();
break;
// case R.id.btn_pause:
// binder.pause();
// break;
case R.id.btn_stop:
binder.stop();
break;
case R.id.btn_previous:
binder.previous();
break;
case R.id.btn_next:
binder.next();
break;
}
}
public Runnablerunnable=new Runnable() {
@Override
public void run() {
if(service.player.isPlaying()){
btn_start.setText("Pause");
}else
btn_start.setText("Play");
handler.postDelayed(runnable,100);
}
};
class Connimplements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder serviceBinder) {
binder= (MusicService.MyBinder) serviceBinder;
service=binder.getService();
Log.d(TAG,"conn on service connected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
Service里面代码
package bourne.com.musicdemo;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import java.io.IOException;
public class MusicServiceextends Service {
final StringTAG="music service--";
final private Stringpath="http://**/upload/app/";
StringurlPath;
private int id=1;
StringgetUrl="";
MediaPlayerplayer=new MediaPlayer();
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG,"service on create");
}
class MyBinderextends Binderimplements Operation{
public MusicService getService(){
Log.d(TAG,"service load attr");
return MusicService.this;
}
@Override
public void play() {
if(player.isPlaying())
player.pause();
else
player.start();
}
@Override
public void pause() {
if(player.isPlaying())
player.pause();
}
@Override
public void stop() {
if(player!=null) {
player.stop();
try {
player.prepare();
}catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void moveOn() {
}
@Override
public void next() {
if(player!=null&&id<3) {
id++;
urlPath=path+id+".mp3";
player.stop();
Log.d(TAG,"next: "+urlPath);
try {
player.reset();
player.setDataSource(urlPath);
player.prepare();
player.start();
}catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void previous() {
if(player!=null&&id>1){
id--;
urlPath=path+id+".mp3";
player.stop();
try {
player.reset();
player.setDataSource(urlPath);
player.prepare();
player.start();
}catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void seekToPosition() {
}
@Override
public void updataSeekbar() {
}
@Override
public void getCurrentTime() {
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
getUrl=intent.getStringExtra("url");
Log.d(TAG,getUrl);
player.reset();
Log.d(TAG,"on bind");
try {
player.setDataSource(getUrl);
player.setLooping(false);
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// mp.start();
Log.d(TAG,"media player on prepared listener");
}
});
player.prepareAsync();
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Log.d(TAG,"media player complete listener");
}
});
}catch (IOException e) {
e.printStackTrace();
}
return new MyBinder();
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG,"on destroy service");
}
@Override
public boolean onUnbind(Intent intent) {
// if(player.isPlaying()){
// player.release();
// }
// player=null;
Log.d(TAG,"service on unbind");
return super.onUnbind(intent);
}
}