IPC机制

作者: Charein | 来源:发表于2018-03-07 23:47 被阅读0次

    1. Android中的多进程模式

    通过给四大组件指定android:process属性,就可以开启多进程模式。如下所示:

            <service
                android:name=".aidl.MyService"
                android:enabled="true"
                android:exported="true"
                android:process=":remote">
            </service>
    

    通过ps命令可以查看到系统所有运行的进程,其中进程名以":"开头的进程属于当前应用的私有进程,其它应用的组件不可以和它跑在同一个进程中。而进程名不以":"开头的进程属于全局进程,其它应用通过ShareUID方式可以和它跑在同一个进程中。

    使用多进程会造成以下几方面的问题:
    1)静态成员和单例模式完全失效;
    2)线程同步机制完全失效;
    3)SharedPreferences的可靠性下降;
    4)Application会多次创建。

    2. IPC基础概念

    2.1 Serializable和Parcelable

    Serializable是Java所提供的一个序列化接口,使用中只需要在类的声明中指定一个类似下面的标识即可自动实现默认的序列化过程:

    private static final long serialVersionUID = 1L;
    

    不申明serialVersionUID同样可以实现序列化,只不过影响反序列化过程。

    Parcelable是Android所提供的一个序列化接口。

    Serializable使用起来简单但是开销很大,序列化和反序列化过程需要大量的I/O操作。而Parcelable效率很高,只是使用起来稍麻烦。

    3. Android中的IPC方式

    3.1 使用Bundle

    Activity、Service和Receiver支持在Intent中传递Bundle数据。

    3.2 使用文件共享
    3.3 使用Messenger

    通过它可以在不同的进程中传递Message对象,它是一个轻量级的IPC方案,它的底层实现是AIDL。
    客户端示例如下:

    public class MessengerActivity extends AppCompatActivity {
        private static final String TAG = MessengerActivity.class.getSimpleName();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_messenger);
    
            Intent intent = new Intent(this, MessengerService.class);
            bindService(intent, mConnection, BIND_AUTO_CREATE);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unbindService(mConnection);
        }
    
        private ServiceConnection mConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.i(TAG, "onServiceConnected: " + name.getClassName());
                //send message
                Messenger messenger = new Messenger(service);
                Message message = Message.obtain(null, 0);
                Bundle bundle = new Bundle();
                bundle.putString("msg", "hello world from client");
    //            bundle.putSerializable("msg", new UserEntity("chen", "123", 28));
                message.setData(bundle);
                message.replyTo = mMessenger;
    
                try {
                    messenger.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.i(TAG, "onServiceDisconnected: " + name.getClassName());
            }
        };
    
        private Messenger mMessenger = new Messenger(new ActivityHandler());
    
        private static class ActivityHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.arg1 == 0) {
                    //receive message
                    String content = msg.getData().getString("msg");
                    System.out.println("receive: " + content);
                }
            }
        }
    }
    

    服务端示例如下:

    public class MessengerService extends Service {
        public MessengerService() {
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return mMessenger.getBinder();
        }
    
        private Messenger mMessenger = new Messenger(new ServiceHandler());
    
        private static class ServiceHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.arg1 == 0) {
                    //receive message
                    String content = msg.getData().getString("msg");
                    System.out.println("receive: " + content);
    //                UserEntity userEntity = (UserEntity) msg.getData().getSerializable("msg");
    //                if (userEntity != null) {
    //                    System.out.println("receive: " + userEntity.toString());
    //                }
    
                    //replay message
                    Messenger client = msg.replyTo;
                    Message replayMsg = Message.obtain(this);
                    replayMsg.arg1 = 0;
                    Bundle bundle = new Bundle();
                    bundle.putString("msg", "ok");
                    replayMsg.setData(bundle);
                    try {
                        client.send(replayMsg);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    3.4 使用AIDL

    aidl文件如下:

    // IMyAidlInterface.aidl
    package com.charein.ipc;
    
    // Declare any non-default types here with import statements
    
    interface IMyAidlInterface {
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
        void basicTypes(int anInt);
    }
    

    客户端示例如下:

    public class AidlActivity extends AppCompatActivity {
        private static final String TAG = AidlActivity.class.getSimpleName();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_aidl);
    
            Intent intent = new Intent(this, MyService.class);
            bindService(intent, mConnection, BIND_AUTO_CREATE);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unbindService(mConnection);
        }
    
        private ServiceConnection mConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.i(TAG, "onServiceConnected: " + name.getClassName());
                IMyAidlInterface asInterface = IMyAidlInterface.Stub.asInterface(service);
                try {
                    asInterface.basicTypes(123);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.i(TAG, "onServiceDisconnected: " + name.getClassName());
            }
        };
    }
    

    服务端示例如下:

    public class MyService extends Service {
        public MyService() {
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return new TestService().asBinder();
        }
    
        public class TestService extends IMyAidlInterface.Stub {
    
            @Override
            public void basicTypes(int anInt) throws RemoteException {
                System.out.println("basicTypes: " + anInt);
            }
        }
    }
    
    3.5 使用ContentProvider

    它是Android中提供的专门用于不同应用间进行数据共享的方式,底层实现也是Binder。
    客户端示例如下:

    public class ProviderActivity extends AppCompatActivity {
    
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_provider);
    
           Uri uri = Uri.parse("content://com.charein.ipc.PROVIDER");
           ContentValues values = new ContentValues();
           values.put("name", "chen");
           getContentResolver().insert(uri, values);
       }
    }
    

    服务端示例如下:

    public class MyContentProvider extends ContentProvider {
        private static final String TAG = MyContentProvider.class.getSimpleName();
    
        public MyContentProvider() {
        }
    
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            Log.i(TAG, "delete: ");
            return 0;
        }
    
        @Override
        public String getType(Uri uri) {
            // TODO: Implement this to handle requests for the MIME type of the data
            // at the given URI.
            throw new UnsupportedOperationException("Not yet implemented");
        }
    
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            Log.i(TAG, "insert: ");
            for (String key : values.keySet()) {
                String value = (String) values.get(key);
                Log.i(TAG, "insert: " + key + ", " + value);
            }
            return uri;
        }
    
        @Override
        public boolean onCreate() {
            return false;
        }
    
        @Override
        public Cursor query(Uri uri, String[] projection, String selection,
                            String[] selectionArgs, String sortOrder) {
            Log.i(TAG, "query: ");
            return null;
        }
    
        @Override
        public int update(Uri uri, ContentValues values, String selection,
                          String[] selectionArgs) {
            Log.i(TAG, "update: ");
            return 0;
        }
    

    provider定义如下:

            <provider
                android:name=".provider.MyContentProvider"
                android:authorities="com.charein.ipc.PROVIDER"
                android:enabled="true"
                android:exported="true"
                android:process=":remote">
            </provider>
    
    3.6 使用socket

    相关文章

      网友评论

          本文标题:IPC机制

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