美文网首页Android高级进阶
2019-08-13-Android进程通信方式总结

2019-08-13-Android进程通信方式总结

作者: 王元 | 来源:发表于2019-08-14 00:03 被阅读0次

首先,我们可以想一些通信的方式,

  • 第一种方式就是需要有一个消息的发送方(client,指发送消息),消息的接收方(server-接收并处理消息)
  • 第二种方式就是发送方和接收方都向同一个消息中心发送消息,消息中心负责将消息转发给对应的接收方
  • 第三种方式就是通过访问共享对象,达到通信

大部分通信基于以上俩种方式来实现的,接下来我们看下Android
为我们提供的进程通信方式有哪些

一,广播

通过系统AMS的机制实现多进程通信

二,ContentProvider

通过共享内容的方式

三,共享文件

并发不多或者无并发的情况可以使用

四,Socket

服务端建立severSocket,客户端建立连接,实现相互通信。socket常用于网络通信

五,使用Bundle的方式

  • 传输的数据必须基本数据类型或者能够被序列化

    • 基本数据类型(int, long, char, boolean, double等)
    • String和CharSequence
    • List:只支持ArrayList,并且里面的元素都能被AIDL支持
    • Map:只支持HashMap,里面的每个元素能被AIDL支持
    • Parcelable:所有实现Parcelable接口的对象
  • 利用Bundle进行进程间通信

      Intent intent = new Intent(MainActivity.this, MyActivity.class);
      Bundle bundle = new Bundle();
      bundle.putString("data", "data"); intent.putExtras(bundle);
      startActivity(intent);
    

利用Bundle进行进程间通信是很容易的,大家应该注意到,这种方式进行进程间通信只能是单方向的简单数据传输,它使用时有一定的局限性。

六,Messenger(信息员)

消息是单向的,使用的是handler来实现,因此并发的效率不高,适合消息较少的情况下使用

1,消息的发送方:

public class ClientActivity extends AppCompatActivity {
    private Messenger mPutMessage;
    private final WeakHandler mClientHandler = new WeakHandler(msg -> {
        try {
//            msg.replyTo = new Messenger()
            if(mPutMessage != null)mPutMessage.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    });

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent i = new Intent(this, MessagerService.class);
        bindService(i, conn, Service.BIND_AUTO_CREATE);

        Button btn = new Button(this);
        setContentView(btn);
        btn.setText("send");
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Message pool = Message.obtain();
                pool.what = 1;
                Bundle bundle = new Bundle();
                bundle.putString("key", "test messager");
                pool.obj = bundle;
                mClientHandler.sendMessage(pool);
            }
        });

    }

    private final ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mPutMessage = new Messenger(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mPutMessage = null;
        }
    };


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

2,消息的接收方

public class MessagerService extends Service {

    private final WeakHandler mServiceHandler = new WeakHandler(msg -> {
        switch (msg.what) {
            case 1:
                Log.e("MessagerService", "服务端收到客户端的消息=" + msg.obj);

                Bundle b = (Bundle) msg.obj;
                Toast.makeText(getApplicationContext(), "服务端收到客户端的消息=" + b.getString("key"), Toast.LENGTH_LONG).show();
                break;

            default:
                break;
        }
    });

    private Messenger messenger;

    @Override
    public void onCreate() {
        super.onCreate();
        messenger = new Messenger(mServiceHandler);
    }

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

注意:这种方式的消息不仅是单向的,而且发送的所有消息类型必须是实现Parcelable序列化的,否则会 Can't marshal non-Parcelable objects across processes.异常

七,AIDL

Android系统内的大部分进程通信都是基于AIDL来实现的

1,创建进程通信桥梁-AIDl文件

MediaInfo.aidl

package com.aidl.data;

// Declare any non-default types here with import statements

parcelable MediaInfo;

IMeidia.aidl

package com.aidl;

import com.aidl.data.MediaInfo;
// Declare any non-default types here with import statements

interface IMeidia {
    MediaInfo getMeidiaInfo();
    void playMedia(String url);
    void stopMedia();
}

2,声明进程通信访问对象

public class MediaInfo implements Parcelable {
    public int mediaId;
    public String mediaName;
    public String url;
        
    public MediaInfo(int mediaId, String mediaName, String url) {
        this.mediaId = mediaId;
        this.mediaName = mediaName;
        this.url = url;
    }
        
    protected MediaInfo(Parcel in) {
        mediaId = in.readInt();
        mediaName = in.readString();
    }
        
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mediaId);
        dest.writeString(mediaName);
    }
        
        
        
    @Override
    public int describeContents() {
        return 0;
    }
        
    public static final Creator<MediaInfo> CREATOR = new Creator<MediaInfo>() {
        @Override
        public MediaInfo createFromParcel(Parcel in) {
            return new MediaInfo(in);
        }
        
        @Override
        public MediaInfo[] newArray(int size) {
            return new MediaInfo[size];
        }
    };
        
    @Override
    public String toString() {
        return "MediaInfo{" +
                "mediaId=" + mediaId +
                ", mediaName='" + mediaName + '\'' +
                '}';
    }
}

2,建立服务端

/**
 * 进程通信服务端
 */
public class MediaService extends Service {

    public static final String ACTION = "service.com.aidl.MediaService";

    private final com.aidl.IMeidia.Stub mBinder = new com.aidl.IMeidia.Stub() {
        @Override
        public MediaInfo getMeidiaInfo() throws RemoteException {
            return new MediaInfo(10001, MediaService.class.getSimpleName(), "");
        }

        @Override
        public void playMedia(String url) throws RemoteException {
            startPlayer(url);
        }

        @Override
        public void stopMedia() throws RemoteException {
            stopMPlayer();
        }
    };

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

2,客户端绑定server,获取消息或者发送消息

public class AidlClientActivity extends Activity {

    private com.aidl.IMeidia mMedia;
    
    private final ServiceConnection mConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mMedia = com.aidl.IMeidia.Stub.asInterface(service);
            try {
                //获取消息
                mMedia.getMeidiaInfo();
                //发送消息
                mMedia.playMedia("url");
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void onServiceDisconnected(ComponentName name) {
            try {
                mMedia.stopMedia();
                mMedia = null;
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent i = new Intent(this, MediaService.class);
        bindService(i, mConn, Context.BIND_AUTO_CREATE);
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mConn);
    }
}

相关文章

  • 2019-08-13-Android进程通信方式总结

    首先,我们可以想一些通信的方式, 第一种方式就是需要有一个消息的发送方(client,指发送消息),消息的接收方(...

  • Android 系统复习面试系列(五)进程间通信

    Android 系统复习面试系列(五)进程间通信 本篇主要总结 Binder 原理,顺带提下其他进程间通信方式 A...

  • 操作系统拾遗--进程同步、互斥

    进程通信 进程通信--进程之间的信息交换,如同步、互斥。 进程通信分为: 低级通信方式:同步与互斥 高级通信方式:...

  • 仅限两个App间传递信息方法

    Android 进程间通信有很多方法,比如Android中进程间通信(IPC)方式总结 由于项目需求简单,只是由A...

  • 面试问题,网络相关

    1. 进程间通信方式? 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道、命名管道(...

  • 进程间通信方式总结

    前言 进程间的通信方式,其实我们一直在用它,但是我们都不会去注意它。如果碰到面试官问你知道多少种进程间的通信方式,...

  • 进程间通信方式总结

    一、共享内存 一种常用的进程间共享方式,两个线程可以共享访问同一块内存区域,减少了数据的复制操作,因此具有速度上的...

  • 关于linux的socket

    本文摘抄自吴秦(Tyler) 网络中进程之间如何通信? 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4...

  • Binder相关总结

    本文用于记录Binder机制的相关知识总结。简单讲,Binder是Android跨进程通信方式。进程本质是一个对象...

  • 第二十三章 进程间通信介绍(一)

    本章目标: 进程同步与进程互斥 进程间通信目的 进程间通信发展 进程间通信分类 进程间共享信息的三种方式 IPC对...

网友评论

    本文标题:2019-08-13-Android进程通信方式总结

    本文链接:https://www.haomeiwen.com/subject/fyaijctx.html