美文网首页
Android ICP

Android ICP

作者: 懒猫1105 | 来源:发表于2018-06-24 23:33 被阅读0次

    Android ICP

    ICP(Inter-Process Commnication)跨进程通信。

    Android一般情况下一个应用在一个进程中,但一个应用可能需要采取多进程模式(获取更多的内存空间),或者2个应用之间传递数据,还有系统服务等,都需要ICP

    1.Android中开启多线程
    • 在Manifest文件中给(Activity,Service,Receiver,ContentProvider)指定android:process属性,
    • android:process属性内容以":"开头的进程属于私有的,其他应用组件不能和它跑在同一个进程
    • 不以":"开头的属于全局进程,其他应用可以通过ShareUID和它跑在同一个进程
    • Android会为每个应用分配一个UID,相同UID的应用才能共享数据。只有2个应用ShareUID相同并且签名相同,才能跑在同一个进程
    2.为啥是Binder作为ICP
    • 性能:Binder数据拷贝只要一次,管道、消息队列、socket都要2次,共享内存1次
    • 稳定:Binder采用C/S架构,client和server相对独立,共享内存需要考虑访问临界资源的并发问题
    • 安全:
    3.使用AIDL进行跨进程通信(简单来说就是远程Service)

    写一个AIDL文件
    选择包名 --> 右键 --> New --> AIDL --> AIDL File --> 文件名字(ILearnAIDLInterface) --> Finish
    可以看到自动生成了ILearnAIDLInterface.aidl文件,我们添加一些抽象方法以便测试

    package com.lm.learndemo;
    
    interface ILearnAIDLInterface {
        
        void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
                double aDouble, String aString);
    
        void callMethod();
    }
    

    点击Build --> Make Project
    Android Studio会自动生成ILearnAIDLInterface.java文件

    我们编写一个Service,让onBind方法返回ILearnAIDLInterface.Stub子类

            public class LearnAIDLService extends Service {
    
                @Nullable
                @Override
                public IBinder onBind(Intent intent) {
                    return new LearnAIDLBinder();
                }
    
                private class LearnAIDLBinder extends ILearnAIDLInterface.Stub {
    
                    @Override
                    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
                        Log.i("LearnAIDLBinder", "basicTypes: ");
                    }
    
                    @Override
                    public void callMethod() throws RemoteException {
                        Log.i("LearnAIDLBinder", "callMethod: ");
                    }
                }
            }
    

    并在AndroidManifest.xml文件中注册

            <service
                android:name=".LearnAIDLService"
                android:enabled="true"
                android:exported="true">
                <intent-filter>
                    <action android:name="com.lm.learndemo.LearnAIDLService" />
                </intent-filter>
            </service>
    

    在AndroidManifest.xml文件中注册一个Activity,并指定他在另一个进程运行

            <activity
                android:name=".SecondActivity"
                android:process=":second"/>
    

    编写SecondActivity,并让他调用AIDL中的方法

            public class SecondActivity extends AppCompatActivity implements View.OnClickListener {
    
                ILearnAIDLInterface iLearnAIDLInterface;
    
                ServiceConnection serviceConnection = new ServiceConnection() {
                    @Override
                    public void onServiceConnected(ComponentName name, IBinder service) {
                        iLearnAIDLInterface = ILearnAIDLInterface.Stub.asInterface(service);
                    }
    
                    @Override
                    public void onServiceDisconnected(ComponentName name) {
                        iLearnAIDLInterface = null;
                    }
                };
    
                @Override
                protected void onCreate(Bundle savedInstanceState) {
                    super.onCreate(savedInstanceState);
                    setContentView(R.layout.activity_second);
                    Intent intent = new Intent("com.lm.learndemo.LearnAIDLService");
                    intent.setPackage("com.lm.learndemo");
                    bindService(intent, serviceConnection, BIND_AUTO_CREATE);
                    findViewById(R.id.btn_call_aidl_method).setOnClickListener(this);
                }
    
                @Override
                protected void onDestroy() {
                    super.onDestroy();
                    unbindService(serviceConnection);
                }
    
                @Override
                public void onClick(View v) {
                    if (iLearnAIDLInterface != null) {
                        try {
                            iLearnAIDLInterface.callMethod();
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
    

    到此一个AIDL进行跨进程通信Demo完成

    4.解析下自动生成ILearnAIDLInterface.java文件

    ILearnAIDLInterface是个接口并且继承了IInterface这个接口。因为在Binder中可以传输的接口,必须继承IInterface。

    ILearnAIDLInterface申明了2个方法,这2个方法是我们写在ILearnAIDLInterface.aidl文件中的。
    同时申明了2个int类型的整数id来标识这2个方法。这2个id用于标识在transact过程中请求的是哪个方法。

    接着申明了Stub的内部类,他是个抽象类,继承Binder,实现ILearnAIDLInterface。当在同一个进程的时候,Stub这个Binder的子类
    就不会走跨进程的transact,当不在同一个进程,方法调用需要走transact流程。这个逻辑由Stub的内部代理类Proxy完成

    public interface ILearnAIDLInterface extends android.os.IInterface
    {
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.lm.learndemo.ILearnAIDLInterface
    {
    private static final java.lang.String DESCRIPTOR = "com.lm.learndemo.ILearnAIDLInterface";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
    this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an com.lm.learndemo.ILearnAIDLInterface interface,
     * generating a proxy if needed.
     */
    public static com.lm.learndemo.ILearnAIDLInterface asInterface(android.os.IBinder obj)
    {
    if ((obj==null)) {
    return null;
    }
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin!=null)&&(iin instanceof com.lm.learndemo.ILearnAIDLInterface))) {
    return ((com.lm.learndemo.ILearnAIDLInterface)iin);
    }
    return new com.lm.learndemo.ILearnAIDLInterface.Stub.Proxy(obj);
    }
    @Override public android.os.IBinder asBinder()
    {
    return this;
    }
    @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
    {
    switch (code)
    {
    case INTERFACE_TRANSACTION:
    {
    reply.writeString(DESCRIPTOR);
    return true;
    }
    case TRANSACTION_basicTypes:
    {
    data.enforceInterface(DESCRIPTOR);
    int _arg0;
    _arg0 = data.readInt();
    long _arg1;
    _arg1 = data.readLong();
    boolean _arg2;
    _arg2 = (0!=data.readInt());
    float _arg3;
    _arg3 = data.readFloat();
    double _arg4;
    _arg4 = data.readDouble();
    java.lang.String _arg5;
    _arg5 = data.readString();
    this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
    reply.writeNoException();
    return true;
    }
    case TRANSACTION_callMethod:
    {
    data.enforceInterface(DESCRIPTOR);
    this.callMethod();
    reply.writeNoException();
    return true;
    }
    }
    return super.onTransact(code, data, reply, flags);
    }
    private static class Proxy implements com.lm.learndemo.ILearnAIDLInterface
    {
    private android.os.IBinder mRemote;
    Proxy(android.os.IBinder remote)
    {
    mRemote = remote;
    }
    @Override public android.os.IBinder asBinder()
    {
    return mRemote;
    }
    public java.lang.String getInterfaceDescriptor()
    {
    return DESCRIPTOR;
    }
    /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
    @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException
    {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    try {
    _data.writeInterfaceToken(DESCRIPTOR);
    _data.writeInt(anInt);
    _data.writeLong(aLong);
    _data.writeInt(((aBoolean)?(1):(0)));
    _data.writeFloat(aFloat);
    _data.writeDouble(aDouble);
    _data.writeString(aString);
    mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
    _reply.readException();
    }
    finally {
    _reply.recycle();
    _data.recycle();
    }
    }
    @Override public void callMethod() throws android.os.RemoteException
    {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    try {
    _data.writeInterfaceToken(DESCRIPTOR);
    mRemote.transact(Stub.TRANSACTION_callMethod, _data, _reply, 0);
    _reply.readException();
    }
    finally {
    _reply.recycle();
    _data.recycle();
    }
    }
    }
    static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_callMethod = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }
    /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
    public void callMethod() throws android.os.RemoteException;
    }
    

    相关文章

      网友评论

          本文标题:Android ICP

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