Wear OS 应用可以在没有配套应用的情况下独立运行。这意味着 Wear OS 应用在访问来自互联网的数据时需要自行管理身份验证。但手表的屏幕尺寸小,输入功能有限,限制了 Wear OS 应用可以使用身份验证选项。
本指南介绍了 Wear OS 应用的推荐身份验证方法,以及当这些方法不适合应用的用例时的替代方法。
要详细了解如何设计良好的登录体验,请查看 登录 UX 指南。
访客模式
不要对所有功能都要求身份验证。相反,应尽可能地为用户提供无需登录即可使用功能。
用户可能会在没有使用移动应用的情况下发现并安装您的 Wear 应用,因此他们可能没有帐户,也不了解应用提供的功能。确保访客模式功能准确地展示了应用的功能。
某些设备可能会保持解锁更长时间
在支持运行 Wear OS 5 或更高版本的设备上,系统会检测用户是否将设备佩戴在手腕上。如果用户关闭手腕检测,然后从手腕上取下设备,系统会将设备保持解锁状态的时间比平时更长。
如果您的应用需要更高级别的安全性(例如在显示可能敏感或私密数据时),首先检查手腕检测是否已启用
val wristDetectionEnabled =
isWristDetectionAutoLockingEnabled(applicationContext)
如果此方法的返回值为 false
,则在显示用户特定内容之前,提示用户登录应用中的帐户。
推荐的身份验证方法
使用以下身份验证方法来使独立 Wear OS 应用能够获取用户身份验证凭据。
使用数据层传递令牌
手机配套应用可以使用 Wearable Data Layer 安全地将身份验证数据传输到 Wear OS 应用。将凭据作为消息或数据项传输。
这种身份验证通常不需要用户进行任何操作。但是,请避免在未告知用户正在登录的情况下执行身份验证。您可以使用简单的、可关闭的屏幕告知用户其帐户正在从移动设备转移。
重要提示:您的 Wear 应用必须提供至少一种其他身份验证方法,因为此选项仅在安装了相应移动应用的 Android 配对手表上有效。为没有相应移动应用或其 Wear OS 设备与 iOS 设备配对的用户提供备用身份验证方法。
使用来自移动应用的数据层传递令牌,如以下示例所示
val token = "..." // Auth token to transmit to the wearable device. val dataClient: DataClient = Wearable.getDataClient(context) val putDataReq: PutDataRequest = PutDataMapRequest.create("/auth").run { dataMap.putString("token", token) asPutDataRequest() } val putDataTask: Task<DataItem> = dataClient.putDataItem(putDataReq)
监听手表应用上的数据更改事件,如以下示例所示
val dataClient: DataClient = Wearable.getDataClient(context) dataClient.addListener{ dataEvents -> dataEvents.forEach { event -> if (event.type == DataEvent.TYPE_CHANGED) { val dataItemPath = event.dataItem.uri.path ?: "" if (dataItemPath.startsWith("/auth")) { val token = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("token") // Display interstitial screen to notify the user they are being signed in. // Then, store the token and use it in network requests. } } } }
有关使用可穿戴数据层的更多信息,请参阅 在 Wear OS 上发送和同步数据.
使用 OAuth 2.0
Wear OS 支持两种基于 OAuth 2.0 的流程,将在以下部分中介绍
注意:为帮助确保您的应用在手表进入环境模式时不会关闭,请使用 AmbientModeSupport.attach
在执行身份验证的活动中启用始终开启。有关环境模式最佳实践的更多信息,请参阅 让您的应用在 Wear 上可见.
代码交换证明密钥 (PKCE)
要有效地使用 PKCE,请使用 RemoteAuthClient
.
要从您的 Wear OS 应用执行对 OAuth 提供者的身份验证请求,请创建一个 OAuthRequest
对象。此对象包含一个指向您 OAuth 端点的 URL(用于获取令牌)和一个 CodeChallenge
对象。以下代码显示了创建身份验证请求的示例
val request = OAuthRequest.Builder(this.applicationContext) .setAuthProviderUrl(Uri.parse("https://....")) .setClientId(clientId) .setCodeChallenge(codeChallenge) .build()
构建身份验证请求后,使用 sendAuthorizationRequest()
方法将其发送到配套应用
val client = RemoteAuthClient.create(this) client.sendAuthorizationRequest(request, { command -> command?.run() }, object : RemoteAuthClient.Callback() { override fun onAuthorizationResponse( request: OAuthRequest, response: OAuthResponse ) { // Extract the token from the response, store it and use it in network requests. } override fun onAuthorizationError(errorCode: Int) { // Handle error } } )
此请求将触发对配套应用的调用,然后配套应用将在用户手机上的网络浏览器中显示一个授权 UI。OAuth 2.0 提供者将对用户进行身份验证,并获得用户对请求的权限的同意。响应将发送到自动生成的重定向 URL。
成功或失败授权后,OAuth 2.0 服务器将重定向到请求中指定的 URL。如果用户批准访问请求,则响应将包含一个授权代码。如果用户不批准请求,则响应将包含一个错误消息。
响应采用查询字符串的形式,如下面的示例所示
https://wear.googleapis.com/3p_auth/com.your.package.name?code=xyz https://wear.googleapis-cn.com/3p_auth/com.your.package.name?code=xyz
这将加载一个页面,该页面将引导用户进入配套应用。配套应用将验证响应 URL 并使用 onAuthorizationResponse
API 将响应中继到第三方手表应用。
手表应用然后可以将授权代码交换为访问令牌。
注意:构建 OAuthRequest
后,您可以通过访问 redirectUrl 来查找您的重定向 URL。
设备授权授予
使用设备授权授予时,用户会在另一台设备上打开验证 URI。然后授权服务器会要求他们批准或拒绝请求。
为了简化此过程,请使用 RemoteActivityHelper
在用户配对的移动设备上打开一个网页,如以下示例所示
// Request access from the authorization server and receive Device Authorization Response. val verificationUri = "..." // Extracted from the Device Authorization Response. RemoteActivityHelper.startRemoteActivity( this, Intent(Intent.ACTION_VIEW) .addCategory(Intent.CATEGORY_BROWSABLE) .setData(Uri.parse(verificationUri)), null ) // Poll the authorization server to find out if the user completed the user authorization // step on their mobile device.
如果您有 iOS 应用,请使用 通用链接 在您的应用中拦截此意图,而不是依赖浏览器授权令牌。
其他身份验证方法
Wear OS 支持其他登录方法,将在以下部分中介绍。
Google 登录
Google 登录允许用户使用其现有的 Google 帐户登录。它提供最佳的用户体验,并且易于支持,尤其是在您已经在手持设备应用中实现它的情况下。
在之前介绍的推荐身份验证方法之后,Google 登录是下一个首选解决方案,因为它在 iOS 上也能很好地工作。以下部分介绍如何完成基本 Google 登录集成。
先决条件
在开始在 Wear OS 应用中集成 Google 登录之前,您必须配置 Google API 控制台项目并设置 Android Studio 项目。有关更多信息,请参阅 开始将 Google 登录集成到您的 Android 应用中.
如果您将 Google 登录与与后端服务器通信的应用或网站一起使用,则还有两个额外的先决条件
- 为您的后端服务器创建 OAuth 2.0 网络应用客户端 ID。此客户端 ID 与您的应用的客户端 ID 不同。有关更多信息,请参阅 启用服务器端访问.
- 通过使用 HTTPS 发送用户的 ID 令牌来安全地在服务器上识别当前登录的用户。要了解如何在后端服务器上对用户进行身份验证,请参阅 使用后端服务器进行身份验证.
将 Google 登录集成到您的应用中
查看并执行以下步骤(将在以下部分中详细介绍),将 Google 登录集成到您的 Wear OS 应用中
配置 Google 登录并构建 GoogleApiClient 对象
在您的登录活动的 onCreate()
方法中,配置 Google 登录以请求您的应用所需的用户信息。然后,创建一个具有对 Google 登录 API 以及您指定的选项的访问权限的 GoogleApiClient
对象。以下示例显示了这些步骤
public class MyNewActivity extends AppCompatActivity { private static final int RC_SIGN_IN = 9001; private GoogleSignInClient mSignInClient; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); GoogleSignInOptions options = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .build(); mSignInClient = GoogleSignIn.getClient(this, options); } }
将 Google 登录按钮添加到您的应用中
完成以下步骤以添加 Google 登录按钮
- 将
SignInButton
添加到您的应用布局中 - 在您的应用的
onCreate()
方法中,注册按钮的OnClickListener
,以便在点击时登录用户
<com.google.android.gms.common.SignInButton android:id="@+id/sign_in_button" android:layout_width="wrap_content" android:layout_height="wrap_content" />
Kotlin
findViewById<View>(R.id.sign_in_button).setOnClickListener(this)
Java
findViewById(R.id.sign_in_button).setOnClickListener(this);
创建登录意图并启动登录流程
在您的 onCLick()
方法中使用 getSignInIntent()
方法创建登录意图来处理登录按钮的点击。然后使用 startActivityForResult()
方法启动该意图。
Intent intent = mSignInClient.getSignInIntent(); startActivityForResult(intent, RC_SIGN_IN);
系统将提示用户选择一个 Google 帐户进行登录。如果您请求了除个人资料、电子邮件和公开 ID 之外的范围,则还会提示用户授予对这些资源的访问权限。
最后,在活动的 onActivityResult
方法中,使用 getSignInResultFromIntent
检索登录结果。检索到登录结果后,您可以使用 isSuccess
方法检查登录是否成功。如果登录成功,您可以调用 getSignInAccount
方法来获取一个 GoogleSignInAccount
对象,该对象包含有关登录用户的信息,例如用户的姓名。以下示例显示了这些步骤
Kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { super.onActivityResult(requestCode, resultCode, data) // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...). if (requestCode == RC_SIGN_IN) { Auth.GoogleSignInApi.getSignInResultFromIntent(data)?.apply { if (isSuccess) { // Get account information. fullName = signInAccount?.displayName mGivenName = signInAccount?.givenName mFamilyName = signInAccount?.familyName mEmail = signInAccount?.email } } } }
Java
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...). if (requestCode == RC_SIGN_IN) { GoogleSignInResult signInResult = Auth.GoogleSignInApi.getSignInResultFromIntent(data); if (signInResult.isSuccess()) { GoogleSignInAccount acct = signInResult.getSignInAccount(); // Get account information. fullName = acct.getDisplayName(); givenName = acct.getGivenName(); familyName = acct.getFamilyName(); email = acct.getEmail(); } } }
要查看实现 Google 登录的示例应用,请参阅 GitHub 上的 Horologist Google 登录示例.
自定义代码身份验证
作为之前介绍的身份验证方法的替代方法,您可以要求用户从其他设备(例如手机和平板电脑)进行身份验证,并获取一个短暂的数字代码。然后,用户在他们的 Wear OS 设备上输入该代码以确认其身份,并接收一个身份验证令牌。
此身份验证流程使用您的应用的登录模块,或者将第三方身份验证提供商登录方法手动集成到您的应用代码中。尽管此身份验证方法需要手动操作,并且需要付出额外的努力才能使其更安全,但如果您需要在独立的 Wear OS 应用中更早地进行身份验证,则可以使用此方法。
此设置的身份验证流程如下所示
- 用户对 Wear OS 应用执行需要授权的操作。
- Wear OS 应用向用户显示身份验证屏幕,并指示用户从指定 URL 输入代码。
- 用户切换到手机、平板电脑或 PC,然后启动浏览器,导航到 Wear OS 应用上指定的 URL,并登录。
- 用户会收到一个短暂的数字代码,他们使用 Wear OS 中的板载键盘将其输入到 Wear OS 应用的身份验证屏幕中
- 从这一点开始,您可以使用输入的代码作为证明这是正确用户的凭据,并将该代码交换为存储在 Wear OS 设备上的身份验证令牌,以确保以后进行的身份验证调用安全。
注意:用户生成的代码必须是纯数字的,不能包含任何字母字符。
以下图表显示了此身份验证流程