IPC(三)---IPC实现之Messenger和AIDL的使用讲解

一、AIDL的使用

首先是service端的实现,在app Mudule中右键new->aidl->Book.aidl

// Book.aidl
package com.example.administrator.contact;

parcelable Book;

aidl接口IBook.aidl的实现

// IBook.aidl
package com.example.administrator.contact;

import com.example.administrator.contact.Book;

interface IBook {
    void addBook(in Book book);
    Book getBook();
}


关于定向tag的说明:

in 为定向 tag 的话表现为服务端将会接收到一个那个对象的完整数据,但是客户端的那个对象不会因为服务端对传参的修改而发生变动;out 的话表现为服务端将会接收到那个对象的参数为空的对象,但是在服务端对接收到的空对象有任何修改之后客户端将会同步变动;inout 为定向 tag 的情况下,服务端将会接收到客户端传来对象的完整信息,并且客户端将会同步服务端对该对象的任何变动。


Book.java的实现

package com.example.administrator.contact;

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

/**
 * Created by Administrator on 2017/2/4.
 */

public class Book implements Parcelable {
    public String name;
    public int id;
    public Book(String name,int id){
        this.name=name;
        this.id=id;
    }
    protected Book(Parcel in) {
        id=in.readInt();
        name=in.readString();
    }

    public static final Creator CREATOR = new Creator() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

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

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

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeInt(id);
        parcel.writeString(name);
    }
}


这时候点击make按钮,就在build/generated/source/aidl/debug/IBook.java,系统帮实现的一个接口


MyService.java的代码实现,调用IBook接口的方法获取Binder对象

package com.example.administrator.contact;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;

public class MyService extends Service {
    public MyService() {
    }
    private Book book;
    private Binder binder=new IBook.Stub(){

        @Override
        public void addBook(Book book) throws RemoteException {
            MyService.this.book=book;
        }

        @Override
        public Book getBook() throws RemoteException {
            return  MyService.this.book;
        }
    };
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }
}


client端的实现比较简单

右键new->mudule创建一个client的mudule,把生成的IBook.java和Book.java文件复制过来,新建一个和service端一样的包粘贴进去

package com.example.client;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.example.administrator.contact.Book;
import com.example.administrator.contact.IBook;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent=new Intent();
        intent.setAction("fanday");
        intent.setPackage("com.example.administrator.contact");
        startService(intent);
        bindService(intent,new Conn(),BIND_AUTO_CREATE);
    }
    private IBook iBook;
    private class Conn implements ServiceConnection{

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            iBook=IBook.Stub.asInterface(iBinder);
            Book book=new Book("thinking in java",1);
            try {
                iBook.addBook(book);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    }

    public void go(View v) throws RemoteException {
        ((TextView)findViewById(R.id.textView)).setText(iBook.getBook().name);
    }

}

service端的项目结构

IPC(三)---IPC实现之Messenger和AIDL的使用讲解_第1张图片

client端的项目结构

IPC(三)---IPC实现之Messenger和AIDL的使用讲解_第2张图片


二、Messenger的使用

Messenger可以翻译为信使,可以在不同进程之间传递Message对象,在Message中放入我们需要传递的数据,就可以轻松地实现进程间传递了.Messenger是一种轻量级的IPC方案,它的底层实现实AIDL,Messenger的使用方法很简单,它对AIDL做了封装,使我们可以更简洁地进行进程间通信.同时由于它一次处理一个请求,因此在服务端我们不用考虑线程同步的问题,这是因为服务端中不存在并发执行的情形.实现Messenger有以下步骤

服务端进程:

package com.fanday.layout;

import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.widget.Toast;

public class MyService extends Service {
    public MyService() {
    }

    private Messenger message=new Messenger(new Handler(){
        @Override
        public void handleMessage(Message msg) {
            if(msg.what==100){
                //Toast.makeText(MyService.this,msg.getData().getString("data"),Toast.LENGTH_LONG).show();
                Messenger client=msg.replyTo;//获取到客户端传过来的Messenger用于向客户端回馈消息
                Message msg2=Message.obtain(null,101);
                Bundle bundle=new Bundle();
                bundle.putString("data","i am serve i have receive");
                msg2.setData(bundle);

                try {
                    client.send(msg2);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
            super.handleMessage(msg);
        }
    });

    @Override
    public IBinder onBind(Intent intent) {
        return message.getBinder();
    }
}



客户端进程:

package com.fanday.layout;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Color;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.ForegroundColorSpan;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent=new Intent(this,MyService.class);
        startService(intent);
        bindService(intent,new MyConn(),BIND_AUTO_CREATE);
    }

    private Messenger service;

    private Messenger client=new Messenger(new Handler(){
        @Override
        public void handleMessage(Message msg) {
            if(msg.what==101){
                Toast.makeText(MainActivity.this,msg.getData().getString("data"),Toast.LENGTH_LONG).show();
            }
            super.handleMessage(msg);
        }
    });

    private class MyConn implements ServiceConnection{

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            MainActivity.this.service=new Messenger(service);
            Message msg=Message.obtain();
            msg.what=100;
            Bundle bundle=new Bundle();
            bundle.putString("data","thinking in java");
            msg.setData(bundle);
            msg.replyTo=client;//把客户端处理请求的Messenger传递给发给服务端的Message

            try {
                MainActivity.this.service.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }
}


IPC(三)---IPC实现之Messenger和AIDL的使用讲解_第3张图片


你可能感兴趣的:(android)