Service communication between two APPs through AIDL

1. Project introduction

【Knowledge preparation】

①Android Interface definition language (aidl, android interface definition language), whose purpose is to implement cross-process calls. Process is the carrier of program execution in os. One program corresponds to one process. Different processes refer to different programs. Aidl implements calls between different programs.

②The main thread communicates with the sub-threads Using the handler, the handler can send messages in the sub-threads and process the messages in the main thread, thus completing the communication between the threads. Even if there are multiple threads, it is still a program.

③ Different programs need to communicate through aidl. There are many communication methods, and aidl is one of them. The implemented result feels like a program just as its own program calls its own other methods.

④Business scenarios: For example, the shopping app needs to be paid, the shopping app is Taobao, and the payment app is Alipay. Therefore, different programs are required to communicate.

 

Second, first introduce the communication between the Service and the Activity between an App

【Project Structure】

 

【MyService】

【hint】

①Create Service

 ②If it is not created by the above method, be sure to remember to register

1 <service
2             android:name=".MyService"
3             android:enabled="true"
4             android:exported="true"></service>

【Code】

 1 public class MyService extends Service {
 2     public MyService() {
 3     }
 4 
 5     @Override
 6     public IBinder onBind(Intent intent) {
 7         return new MyBinder();//return MyBinder通过ServiceConnection在activity中拿到MyBinder
 8     }
 9 
10     @Override
11     public int onStartCommand(Intent intent, int flags, int startId) {
12 
13         return super.onStartCommand(intent, flags, startId);
 14      }
 15  
16      public   void   payService(){
 17          Log.i("MyService", "payService: --------" );
 18      }
 19  
20      class MyBinder extends Binder{
 21  
22          public  void pay(){
 23              payService();
 24          } // The methods in the service are exposed through the Binder instance 
25      }
 26 }

【layout_main】

      Add button, click for easy call

1     <Button
2         android:id="@+id/btn_paly"
3         android:text="Pay"
4         android:layout_width="wrap_content"
5         android:layout_height="wrap_content" />

【MainActivity】

 1 public class MainActivity extends AppCompatActivity {
 2 
 3     MyService.MyBinder binder = null;
 4     ServiceConnection conn;
 5 
 6     @Override
 7     protected void onCreate(Bundle savedInstanceState) {
 8         super.onCreate(savedInstanceState);
 9         setContentView(R.layout.activity_main);
10 
11         Button btnPlay = (Button) findViewById(R.id.btn_paly);
12         conn = new ServiceConnection() {
13             @Override
14             public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
15                 binder = (MyService.MyBinder) iBinder;
16             }
17 
18             @Override
19             public void onServiceDisconnected(ComponentName componentName) {
20 
21             }
22         };
23 
24         Intent intent = new Intent(MainActivity.this,MyService.class);
25         bindService(intent,conn,BIND_AUTO_CREATE);//开启服务
26 
27         btnPlay.setOnClickListener(new View.OnClickListener() {
28             @Override
29             public void onClick(View view) {
30                 if (binder!=null){
31                     binder.play();
32                 }
33             }
34         });
35     }
36 }

【效果】

点击后输出service中pay方法中的内容

 

 三、两个App之间的Service通信

【项目结构】

 

【步骤】

①在AppPayProvider中创建MyService

  代码同上

【注册】

  Ⅰ、注册时(android:enabled="true"   android:exported="true")设置为true,将Service暴露出去,另一个App才能访问到它

  Ⅱ、添加『<intent-filter>』。由于不是同一个App,通过intent-filter对Intent进行过滤,让另一个app通过action开启服务

 1         <service
 2             android:name=".MyService"
 3             android:enabled="true"
 4             android:exported="true">
 5             <!--enable:ture设置可用
 6             exported:ture对外暴露 -->
 7             <intent-filter>
 8                 <action android:name="com.xqz.apppayprovider.MyService" />
 9             </intent-filter>
10         </service>

 

②MainActivity和layout_main保留创建时不作任何修改,但也不要删掉,因为安装程序必须提供起始页面,否则将会出错

 

③在AppPayProvider中添加AIDL

【代码】

【提示】接口中定义中方法要和Service中的MyBinder中的方法一致

 

④再创建好AIDL,添加完方法后,android studio需要对这个aidl进行编译,会自动按aidl规范生成一个Binder子类的代码。

 

⑤对MyService中的MyBinder进行修改

【提示】继承IPay.Stub。在这之前必须Make Project,否则将没有只能联想

 

⑥创建AppPayUser对AppPayProvider中的MyService进行操作

【layout-main】

1     <Button
2         android:id="@+id/btnPay"
3         android:text="pay"
4         android:layout_width="wrap_content"
5         android:layout_height="wrap_content" />

 

⑦将AppPayProvider中AIDL拷贝到AppPayUser中

【提示】Ⅰ、包名要相同,按目录位置复制,通过下述方法,直接在文件夹进行复制。『此处可以查看项目结构,可以看到包名是相同的』

    Ⅱ、同样拷贝过来后需要Make Project

 

⑧【AppPayUser-MainActivity】

 1 public class MainActivity extends AppCompatActivity {
 2 
 3     Button btnPay;
 4     private IPay myBinder;//定义AIDL
 5 
 6     ServiceConnection conn = new ServiceConnection() {
 7         @Override
 8         public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
 9 
10             myBinder = IPay.Stub.asInterface(iBinder);
11         }
12 
13         @Override
14         public void onServiceDisconnected(ComponentName componentName) {
15 
16         }
17     };
18 
19     @Override
20     protected void onCreate(Bundle savedInstanceState) {
21         super.onCreate(savedInstanceState);
22         setContentView(R.layout.activity_main);
23 
24         Intent intent = new Intent();
25         intent.setAction("com.xqz.apppayprovider.MyService");
26         //表示按照什么进行过滤,启动意图
27         /*android5.0之后,如果servicer不在同一个App的包中,
28          需要设置service所在程序的包名
29          (包名可以到App的清单文件AndroidManifest中查看)*/
30         intent.setPackage("com.xqz.apppayprovider");
31         bindService(intent,conn,BIND_AUTO_CREATE);//开启Service
32 
33         btnPay = (Button) findViewById(R.id.btnPay);
34 
35         btnPay.setOnClickListener(new View.OnClickListener() {
36             @Override
37             public void onClick(View view) {
38                 try {
39                     myBinder.pay();
40                 } catch (RemoteException e) {
41                     //因为是跨程序调用服务,可能会出现远程异常
42                     e.printStackTrace();
43                 }
44             }
45         });
46     }
47 }

 

【安装】

  先安装AppPayProvider再安装AppPayUser。

【效果】

  将run中的 视图调到AppPayProvider,点击模拟器AppPayUser中的pay按钮,将会执行AppPayProvider中MyService中pay方法中的内容。

 

四、总结

 【跨App和同App之间的区别】

①跨App开启服务是提供服务的App需要设置intent-filter过滤器,控制服务的App需要通过。setAction和setPackage方法进行设置action和包名,才能开启服务。而同App只需要指定启动的service就可。

②跨App的MyBinder实例要通过AIDL获取,两个应用定义同样的接口的方法,通过对应的AIDL名称.Stub.asInterface方法得到binder实例,然后就和同App的myBinder使用么有区别了。

③跨App的MyBinder对象的使用必须捕获异常,而同App不需要。

④可以根据上方简单的例子实现很多类似的功能。

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324946736&siteId=291194637