IPC中AIDL自定义类型传递

今天放空的时候,突然心生疑问,Android底层不是Linux系统吗? 而linux跨进程通信的方式有:

  1。 管道

  2。 有名管道

  3。 信号

  4。 信号量

  5。 套接字

  6。 消息队列

他们优缺点请参考百度:http://zhidao.baidu.com/link?url=I3_fI7ruzt1DPQJqUqJhkkuRGzv2M4DbLBVWu_m6OvDhpoSWVElG-EZi0MuE4vyj75ze8mMD4Hr7D2Jve60kYOo3dYYU8_qHpIsJll6iMRi

 既然Android是凌驾于Linux之上,那么就完全有能力实现进程间的通讯,那么Android系统是怎么利用这些方式进行进程通讯的?

===========================涯上月灬指香专用分隔线=================================

参考android官方文档     地址:http://developer.android.com/index.html

其中在AIDL官方说明中有这么一段话:

  Note: Using AIDL is necessary only if you allow clients from different applications to access your service for IPC and want to handle multithreading in your service. If you do not need to perform concurrent IPC across different applications, you should create your interface by implementing a Binder or, if you want to perform IPC, but do not need to handle multithreading, implement your interfaceusing a Messenger. Regardless, be sure that you understand Bound Services before implementing an AIDL.

 在百度翻译的帮助下,勉强的读懂了这段洋文,大致的说明了:

  IPC(interprocess communication)跨进程通讯的方式有:

  一》  Binder方式:       使用情形:  在同一应用,跨进程通讯              ps:同一应用不是在一个进程中吗?如果有此疑问请继续往下看。

  —》  Messenger方式    使用情形:  不同应用,不需要处理多线程

  —》 AIDL方式:    使用情形:  不同应用,处理多线程 

 解疑:  同一应用不是在一个进程中运行吗?   

  <application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
      android:name="com.example.bindservice.MainActivity"
      android:label="@string/app_name" >
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <service
      android:name="com.example.bindservice.LoadeService"
      android:process="com.yl.service">
    </service>
  </application>

   通过这个属性,无论是通过startService 还是通过 binderService  这个service将会在 com.yl.service 进程中运行,独立于原来的进程。

===========================涯上月灬指香专用分隔线===================================

由于本博文是讲如何使用AIDL实现自定义类型传递,所有有关Messenger 和 Binder的相关问题请自行百度。

 服务端:

AIDL自定义类型传递流程:

   注意我的包层级关系:

   

  

  1。 创建一个javabean对象(People.java),并实现Parcelable(包裹化),如:

    

 package com.example.romateservice;

  import android.os.Parcel;
  import android.os.Parcelable;

  public class People implements Parcelable {

    private String name;
    private int age;

  @Override
  public String toString() {
    return "People [name=" + name + ", age=" + age + "]";
  }

  public People(Parcel source) {
  name = source.readString();
  age = source.readInt();
  }

  public People(String name, int age) {
  this.name = name;
  this.age = age;
  }

  @Override
  public int describeContents() {
    return 0;
  }

  @Override
  public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeInt(age);
  }

  public static final Parcelable.Creator<People> CREATOR = new Creator<People>() {

  @Override
  public People[] newArray(int size) {
  return new People[size];
  }

  @Override
  public People createFromParcel(Parcel source) {
  return new People(source);
  }
  };

}

  2。 在javabean同包下创建一个aidl文件声明该对象(People.aidl),内容如下: (就两句话这么简洁!)

    package com.example.romateservice;
    parcelable People;

  3。 创建一个aidl接口文件(PeopleQuery.aidl),内容如下:

  package com.example.aidl;
  import com.example.romateservice.People;

  interface PeopleQuery {

    People getPeople(String name);
  }

 

  4。 创建一个service,并创建一个内部类,作为Onbinder()方法的返回对象。     

    package com.example.romateservice;

    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    import com.example.aidl.PeopleQuery;

    public class MyService extends Service {

      @Override
      public IBinder onBind(Intent intent) {
        return new QueryBinder();
       }

      public class QueryBinder extends PeopleQuery.Stub{

        @Override
        public People getPeople(String name) throws RemoteException {
          return new People(name, 21);
         }
      }
    }

  5。 在AndroidMainfest.xml文件中为service定义隐式意图提供给调用端调用服务。  

    <service android:name="com.example.romateservice.MyService">
      <intent-filter >
        <action android:name="com.yl.peopleaidl"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
    </service>

 客户端:

    ( 其中第一个包和第三个包是从服务器拷贝过来的,切记一定不要将service也拷过来,因为里面包括核心代码)

  

    package com.example.romateclient;

    import com.example.aidl.PeopleQuery;
    import com.example.romateservice.People;

    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.support.v7.app.ActionBarActivity;
    import android.view.View;
    import android.widget.TextView;

    public class MainActivity extends ActionBarActivity {

    private PeopleQuery peopleQuery;
    private TextView tv_Info;

    private ServiceConnection conn = new ServiceConnection() {
      @Override
      public void onServiceDisconnected(ComponentName name) {
        peopleQuery = null;
        }

      @Override
      public void onServiceConnected(ComponentName name, IBinder service) {
        peopleQuery = PeopleQuery.Stub.asInterface(service);
        }
    };

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tv_Info = (TextView) findViewById(R.id.tv_info);
    bindService(new Intent("com.yl.peopleaidl"),conn,BIND_AUTO_CREATE);
   }

   public void getInfo(View view) throws RemoteException{
    People people = peopleQuery.getPeople("zhangsan");
    tv_Info.setText(people.toString());
   }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    unbindService(conn);
   }
  }

源码下载地址: http://pan.baidu.com/s/1nuC6xCH

  

      

原文地址:https://www.cnblogs.com/android-er/p/5477071.html