远程服务:调用者和服务在不同的工程代码里面。

本地服务:调用者和服务在同一个工程代码里面。


本地服务:服务和启动它的组件在同一个进程
##远程服务:服务和启动它的组件不在同一个进程
* 远程服务只能隐式启动,类似隐式启动Activity,在清单文件中配置Service标签时,必须配置intent-filter子节点,并指定action子节点


#AIDL
* Android interface definition language
* 安卓接口定义语言
* 作用:跨进程通信
* 应用场景:远程服务中的中间人对象,其他应用是拿不到的,那么在通过绑定服务获取中间人对象时,就无法强制转换,使用aidl,就可以在其他应用中拿到中间人类所实现的接口


##支付宝远程服务
1. 定义支付宝的服务,在服务中定义pay方法
2. 定义中间人对象,把pay方法抽取成接口
3. 把抽取出来的接口后缀名改成aidl
4. 中间人对象直接继承Stub对象
5. 注册这个支付宝服务,定义它的intent-Filter


##需要支付的应用
1. 把刚才定义好的aidl文件拷贝过来,注意aidl文件所在的包名必须跟原包名一致
2. 远程绑定支付宝的服务,通过onServiceConnected方法我们可以拿到中间人对象
3. 把中间人对象通过Stub.asInterface方法强转成定义了pay方法的接口
4. 调用中间人的pay方法


服务的分类
###远程服务
* 与启动者在不同应用的服务
###本地服务
* 与启动者在同一应用的服务


#AIDL
* Android interface definition language
* 在Android中用于进程间通讯
###步骤
#####修改 05远程服务
1. 把接口文件的后缀名改成aidl
2. aidl文件中所有东西都是public的,不需要也不能自己定义访问修饰符
3. 中间人对象继承Stub,这个对象已经继承了Binder并实现了PublicBusiness接口
#####修改 06启动远程服务
1. 把05项目的aidl文件复制到06项目,然后aidl所在的包名06和05项目必须一致
2. 把06项目获取到的中间人对象使用Stub.asInterface强转


aidl:android interface definition language 安卓接口定义语言
aidl文件都是公有的,没有访问权限修饰符
IPC: inter process communication 进程间通讯


每一个应用程序都是运行在自己独立的进程里面的。

进程操作系统分配内存空间的一个单位。进程的数据都是独立的。独立的内存空间。


把服务看成一个领导,服务中有一个banZheng方法,如何才能访问?
* 绑定服务时,会触发服务的onBind方法,此方法会返回一个Ibinder的对象给MainActivity,通过这个对象访问服务中的方法
* 绑定服务


Intent intent = new Intent(this, BanZhengService.class);
bindService(intent, conn, BIND_AUTO_CREATE);
* 绑定服务时要求传入一个ServiceConnection实现类的对象
* 定义这个实现类


class MyServiceconn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
zjr = (PublicBusiness) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}

}
* 创建实现类对象


conn = new MyServiceconn();
* 在服务中定义一个类实现Ibinder接口,以在onBind方法中返回


class ZhongJianRen extends Binder implements PublicBusiness{
public void QianXian(){
//访问服务中的banZheng方法
BanZheng();
}
public void daMaJiang(){

}
}
* 把QianXian方法抽取到接口PublicBusiness中定义


绑定本地服务调用方法的步骤:
1.在服务的内部创建一个内部类 提供一个方法,可以间接调用服务的方法
private class MiddlePerson extends Binder implements IMiddlePerson{}
2.实现服务的onbind方法,返回的就是中间人 MiddlePerson
3.在activity 绑定服务。bindService();
4.在服务成功绑定的时候 会执行一个方法 onServiceConnected 传递过来一个 IBinder对象
5.强制类型转化 调用接口里面的方法。

/**
* 中间人的接口定义
*
*/
public interface IMiddlePerson {
/**
* 代办暂住证
* @param money
*/
public void callMethodInService(int money);
}
public class MyService extends Service {	//2.实现服务成功绑定的代码 ,返回一个中间人。	@Override	public IBinder onBind(Intent arg0) {		System.out.println("服务被成功绑定了。。。。");		return new MiddlePerson();	}		@Override	public boolean onUnbind(Intent intent) {		System.out.println("onunbind");		return super.onUnbind(intent);	}		@Override	public void onCreate() {		System.out.println("oncreate");		super.onCreate();	}		@Override	public int onStartCommand(Intent intent, int flags, int startId) {		System.out.println("onstartcommand");		return super.onStartCommand(intent, flags, startId);	}		@Override	public void onDestroy() {		System.out.println("ondestory");		super.onDestroy();	}					/**	 * 这是服务里面的一个方法	 */	public void methodInService(){		Toast.makeText(this, "哈哈,服务给你办好了暂住证。", 0).show();	}		//1.第一步服务要暴露方法 必须要有一个中间人	private class MiddlePerson extends Binder implements IMiddlePerson{		/**		 * 代办暂住证		 * @param money 给钱 50块钱以上才给办。		 */		public void callMethodInService(int money){			if(money>=50){				methodInService();			}else{				Toast.makeText(getApplicationContext(), "多准备点钱。", 0).show();			}		}		/**		 * 陪领导打麻将		 */		public void playMajiang(){			System.out.println("陪领导打麻将。");		}	}}
activity_main.xml

<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"
tools:context=".MainActivity" >

<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="bind"
android:text="绑定服务" />

<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="unbind"
android:text="解除绑定服务" />

<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="call"
android:text="调用服务里面的方法" />

</LinearLayout>

public class MainActivity extends Activity {
private MyConn conn;
private IMiddlePerson mp;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

// 绑定服务
public void bind(View view) {
// 3.activity采用绑定的方式去开启服务。
Intent intent = new Intent(this, MyService.class);
conn = new MyConn();
bindService(intent, conn, BIND_AUTO_CREATE);

}

// 解除绑定服务
public void unbind(View view) {
unbindService(conn);
mp = null;
}

@Override
protected void onDestroy() {
System.out.println("啊啊啊,我是activity,我挂了");
super.onDestroy();
}

// 调用服务里面的方法。
public void call(View view) {
// 5.通过中间人调用服务里面的方法。
mp.callMethodInService(55);
}

private class MyConn implements ServiceConnection {
// 4. 当服务被连接的时候调用 服务别成功 绑定的时候调用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("在activity里面成功得到了中间人");
mp = (IMiddlePerson) service;
}

// 当服务失去连接的时候调用(一般进程挂了,服务被异常杀死)
@Override
public void onServiceDisconnected(ComponentName name) {

}
}
}
绑定远程服务调用方法的步骤:
1.在服务的内部创建一个内部类 提供一个方法,可以间接调用服务的方法
2.把暴露的接口文件的扩展名改为aidl文件 去掉访问修饰符 public
private class MiddlePerson extends IMiddlePerson.Stub{} IPC的子类
3.实现服务的onbind方法,返回的就是中间人 IMiddlePerson
4.在activity 绑定服务。bindService();
5.在服务成功绑定的时候 会执行一个方法 onServiceConnected 传递过来一个 IBinder对象
6.IMiddlePerson.Stub.asInterface(binder) 调用接口里面的方法。


远程服务的代码:


 interface IMiddlePerson {
/**
* 调用服务里面的方法
*/
void callMethodInService();
}

public class RemoteService extends Service {

@Override
public void onCreate() {
System.out.println("远程服务被创建了。。。");
super.onCreate();
}

@Override
public void onDestroy() {
System.out.println("远程服务被销毁了。");
super.onDestroy();
}

@Override
public IBinder onBind(Intent intent) {
return new MiddlePerson();
}

private void methodInService(){
System.out.println("我是远程服务的方法,我被调用了。。。。");
}

//1.创建一个中间人 远程服务继承的是ipc的一个实现类
private class MiddlePerson extends IMiddlePerson.Stub{
@Override
public void callMethodInService() {
methodInService();
}

}

}


绑定远程服务(调用远程服务)的代码:



 interface IMiddlePerson {
/**
* 调用服务里面的方法
*/
void callMethodInService();
}

public class MainActivity extends Activity {
private MyConn conn;
private IMiddlePerson iMp;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

/**
* 绑定远程服务
* @param view
*/
public void bind(View view){
Intent intent = new Intent();
intent.setAction("com.itheima.remoteservice");
conn = new MyConn();
bindService(intent, conn, BIND_AUTO_CREATE);
}

private class MyConn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iMp = IMiddlePerson.Stub.asInterface(service);
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
}

public void call(View view){
try {
iMp.callMethodInService();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}
}

参考:

Android Service 的生命周期

混合调用Service(Service既能后台长期运行,又能调用Service中方法)



更多相关文章

  1. "AndroidStudio 单元测试"-最简单最快的方法-ApplicationTest
  2. android在onCreate()方法中获取View的宽度与高度的方法实战
  3. W/System.err:at java.net.PlainDatagramSocketImpl.bind(PlainDa
  4. Android Studio获取数字签名(SHA1)的方法
  5. Android Volley:使用方法总结及实例解析
  6. eclipse下运行EasyAR官方sample的方法
  7. Android App性能信息获取方法
  8. Android Studio 检测内存泄漏与解决方法
  9. C#/Java 调用WSDL接口及方法

随机推荐

  1. android 设置EditText只能输入数字
  2. Android四大组件的工作过程
  3. Android ListView 的简单用法
  4. Android Development
  5. 完美解决listView滚动条隐藏的问题!
  6. 拥抱 Android Studio 之一:从 ADT 到 Andr
  7. 【魔幻塔防】60关配置文件
  8. ch020 Android SQLite3(第二部分)
  9. 对话框大合集
  10. Android录音实现——使用AtudioRecord