Service知识点之远程Service

xiaoxiao2021-02-28  79

@(读书笔记)   之前开启的Service都是在主进程中开启的,那么怎么开启一个不同进程的Service呢,不同进程的Service又有哪些特性呢? 将普通的Service转化成一个Remote Service是非常简单的一件事情,只需要在注册的时候将它的android:process属性指定为:remote就可以了,代码如下:

<service android:name=".RemoteService" android:process=":remote" > </service>

远程的Service start的方法和普通Service方法相同,但是绑定的方法和普通的Service方法不同,需要使用AIDL方法进行绑定。

AIDL(Android Interface Definition Language)是Android接口定义语言的意思,它可以用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。

方式如下: 1.先新建一个AIDL文件,在这个文件中定义好Activity需要与Service进行的方法新建MyAIDLService.aidl文件,代码如下所示:

package com.simon.activity; // Declare any non-default types here with import statements interface MyAIDLService { /** * 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); int plus(int a, int b); String toUpperCase(String str); }

2.build项目,然后修改要绑定的远程Service文件实现前面定义的MyALDLService接口,如下所示:

public class RemoteService extends Service { ...... @Override public IBinder onBind(Intent intent) { Log.i(TAG,"onBind"); return binder; } MyAIDLService.Stub binder=new MyAIDLService.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 { if (str != null) { return str.toUpperCase(); } return null; } }; }

可以看到我们先是对MyAIDLService.Stub进行了实现,重写了toUpperCase()和plus()这两个方法。这两个方法的作用分别是将一个字符串全部转换成大写格式,以及将两个传入的整数进行相加。然后onBind()方法中将MyAIDLService.Stub的实现返回。 因为Stub就算Binder的子类,所以可以直接返回。

3.修改Activity的代码进行绑定Service

public class MainActivity extends AppCompatActivity { public static final String TAG = "tag"; // private MyService.MyBinder myBinder; private MyAIDLService myAIDLService; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { myAIDLService = MyAIDLService.Stub.asInterface(service); try { int result = myAIDLService.plus(1, 2); String toUpperCase = myAIDLService.toUpperCase("hello word"); Log.i(TAG, "result=" + result); Log.i(TAG, "toUpperCase=" + toUpperCase); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i(TAG, "MainActivity-onCreate"); findViewById(R.id.button_stop).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, RemoteService.class); stopService(intent); } }); findViewById(R.id.bind_service).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, RemoteService.class); bindService(intent, connection, BIND_AUTO_CREATE); } }); } }

和普通service绑定有区别的时候,ServiceConnection中的代码。可以看到,这里首先使用了MyAIDLService.Stub.asInterface()方法将传入的BInder对象转换成了MyAIDLService对象,然后就可以调用MyAIDLService.aidl文件中定义的接口了。

到这里我们就实现了同一个应用中的跨进程访问了。

那另一个应用怎么访问这个Remote Service呢? 我们很多时候开启远程服务就是做一下应用间的相互调用操作的!其实也很多简单: 1.添加一个特定的的Action属性:

<service android:name=".RemoteService" android:process=":remote" > <intent-filter> <action android:name="com.simon.activity.MyAIDLService"/> </intent-filter> </service>

2.将MyAIDLService.aidl文件拷贝到另一个项目,注意要将原有的包路径一起拷贝过来

3.修改绑定Service代码如下所示,其他的和之前相同。

//5.0之前 if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { Intent intent = new Intent("com.simon.activity.MyAIDLService"); bindService(intent, connection, BIND_AUTO_CREATE); }else{ //5.0之后 Intent intent = new Intent("com.simon.activity.MyAIDLService"); intent.setPackage("com.simon.activity"); bindService(intent, connection, BIND_AUTO_CREATE); }
转载请注明原文地址: https://www.6miu.com/read-21936.html

最新回复(0)