当前位置: 首页 > news >正文

再次理解Android账号管理体系

目录

✅ 0. 需求

📂 1. 前言

🔱 2. 使用

2.1 账户体系前提

2.2 创建账户服务

2.3 操作账户-增删改查

💠 3. 源码流程


✅ 0. 需求

        试想,自己去实现一个账号管理体系,该如何做呢?

        ——————————

        最近有遇到这样一个需求:AR眼镜只支持同时与一个手机绑定,即:AR眼镜已与手机绑定过的话,不再支持与其他手机绑定;如要绑定其他手机,需要先解绑当前手机才能重新绑定。

        理解一下需求,即是:眼镜端需要账号管理体系,主要用来存储已绑定过手机的token。

        AR眼镜绑定手机时序图,如下所示:


 

📂 1. 前言

        我们知道,Android的账号管理体系是用来管理用户在Android设备上的身份验证和授权的系统,包括了对账号的创建、授权、修改和删除等操作的管理。

        那么,我们为什么要使用Android的账号管理体系?

        ——————————

        尽管,我们可以自己使用SP、MMKV、文件或数据库等方式来存储、更新、删除账户、密码或AuthToken;但其实涉及到跨进程通信,实现起来其实是稍显麻烦的;并且对于数据安全,信息加密这块的可靠性也有待商榷。

        另外,从本文第一张图可见,我们在架构设计中规划的账号体系服务,是寄生于Android启动时system_server开启的服务,然后通过binder方式,提供给其他进程使用。

        然而,在技术预研时发现,强大的Android早已想到了这点,在Android 2.0开始就加入了新包android.accounts,为我们准备好了这样一个服务ACCOUNT_SERVICE。

        而且,该包功能已十分强大,我们可以直接拿来使用,功能主要包括:

  1. 集中式的账户管理API,可以安全地存储和访问认证的令牌和密码;
  2. 可以在同一个设备中管理同一应用的多个不同账号,能够自动批量的同步服务器更新账户,甚至可以和不同服务器进行数据同步和安全认证;
  3. 把账户的验证过程、AuthToken的获取过程分离出来,降低程序的耦合性;
  4. 并且会在”设置”应用中添加一个账户入口;
  5. 方便应用间账号共享。

🔱 2. 使用

2.1 账户体系前提

        1)账号体系共享前提:使用相同的签名

        2)权限申明:

<uses-permission android:name="android.permission.GET_ACCOUNTS" />

2.2 创建账户服务

        步骤一:定义一个action为android.accounts.AccountAuthenticator的Intent的Service,并在meta-data的resource属性指定该Account基本显示信息的xml文件authenticator,模版代码如下:

<serviceandroid:name=".portal.feature.account.service.AccountService"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.accounts.AccountAuthenticator" /></intent-filter><meta-dataandroid:name="android.accounts.AccountAuthenticator"android:resource="@xml/authenticator" />
</service>

        步骤二:在res下的xml文件夹中新建authenticator.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"android:accountType="com.agg.account"android:icon="@drawable/ic_test"android:label="AggAccount"android:smallIcon="@drawable/ic_test" />

        :android:accountType表示的是Account类型,它必须是唯一的,一般是包名。

        步骤三:创建继承自AbstractAccountAuthenticator的Authenticator文件,如下:

class Authenticator(context: Context) : AbstractAccountAuthenticator(context) {override fun editProperties(response: AccountAuthenticatorResponse?, accountType: String?): Bundle? {return null}override fun addAccount(response: AccountAuthenticatorResponse?,accountType: String?,authTokenType: String?,requiredFeatures: Array<out String>?,options: Bundle?): Bundle? {return null}override fun getAuthToken(response: AccountAuthenticatorResponse?,account: Account,authTokenType: String?,options: Bundle?): Bundle? {return null}override fun confirmCredentials(response: AccountAuthenticatorResponse?, account: Account?, options: Bundle?): Bundle? {return null}override fun getAuthTokenLabel(authTokenType: String?): String {return ""}override fun updateCredentials(response: AccountAuthenticatorResponse?,account: Account?,authTokenType: String?,options: Bundle?): Bundle? {return null}override fun hasFeatures(response: AccountAuthenticatorResponse?, account: Account?, features: Array<out String>?): Bundle? {return null}}

        步骤四:创建帐户Service,并在Service的onBind中调AbstractAccountAuthenticator的getIBinder()返回其用于远程调用的IBinder,如下所示:

class AccountService : Service() {private var authenticator: Authenticator? = nulloverride fun onCreate() {super.onCreate()authenticator = Authenticator(this)}override fun onBind(intent: Intent?): IBinder? {return authenticator?.iBinder}}

        :运行起来程序后,在“设置”应用-“帐户”-“添加帐户”列表中就已可以发现自己的app了。

2.3 操作账户-增删改查

        1)获取所有账号

    /*** 获取所有账号*/fun getAllAccount(context: Context) {val accountManager = context.getSystemService(Context.ACCOUNT_SERVICE) as AccountManagerLog.e(TAG, "getAllAccount: size = ${accountManager.accounts.size}")for (account in accountManager.accounts) {Log.e(TAG, "getAllAccount: $account")}}

         2)添加账号

    /*** 添加账号*/fun addAccount(context: Context, account: Account, password: String, authToken: String) {val bundle = Bundle()bundle.putString(AccountManager.KEY_ACCOUNT_NAME, account.name)bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type)bundle.putString(AccountManager.KEY_AUTHTOKEN, authToken)bundle.putString(AccountManager.KEY_PASSWORD, password)AccountManager.get(context).addAccountExplicitly(account, password, bundle)}

         3)更新某个账号

    /*** 更新某个账号*/fun updateAccount(context: Context, account: Account, password: String = "", authToken: String = "") {var updatePassword = passwordvar updateAuthToken = authTokenAccountManager.get(context).apply {if (updatePassword.isEmpty()) {updatePassword = getUserData(account, AccountManager.KEY_PASSWORD)}if (updateAuthToken.isEmpty()) {updateAuthToken = getUserData(account, AccountManager.KEY_AUTHTOKEN)}removeAccountExplicitly(account)}addAccount(context, account, updatePassword, updateAuthToken)}

         4)删除某个账号

    /*** 删除某个账号*/fun delAccount(context: Context, account: Account) {val isRemoveSuccess = AccountManager.get(context).removeAccountExplicitly(account)Log.e(TAG, "delAllAccount: isRemoveSuccess = $isRemoveSuccess, $account")}

          5)删除所有账号

    /*** 删除所有账号*/fun delAllAccount(context: Context) {val accountManager = AccountManager.get(context)for (account in accountManager.accounts) {val isRemoveSuccess = accountManager.removeAccountExplicitly(account)Log.e(TAG, "delAllAccount: isRemoveSuccess = $isRemoveSuccess, $account")}}

💠 3. 源码流程

  • 从系统启动system_server进程,进而启动ACCOUNT_SERVICE服务开始;
  • AccountManager是一个面向应用程序开发的组件,它提供了一套对应于IAccountManager协议的应用程序接口;
  • 这组接口通过Binder机制与系统服务AccountManagerService进行通信,协作完成帐号相关的操作;
  • 同时AccountManager接收authenticators提供的回调,以便在帐号操作完成之后向调用此帐号服务的业务返回对应的接口,同时触发这个业务对结果的处理。

相关文章:

再次理解Android账号管理体系

目录 ✅ 0. 需求 &#x1f4c2; 1. 前言 &#x1f531; 2. 使用 2.1 账户体系前提 2.2 创建账户服务 2.3 操作账户-增删改查 &#x1f4a0; 3. 源码流程 ✅ 0. 需求 试想&#xff0c;自己去实现一个账号管理体系&#xff0c;该如何做呢&#xff1f; ——————————…...

如何在Blender中压缩/减小GLTF模型的大小

GLTF 如何在Blender中压缩/减小GLTF模型的大小 Blender是一款功能强大的开源软件&#xff0c;旨在创建3D图形&#xff0c;动画和视觉效果。它支持多种文件格式的导入和导出&#xff0c;包括GLB&#xff0c;GLTF&#xff0c;DAE&#xff0c;OBJ&#xff0c;ABC&#xff0c;USD…...

IntelliJ IDEA使用_Plugin插件推荐

官网插件库&#xff1a;https://plugins.jetbrains.com/search 代码规范检测&#xff1a;Alibaba Java Coding Guidelines码云&#xff1a;Giteemybatis插件&#xff1a;MyBatisX多颜色括号&#xff1a;Rainbow Brackets操作快捷键提示&#xff1a;Key Promoter X力扣&#xff…...

Ajax fetch navigator.sendBeacon 三个的区别

Ajax、fetch 和 navigator.sendBeacon 是用于发送网络请求的不同方法。 Ajax: Ajax 是一种传统的用于发送异步请求的技术。它使用 XMLHttpRequest 对象来发送数据和接收响应。通过创建 XMLHttpRequest 对象&#xff0c;你可以通过调用其 open() 方法指定请求的类型和 URL&#…...

map-reduce执行过程

Map阶段 Map 阶段是 MapReduce 框架中的一个重要阶段&#xff0c;它负责将输入数据转换为中间数据。Map 阶段由一个或多个 Map 任务组成&#xff0c;每个 Map 任务负责处理输入数据的一个子集。 执行步骤 Map 阶段的过程可以分为以下几个大步骤&#xff1a; 输入数据分配&a…...

技术人员怎样提升对业务的理解

技术服务于业务。 一个技术人员想要走得更远&#xff0c;不能仅局限于技术&#xff0c;需要对自己所从事的业务领域有不断深入和全面的理解。 所谓业务领域&#xff0c;就是大家平常自我介绍&#xff0c;不会仅简单说我是搞C的&#xff0c;我是搞JAVA的&#xff0c;而是游戏后台…...

【分布式】分布式事务:2PC

分布式事务的问题可以分为两部分&#xff1a; 并发控制 concurrency control原子提交 atomic commit 分布式事务问题的产生场景&#xff1a;一份数据被分片存在多台服务器上&#xff0c;那么每次事务处理都涉及到了多台机器。 可序列化&#xff08;并发控制&#xff09;&…...

回归与聚类算法系列④:岭回归

目录 1. 背景 2. 数学模型 3. 特点 4. 应用领域 5. 岭回归与其他正则化方法的比较 6、API 7、代码 8、总结 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家博主&#xff0c;专注于Java领域学习&#xff0c;擅长web应用开发、数…...

idea配置git(gitee)并提交(commit)推送(push)

Intellij Idea VCS | 版本控制 - 知乎 IDEA项目上传到gitee仓库_idea上传代码到gitee_robin19712的博客-CSDN博客 git程序下载国内镜像地址&#xff1a; https://registry.npmmirror.com/binary.html?pathgit-for-windows/v2.42.0.windows.2/ 解压后放到固定路径&#xff1a…...

(19)Task异步:任务创建,返回值,异常捕捉,任务取消,临时变量

一、Task任务的创建 1、用四种方式创建&#xff0c;界面button,info各一。 程序代码 private void BtnStart_Click(object sender, EventArgs e){Task t new Task(() >{DisplayMsg($"[{Environment.CurrentManagedThreadId}]new Task.---1");});t.Start()…...

设备树的理解与运用

设备树&#xff1a; 本质是一个文件&#xff0c;包含很多节点&#xff0c;每个节点里边是对设备属性的描述&#xff08;包括GPIO&#xff0c;时钟&#xff0c;中断等等&#xff09;,其中节点&#xff08;node&#xff09;和属性&#xff08;property&#xff09;就是设备树最重…...

【AIGC】提示词 Prompt 分享

提示词工程是什么&#xff1f; Prompt engineering&#xff08;提示词工程&#xff09;是指在使用语言模型进行生成性任务时&#xff0c;设计和调整输入提示&#xff08;prompts&#xff09;以改善模型生成结果的过程。它是一种优化技术&#xff0c;旨在引导模型产生更加准确、…...

【Axure视频教程】取整函数

今天教大家在Axure里如何使用三种不同的取整函数&#xff0c;包括向上取整、向下取整和四舍五入取整。具体效果可以参考下方视频。该教程从0开始制作&#xff0c;手把手教学&#xff0c;无论是新手小白还是有一定基础的同学&#xff0c;都可以学习的哦。 【视频教程——试看版…...

MySQL清空表

当我们需要清空一个表中的所有行时&#xff0c;除了使用 DELETE * FROM table 还可以使用 TRUNCATE TABLE 语句。 如果想要清空一个表&#xff0c; TRUNCATE TABLE 语句比 DELETE语句更加有效。 TRUNCATE TABLE 语法 TRUNCATE TABLE 的语法很简单&#xff0c;如下&#xff1a…...

使用IDEA创建Vue3通过Vite实现工程化

1、创建Vite项目的分步说明 IntelliJ IDEA与Vite构建工具集成&#xff0c;改善了前端开发体验。Vite 由一个开发服务器和一个构建命令组成。构建服务器通过本机 ES 模块提供源文件。生成命令将代码与汇总捆绑在一起&#xff0c;汇总预配置为输出高度优化的静态资产以供生产。In…...

GitLab使用的最简便方式

GitLab介绍 GitLab是一个基于Git版本控制系统的开源平台&#xff0c;用于代码托管&#xff0c;持续集成&#xff0c;以及协作开发。它提供了一套完整的工具&#xff0c;以帮助开发团队协同工作、管理和部署代码。 往往在企业内部使用gitlab管理代码&#xff0c;记录一下将本地代…...

MySQL数据库20G数据迁移至其他服务器的MySQL库或者云MySQL库

背景&#xff1a;20G的MySQL数据迁移至火山云MySQL库&#xff0c;使用navicat的数据传输工具迁移速度耗费时间过长。 方案一&#xff1a;使用火山云提供的MySQL数据迁移服务&#xff08;其他大厂应该提供的也有&#xff09; 方案二&#xff1a;使用数据迁移工具kettle&#x…...

build.gradle配置文件详解

Andorid Studio高版本和低版本的build.gradle配置逻辑有些差异 安卓项目中相关编译文件的介绍 gradle-wrapper.properites&#xff1a;配置Gradle Wrapper gradle.properties&#xff1a;配置Gradle的编译参数。具体配置见Gradle官方文档:com.android.build.gradle | Andro…...

2024拼多多校招面试真题汇总及其解答(二)

6. 【算法题】归并排序 归并排序(Merge Sort)是一种分治算法,它将待排序的序列递归地分成两个子序列,然后将两个有序的子序列合并成一个有序的序列。 归并排序的算法流程如下: 递归地将待排序的序列分成两个子序列,直到每个子序列只有一个元素。将两个有序的子序列合并…...

自动化运维工具Ansible教程(一)【入门篇】

文章目录 前言Ansible 入门到精通入门篇进阶篇精通篇入门篇1. Ansible 简介2. 安装 Ansible1. 通过包管理器安装&#xff1a;2. 通过源码安装&#xff1a; 3. Ansible 的基本概念和核心组件4. 编写和运行第一个 Ansible Playbook5. 主机清单和组织结构主机清单组织结构 6. Ansi…...

基于MCP协议构建AI驱动的Upwork自动化工作流:从工具化接口到安全实践

1. 项目概述&#xff1a;一个连接AI与自由职业平台的智能桥梁如果你是一名自由职业者&#xff0c;或者正在探索如何用AI来优化你的工作流程&#xff0c;那么你肯定对在Upwork、Fiverr这类平台上反复刷新、筛选项目、撰写提案的繁琐过程深有体会。每天花上几个小时&#xff0c;只…...

终极指南:3分钟为Axure RP安装免费中文语言包,彻底告别英文界面困扰

终极指南&#xff1a;3分钟为Axure RP安装免费中文语言包&#xff0c;彻底告别英文界面困扰 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axu…...

别再为地址映射头疼了!台达DVP50MC11T与西门子/欧姆龙PLC的Modbus通信差异对比

台达DVP50MC11T与主流PLC的Modbus通信地址映射实战解析 在工业自动化项目中&#xff0c;Modbus通信协议因其简单可靠的特点被广泛应用。但对于熟悉西门子或欧姆龙PLC的工程师来说&#xff0c;初次接触台达DVP50MC11T系列时&#xff0c;往往会对其特殊的地址映射方式感到困惑。…...

从零移植Debian到红米2:解锁MSM8916上的主线Linux手机体验

1. 为什么选择红米2作为Linux移植平台 红米2作为2015年发布的入门级智能手机&#xff0c;搭载高通骁龙410&#xff08;MSM8916&#xff09;平台&#xff0c;1GB内存8GB存储的配置在今天看来已经相当落伍。但正是这种"过时硬件"反而成为了极客们眼中的宝藏开发板。我选…...

SM3国密算法实战:从原理到Java代码实现与数据完整性校验

1. SM3国密算法&#xff1a;你的数据安全守门人 第一次听说SM3算法时&#xff0c;我正在处理一个政府项目的投标文件加密需求。客户明确要求必须使用国密标准算法&#xff0c;当时我对这类算法还停留在"听说过但没用过"的阶段。经过两周的实战摸索&#xff0c;我发现…...

Win10+Ubuntu双系统避坑指南:从Legacy到UEFI启动模式切换的完整流程

Win10Ubuntu双系统避坑指南&#xff1a;从Legacy到UEFI启动模式切换的完整流程 每次看到朋友在双系统安装过程中反复重启、对着报错界面抓耳挠腮的样子&#xff0c;我都会想起自己第一次尝试时连续报废三块硬盘的惨痛经历。特别是当Windows 10已经以Legacy模式安装在MBR磁盘上&…...

从学生到工程师:我如何用大学单片机课设代码搞定第一个嵌入式项目(STM8实战)

从学生到工程师&#xff1a;STM8实战中如何将课设代码升级为工业级解决方案 记得大三那年&#xff0c;我第一次在实验室里点亮STM8开发板的LED时&#xff0c;那种成就感至今难忘。但当我真正进入企业参与嵌入式项目开发时&#xff0c;才发现学校里的"标准答案"在真实…...

别再死记Ld≠Lq了!从磁路角度,手把手教你区分永磁同步电机的凸极与隐极

永磁同步电机&#xff1a;从磁路本质破解凸极与隐极的认知迷思 在电机工程领域&#xff0c;永磁同步电机(PMSM)的凸极与隐极特性常被简化为"Ld≠Lq"的数学表述&#xff0c;这种表面化的理解就像仅通过体温判断疾病一样片面。真正掌握这一概念需要深入磁路层面&#x…...

AI全领域热点速递(2026年5月11日)

&#x1f48c; 关心家人&#xff0c;从每日报平安开始。万年历提醒微信小程序&#xff0c;您值得体验。&#x1f4f0; 每日整理AI领域核心动态&#xff0c;精选有价值资讯&#xff0c;精简可读&#xff0c;适合收藏备查。&#x1f916; AI全领域热点速递&#xff08;2026年5月1…...

PyCharm专业版SSH远程开发环境一站式部署指南

1. PyCharm专业版安装与激活 作为数据科学和算法开发的主力工具&#xff0c;PyCharm专业版提供了完整的远程开发支持。首先需要从JetBrains官网下载对应操作系统的安装包。这里有个小技巧&#xff1a;如果你使用的是Windows系统但需要连接Linux服务器开发&#xff0c;建议选择W…...