一、IPC

inter process communication  进程间通讯

二、AIDL

android  interface  defination  language  安卓接口定义语言

满足两个进程之间  接口数据的交换(ipc)

首先我们搞清楚两个概念  远程服务和本地服务 ?

           本地服务:服务的代码在应用程序工程的内部

           远程服务:服务的代码在另一个应用程序的里面

三、下面通过案例说明AIDL(IPC)在远程服务中使用

1.首先创建一个Android项目,命名为"远程服务";

(1)工程一栏表如下:

(2)既然是远程服务,我们就先创建远程服务为RemoteServiceDemo.java,同时也需要在AndroidMainfest.xml的清单文件中注册,如下:

AndroidMainfest.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.himi.remoteservice"
  4. android:versionCode="1"
  5. android:versionName="1.0" >
  6.  
  7. <uses-sdk
  8. android:minSdkVersion="15"
  9. android:targetSdkVersion="17" />
  10.  
  11. <application
  12. android:allowBackup="true"
  13. android:icon="@drawable/ic_launcher"
  14. android:label="@string/app_name"
  15. android:theme="@style/AppTheme" >
  16. <activity
  17. android:name=".MainActivity"
  18. android:label="@string/app_name" >
  19. <intent-filter>
  20. <action android:name="android.intent.action.MAIN" />
  21.  
  22. <category android:name="android.intent.category.LAUNCHER" />
  23. </intent-filter>
  24. </activity>
  25. <service android:name="com.himi.remoteservice.RemoteServiceDemo">
  26. <intent-filter >
  27. <action android:name="com.himi.remoteservice"/>
  28. </intent-filter>
  29. </service>
  30. </application>
  31.  
  32. </manifest>

这里我们定义了service的action,这是因为倘若应用程序自己调用服务,直接使用显式意图即可,也就是如下这种形式:

Intent intent = new Intent(this,Service.class);

startActivity(intent);

但是,我们这里是自己定义的远程服务程序,也就是这个程序在远程,让本地(或者其他用户)去调用的,所以这里使用了隐式意图。

与此同时,我们编写RemoteServiceDemo.java代码如下:

  1. package com.himi.remoteservice;
  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.Binder;
  5. import android.os.IBinder;
  6. public class RemoteServiceDemo extends Service {
  7. private class MyBinder extends Binder implements IService {
  8. public void callMethodInService() {
  9. methodInservice();
  10. }
  11. }
  12. @Override
  13. public IBinder onBind(Intent intent) {
  14. System.out.println("远程的服务被绑定 onBind");
  15. return new MyBinder();
  16. }
  17. @Override
  18. public boolean onUnbind(Intent intent) {
  19. System.out.println("远程的服务被解除绑定 onUnbind");
  20. return super.onUnbind(intent);
  21. }
  22. @Override
  23. public void onCreate() {
  24. System.out.println("远程的服务onCreate");
  25. super.onCreate();
  26. }
  27. @Override
  28. public void onDestroy() {
  29. System.out.println("远程的服务onDestroy");
  30. super.onDestroy();
  31. }
  32. public void methodInservice() {
  33. System.out.println("我是远程服务里面的方法,我被调用了");
  34. }
  35. }

这里我们定义的methodInservice(),是远程服务中的方法,这也是本地用户(或者其他用户)希望调用和访问的方法。

现在我们的需求,就是可以由别的用户程序调用这个methodInservice()方法。

上面接口IService.java为如下:

  1. package com.himi.remoteservice;
  2. public interface IService {
  3. public void callMethodInService();
  4. }

(3)其他的MainActivity和activity_main布局文件我们这里没有修改

(4)这样一个远程的服务就搭建好了

工程一览表如下:

2.接下来我们再新建一个Android项目,命名为" 调用远程服务的方法 ",如下:

(1)项目一览表:

(2)先编写布局文件activity_main.xml,如下:

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical"
  6. tools:context="com.himi.remotecall.MainActivity" >
  7. <Button
  8. android:onClick="bind"
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:text="绑定远程服务" />
  12. <Button
  13. android:onClick="call"
  14. android:layout_width="match_parent"
  15. android:layout_height="wrap_content"
  16. android:text="调用远程服务方法" />
  17. </LinearLayout>

布局效果如下:

(3)实现一下MainActivity里面的代码,如下:

  1. package com.himi.remotecall;
  2. import android.app.Activity;
  3. import android.content.ComponentName;
  4. import android.content.Intent;
  5. import android.content.ServiceConnection;
  6. import android.os.Bundle;
  7. import android.os.IBinder;
  8. import android.view.View;
  9. public class MainActivity extends Activity {
  10. private MyConn conn;
  11. @Override
  12. protected void onCreate(Bundle savedInstanceState) {
  13. super.onCreate(savedInstanceState);
  14. setContentView(R.layout.activity_main);
  15. }
  16. /**
  17. * 绑定远程服务
  18. * @param view
  19. */
  20. public void bind(View view) {
  21. Intent service = new Intent();
  22. service.setAction("com.himi.remoteservice");
  23. conn = new MyConn();
  24. bindService(service, conn, BIND_AUTO_CREATE);
  25. }
  26. private class MyConn implements ServiceConnection {
  27. public void onServiceConnected(ComponentName name, IBinder service) {
  28. }
  29. public void onServiceDisconnected(ComponentName name) {
  30. }
  31. }
  32. public void call(View view) {
  33. }
  34. }

这个客户端访问远程服务的框架,我们搭建好了;

但是我们不能访问远端的服务方法,因为这里的

public void onServiceConnected(ComponentName name, IBinder service),这个方法是绑定服务成功的时候调用的,Service.java会反馈一个IBinder service的信息,但是我们这里并不像远程服务那样,具备这个IService的接口,通过接口类型转化,也就是如下:

 IService iService = (IService)service;

 iService.callMethodInService();

现在不能这样调用methodInservice()方法,因为根本就不能接收到 IBinder service

所以不能调用远程服务的methodInservice()方法。

3.该怎么办?如何调用远程服务方法这里要利用到AIDL(IPC)

(1)第一步,我们回到"远程服务”的项目,如下:

IService.java文件在工程目录下的路径,如下:

找到这个路径如下:

看到上面的IService.java文件了,这里我们修改它的扩展名,由java 改成 aidl,如下:

回到"远程服务"这个工程,刷新它,结果如下:

这会我们发现这里的IService.java变成了IService.aidl,但是报错了,不用担心我们慢慢修改错误;

(2)来到IService.aidl文件下,如下:

aidl作为两个进程之间的接口,当然是共有的,不是共有的无法互相通信了,这里aidl中没有权限修饰符,所以删除上下两个public,结果如下:

现在IService.aidl文件也就不报错了;

(3)接着,我们来到RemoteServiceDemo.java如下:

修改成如下形式,即可:

为什么这样修改?

相应我们在gen目录下,生成一个IService.java,如下:

因为IService.Stub在gen目录下生成的IService.java的实现了接口com.himi.remoteservice.IService,同时继承了android.os.Binder,如下:

  1. /*
  2. * This file is auto-generated. DO NOT MODIFY.
  3. * Original file: C:\\Users\\Administrator.GDIZOK2X2LA0SQG\\workspace\\远程服务\\src\\com\\himi\\remoteservice\\IService.aidl
  4. */
  5. package com.himi.remoteservice;
  6. public interface IService extends android.os.IInterface
  7. {
  8. /** Local-side IPC implementation stub class. */
  9. public static abstract class Stub extends android.os.Binder implements com.himi.remoteservice.IService
  10. {
  11. private static final java.lang.String DESCRIPTOR = "com.himi.remoteservice.IService";
  12. /** Construct the stub at attach it to the interface. */
  13. public Stub()
  14. {
  15. this.attachInterface(this, DESCRIPTOR);
  16. }
  17. /**
  18. * Cast an IBinder object into an com.himi.remoteservice.IService interface,
  19. * generating a proxy if needed.
  20. */
  21. public static com.himi.remoteservice.IService asInterface(android.os.IBinder obj)
  22. {
  23. if ((obj==null)) {
  24. return null;
  25. }
  26. android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
  27. if (((iin!=null)&&(iin instanceof com.himi.remoteservice.IService))) {
  28. return ((com.himi.remoteservice.IService)iin);
  29. }
  30. return new com.himi.remoteservice.IService.Stub.Proxy(obj);
  31. }
  32. @Override public android.os.IBinder asBinder()
  33. {
  34. return this;
  35. }
  36. @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
  37. {
  38. switch (code)
  39. {
  40. case INTERFACE_TRANSACTION:
  41. {
  42. reply.writeString(DESCRIPTOR);
  43. return true;
  44. }
  45. case TRANSACTION_callMethodInService:
  46. {
  47. data.enforceInterface(DESCRIPTOR);
  48. this.callMethodInService();
  49. reply.writeNoException();
  50. return true;
  51. }
  52. }
  53. return super.onTransact(code, data, reply, flags);
  54. }
  55. private static class Proxy implements com.himi.remoteservice.IService
  56. {
  57. private android.os.IBinder mRemote;
  58. Proxy(android.os.IBinder remote)
  59. {
  60. mRemote = remote;
  61. }
  62. @Override public android.os.IBinder asBinder()
  63. {
  64. return mRemote;
  65. }
  66. public java.lang.String getInterfaceDescriptor()
  67. {
  68. return DESCRIPTOR;
  69. }
  70. @Override public void callMethodInService() throws android.os.RemoteException
  71. {
  72. android.os.Parcel _data = android.os.Parcel.obtain();
  73. android.os.Parcel _reply = android.os.Parcel.obtain();
  74. try {
  75. _data.writeInterfaceToken(DESCRIPTOR);
  76. mRemote.transact(Stub.TRANSACTION_callMethodInService, _data, _reply, 0);
  77. _reply.readException();
  78. }
  79. finally {
  80. _reply.recycle();
  81. _data.recycle();
  82. }
  83. }
  84. }
  85. static final int TRANSACTION_callMethodInService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
  86. }
  87. public void callMethodInService() throws android.os.RemoteException;
  88. }

(4)这样"远端服务",我们就修改好了,如下洁白无瑕:

4. 接着回到"调用远程服务的方法”这个项目下:

(1)在src目录下,创建一个包名,这个包名要  和 远程服务下的RemoteServiceDemo.java的包名一致, 这里都是com.himi.remoteservice,如下:

(2)把工程"远程服务"中的IService.aidl   复制到  工程”调用远程服务的方法"的src/com.himi.remoteservice,如下:

工程”调用远程服务的方法"的gen目录下也生成了IService.java

(3)回到工程”调用远程服务的方法"的MainActivity,编写代码如下:

  1. package com.himi.remotecall;
  2. import com.himi.remoteservice.IService;
  3. import android.app.Activity;
  4. import android.content.ComponentName;
  5. import android.content.Intent;
  6. import android.content.ServiceConnection;
  7. import android.os.Bundle;
  8. import android.os.IBinder;
  9. import android.os.RemoteException;
  10. import android.view.View;
  11. public class MainActivity extends Activity {
  12. private MyConn conn;
  13. private IService iservice;
  14. @Override
  15. protected void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.activity_main);
  18. }
  19. /**
  20. * 绑定远程服务
  21. * @param view
  22. */
  23. public void bind(View view) {
  24. Intent service = new Intent();
  25. service.setAction("com.himi.remoteservice");
  26. conn = new MyConn();
  27. bindService(service, conn, BIND_AUTO_CREATE);
  28. }
  29. private class MyConn implements ServiceConnection {
  30. public void onServiceConnected(ComponentName name, IBinder service) {
  31. iservice = IService.Stub.asInterface(service);
  32. }
  33. public void onServiceDisconnected(ComponentName name) {
  34. }
  35. }
  36. public void call(View view) {
  37. try {
  38. iservice.callMethodInService();
  39. } catch (RemoteException e) {
  40. // TODO 自动生成的 catch 块
  41. e.printStackTrace();
  42. }
  43. }
  44. }

(4)布署程序到模拟器上演示:

首先布署"远端服务" 到模拟器上,如下:

最小化 "远程服务", 然后布署" 调用远程服务的方法"到模拟器上,如下:

接下我们点击  按钮----绑定远程服务 ,观察logcat打印的日志,如下:

这两条日志是 工程"远程服务"中的RemoteServiceDemo中打印的;

我们再点击多次这个  按钮----调用远程服务的方法  ,在观察logcat打印的日志,如下:

这两条日志是 工程"调用远程服务的方法"中的MainActivity中call点击事件,调用工程“远程服务”中RemoteServiceDemo的methodInservice()方法打印的;如下:

四、使用 AIDL 远程服务绑定调用的步骤:

 ()采用bind的方法绑定开启服务。

  Intent intent = new Intent();//隐式的意图

      intent.setAction("action");
  bindService(intent, conn, BIND_AUTO_CREATE);

 ()  .java的接口文件改成.aidl文件,删除public 访问修饰符。

 () 在工程目录gen目录下会自动编译生成IService.java的接口文件

      生成的IService.java,是通过aidl文件生成的。服务的中间人想暴露什么方法,就怎么定义接口

 ()  远程服务代码为private class MyBinder extends  IService.Stub

       同时在返回代理人对象,如下:

       public IBinder onBind(Intent intent){……}  

 ()实现ServiceConnection接口里面的方法

  private class MyConn implements ServiceConnection{
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
      IService.Sub.asInterface(service);
      System.out.println("Activity,得到代理人对象");
    }

  注意:iService = IService.Stub.asInterface(service)

 ()  iService.callMethodInService();

Android(java)学习笔记232:Android进程间通讯(IPC)之AIDL的更多相关文章

  1. Android AIDL 进行进程间通讯(IPC)

    编写AIDL文件时,需要注意: 1.接口名和aidl文件名相同. 2.接口和方法前不用加访问权限修饰符 (public.private.protected等,也不能用final.static). 3. ...

  2. High Performance Networking in Google Chrome 进程间通讯(IPC) 多进程资源加载

    小结: 1. 小文件存储于一个文件中: 在内部,磁盘缓存(disk cache)实现了它自己的一组数据结构, 它们被存储在一个单独的缓存目录里.其中有索引文件(在浏览器启动时加载到内存中),数据文件( ...

  3. QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSharedMemory共享内存实现进程间通讯(IPC)及禁止程序多开     本文地址:h ...

  4. 服务 进程间通讯 IPC AIDL Parcelable 简介

    1.IBinder和Binder是什么鬼? 我们来看看官方文档怎么说: 中文翻译:  IBinder是远程对象的基本接口,是为了高性能而设计的轻量级远程调用机制的核心部分. 但他不仅用于远程调用,也用 ...

  5. 服务 远程服务 AIDL 进程间通讯 IPC

    Activity aidl接口文件 package com.bqt.aidlservice;  interface IBinderInterface {     /* 更改文件后缀为[.aidl]去掉 ...

  6. Android开发学习笔记-关于Android的消息推送以及前后台切换

    下面是最简单的Android的消息推送的实现方法 package com.example.shownotic; import java.util.Random; import android.supp ...

  7. Adnroid 源码学习笔记:Handler 线程间通讯

    常见的使用Handler线程间通讯: 主线程: Handler handler = new Handler() { @Override public void handleMessage(Messag ...

  8. 服务 远程服务 AIDL 进程间通讯 IPC 深化

    示例 aidl接口文件 package com.bqt.aidlservice.aidl; parcelable Person;  package com.bqt.aidlservice.aidl; ...

  9. 进程间通讯IPC的几种方式总结

    Linux进程间的通讯 Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间通信方面的侧重点有所不同.前者对Unix早期的进程间通信 ...

  10. Java学习笔记-基础语法Ⅹ-进程线程

    学习快一个月了,现在学到了黑马Java教程的300集 打印流的特点: 只负责输出数据,不负责读取数据 有自己的特有方法 字节打印流:PrintStream,使用指定的文件名创建新的打印流 import ...

随机推荐

  1. js以json形式提交数据,后台接受

    $("#savename").click(function(){ var fananname=$("#editname").val(); var jsonLis ...

  2. Cobar介绍及配置

    from:http://code.alibabatech.com/wiki/display/cobar/Home Skip to end of metadata   Page restrictions ...

  3. GNU INET SOCKET

    Linux程序设计入门 - socket/inetd programming UNIX Socket Programming基本上是一本书名.Socket programming其实需要相 当程度的基 ...

  4. Node.js快速入门

    Node.js是什么? Node.js是建立在谷歌Chrome的JavaScript引擎(V8引擎)的Web应用程序框架. 它的最新版本是:v0.12.7(在编写本教程时的版本).Node.js在官方 ...

  5. Volatile vs. Interlocked vs. lock

    今天在stackoverflow上看到一个关于Volatile, Interlock, Lock的问题,发现回答的特别好,所以就想到把它翻译一下, 希望给那些对它们有疑惑的人提供点帮助 :假设有一个类 ...

  6. hiho #1044 : 状态压缩·一

    描述 小Hi和小Ho在兑换到了喜欢的奖品之后,便继续起了他们的美国之行,思来想去,他们决定乘坐火车前往下一座城市——那座城市即将举行美食节! 但是不幸的是,小Hi和小Ho并没有能够买到很好的火车票—— ...

  7. 2015第40周一Node学习

    node学习尝试 早上看了张丹大牛博客文章nodeJS学习路线图和node从零入门系列,感觉获益匪浅,尝试了里面几项内容,对node有了更深入的认识. npm npm是一个node包管理和分发工具,已 ...

  8. 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)

      HDU 1565 方格取数(1) 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的 ...

  9. 【动态规划】Codeforces 698A & 699C Vacations

    题目链接: http://codeforces.com/problemset/problem/698/A http://codeforces.com/problemset/problem/699/C ...

  10. SCU 4440 Rectangle 2015年四川省赛题

    题目链接:http://acm.scu.edu.cn/soj/problem/4440/ 题目大意:给一个n*m的方格,求周长小于等于k的矩形有多少个. 解题思路:我之前直接暴力,显然超时,所以后来发 ...