Android 远程Service
远程Service
在清单文件中给Service添加属性process 为:remote
<service android:name="com.example.servicetest.MyService" android:process=":remote" > </service>
使用远程Service,MyService将在另一个进程中运行,只会阻塞所在进程中的主线程,不会当前应用程序。
远程Service会在应用包名加上:remote;
远程Service的弊端:
开启多进程时 Application会运行两次 (初始化数据时不妥当 : 需要判断进程名与当前应用的的进程名)
使用bind方式与Activity建立连接时 程序会崩溃。
因为Service与Activity 运行在两个不同的进程中 ,不能使用传统的建立连接方式,需要引入AIDL;
Activity与远程Service 建立关联, 使用AIDL 进行跨进程通信(IPC)
AIDL(Android Interface Definition Languge) android接口定义语言
AIDL的作用: 用于Service与多个应用程序组件之间进行跨进程通信 ,实现多个应用程序共享一个Service的功能
使用跨进程通信的步骤
1. 首先新建一个AIDL文件 进行文件MyAIDLService.aidl文件
package com.example.service.remote; interface MyAIDLService { int plus(int a, int b); String toUpperCase(String str); }
//保存后,gen目录下会生产一个对应的java文件 ;
//编写Aidl文件时,需要注意下面几点:
1.接口名和aidl文件名相同。
2.接口和方法前不用加访问权限修饰符public,private,protected等,也不能用final,static。
3.Aidl默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、 CharSequence),使用这些类型时不需要import声明。对于List和Map中的元素类型必须是Aidl支持的类型。如果使用自定义类型作 为参数或返回值,自定义类型必须实现Parcelable接口。
4.自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义的包在同一个包中。
5.在aidl文件中所有非Java基本类型参数必须加上in、out、inout标记,以指明参数是输入参数、输出参数还是输入输出参数。
6.Java原始类型默认的标记为in,不能为其它标记。
2、然后修改MyService中的代码 实现刚定义好的MyAIDLService接口 并且在onBInd中返回对象
@Override public IBinder onBind(Intent intent) { return mBinder; } MyAIDLService.Stub mBinder = new Stub() { @Override public String toUpperCase(String str) throws RemoteException { if (str != null) { return str.toUpperCase(); } return null; } @Override public int plus(int a, int b) throws RemoteException { return a + b; } };
// Stub是Binderd的子类
3、在MainActivity中写实现代码
private MyAIDLService myAIDLService;
//创建 ServiceConnection对象 并实现MyAIDLeService中的方法 private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) {
// 获取MyAIDLService对象 myAIDLService = MyAIDLService.Stub.asInterface(service); try { int result = myAIDLService.plus(3, 5); String upperStr = myAIDLService.toUpperCase("hello world"); Log.d("TAG", "result is " + result); Log.d("TAG", "upperStr is " + upperStr); } catch (RemoteException e) { e.printStackTrace(); } } };
4.在其他应用程序中调用MyService的方法
4.1、在清单文件中给MyService 添加隐式Intent; 用于其他应用程序调用
<service android:name="com.example.service.remote.MyService" android:process=":remote" > <intent-filter> <action android:name="com.example.service.remote.MyService.MyAIDLService"></action> </intent-filter> </service>
//MyService可以响应这个action的Intent
4.2.然后在一个新的项目中,把MyAIDLService.aidl文件拷贝过来(要将原有的包路径一起拷贝过来)
4.3 然后在MainActivity中 加入MyService建立关联的代码
private MyAIDLService myAIDLService; //创建 ServiceConnection对象 并实现MyAIDLeService中的方法 private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { // 获取MyAIDLService对象 myAIDLService = MyAIDLService.Stub.asInterface(service); try { int result = myAIDLService.plus(3, 5); String upperStr = myAIDLService.toUpperCase("hello world"); Log.d("TAG", "result is " + result); Log.d("TAG", "upperStr is " + upperStr); } catch (RemoteException e) { e.printStackTrace(); } } };
4.4 bindService 通过隐式意图
case R.id.btn_bind: Intent intent1 = new Intent("com.example.service.remote.MyService.MyAIDLService"); bindService(intent1, conn , BIND_AUTO_CREATE); break;
实现不同应用程序跨进程通信功能。