Android中Binder在项目中的具体使用详解

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Android中Binder在项目中的具体使用详解

前言:Binder的介绍

在 Android 中,Binder 是一种跨进程通信(IPC)机制,它是基于进程间通信(IPC)机制中的共享内存和消息传递机制实现的。Binder 的主要作用是在 Android 操作系统中跨进程传递数据和服务,例如 Activity、Service、Broadcast 等都是通过 Binder 实现跨进程通信和交互的

Binder 是 Android 系统的一个重要组成部分,它主要由以下三部分组成:

Binder 驱动:位于底层的驱动程序,它负责提供进程间通信的基础设施和实现对 Binder 对象的创建和跟踪。

Binder API:位于 Java 层,是 Android 应用程序和 Binder 驱动之间的接口,它提供了创建 Binder 服务和跨进程访问 Binder 服务的方法和实现。

Binder 对象:也称为 Binder 服务,是 Android 应用程序中提供跨进程通信的关键对象。每个 Binder 对象都有一个唯一的标识符,被用来标识不同的 Binder 服务,其他进程可以通过这个标识符获取对这个服务的引用并使用它。

在 Android 应用程序中使用 Binder 通常可以通过两种方式实现,一种是使用 AIDL(Android 接口定义语言)定义接口,并通过 Binder 服务实现接口的跨进程调用,另一种是通过 Messenger 实现基于消息的跨进程通信。

本篇使用Binder实现一个模拟第三方QQ登录的一个效果,效果图如下

一、首先创建服务端程序BinderB,详细步骤如下

1、创建BLoginActivity类和activity_b_login.xml,布局不再给出,java代码如下:

private const val NAME = "android"
private const val PWD = "123456"
class BLoginActivity : AppCompatActivity() {
    private var isStartRemote = false
    private lateinit var iLogin: ILoginInterface
    private var conn = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            iLogin = ILoginInterface.Stub.asInterface(service)
        }
        override fun onServiceDisconnected(name: ComponentName?) {
            TODO("Not yet implemented")
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_b_login)
        btn_login.setOnClickListener {
            var account = et_account.text.toString()
            var pwd = et_password.text.toString()
            if (TextUtils.isEmpty(account) || TextUtils.isEmpty(pwd)) {
                ToastUtils.showShort("账号或者密码为空!")
                return@setOnClickListener
            }
            val progress = ProgressDialog(this)
            progress.setTitle("登录")
            progress.setMessage("登录中")
            progress.show()
            Thread {
                SystemClock.sleep(2000)
                runOnUiThread {
                    var loginStatus = false
                    if (NAME == account && PWD == pwd) {
                        ToastUtils.showShort("登录成功!")
                        loginStatus = true
                        finish()
                    } else {
                        ToastUtils.showShort("登录失败!")
                    }
                    iLogin.loginCallback(loginStatus, account)
                    progress.dismiss()
                }
            }.start()
        }
        initBindService()
    }
    private fun initBindService() {
        val intent = Intent()
        intent.action = "BinderA_Action"
        intent.`package` = "com.king.learn" //客户端程序的包名
        bindService(intent, conn, Context.BIND_AUTO_CREATE) 
        isStartRemote = true
    }
    override fun onDestroy() {
        super.onDestroy()
        if (isStartRemote) {
            unbindService(conn)
        }
    }
}

2、创建服务

class LoginService : Service() {
    override fun onBind(intent: Intent?): IBinder? {
        return object : ILoginInterface.Stub() {
            override fun login() {
                LogUtils.d("BinderB_LoginService")
                //单向通信,真实项目中,跨进程都是双向通信,双向服务绑定的
                //做qq登录,qq分享的时候,需要填入自己的包名,就是这个原因
                serviceStartActivity()
            }
            override fun loginCallback(loginStatus: Boolean, loginUser: String?) {
                TODO("Not yet implemented")
            }
        }
    }
    /**
     * 启动页面
     */
    private fun serviceStartActivity() {
        val intent = Intent(this, BLoginActivity::class.java)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        startActivity(intent)
    }
}

2.1、并在清单文件中注册服务

<!--
             android:enabled="true" 是否可以被系统实例化
             android:exported="true" 是否可以能被其他应用隐式调用
             android:process=":remote_server" 表示:应用程序当中需要使用该服务的话,
                                                    会自动创建名为:remote_server的进程
        -->
        <service
            android:name=".service.LoginService"
            android:enabled="true"
            android:exported="true"
            android:process=":remote_server">
            <intent-filter>
                <action android:name="BinderB_Action" />
            </intent-filter>
        </service>

3、创建AIDL名字为ILoginInterface代码如下,服务端程序和客户端程序在同一个包名下面,我这里统一在package com.aidl;

interface ILoginInterface {
      void login();//登录
      void loginCallback(boolean loginStatus,String loginUser);//登录回调
}

二、客户端程序A

1、创建步骤类似,首先创建AActivity 和activity_a.xml

class AActivity : AppCompatActivity() {
    private var isStartRemote: Boolean = false
    private  var iLogin: ILoginInterface?=null
    /**
     * 服务的连接
     */
    private var conn: ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            //使用服务端的功能(方法)
            iLogin = ILoginInterface.Stub.asInterface(service)
        }
        override fun onServiceDisconnected(name: ComponentName?) {
            LogUtils.d("测试")
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_a)
        initBindService()
        btn_login.setOnClickListener {
            if (iLogin != null) {
                try {
                    iLogin?.login()
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            } else {
                ToastUtils.showShort("请先安装QQ应用!")
            }
        }
    }
    /**
     * 绑定服务
     */
    private fun initBindService() {
        val intent = Intent()
        //设置Server应用Action(服务的唯一标识)
        intent.action = "BinderB_Action"
        //设置Server应用包名
        intent.`package` = "com.king.kotlinproject"
        bindService(intent, conn, BIND_AUTO_CREATE)
        isStartRemote = true
    }
    override fun onDestroy() {
        super.onDestroy()
        if (isStartRemote) {
            //解绑服务,一定要记得,不然服务连接异常
            unbindService(conn)
        }
    }
}

2、创建三方应用登录后,返回的服务

class ResultService : Service() {
    override fun onBind(intent: Intent?): IBinder? {
        return object : ILoginInterface.Stub() {
            override fun login() {
                TODO("Not yet implemented")
            }
            override fun loginCallback(loginStatus: Boolean, loginUser: String?) {
                //第三方登录成功后,不用挂起,直接打印了日志
                LogUtils.d("loginStatus:$loginStatus/ loginUser:$loginUser")
            }
        }
    }
}

在AndroidManifest.xml清单文件中,进行注册

<service android:name=".service.ResultService"
            android:enabled="true"
            android:exported="true"
            android:process=":remote">
            <intent-filter>
                <action android:name="BinderA_Action"/>
            </intent-filter>
        </service>

3、创建对应的AIDL ,ILoginInterface

interface ILoginInterface {
    void login();//登录
    void loginCallback(boolean loginStatus,String loginUser);//登录回调
}

日志输入如下:

在服务端B已经启动的情况下,启动客户端程序A,点击进行三方登录

服务端B程序进行日志打印:

在服务端B程序进行登录后,跳转到客户端程序A,打印的

日志如下:


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
8天前
|
JavaScript 前端开发 Android开发
让Vite+Vue3项目在Android端离线打开(不需要起服务)
让Vite+Vue3项目在Android端离线打开(不需要起服务)
|
9天前
|
IDE 开发工具 Android开发
安卓与iOS开发对比:平台选择对项目成功的影响
【9月更文挑战第10天】在移动应用开发的世界中,选择正确的平台是至关重要的。本文将深入探讨安卓和iOS这两大主要移动操作系统的开发环境,通过比较它们的市场份额、开发工具、编程语言和用户群体等方面,为开发者提供一个清晰的指南。我们将分析这两个平台的优势和劣势,并讨论如何根据项目需求和目标受众来做出最佳选择。无论你是初学者还是有经验的开发者,这篇文章都将帮助你更好地理解每个平台的特性,并指导你做出明智的决策。
|
12天前
|
Java 开发工具 Android开发
安卓与iOS开发:平台选择对项目成功的影响
在移动应用开发的浩瀚宇宙中,安卓和iOS两大星系璀璨夺目,各自拥有独特的光芒。本文将穿梭于这两个平台之间,探讨它们在开发环境、用户群体、成本效益等方面的差异,以及这些差异如何影响一个项目的航向和终点。我们将从初学者的视角出发,逐步深入,揭示选择合适平台的重要性,以及如何根据项目需求做出明智的选择。无论你是即将启航的新手开发者,还是已经在这片星海中航行的老手,这篇文章都将为你提供有价值的导航信息。
25 2
|
17天前
|
Java 开发工具 Android开发
探索安卓与iOS开发的差异:平台选择对项目的影响
在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据着重要的位置。本文旨在深入探讨这两个平台在开发过程中的主要差异,包括编程语言、开发工具、用户界面设计、性能优化以及市场分布等方面。通过对比分析,我们将揭示平台选择如何影响项目规划、执行效率和最终成果,为开发者在选择适合自己项目需求的平台时提供参考依据。
|
29天前
|
IDE 开发工具 Android开发
探索安卓与iOS开发的差异:平台选择对项目成功的影响
在移动应用开发的广阔天地中,安卓和iOS两大平台各领风骚,引领着技术进步的潮流。本文旨在深入剖析这两个平台在开发过程中的关键差异点,包括编程语言、开发工具、用户界面设计以及市场分布等方面。通过对比分析,我们不仅能更好地理解每个平台的独特优势,还能洞察这些差异如何影响项目决策和最终成果。无论你是开发者还是企业决策者,了解这些内容都将助你一臂之力,在选择适合自己项目的开发平台时做出更明智的决策。
|
29天前
|
IDE 开发工具 Android开发
探索iOS与安卓开发的差异:平台选择对项目成功的影响
【8月更文挑战第22天】在数字化时代,移动应用成为企业和个人展示创意、提供服务的重要工具。iOS和安卓作为两大主流平台,各自拥有独特的优势和限制。本文将深入探讨这两个平台在开发过程中的主要差异,以及这些差异如何影响项目规划、用户体验和市场策略。通过比较分析,旨在为开发者和企业决策者提供有价值的见解,帮助他们根据项目需求做出明智的平台选择。
|
29天前
|
SQL 分布式计算 大数据
Android项目架构设计问题之平衡技术选型与业务需求之间的关系如何解决
Android项目架构设计问题之平衡技术选型与业务需求之间的关系如何解决
28 0
|
29天前
|
开发工具 Android开发
Android项目架构设计问题之SDK内部减少每次回调时的冗余判断逻辑如何解决
Android项目架构设计问题之SDK内部减少每次回调时的冗余判断逻辑如何解决
17 0
|
29天前
|
开发工具 Android开发
Android项目架构设计问题之外部客户方便地设置回调如何解决
Android项目架构设计问题之外部客户方便地设置回调如何解决
17 0
|
29天前
|
Java API 开发工具
Android项目架构设计问题之为SDK添加新的回调支持如何解决
Android项目架构设计问题之为SDK添加新的回调支持如何解决
14 0