Erlo

《犬夜叉2021》我想通过Binder找到你

时间:2021-01-14   阅读:13次   来源:开源中国
页面报错
点赞

点击上方蓝字关注我,每天一见,给你力量


前言

大家之前看源码都看累了吧,今天给大家讲个故事~

本故事纯属虚构,如有不通顺的逻辑请轻喷。❤️

《犬夜叉2021》

第一章:我还能找到你吗,阿篱

犬夜叉和奈落大决战之后,四魂之玉、食骨之井消失,谁也不知道去了哪,而犬夜叉和阿篱再次被分割到两个世界

于是犬夜叉拜托一位研究世界宇宙的法师——积木,来帮助他找到阿篱。

时间转眼来到了2021年,积木终于发现了这个世界的秘密。。

其实我们所在的整个宇宙叫做Android宇宙,犬夜叉和阿篱所处的两个世界其实是两个进程,两个世界可以通过食骨之井相连接。

所以想让犬夜叉重新联系到阿篱,必须再找到当年的食骨之井。

第二章:食骨之井改名Binder井?

“犬夜叉,我终于找到了”

“找到什么了?是阿篱吗?阿篱找到了????”

“没有,不过我找到了关键的东西——食骨之井”

“在哪,快带我去”

于是,积木法师带着犬夜叉来到一间屋子里:

这间屋子门面上写着《内核屋》三个大字,犬夜叉一个箭步飞了进去,在里面果然找到了当年那个食骨之井,但是又有点不一样,因为它被改了名,旁边一个破碎的板子上写着——Binder井。板子上还同时刻有使用说明:

Binder井
这口井联系这两个世界,你看到的也许不是真实的,请慎用!
如需使用,请找到当年遗落的四魂之玉,现在它叫SM之玉(ServiceManager)
找到SM之玉,心里默念你想联系的那个世界那个人,如果她在那个世界的SM之玉碎片中留下了地址,那么你就能找到她。

“积木法师,你知道SM之玉吗,哪里可以找到它”,犬夜叉问到。

第三章:四魂之玉——ServiceManager

“说到SM之玉,还要从宇宙的起源说起,Android宇宙创建初期,诞生了第一个有人的世界(用户进程),叫做Init世界,而SM之玉就是由这个世界创建的。

SM之玉创建后,启动了Binder井,成为了他的守护神。

但是它的真身存在于单独的世界中,无法获得。为了让人们能够使用到它,它特意在每个世界都留下了自己的碎片(代理)。”

“在哪在哪,快告诉我”。

“第0街道(句柄值固定为0)”,积木法师指了一个方向说到。

第四章:阿篱,我想你了

犬夜叉急忙去第0街道找到了SM之玉的碎片,然后回到Binder井旁边,心里默念道:

“ SM之玉, 求求你帮我找到阿篱吧。”

忽然,Binder井刮出一阵狂风,一个虚影出现在了犬夜叉的面前。

是阿篱~

“阿篱,你能听到我说话吗?”

“犬夜叉,我能听到,没想到还能看到你”,阿篱的虚影说到。

“我想你了,阿篱...”

故事End

故事结束了。

再帮大家理一下故事梗概,其实也就是Binder的工作流程:

  • 阿篱(服务端)为了让犬夜叉(客户端)找到她,在四魂之玉(ServiceManager)上留下了他们世界(进程)的地址。
  • 犬夜叉在第0街道(句柄为0)找到了四魂之玉碎片(ServiceManager代理)。
  • 通过四魂之玉碎片,犬夜叉看到了阿篱的虚影(服务端代理),并通过虚影告诉了阿篱,想她了(通信)。

当然,故事毕竟是故事,并不能完全说清楚。

所以下面就完整看看Binder的工作流程和原理~

代码实现犬夜叉的需求

首先,我们使用AIDL来实现刚才故事中的场景——让犬夜叉和阿篱两个不同进程的人说上话:

//IMsgManager.aidl

interface IMsgManager {
      String getMsg();
      void tell(in String msg);
}

//阿篱
public class AliWorldService extends Service {

    private static final String TAG = "lz1";

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

    private Binder mBinder = new IMsgManager.Stub() {
        @Override
        public String getMsg() throws RemoteException {
            String tellMsg="犬夜叉...是我";
            Log.e(TAG, "阿篱:" + tellMsg);
            return tellMsg;
        }

        @Override
        public void tell(String msg) throws RemoteException {
            Log.e(TAG, "我是阿篱,我收到了你说的:" + msg);
        }
    };
}

<service
    android:name=".binder.AliWorldService"
    android:process=":aliworld">
</service>


//犬夜叉
public class QycWorldActivity extends Activity {
    private static final String TAG = "lz1";

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

        Intent i = new Intent(this, AliWorldService.class);
        bindService(i, mConnection, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            IMsgManager msgManager = IMsgManager.Stub.asInterface(service);
            try {
                String tellMsg="阿篱,是你吗";
                Log.e(TAG, "犬夜叉:" + tellMsg);
                msgManager.tell(tellMsg);


                String msg = msgManager.getMsg();
                Log.e(TAG, "我是犬夜叉,我收到了你说的:" + msg);

            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

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

}

运行,打印结果:

E/lz1: 犬夜叉:阿篱,是你吗
E/lz1: 我是阿篱,我收到了你说的:阿篱,是你吗
E/lz1: 阿篱:犬夜叉...是我
E/lz1: 我是犬夜叉,我收到了你说的:犬夜叉...是我

AIDL原理

代码比较简单,服务器端新建一个Binder对象并传到onBind方法中,客户端bindservice之后,拿到到服务端的IBinder对象,通过asInterface方法获取到服务端的代理接口,就可以进行方法的调用了。

AIDL其实只是一个帮助我们实现进程间通信的工具,它会根据我们写的AIDL文件代码,生成相应的java接口代码,其内部也是通过Binder实现的。

我们可以通过build——generated——aidl_source_output_dir——debug——out文件路径找到AIDL为我们生成的接口类。这里是主要代码,比较长,可以边看解析边读代码:

public interface IMsgManager extends android.os.IInterface {

    public static abstract class Stub extends android.os.Binder implements com.example.studynote.binder.IMsgManager {

        //1
        private static final java.lang.String DESCRIPTOR = "com.example.studynote.binder.IMsgManager";

        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        //2
        public static com.example.studynote.binder.IMsgManager asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.example.studynote.binder.IMsgManager))) {
                return ((com.example.studynote.binder.IMsgManager) iin);
            }
            return new com.example.studynote.binder.IMsgManager.Stub.Proxy(obj);
        }

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


        //4
        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            java.lang.String descriptor = DESCRIPTOR;
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
                case TRANSACTION_getMsg: {
                    data.enforceInterface(descriptor);
                    java.lang.String _result = this.getMsg();
                    reply.writeNoException();
                    reply.writeString(_result);
                    return true;
                }
                case TRANSACTION_tell: {
                    data.enforceInterface(descriptor);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    this.tell(_arg0);
                    reply.writeNoException();
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }

        private static class Proxy implements com.example.studynote.binder.IMsgManager {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            

评论留言

还没有评论留言,赶紧来抢楼吧~~

吐槽小黑屋()

* 这里是“吐槽小黑屋”,所有人可看,只保留当天信息。

  • Erlo吐槽

    Erlo.vip2021-01-27 20:48:03Hello、欢迎使用吐槽小黑屋,这就是个吐槽的地方。
  • 返回顶部

      给这篇文章打个标签吧~

      棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认