You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android端基于自有服务器URL的Google Fit OAuth2原生认证改造需求

Replace WebView with Google Native Auth for Google Fit on Android

Got it, let's break this down. You've already got your OAuth2 backend set up to handle token storage, and now you want to ditch the WebView for Google's native auth window on Android—plus have full control over when the user sees the authorization prompt. Here's exactly how to implement this:

Step 1: Add Required Dependencies

First, make sure you have the Google Play Services auth and Fit dependencies in your app-level build.gradle (Module level):

dependencies {
    // Google Sign-In
    implementation 'com.google.android.gms:play-services-auth:20.7.0'
    // Google Fit (for scope definitions)
    implementation 'com.google.android.gms:play-services-fitness:21.1.0'
}

Step 2: Configure the Google Sign-In Client

Create a GoogleSignInClient instance tailored to your Google Fit scopes. Define this in the Activity/Fragment where you want to trigger the auth flow:

private lateinit var googleSignInClient: GoogleSignInClient

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Configure sign-in to request user info, Fit scopes, and an auth code for your backend
    val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestEmail()
        // Add the exact Google Fit scopes your backend needs access to
        .requestScopes(Scope(FitnessScopes.FITNESS_ACTIVITY_READ), Scope(FitnessScopes.FITNESS_BODY_READ))
        // Critical: Request an authorization code to send to your server
        .requestServerAuthCode("YOUR_OAUTH2_CLIENT_ID_FROM_GOOGLE_CLOUD_CONSOLE")
        .build()

    // Build the client with your configured options
    googleSignInClient = GoogleSignIn.getClient(this, gso)
}

Note: Replace YOUR_OAUTH2_CLIENT_ID_FROM_GOOGLE_CLOUD_CONSOLE with the same client ID your backend uses for OAuth2 setup.

Step 3: Trigger the Native Auth Flow on Your Terms

You can launch the native auth prompt whenever you want—like when the user taps a "Connect Google Fit" button. Use the Activity Result API (since startActivityForResult is deprecated):

// Call this method to start the auth flow (e.g., in a button click listener)
private fun startGoogleFitAuth() {
    val signInIntent = googleSignInClient.signInIntent
    signInLauncher.launch(signInIntent)
}

// Register the result launcher in onCreate
private val signInLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
        handleSignInResult(task)
    }
}

Step 4: Handle the Auth Result and Send Code to Your Backend

Once the user completes the native flow, grab the authorization code and send it to your backend—your server will handle exchanging it for access/refresh tokens (which it already knows how to store):

private fun handleSignInResult(completedTask: Task<GoogleSignInAccount>) {
    try {
        val account = completedTask.getResult(ApiException::class.java)
        // Get the auth code to send to your backend
        val authCode = account.serverAuthCode ?: run {
            Toast.makeText(this, "Failed to retrieve auth code", Toast.LENGTH_SHORT).show()
            return
        }

        // Send the authCode to your backend via your existing API
        // Example using Retrofit:
        yourBackendApi.submitAuthCode(authCode).enqueue(object : Callback<Void> {
            override fun onResponse(call: Call<Void>, response: Response<Void>) {
                Toast.makeText(this@YourActivity, "Google Fit connected successfully!", Toast.LENGTH_SHORT).show()
            }

            override fun onFailure(call: Call<Void>, t: Throwable) {
                Toast.makeText(this@YourActivity, "Connection failed: ${t.message}", Toast.LENGTH_SHORT).show()
            }
        })
    } catch (e: ApiException) {
        // Handle sign-in errors (e.g., user canceled, invalid scopes)
        Log.w(TAG, "Sign-in failed with code: ${e.statusCode}")
        Toast.makeText(this, "Sign-in failed", Toast.LENGTH_SHORT).show()
    }
}

Key Notes to Remember

  • Scope Matching: Ensure the scopes you request here exactly match what your backend needs to access Google Fit data. Add more scopes with .requestScopes() if required.
  • Client ID Consistency: The client ID used in requestServerAuthCode() must match the one registered in your Google Cloud Console, and it should allow your backend's redirect URI.
  • Token Management: Your backend handles token exchange, refresh, and Google Fit data requests—you don't need to store tokens on the Android side.
  • User Experience: The native auth window leverages the user's existing Google account session on the device, making the flow faster and more trustworthy than a WebView.

That's it! This setup replaces the WebView flow with Google's native UI, gives you full control over when the auth prompt appears, and integrates seamlessly with your existing backend token system.

内容的提问来源于stack exchange,提问作者Juan Echevarria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:56:48