关于Android中Service与Activity的信息交互

来源:互联网 发布:秘鲁域名后缀 编辑:程序博客网 时间:2024/04/30 10:37

Android中信息交互大致有两种方式:
1. 使用intent在service和activity之间不停地传递信息
2. 使用bindService实现, 这里有两种实现方式, 在重写service当中的onBind方法是, 一种方式是通过实现一个Binder接口, 通过在这个接口中的实现一个getService方法返回service.this实现, 另一种方法是使用aidl这种接口来实现.
现在截取部分代码:
第一种实现方式
Service中代码
class MBinder extends Binder {
MyService getService(){

return MyService.this;
}
}
//切记此处需要进行初始化
private MBinder mBinder = new MBinder();

第二种实现方式
Service中代码:
public int playMusic() throws android.os.RemoteException {
Log.i("CHEN","Play music");
//创建音乐播放器
if(mp == null) {
mp = MediaPlayer.create(MyService.this, R.raw.today);
mp.stop();
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.start();
isStart = true;
return CREATE;
} else if(!isStart) {
mp.stop();
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.start();
isStart = true;
return START;
} else if(mp.isPlaying()) {
mp.pause();
return PAUSE;
} else {
mp.start();
return PLAY;
}

}
public void stopMusic() throws android.os.RemoteException {
Log.i("CHEN", "Stop music");
if(mp.isPlaying()) {
isStart = false;
mp.stop();
}
}

public int getCondition() throws android.os.RemoteException {
if(mp == null)
return UNCREATE;
else if(!isStart)
return STOP;
else if(!mp.isPlaying())
return PAUSE;
else
return PLAY;
}
};

@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
Log.v("MyService", "Bind");
return binder;
}
.aidl接口定义
//切记此处需要指明包名
package android.mp3player;
interface MusicControlService
{
int playMusic();
void stopMusic();
int getCondition();
}

在解决了信息交互的问题后, 仍存在一个容易忽视的问题, 你的Service如何被多次创建的activity取得而不是在创建新的service, 也就是说怎么样实现在一个activity被关闭后再次打开仍能够取得你之前创建的service.
这里有一个小技巧.
通过为activity和service中主要方法(onCreate, onStart, bindService, unBindService, reBind等添加log.v()的日志输出命令) 我们可以观察到整个程序的执行顺序:
activityCreate, activityStart, bindService, serviceCreate, serviceStart, activityUnBind, activityStop, activityDestroy.
这个周期中我没有调用startService方法, 而是只是用了bindService方法, 它自动调用了service的Create, Start方法, 也就是说这样会再次创建一个Service.
想要取得之前创建的Service, 达到创建一次, 使用多次的目的, 需要直接调用startActivity方法, 同时重写Service中unbind方法和rebind方法. 这次当activity调用startService方法的时候会自动判断是否存在以创建的Service, 然后调用rebind方法取得这个对象.
粘贴代码如下
Service中
package android.mp3player;
import java.io.IOException;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {

public static final int CREATE = 0;
public static final int START = 1;
public static final int PAUSE = 2;
public static final int PLAY = 3;
public static final int STOP = 4;
public static final int UNCREATE = 5;

private final MusicControlService.Stub binder = new MusicControlService.Stub()
{
MediaPlayer mp;
boolean isStart;

public int playMusic() throws android.os.RemoteException {
Log.i("CHEN","Play music");
//创建音乐播放器
if(mp == null) {
mp = MediaPlayer.create(MyService.this, R.raw.today);
mp.stop();
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.start();
isStart = true;
return CREATE;
} else if(!isStart) {
mp.stop();
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.start();
isStart = true;
return START;
} else if(mp.isPlaying()) {
mp.pause();
return PAUSE;
} else {
mp.start();
return PLAY;
}

}
public void stopMusic() throws android.os.RemoteException {
Log.i("CHEN", "Stop music");
if(mp.isPlaying()) {
isStart = false;
mp.stop();
}
}

public int getCondition() throws android.os.RemoteException {
if(mp == null)
return UNCREATE;
else if(!isStart)
return STOP;
else if(!mp.isPlaying())
return PAUSE;
else
return PLAY;
}
};

@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
Log.v("MyService", "Bind");
return binder;
}

@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.v("MyService", "Create");
}

@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Log.v("MyService", "Unbind");
return true;
}

@Override
public void onRebind(Intent intent) {
// TODO Auto-generated method stub
super.onRebind(intent);
Log.v("MyService", "Rebind");
}

}
Activity当中
package android.mp3player;
import java.io.IOException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
public class Mp3Player extends Activity {
private Context mContext;
private ImageButton bt1;
private ImageButton bt2;
private Intent intent;
public MusicControlService musicControlService;
private ServiceConnection sc;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bt1 = (ImageButton) findViewById(R.id.iButton01);
bt2 = (ImageButton) findViewById(R.id.iButton02);
bt1.setBackgroundResource(R.drawable.ibtbg);
bt2.setBackgroundResource(R.drawable.ibtbg);
mContext = this;

//将Mp3Player与MyService绑定
intent = new Intent(mContext, MyService.class);
sc = new ServiceConnection() {
public void onServiceConnected(ComponentName arg0, IBinder iBinder) {
// TODO Auto-generated method stub
musicControlService = MusicControlService.Stub.asInterface(iBinder);
//如果希望程序能够取得Service中的信息, 请将代码写在ServiceConnected方法中, 写在外部 onCreate
//或是 onStart程序无法执行(参照之前我说的执行顺序)
try {
if(musicControlService.getCondition() == MyService.PLAY)
{
bt1.setImageResource(R.drawable.ibt3);
Log.v("ServiceConnection", "Pause Button replaced");
}
else {
bt1.setImageResource(R.drawable.ibt1);
Log.v("ServiceConnection", "Play Button replaced");
}
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.v("MusicControlService", "fail init");
}
}
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
musicControlService = null;
}
};
bindService(intent, sc, BIND_AUTO_CREATE);
startService(intent);
Log.v("mp3player", "Create");
}

@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();

bt1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Log.v("Mp3playerbt1", "Clicked");
try {
if(musicControlService.playMusic() == MyService.PAUSE) {
bt1.setImageResource(R.drawable.ibt1);
} else {
bt1.setImageResource(R.drawable.ibt3);
}
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

});
bt2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Log.v("Mp3playerbt2", "Clicked");
try {
musicControlService.stopMusic();
bt1.setImageResource(R.drawable.ibt1);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}

@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Log.v("Mp3Player", "Stop");
}

@Override
protected void onDestroy() {
// TODO Auto-generated method stub
unbindService(sc);
super.onDestroy();
Log.v("Mp3Player", "Destroy");
}
}