Android Tutorial Google Authorization – Fix for ClearTokenRequest Class Not Found Error

If you are using this example:

Google Authorization with AuthorizationClient

Might encounter this error:

B4X:
Clearing token cache
Error occurred on line: 0 (GoogleAuthorization)
java.lang.ClassNotFoundException: com.google.android.gms.auth$api$identity$ClearTokenRequest
    at anywheresoftware.b4j.object.JavaObject.getCorrectClassName(JavaObject.java:289)
    at anywheresoftware.b4j.object.JavaObject.InitializeStatic(JavaObject.java:75)

For the solution, just comment out this Sub (apparently you don't need it):

B4X:
Public Sub ClearToken(Token As String) As ResumableSub
    Dim ClearTokenRequest As JavaObject
    ClearTokenRequest = ClearTokenRequest.InitializeStatic("com/google/android/gms/auth/api/identity/ClearTokenRequest".Replace("/", ".")) _
        .RunMethodJO("builder", Null) _
        .RunMethodJO("setToken", Array(Token)).RunMethod("build", Null)
    Dim task As JavaObject = AuthorizationClient.RunMethod("clearToken", Array(ClearTokenRequest))
    Do While task.RunMethod("isComplete", Null).As(Boolean) = False
        Sleep(50)
    Loop
    Return task.RunMethod("isSuccessful", Null).As(Boolean)
End Sub

And then use these two Sub for getting Info:

B4X:
Private Sub Button1_Click
    Dim scopes As List = Array("profile", "email")
    Wait For (ga.AuthorizeMaybeAutomatic(scopes)) Complete (Result As AuthorizationResult)

    If Result.Success = False Then
        Log("Failed: " & Result.Error)
        Return
    Else If Result.ResolutionNeeded Then
        Log("resolution needed...")
        Wait For (ga.AuthorizeRequestAccess(Result)) Complete (Result As AuthorizationResult)
        If Result.Success = False Then
            Log("Failed: " & Result.Error)
            Return
        End If
    End If

    If Result.Token <> "" Then
        Dim j As HttpJob
        j.Initialize("", Me)

        j.Download2("https://www.googleapis.com/oauth2/v3/userinfo", _
            Array As String("access_token", Result.Token))

        Wait For (j) JobDone(j As HttpJob)

        If j.Success Then
            Log("UserInfo: " & j.GetString)
            ParseUserInfo(j.GetString)
        Else
            Log("Error: " & j.ErrorMessage)
        End If

        j.Release
    End If
End Sub

Private Sub ParseUserInfo(json As String)
    Dim p As JSONParser
    p.Initialize(json)
    Dim m As Map = p.NextObject

    Log("ID: " & m.Get("sub"))
    Log("Email: " & m.Get("email"))
    Log("Name: " & m.Get("name"))
    Log("Picture: " & m.Get("picture"))
End Sub


I have tested it and it works 100%
Note: most of the time, you won't need the birthday, and you can get it from the user.
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
The correct solution is explained in the tutorial:
"There is a ClearToken method that clears a cached token. It should be used when a request made with the token fails. Another usage for this is for testing. On the browser, log into your Google account and find the list of connected apps. Remove the app from the list and then call ClearToken to test the full flow again. Note that this method depends on com.google.android.gms:play-services-auth v21.4.0 which isn't installed by default."

You need to update the underlying SDK.
 

Mehrzad238

Active Member
Thank you for letting me publish this so others could learn something from my mistake

I did this with ChatGPT, which is not a very reliable source, but in defence of myself, I got to say:

I did update the com.google.android.gmslay-services-auth v21.4.0 fromSDK-Manager


Even after that, I was still getting the same error, and I had to do this

I will work on clear-token and post the result here
 

Mehrzad238

Active Member
Update:
Here is a clean and working implementation for clearing the Google token using ClearTokenRequest.
It may not be the “perfect” solution, but it works reliably and solves the logout issue.

B4X:
Public Sub ClearToken(Token As String) As ResumableSub
    Try
        Dim builder As JavaObject
        Dim jo As JavaObject

        jo.InitializeStatic("com.google.android.gms.auth.api.identity.ClearTokenRequest")
        builder = jo.RunMethod("builder", Null)

        builder.RunMethod("setToken", Array(Token))
        Dim request As JavaObject = builder.RunMethod("build", Null)

        Dim task As JavaObject = AuthorizationClient.RunMethod("clearToken", Array(request))
        Wait For (task) Complete (Ignored As JavaObject)

        Dim success As Boolean = task.RunMethod("isSuccessful", Null)
        Log("ClearToken result: " & success)
        Return success

    Catch
        Log("ClearToken error: " & LastException)
        Return False
    End Try
End Sub

' Add this method to your class (or before AuthorizeMaybeAutomatic)
Public Sub ForceAccountPicker
    ' This forces Google to always show the Account Picker dialog,
    ' even if a previous account was already selected.
    Dim Identity As JavaObject
    Identity.InitializeStatic("com.google.android.gms.auth.api.identity.Identity")
    
    Dim signInClient As JavaObject = Identity.RunMethod("getSignInClient", Array(GetContext))
    signInClient.RunMethod("signOut", Null)   ' Clears Google internal cached account
    
    Sleep(300) ' Give it a short delay to complete the signOut process
End Sub

Private Sub GetContext As JavaObject
    Dim ctx As JavaObject
    ctx.InitializeContext
    Return ctx
End Sub

Usage:

B4X:
Private Sub Logout_Click
    ProgressDialogShow("Logging out...")

    Dim token As String = Setting.GetString("googletoken")
    Wait For (g.ClearToken(token)) Complete (b As Boolean)

    Setting.ClearAll
    Sleep(1500)
    ProgressDialogHide

    B4XPages.ShowPage("MainPage")
    xui.MsgboxAsync("You have successfully logged out", "")
End Sub

Notice: You need to save the token that Google is giving to you, so here is the new code for login:

In Process_Globals
B4X:
Sub Process_Globals
    Dim Setting As AHPreferenceManager
End Sub

And here is the Login Code (Updated):

B4X:
Private Sub Button1_Click
    ProgressDialogShow("Connecting to Google...")

    ga.ForceAccountPicker
    Wait For (ga.ClearToken("")) Complete (x As Boolean)

    Dim scopes As List = Array("profile", "email")
    Wait For (ga.AuthorizeMaybeAutomatic(scopes)) Complete (Result As AuthorizationResult)

    If Result.Success = False Then
        Log("Failed: " & Result.Error)
        Return
    Else If Result.ResolutionNeeded Then
        Log("Resolution needed...")
        Wait For (ga.AuthorizeRequestAccess(Result)) Complete (Result As AuthorizationResult)
        If Result.Success = False Then
            Log("Failed: " & Result.Error)
            Return
        End If
    End If

    If Result.Token <> "" Then
        Dim j As HttpJob
        j.Initialize("", Me)

        j.Download2("https://www.googleapis.com/oauth2/v3/userinfo", _
            Array As String("access_token", Result.Token))

        ' Save the token for future ClearToken calls
        Setting.SetString("googletoken", Result.Token)

        Wait For (j) JobDone(j As HttpJob)

        If j.Success Then
            Log("UserInfo: " & j.GetString)
            ParseUserInfo(j.GetString)
        Else
            Log("Error: " & j.ErrorMessage)
        End If

        j.Release
    End If
End Sub


Tested: I have fully tested this solution in my own project, and the logout flow works reliably.
 
Last edited:
Cookies are required to use this site. You must accept them to continue using the site. Learn more…