美文网首页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进程通信方式总结

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