Android Binder的实战与原理

服务端编写

用AIDL生成一个Binder类

package com.example.myapplication;

public interface BookAIDL extends android.os.IInterface
{
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements BookAIDL
    {
        private static final String DESCRIPTOR = "com.example.server.aidl.BookAIDL";
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
            this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an com.example.server.aidl.BookAIDL interface,
         * generating a proxy if needed.
         */
        public static BookAIDL asInterface(android.os.IBinder obj)
        {
            if ((obj==null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof BookAIDL))) {
                return ((BookAIDL)iin);
            }
            return new BookAIDL.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_getBookName:
                {
                    data.enforceInterface(DESCRIPTOR);
                    String _result = this.getBookName();
                    reply.writeNoException();
                    reply.writeString(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }
        private static class Proxy implements BookAIDL
        {
            private android.os.IBinder mRemote;
            Proxy(android.os.IBinder remote)
            {
                mRemote = remote;
            }
            @Override public android.os.IBinder asBinder()
            {
                return mRemote;
            }
            public String getInterfaceDescriptor()
            {
                return DESCRIPTOR;
            }
            @Override public String getBookName() throws android.os.RemoteException
            {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                String _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(BookAIDL.Stub.TRANSACTION_getBookName, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readString();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }
        static final int TRANSACTION_getBookName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }
    public String getBookName() throws android.os.RemoteException;
}

编写Service代码

package com.example.server;

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

import com.example.server.aidl.BookAIDL;

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

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

    private final BookAIDL.Stub binder = new BookAIDL.Stub() {
        @Override
        public String getBookName() {
            return "Android源代码情景分析";
        }
    };
}

然后你必须在你的模拟器里安装这个server app


客户端编写

然后BookAIDL也需要拷贝到客户端

客户端调用

package com.example.myapplication;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.example.server", "com.example.server.BookService"));
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    private static final String TAG = "xbh";

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            BookAIDL aidl = BookAIDL.Stub.asInterface(service);
            try {
                Log.i(TAG, aidl.getBookName());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

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

成功输出



其实简单的理解:ServiceManager管理所有的服务端,客户端从ServiceManager中去找服务端。


分析那个Binder类

public static BookAIDL asInterface(android.os.IBinder obj) {
    if ((obj == null)) {
        return null;
    }
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin != null) && (iin instanceof BookAIDL))) {
        return ((BookAIDL) iin);
    }
    return new BookAIDL.Stub.Proxy(obj);
}

如果是同进程,我们直接返回服务端的对象。如果是异进程,需要封装一下。


@Override
public boolean onTransact(int code, @NonNull 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_getBookName: {
            data.enforceInterface(DESCRIPTOR);
            String _result = this.getBookName();
            reply.writeNoException();
            reply.writeString(_result);
            return true;
        }
    }
    return super.onTransact(code, data, reply, flags);
}


@Override
public boolean onTransact(int code, @NonNull 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_getBookName: {
            data.enforceInterface(DESCRIPTOR);
            String _result = this.getBookName();
            reply.writeNoException();
            reply.writeString(_result);
            return true;
        }
    }
    return super.onTransact(code, data, reply, flags);
}

这个方法运行在服务端的Binder线程池。

_data用来存放方法的输入参数,_reply是返回值



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值