• 两APP通信之AIDL使用。


    1.效果展示

    无效果无真相,先上图,以下为Service App和Client App两App间的跨进程通信

    AIDL实现两应用通信

    在这里插入图片描述
    在这里插入图片描述

    2.新建服务端AIDL文件

    在main路径下新建AIDL文件
    在这里插入图片描述

    a. IMsgReceiveListener

    // IMsgReceiveListener.aidl
    package com.scash.aidlservice;
    
    // Declare any non-default types here with import statements
    //用于接收两App的消息接口回调
    import com.scash.aidlservice.Msg;//导入要传输对象的包
    interface IMsgReceiveListener {
       void onReceiveMsg(in Msg msg);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    b. IMsgManagerListener

    // IMsgManagerListener.aidl
    package com.scash.aidlservice;
    
    // Declare any non-default types here with import statements
    import com.scash.aidlservice.Msg;//导入要传输对象的包
    import com.scash.aidlservice.IMsgReceiveListener;
    interface IMsgManagerListener {
         void sendMsg(in Msg msg);
         void registerListener(IMsgReceiveListener receiveListener);
         void unRegisterListener(IMsgReceiveListener receiveListener);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    c. Msg

    // Msg.aidl
    package com.scash.aidlservice;
    // Declare any non-default types here with import statements
    parcelable Msg;
    
    • 1
    • 2
    • 3
    • 4

    d. 然后Rebuild Project

    在这里插入图片描述

    3.编写Msg(AIDL传输只能是Parcelable对象)

    package com.scash.aidlservice;
    
    import android.os.Parcel;
    import android.os.Parcelable;
    
    /**
     * @create 2022/6/17
     * @Describe  AIDL 传输对象时,只能传输实现Parcelable接口的对象
     */
    public class Msg implements Parcelable {
        private String msg;
        private String type;
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    
        protected Msg(Parcel in) {
            msg = in.readString();
            type = in.readString();
        }
    
        public static final Creator<Msg> CREATOR = new Creator<Msg>() {
            @Override
            public Msg createFromParcel(Parcel in) {
                return new Msg(in);
            }
    
            @Override
            public Msg[] newArray(int size) {
                return new Msg[size];
            }
        };
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(msg);
            dest.writeString(type);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    4.编写RemotoService

    package com.scash.aidlservice
    
    import android.app.Service
    import android.content.Intent
    import android.os.IBinder
    import android.os.RemoteCallbackList
    import android.util.Log
    
    /**
     * @create 2022/6/17
     * @Describe
     */
    open class RemotoService : Service() {
        //AIDL不支持正常的接口回调,使用RemoteCallbackList实现接口回调
        val mReceiveListener: RemoteCallbackList<IMsgReceiveListener> =
            RemoteCallbackList<IMsgReceiveListener>()
    
        override fun onBind(intent: Intent?): IBinder? {
            return iBinder
        }
    
        val iBinder = object : IMsgManagerListener.Stub() {
            override fun sendMsg(msg: Msg?) {
                msg?.let { receiveMsg(it) }
            }
    
            override fun registerListener(receiveListener: IMsgReceiveListener?) {
                mReceiveListener.register(receiveListener)
            }
    
            override fun unRegisterListener(receiveListener: IMsgReceiveListener?) {
                val success = mReceiveListener.unregister(receiveListener)
                Log.i("Ljw", "注册是否成功:$success")
            }
    
        }
    
        fun receiveMsg(message: Msg) {
            //通知Callback循环开始,返回N为实现mReceiveListener回调的个数
            var Num = mReceiveListener.beginBroadcast()
            message.msg = message.msg
            repeat(Num) {
                val listener: IMsgReceiveListener = mReceiveListener.getBroadcastItem(it)
                listener.onReceiveMsg(message)
            }
            //通知通知Callback循环结束
            mReceiveListener.finishBroadcast()
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    注册Service

     <service
                android:name=".RemotoService"
                android:exported="true" />
    
    • 1
    • 2
    • 3

    5.编写MsgAdapter(接收消息适配器)

    /**
     * @create 2022/6/23
     * @Describe
     */
    class MsgAdapter(val context: Context, val mList: List<Msg>) :
        RecyclerView.Adapter<MsgAdapter.MyViewHolder>() {
        inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
            val mTvMsg :TextView= view.findViewById(R.id.tv_msg)
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
            val view = LayoutInflater.from(context)
                .inflate(R.layout.item_msg, parent, false)
            return MyViewHolder(view)
        }
    
        override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
            val mSimpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
            (mSimpleDateFormat.format(Date(mList[position].date)) + mList[position].msg).also {
                holder.mTvMsg.text = it
            }
        }
    
        override fun getItemCount(): Int {
           return mList.size
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    6.编写MainActivity

    class MainActivity : AppCompatActivity(), View.OnClickListener {
        val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
        var binder: MyBinder? = null
        var mManagerListener: IMsgManagerListener? = null
        var msgAdapter: MsgAdapter? = null
        var mList: ArrayList<Msg> = ArrayList()
        var mBtnClickStamp: Long = 0//记录按键点击的时间戳
        var mMsg = Msg()
        val mHandler = object : Handler(Looper.getMainLooper()) {
            override fun handleMessage(msg: Message) {
                super.handleMessage(msg)
                if (msg.what == 1) {
                    msgAdapter?.notifyDataSetChanged()
                    binding.rvClient.smoothScrollToPosition(mList.size - 1)
                }
            }
        }
        var mConnection = object : ServiceConnection {
            override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
                binder = iBinder as MyBinder
                mManagerListener = IMsgManagerListener.Stub.asInterface(iBinder)
                mManagerListener?.registerListener(mReceiveListener)
            }
    
            override fun onServiceDisconnected(name: ComponentName?) {
                TODO("Not yet implemented")
            }
    
        }
        val mReceiveListener = object : IMsgReceiveListener.Stub() {
            override fun onReceiveMsg(msg: Msg?) {
                if (IMsgType.CLIENT == msg?.type) {
                    msg.date = System.currentTimeMillis()
                    mList.add(msg)
                    mHandler.sendEmptyMessage(1)
                }
            }
    
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(binding.root)
            var intent = Intent(this, RemotoService::class.java)
            bindService(intent, mConnection, BIND_AUTO_CREATE)
            msgAdapter = MsgAdapter(this, mList)
            binding.rvClient.layoutManager =
                LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
            binding.rvClient.adapter = msgAdapter
            binding.btnSend.setOnClickListener(this)
        }
    
        override fun onDestroy() {
            super.onDestroy()
            mManagerListener?.unRegisterListener(mReceiveListener)
            unbindService(mConnection)
        }
    
        fun isBtnBuffering(): Boolean {
            var duration = System.currentTimeMillis() - mBtnClickStamp
            mBtnClickStamp = System.currentTimeMillis()//记录点击时间
            return Math.abs(duration) <= 400
        }
    
        override fun onClick(v: View?) {
            if (isBtnBuffering()) {
                return
            }
            if (TextUtils.isEmpty(binding.etSendMsg.text.toString())) {
                Toast.makeText(this, "不能发送空数据", Toast.LENGTH_SHORT).show()
            }
            mMsg.msg = binding.etSendMsg.text.toString()
            mMsg.type = IMsgType.SERVICE
            binder?.sendMsg(mMsg)
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    7.新建客户端AIDL文件(跟服务端一致即可)

    在这里插入图片描述

    8.创建客户端传输对象,注意包名要和服务端一致。(路径如下图)在这里插入图片描述

    /**
     * @create 2022/6/17
     * @Describe AIDL 传输对象时,只能传输实现Parcelable接口的对象
     */
    public class Msg implements Parcelable {
        private String msg;
        private String type;
        private long date;
    
        public Msg() {
    
        }
    
        public Msg(String msg, String type) {
            this.msg = msg;
            this.type = type;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    
        public long getDate() {
            return date;
        }
    
        public void setDate(long date) {
            this.date = date;
        }
    
        protected Msg(Parcel in) {
            msg = in.readString();
            type = in.readString();
        }
    
        public static final Creator<Msg> CREATOR = new Creator<Msg>() {
            @Override
            public Msg createFromParcel(Parcel in) {
                return new Msg(in);
            }
    
            @Override
            public Msg[] newArray(int size) {
                return new Msg[size];
            }
        };
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(msg);
            dest.writeString(type);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    9.编写MsgAdapter

    
    /**
     * @create 2022/6/22
     * @Describe
     */
    class MsgAdapter(val context: Context, val mList: List<Msg>) :
        RecyclerView.Adapter<MsgAdapter.MyViewHolder>() {
    
    
        inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
            val tvMsg: TextView = view.findViewById(R.id.tv_msg)
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
            val view = LayoutInflater.from(context)
                .inflate(R.layout.item_msg, parent, false)
            return MyViewHolder(view)
        }
    
        override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
            val mSimpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
            (mSimpleDateFormat.format(Date(mList[position].date)) + mList[position].msg).also {
                holder.tvMsg.text = it
            }
        }
    
        override fun getItemCount(): Int {
            return mList.size
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    10.编写客户端MainActivity

    
    class MainActivity : AppCompatActivity() {
        val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
        var mMsgManger: IMsgManagerListener? = null//定义AIDL
        var myBinder: IMsgManagerListener? = null//定义AIDL
        var mAdapter: MsgAdapter? = null
        val mList = ArrayList<Msg>()
    
        val mHandler = object : Handler(Looper.getMainLooper()) {
            override fun handleMessage(msg: Message) {
                super.handleMessage(msg)
                if (msg.what == 1) {
                    mAdapter?.notifyDataSetChanged()
                    binding.rvItem.smoothScrollToPosition(mList.size - 1)
                }
            }
        }
        var mReceiverMsgListener = object : IMsgReceiveListener.Stub() {
    
            override fun onReceiveMsg(msg: Msg?) {
                if (IMsgType.SERVICE == msg?.type) {
                    msg.date=System.currentTimeMillis()
                    mList.add(msg)
                    mHandler.sendEmptyMessage(1)
                }
            }
    
        }
        var mConnection = object : ServiceConnection {
            override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
                myBinder = IMsgManagerListener.Stub.asInterface(iBinder);
                mMsgManger = IMsgManagerListener.Stub.asInterface(iBinder)
                //链接到死亡代理
                mMsgManger?.asBinder()?.linkToDeath(mDeathRecipient, 0)
                //注册监听
                mMsgManger?.registerListener(mReceiverMsgListener)
            }
    
            override fun onServiceDisconnected(name: ComponentName?) {
    
            }
    
        }
    
        var mDeathRecipient = object : IBinder.DeathRecipient {
            override fun binderDied() {
                if (mMsgManger == null) {
                    return
                }
                mMsgManger!!.asBinder().unlinkToDeath(this, 0)
                mMsgManger = null
            }
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(binding.root)
            val intent = Intent()
            intent.action = "com.scash.aidlservice.RemotoService"
            intent.`package` = "com.scash.aidlservice"
            bindService(intent, mConnection, BIND_AUTO_CREATE)
            mAdapter = MsgAdapter(this, mList)
            binding.rvItem.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL,false)
            binding.rvItem.adapter = mAdapter
            val btn: Button = findViewById(R.id.btn_client_send)
            btn.setOnClickListener {
                val mMsg = Msg()
                mMsg.msg = binding.etSendMsgTest.text.toString()
                mMsg.type = IMsgType.CLIENT
                mMsgManger?.sendMsg(mMsg)
            }
    //        binding.btnClientSend.setOnClickListener {
    //            mMsgManger?.sendMsg(mMsg)
    //        }
        }
    
        override fun onDestroy() {
            super.onDestroy()
            unbindService(mConnection)
            mMsgManger?.unRegisterListener(mReceiverMsgListener)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
  • 相关阅读:
    基于JSP+MySQL的校园网上订餐系统
    工控机设备安全-系统加固的意义
    卷妹带你回顾Java基础(一)每日更新Day4
    资深java面试题及答案整理(五)
    js 数组相同的数据合并,并返回数据个数
    自然语言处理 (NLP) 简介
    机器学习自学成才的十条戒律
    解锁编程潜能:探索亚马逊CodeWhisperer,打造编程世界的声音引导者
    Java NIO 文件通道 FileChannel 用法
    计算机网络笔记4 网络层
  • 原文地址:https://blog.csdn.net/qq_38363506/article/details/125336496