ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Android Sync Adapter 框架中的 Stub 授权器(Authenticator):Android 官方培训课程中文版账户组件创建实战

2026/10/5 1:53:07 拓冰建站 浏览量
Android Sync Adapter 框架中的 Stub 授权器(Authenticator):Android 官方培训课程中文版账户组件创建实战 文档教程移动开发【免费下载链接】android-training-course-in-chineseAndroid官方培训课程中文版项目地址https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese点击查看免费下载导读在 Android 官方培训课程中文版《使用 Sync Adapter 传输数据》系列中Sync Adapter同步适配器框架要求应用在同步数据时必须关联一个设备端账户并提供一个能够接入系统账户与认证框架的授权器Authenticator组件。本篇技术指南以 创建 Stub 授权器 一课为骨架完整讲解如何创建满足框架要求的 Stub 授权器、编写绑定 Service、声明authenticator.xml元数据并在 Manifest 中注册同时结合系列课程的后续内容Stub Content Provider、Sync Adapter 本身及其执行方式说明整个集成链路。读完本文你将能够在自己的 Android 应用中独立实现一个符合 Sync Adapter 框架要求的账户处理组件即使你的应用根本不需要真实的用户账户登录。为什么 Sync Adapter 框架需要一个授权器Sync Adapter 框架在设计上做出两个基本假设详见 系列索引设备端存储了一个账户同步行为总是与某个账户Account绑定发生服务器端可能需要进行登录验证同步过程可能需要把用户凭据如登录名与密码提交给服务器。因此框架要求应用提供一个名为授权器Authenticator的组件作为 Sync Adapter 的组成部分。该组件会集成进 Android 的账户及认证框架android.accounts并通过一组标准的接口来处理用户凭据比如登录信息、认证令牌Auth Token等。即使不用账户也必须提供一个授权器一个常见的误区是如果应用不使用账户系统就可以跳过授权器组件。实际上并非如此——Sync Adapter 框架在结构上强制要求授权器的存在。当应用不使用账户时授权器所处理的凭据信息会被框架忽略因此我们完全可以用一个Stub桩授权器来占位所有需要重写的方法都只是方法存根Stub Method不执行任何真实逻辑按原文档的要求各方法要么返回null要么抛出UnsupportedOperationException与此同时我们需要提供一个绑定 ServiceBound Service让 Sync Adapter 框架能够调用授权器的方法。如果你需要实现一个能够真正处理用户账户的授权器如添加账户获取令牌等真实逻辑原文档建议直接参考android.accounts.AbstractAccountAuthenticator类及其完整的 API 约定本课的重点则是先用最小的成本满足框架的结构性要求。第一步创建继承 AbstractAccountAuthenticator 的 Stub 授权器类添加 Stub 授权器的第一步是创建一个继承AbstractAccountAuthenticator的 Java 类并在所有需要重写的方法中不做任何处理仅返回null或抛出异常。原文档给出的完整示例代码如下/* * Implement AbstractAccountAuthenticator and stub out all * of its methods */ public class Authenticator extends AbstractAccountAuthenticator { // Simple constructor public Authenticator(Context context) { super(context); } // Editing properties is not supported Override public Bundle editProperties( AccountAuthenticatorResponse r, String s) { throw new UnsupportedOperationException(); } // Dont add additional accounts Override public Bundle addAccount( AccountAuthenticatorResponse r, String s, String s2, String[] strings, Bundle bundle) throws NetworkErrorException { return null; } // Ignore attempts to confirm credentials Override public Bundle confirmCredentials( AccountAuthenticatorResponse r, Account account, Bundle bundle) throws NetworkErrorException { return null; } // Getting an authentication token is not supported Override public Bundle getAuthToken( AccountAuthenticatorResponse r, Account account, String s, Bundle bundle) throws NetworkErrorException { throw new UnsupportedOperationException(); } // Getting a label for the auth token is not supported Override public String getAuthTokenLabel(String s) { throw new UnsupportedOperationException(); } // Updating user credentials is not supported Override public Bundle updateCredentials( AccountAuthenticatorResponse r, Account account, String s, Bundle bundle) throws NetworkErrorException { throw new UnsupportedOperationException(); } // Checking features for the account is not supported Override public Bundle hasFeatures( AccountAuthenticatorResponse r, Account account, String[] strings) throws NetworkErrorException { throw new UnsupportedOperationException(); } }逐个方法的作用与 Stub 策略方法正常场景下的用途Stub 策略原因editProperties()允许用户编辑账户属性弹出属性编辑 UI抛UnsupportedOperationExceptionStub 不支持编辑属性addAccount()向系统添加账户返回nullStub 不添加额外账户confirmCredentials()验证用户凭据是否正确返回nullStub 忽略凭据确认请求getAuthToken()为账户获取认证令牌抛UnsupportedOperationExceptionStub 不提供认证令牌getAuthTokenLabel()返回认证令牌的可读标签抛UnsupportedOperationExceptionStub 不支持令牌标签updateCredentials()更新用户的登录凭据抛UnsupportedOperationExceptionStub 不支持更新凭据hasFeatures()查询账户是否支持某项特性抛UnsupportedOperationExceptionStub 不支持特性检查可以注意到 Stub 策略的差异是有讲究的涉及被动应答的方法addAccount、confirmCredentials返回null表示无操作成功而涉及主动能力的方法则直接抛异常明确声明该能力不存在。这与 Sync Adapter 框架即使忽略凭据信息也能正常工作的设计是一致的——框架要求组件存在但并不强制组件实现全部能力。构造函数的细节构造函数必须调用super(context)将Context传给父类AbstractAccountAuthenticator。这个Context由后续的绑定 Service 在onCreate()中实例化授权器时传入见下文第二步。第二步创建绑定 Service将授权器接入框架Stub 授权器类本身不会被框架直接调用。为了让 Sync Adapter 框架可以访问授权器我们需要创建一个绑定 ServiceBound Service它负责提供一个 Android Binder 对象使框架能够跨进程调用授权器的方法并在授权器与框架之间传递数据。在 onCreate() 中实例化授权器框架会在第一次需要访问授权器时启动该 Service。因此最合适的做法是在Service.onCreate()中调用授权器的构造函数完成实例化将授权器的生命周期与 Service 绑定在一起。原文档的示例代码如下/** * A bound Service that instantiates the authenticator * when started. */ public class AuthenticatorService extends Service { ... // Instance field that stores the authenticator object private Authenticator mAuthenticator; Override public void onCreate() { // Create a new authenticator object mAuthenticator new Authenticator(this); } /* * When the system binds to this Service to make the RPC call * return the authenticators IBinder. */ Override public IBinder onBind(Intent intent) { return mAuthenticator.getIBinder(); } }关键点解析mAuthenticator实例字段保存授权器对象的引用供onBind()使用onCreate()Service 首次创建时实例化Authenticator传入的this即 Service 的 ContextonBind()返回mAuthenticator.getIBinder()。AbstractAccountAuthenticator内部会构建一个 Binder 实现这是父类源码行为从代码结构可以推断框架拿到这个IBinder后即可发起 RPC 调用执行授权器的各个方法。第三步编写授权器元数据文件authenticator.xml要将授权器组件集成进 Sync Adapter 框架与账户框架还需要向框架提供描述组件信息的元数据。元数据声明了为 Sync Adapter 创建的账户类型以及如果需要用户可见系统将要显示的UI 元素。元数据文件放在项目目录的/res/xml/下文件名可以自定义但按照惯例通常命名为authenticator.xml。该文件的核心是一个account-authenticator标签包含以下四个属性android:accountType账户类型必填Sync Adapter 框架要求每一个适配器都有一个域名形式的账户类型例如example.com框架会把它作为 Sync Adapter 的内部标识的一部分如果服务器端需要登录账户类型会和账户一起发送到服务器作为登录凭据的一部分即使服务器不需要登录也必须提供一个账户类型——此时使用一个我们能控制域名的值即可例如自己拥有的域名。框架仍会使用它来管理 Sync Adapter只是该值不会被发送到服务器。android:icon图标指向一个包含图标的 Drawable 资源如果在res/xml/syncadapter.xml中通过android:userVisibletrue让 Sync Adapter 可见则必须提供该图标资源图标会显示在系统设置中的账户Accounts一栏内。android:smallIcon小图标指向一个微小版本图标的 Drawable 资源当屏幕尺寸较小时该资源可能会替代android:icon中指定的图标资源。android:label标签指明用户账户类型的本地化字符串string/...资源引用便于做多语言适配若 Sync Adapter 可见userVisibletrue则需要提供它显示在系统设置账户一栏中位于授权器图标旁边。原文档给出的完整 XML 示例?xml version1.0 encodingutf-8? account-authenticator xmlns:androidhttp://schemas.android.com/apk/res/android android:accountTypeexample.com android:icondrawable/ic_launcher android:smallIcondrawable/ic_launcher android:labelstring/app_name/关于 accountType 一致性的重要约定从 创建 Sync Adapter 一课可以看出这个android:accountType的值不是孤立的它与整条同步链路中的多个位置必须保持一致Sync Adapter 元数据文件syncadapter.xml中的android:accountType必须与authenticator.xml中的值一致应用代码中用于创建虚拟账户的常量ACCOUNT_TYPE见 创建 Sync Adapter 中CreateSyncAccount()的示例也必须使用同一值后续调用ContentResolver.requestSync()、addPeriodicSync()等方法时传入的账户都基于该账户类型。这一一处声明、多处引用的约束是 Sync Adapter 集成中最容易踩坑的地方之一。第四步在 Manifest 清单文件中声明授权器 Service元数据文件只是描述信息要让系统真正认识并启动授权器必须在应用的AndroidManifest.xml中添加service标签作为application的子标签。原文档的示例service android:namecom.example.android.syncadapter.AuthenticatorService intent-filter action android:nameandroid.accounts.AccountAuthenticator/ /intent-filter meta-data android:nameandroid.accounts.AccountAuthenticator android:resourcexml/authenticator / /service两个关键配置元素的职责intent-filter配置了一个可被android.accounts.AccountAuthenticator这个 Action 激活的过滤器。这个 Intent 由系统在需要运行授权器时发出过滤器被激活后系统会启动AuthenticatorService也就是第二步中封装授权器的 Service。meta-data声明授权器的元数据。android:nameandroid.accounts.AccountAuthenticator将这段元数据与授权器框架连接起来android:resourcexml/authenticator指向我们第三步创建的授权器元数据文件。值得注意的是这里service的android:name必须与 创建 Sync Adapter 中 Sync Adapter 绑定 ServiceSyncService区分开来授权器 Service 与 Sync Adapter Service 是两个不同的组件各自有独立的 intent-filter Action——前者是android.accounts.AccountAuthenticator后者是android.content.SyncAdapter。完整的四步集成清单把前文串起来一个 Stub 授权器在应用中的完整落地路径是步骤产物位置1. 创建授权器类Authenticator extends AbstractAccountAuthenticator全部方法为存根src/源码目录2. 创建绑定 ServiceAuthenticatorServiceonCreate()实例化授权器onBind()返回getIBinder()src/源码目录3. 编写元数据authenticator.xml声明accountType、icon、smallIcon、labelres/xml/4. Manifest 声明service intent-filter meta-dataAndroidManifest.xml与后续课程的衔接这条同步链路的其他环节Stub 授权器只是 Sync Adapter 集成中的第一个组件。根据原文档结尾的指引Sync Adapter 框架除了授权器之外还需要Content Provider框架被设计为与设备数据由 Content Provider 管理协同工作。如果应用没有自己的 Content Provider需要创建Stub Content Provider创建 Stub Content Provider它继承ContentProvider但所有方法返回null或0并且在 Manifest 中以android:syncabletrue声明以避免 Sync Adapter 运行崩溃若应用已有 Content Provider 则可跳过这一步。Sync Adapter 本身将数据传输代码封装进继承AbstractThreadedSyncAdapter的类实现onPerformSync()再配以绑定 Service、syncadapter.xml元数据与 Manifest 声明详见 创建 Sync Adapter。虚拟账户在 创建 Sync Adapter 中还需要通过AccountManager.addAccountExplicitly()在系统中注册一个使用授权器accountType的虚拟账户通常在启动 Activity 的onCreate()中完成框架才能将同步请求与账户关联起来。权限声明完整的 Sync Adapter 应用还需要在 Manifest 中声明android.permission.INTERNET网络访问、android.permission.READ_SYNC_SETTINGS与android.permission.WRITE_SYNC_SETTINGS读写同步配置以及android.permission.AUTHENTICATE_ACCOUNTS使用授权器组件等权限。运行方式最后通过事件响应、数据变更、网络消息、定时调度等机制触发同步详见 执行 Sync Adapter。整个系列的四篇课程索引正好构成一条从授权器 → Content Provider → Sync Adapter → 调度执行的完整链条本课创建 Stub 授权器是这条链路的第一块基石。常见问题与排查要点结合本课内容与系列后续课程的约束集成时建议重点检查以下几点accountType是否在全部位置保持一致authenticator.xml、syncadapter.xml、代码中的ACCOUNT_TYPE常量三处必须为同一个域名形式的值否则框架无法将账户、授权器与 Sync Adapter 关联起来authenticator.xml中的资源引用是否真实存在drawable/ic_launcher、string/app_name等资源必须存在尤其在userVisibletrue时图标与标签是硬性要求Manifest 中service的android:name是否与授权器 Service 类的完整包名一致meta-data的android:resource是否指向正确的xml/authenticator文件名与res/xml/下实际文件一致是否区分了授权器 Service 与 Sync Adapter Service两者 Action 不同切勿混淆或遗漏其一同步链路完整性仅有授权器还不够还需 Stub Content Provider、Sync Adapter 组件与虚拟账户缺一不可否则 Sync Adapter 运行时会失败。小结本课虽然标题是Stub桩但它是理解 Android 账户与认证框架如何与 Sync Adapter 框架协作的绝佳切入点AbstractAccountAuthenticator定义了一组标准化的凭据处理接口绑定 Service 负责把组件暴露给系统authenticator.xml声明账户类型与 UI 元数据Manifest 完成最后的注册。对于不需要真实账户的应用这四步即可满足框架的结构性要求而当你日后需要实现真实的账户登录与令牌管理时只需要在同样的框架下把各存根方法替换为真实实现即可架构骨架完全复用。赞分享文档教程移动开发【免费下载链接】android-training-course-in-chineseAndroid官方培训课程中文版项目地址https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese点击查看免费下载相关推荐Android官方培训课程中文版教程Android官方培训课程中文版教程 1. 项目介绍 Android官方培训课程中文版Android Training Course in Chinese是文档教程移动开发YimMenu终极防护指南5步打造最安全的GTA5游戏体验YimMenu终极防护指南5步打造最安全的GTA5游戏体验 YimMenu是一款专为GTA5在线模式设计的开源辅助工具它不仅提供了丰富的游戏功能增强更重要逆向工程游戏开发智慧教育平台教材PDF下载器粘贴链接到文件落盘的完整 3 步实操手册智慧教育平台教材PDF下载器粘贴链接到文件落盘的完整 3 步实操手册 老师、学生、家长用这个教材PDF下载器解决一个问题国家中小学智慧教育平台只能在线翻课本文档教程移动开发上一篇React Native Navigation安全考虑防止导航劫持和安全漏洞的终极指南下一篇MindGraph跨平台兼容性Windows与Linux部署差异解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考