Skip to content

fengxiang1990/EasyBinder

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
Apr 12, 2019
Apr 12, 2019
Apr 12, 2019
Apr 12, 2019
Apr 12, 2019
Apr 12, 2019
Apr 12, 2019
Apr 12, 2019
Apr 12, 2019
Apr 12, 2019

Repository files navigation

EasyBinder

这是一个remote进程获取日期字符串的示例,如果能充分理解这里面的逻辑和调用关系,那么对于Android应用开发人员来说Binder的知识就算是掌握了。

第一步,定义一个远程服务接口,它继承了IInterface接口,这个接口其实也可以在IRemoteDateService的具体实现类中实现,

  public interface IRemoteDateService extends IInterface {

    //服务的字符转描述,相当于自定Binder的名称
    String DESCRIPTION  = "com.example.myapplication.IRemoteDateService";
  
    //远程方法的序号
    int DESCRIPTION_getDate  = IBinder.FIRST_CALL_TRANSACTION;

    //远程方法
    String getDate() throws RemoteException;

}

第二步,定义IRemoteDateService的具体实现类RemoteDateServiceImpl,这也是我们手写Binder服务的核心,它直接继承自Binder类,

public abstract class RemoteDateServiceImpl extends Binder implements IRemoteDateService {

    //这一步很重要,这是在Binder服务中注册我们自己的远程服务
    RemoteDateServiceImpl() {
        attachInterface(this, DESCRIPTION);
    }

    //这是一个静态方法,它的主要作用是在bindServise方法启动Service的时候,
    //在ServiceConnection中调用,以获取远程服务的实例
     static IRemoteDateService asInterface(IBinder binder) {
        if (binder == null) {
            return null;
        }
        if (binder instanceof IRemoteDateService) {
            return (IRemoteDateService) binder;
        }
        return new Proxy(binder);
    }

    //自定义Binder必须实现的方法,重中之重
    @Override
    protected boolean onTransact(int code, @NonNull Parcel data, Parcel reply, int flags) throws RemoteException {
        switch (code) {
        //相当于自定义的Binder注册成功后的回调
            case INTERFACE_TRANSACTION:
                reply.writeString(DESCRIPTION);
                return true;
           
           //照葫芦画瓢就可以了     
            case DESCRIPTION_getDate:
                data.enforceInterface(DESCRIPTION);
                reply.writeNoException();
                reply.writeString(getDate());
                return true;
        }
        return super.onTransact(code, data, reply, flags);
    }


//这是一个代理类,如果进程是远程的,则会调用该类,通过IBinder
//的transact方法把调用的方法传给具体的Binder实现类,上面的Binder实现类
//RemoteDateServiceImpl在收到onTransact方法后,根据方法的序列号DESCRIPTIO//N_getDate写入remote //process中返回的实际结果,也就是getDate()的值,并将这个值以reply.writeSt//ring(getDate())的方式写入,这后面实际上是由binder驱动来完成,最终binder驱//动把远程进程的数据传到调用的进程.
    static class Proxy extends RemoteDateServiceImpl {

        IBinder remote;

        Proxy(IBinder remote) {
            this.remote = remote;
        }

        public String getInterfaceDescriptor() {
            return DESCRIPTION;
        }

        @Override
        public String getDate() throws RemoteException {
            Parcel _data = Parcel.obtain();
            Parcel _reply = Parcel.obtain();
            String date;
            try {
                _data.writeInterfaceToken(DESCRIPTION);
                remote.transact(DESCRIPTION_getDate, _data, _reply, 0);
                _reply.readException();
                
            //这里是阻塞的,等待binder驱动把把数据传过来
                date = _reply.readString();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return date;
        }

        @Override
        public IBinder asBinder() {
            return remote;
        }
    }
}

第三部,定义我们的android service 类,并且设置为remote 进程

 <service android:name=".RemoteServise" android:process=":remote"/>
public class RemoteServise extends Service {

    IRemoteDateService remoteDateService = new RemoteDateServiceImpl() {
      
      //具体的返回时期的实现
        @Override
        public String getDate() throws RemoteException {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return simpleDateFormat.format(new Date());
        }

        @Override
        public IBinder asBinder() {
            return this;
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return remoteDateService.asBinder();
    }
}

第四部,在MainActivity中调用getDate()

public class MainActivity extends AppCompatActivity {

    String tag = "MainActivity";

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

        findViewById(R.id.btn_bind).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bindService(new Intent(MainActivity.this, RemoteServise.class), connection, Context.BIND_AUTO_CREATE);
            }
        });

        findViewById(R.id.btn_unbind).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                unbindService(connection);
            }
        });

        findViewById(R.id.btn_getdate).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    String date = remoteDateService.getDate();
                    Log.e(tag, "date from remote->" + date);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });


    }

    IRemoteDateService remoteDateService;

    ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            remoteDateService = RemoteDateServiceImpl.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            remoteDateService = null;
        }
    };
}

Logcat 输出如下:E/MainActivity: date from remote->2019-04-12 14:25:06

至此通过调用一个远程服务获取日期的自定义binder 逻辑就写完了,很简单, AIDL其实就是在帮助我们完成这些步骤,我建议对于简单的逻辑手写就行了,这样可以加深对binder的理解。

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages