远程service,运行在独立的进程中,常驻后台,不受Activity影响。经常用于系统级别服务。由于在不同进程中,进程间通信(ipc)得借助aidl(安卓接口定义语言)。
思路:
1.创建aidl文件。与java同级。在里面写接口里的定义要实现的方法。。
interface IMyAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString);//可返回类型,若这些类型没有则需自定义。要用到parcecle int plus (int a,int b);//定义方法 String toUpperCase (String str); }
2.创建service。(关键点onbind返回值)
IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public int plus(int a, int b) throws RemoteException { return a+b ; } @Override public String toUpperCase(String str) throws RemoteException { return str.toUpperCase(); } };
stub是inerface里的内部类,实例一个IMyAidlInterface.Stub的时候,我们实现之前写的接口方法。
3.在manifest里面注册
<service android:name=".RemoteService" android:enabled="true" android:exported="true" android:process=":remote"> <intent-filter> <action android:name="com.example.vita.service.RemoteService"/> </intent-filter> </service>
android:process=":remote" service服务处于激活状态;
android:exported="true"可以让其他进程绑定;
android:process=":remote"该service运行在另一个进程;
<intent-filter> <action android:name="com.example.vita.service.RemoteService"/> </intent-filter>通过filter在别的进程中启动该service。
#####用户端(使用这个service的一端)#######
1.将aidl文件包含其路径原封不动的复制过来,也放在java同级。
2.在activity中连接该service。
(关键点接口对象)
private IMyAidlInterface mIMyAidlInterface; private ServiceConnection mRemoteConn =new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.i(TAG, "onServiceConnected: "); mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); try { int result = mIMyAidlInterface.plus(11,12); String str = mIMyAidlInterface.toUpperCase("who are you"); Log.i(TAG, "onServiceConnected: result: "+ result+" str:"+ str); }catch (RemoteException e){ e.printStackTrace(); } }
public void onServiceDisconnected(ComponentName name) { Log.i(TAG, "onServiceDisconnected: "); } } ;
mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);将service转化可以进程间通信的接口(stub继承于ibinder);这个接口对象就可以与实现远程service进行通信。
(关键点。由于安卓5.0以后service只能显式启动,启动方式如下)
Intent remoteIntent = new Intent("com.example.vita.service.RemoteService");//这是一个服务端manifext里面fliter注册的action,通过action寻找service remoteIntent.setClassName("com.example.vita.service","com.example.vita.service.RemoteService");//加上这个才算是显式启动。第一个是要启动的service的context,第二个就是要启动的service bindService(remoteIntent,mRemoteConn,BIND_AUTO_CREATE);//第三个参数:本工程若无这个service自动创建一个
大功告成