绑定服务的应用场景——调用服务内的方法
访问服务内部方法,调用服务内部方法
绑定服务调用服务里面方法的流程: 1. 在activity 采用bindService方式开启服务... 2. 写一个实现类 MyConn implements ServiceConnection 3. 接口里面有一个方法onServiceConnected 在服务成功绑定的时候调用的方法 4. 在service代码 实现 onBind方法 返回一个IBinder接口的实现( 里面必须一个调用服务方法的api) 5. 在服务成功绑定的时候 服务里面返回的IBinder对象会传给 activity里面onServiceConnected 方法 6. 获取IBinder对象 中间人, 调用中间人的方法. 间接调用了服务里面的方法 |
小结: 在Activity中调用Service中的方法 ①在Service内部写一个要被调用的方法 iAmAMethodInService() ②在Service内部写一个接口实现类IBinder或者Binder类子类,MyBinder ③在该类中写一个方法,用于调用Service内部的方法,callMethodInService() ④在Service的onBind()方法中返回该实现类的实例,return new MyBinder(); ⑤在Activity的ServiceConnection实现类中的onServiceConnected()方法,在Service中onBind返回一个可用的IBinder后,该方法会被调用,这时,我们也就拿到了可以调用Service内方法的第三方工具了 ⑥在需要的地方调用 |
核心代码: MainActivity.java package cn.zengfansheng.service;
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.view.View;
import cn.zengfansheng.service.MyService.MyBinder;
public class MainActivity extends Activity {
private ServiceConnection conn;
private MyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 开启服务
* @param view
*/
public void start(View view) {
Intent intent = new Intent(this, MyService.class);
startService(intent);
} /**
* TODO 一、 在activity 采用bindService方式开启服务...
* 绑定服务, 目的:为了获取到中间人, 间接的调用到服务里面的方法.
* @param view
*/
public void bind(View view) {
Intent service = new Intent(this, MyService.class);
conn = new MyConn();
this.bindService(service, conn , Context.BIND_AUTO_CREATE);
} // TODO 二、 写一个实现类 MyConn implements ServiceConnection
private class MyConn implements ServiceConnection {
// 服务被成功绑定的时候 调用的方法.如果service中onBind()方法返回为null,那么表示service和activity没有绑定成功,那么该方法是不会被执行的。
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("服务连接上来的。。。");
// TODO 六、方法参数中的service就是Activity和Service连接的中间人
if (service != null) {
myBinder = (MyBinder) service;// 获取服务的代理对象
}
}
// 服务异常终止时,失去连接的时候,会被调用,正常停止服务是不会被调用的
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("服务被异常终止了。。。");
}
}
/**
* 解除绑定服务
* @param view
*/
public void unbind(View view) {
if (conn != null) {
this.unbindService(conn);// 间接调用服务里面的方法
conn = null;
}
}
/**
* 调用服务内的方法
* @param view
*/
public void call(View view){
// MyService myService = new MyService();
// myService.iAmAMethodInService();
// TODO 七、通过返回过来的中间人,调用Service类的方法
myBinder.callMethodInService(5009);
} }
|
结果: 安全隐患:如果MyBinder中打麻将的方法不小心public后,拿到代理人对象都可以调用不安全 所以定义一个接口,对外暴露接口,接口中的方法才是要被暴露出去的 public interface IService {
public boolean callMethodInService(long money);
}
修改后: private class MyBinder extends Binder implements IService {
// TODO 五、提供一个API,调用Service类的方法
public boolean callMethodInService(long money) {
if (money > 5000) {
iAmAMethodInService();
return true;
} else {
System.out.println("这点钱还想打发我...");
return false;
}
}
public void playMahjong() {
System.out.println("陪领导人打麻将。。。");
}
} |
问题:用startActivity()的方式开启的服务,然后new service对象,来调用服务里面的方法,会报下面的异常 10-18 20:31:35.391: E/AndroidRuntime(4870): java.lang.IllegalStateException: Could not execute method of the activity |