Home > database >  java.lang.IllegalArgumentException: the name must not be empty: null - error on one test phone but n
java.lang.IllegalArgumentException: the name must not be empty: null - error on one test phone but n

Time:11-25

I'm writing an android app that is designed for multiple phones to be able to interface with a google sheet at the same time. but I'm getting this error on one of my test phones:

FATAL EXCEPTION: DefaultDispatcher-worker-2
Process: com.example.frcscout22sheets, PID: 9729
java.lang.IllegalArgumentException: the name must not be empty: null
    at android.accounts.Account.<init>(Account.java:84)
    at android.accounts.Account.<init>(Account.java:69)
    at com.google.android.gms.auth.zzl.getToken(com.google.android.gms:play-services-auth-base@@18.0.4:5)
    at com.google.android.gms.auth.GoogleAuthUtil.getToken(com.google.android.gms:play-services-auth-base@@18.0.4:3)
    at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential.getToken(GoogleAccountCredential.java:267)
    at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential$RequestHandler.intercept(GoogleAccountCredential.java:292)
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:880)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:525)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:466)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:576)
    at com.example.frcscout22sheets.Data$onCreateView$2$1.invokeSuspend(Data.kt:55)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@afbaf4, Dispatchers.Default]

this error only occurs on one of my test phones. More specifically, the second one I tested it on. The original one works just fine.

This is the code that throws the error:

package com.example.frcscout22sheets

import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import com.google.api.services.sheets.v4.model.ClearValuesRequest
import com.google.api.services.sheets.v4.model.ValueRange
import kotlinx.coroutines.*

class Data : Fragment(R.layout.fragment_data) {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
    }

    @OptIn(DelicateCoroutinesApi::class)
    @RequiresApi(Build.VERSION_CODES.R)
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view: View = inflater.inflate(R.layout.fragment_data, container, false)
        val matchNumber = view.findViewById<EditText>(R.id.Match_Number)
        val teamNumber = view.findViewById<EditText>(R.id.Team_Number)
        val autoPoints = view.findViewById<EditText>(R.id.Auto_Points)
        val teleopPoints = view.findViewById<EditText>(R.id.Teleop_Points)
        val endgamePoints = view.findViewById<EditText>(R.id.Endgame_Points)

        val clear = view.findViewById<Button>(R.id.button2)
        clear.setOnClickListener(View.OnClickListener {
            matchNumber.setText("")
            teamNumber.setText("")
            autoPoints.setText("")
            teleopPoints.setText("")
            endgamePoints.setText("")
        })

        val send = view.findViewById<Button>(R.id.button)
        send.setOnClickListener(View.OnClickListener {
            GlobalScope.launch {
                if (isFull()) {
                    var row = 0
                    MainActivity.service.spreadsheets()
                    while (true) {
                        row  
                        println(MainActivity.ID)
                        if (MainActivity.service.spreadsheets().values().get(MainActivity.ID, "A$row").execute().getValues()[0][0] == "end") {
                            MainActivity.service.spreadsheets().values().append(MainActivity.ID, "A${row 1}", ValueRange().setValues(listOf(listOf("end")))).setValueInputOption("USER_ENTERED").execute()
                            MainActivity.service.spreadsheets().values().clear(MainActivity.ID, "A${row}", ClearValuesRequest()).execute()
                            println(row)
                            break
                        }
                    }

                    MainActivity.service.spreadsheets().values().append(MainActivity.ID, "A$row", ValueRange().setValues(listOf(listOf(matchNumber.text.toString())))).setValueInputOption("USER_ENTERED").execute()
                    MainActivity.service.spreadsheets().values().append(MainActivity.ID, "B$row", ValueRange().setValues(listOf(listOf(teamNumber.text.toString())))).setValueInputOption("USER_ENTERED").execute()
                    MainActivity.service.spreadsheets().values().append(MainActivity.ID, "C$row", ValueRange().setValues(listOf(listOf(autoPoints.text.toString())))).setValueInputOption("USER_ENTERED").execute()
                    MainActivity.service.spreadsheets().values().append(MainActivity.ID, "D$row", ValueRange().setValues(listOf(listOf(teleopPoints.text.toString())))).setValueInputOption("USER_ENTERED").execute()
                    MainActivity.service.spreadsheets().values().append(MainActivity.ID, "E$row", ValueRange().setValues(listOf(listOf(endgamePoints.text.toString())))).setValueInputOption("USER_ENTERED").execute()
                }
            }
        })
        return view
    }

    private fun isFull() : Boolean {
        if (view?.findViewById<EditText>(R.id.Match_Number)?.text.toString() == "") {
            return false
        }
        if (view?.findViewById<EditText>(R.id.Team_Number)?.text.toString() == "") {
            return false
        }
        if (view?.findViewById<EditText>(R.id.Auto_Points)?.text.toString() == "") {
            return false
        }
        if (view?.findViewById<EditText>(R.id.Teleop_Points)?.text.toString() == "") {
            return false
        }
        if (view?.findViewById<EditText>(R.id.Endgame_Points)?.text.toString() == "") {
            return false
        }
        return true
    }
}

this line specifically:

if (MainActivity.service.spreadsheets().values().get(MainActivity.ID, "A$row").execute().getValues()[0][0] == "end") {

I login to my google account to get the credentials for the google sheet api inside the mainactivity:

package com.example.frcscout22sheets

import Home
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import com.example.frcscout22sheets.databinding.ActivityMainBinding
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.api.Scope
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
import com.google.api.client.json.gson.GsonFactory
import com.google.api.services.sheets.v4.Sheets
import com.google.api.services.sheets.v4.SheetsScopes


class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private var isLoggedIn = false

    companion object {
        private const val REQUEST_SIGN_IN = 1
        lateinit var service : Sheets
        lateinit var ID : String
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val dataFragment = Data()
        val allianceSelectionFragment = AllianceSelection()
        val homeFragment = Home()

        setCurrentFragment(homeFragment)

        if (!isLoggedIn) {
            requestSignIn(baseContext)
        }

        binding.bottomNavigationView.setOnItemSelectedListener {
            when (it.itemId) {
                R.id.data -> setCurrentFragment(dataFragment)
                R.id.alliance_selection -> setCurrentFragment(allianceSelectionFragment)
                R.id.home -> setCurrentFragment(homeFragment)
            }
            true
        }
    }

    private fun setCurrentFragment(fragment: Fragment) =
        supportFragmentManager.beginTransaction().apply {
            replace(R.id.flFragment, fragment)
            commit()
        }

    @Deprecated("Deprecated in Java")
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == REQUEST_SIGN_IN) {
            if (resultCode == RESULT_OK) {
                GoogleSignIn.getSignedInAccountFromIntent(data)
                    .addOnSuccessListener { account ->
                        val scopes = listOf(SheetsScopes.SPREADSHEETS)
                        val credential = GoogleAccountCredential.usingOAuth2(baseContext, scopes)
                        credential.selectedAccount = account.account

                        val jsonFactory = GsonFactory.getDefaultInstance()
                        val httpTransport = GoogleNetHttpTransport.newTrustedTransport()
                        val sheet = Sheets.Builder(httpTransport, jsonFactory, credential)
                            .setApplicationName(getString(R.string.app_name))
                            .build()
                        getSheet(sheet)
                    }
            }
        }
    }

    private fun requestSignIn(context: Context) {
        val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestScopes(Scope(SheetsScopes.SPREADSHEETS))
            .build()
        val client = GoogleSignIn.getClient(context, signInOptions)

        startActivityForResult(client.signInIntent, REQUEST_SIGN_IN)
    }

    private fun getSheet(sheets: Sheets) : Sheets {
        service = sheets
        println(service)
        return sheets
    }

}

I logged in to the account that was working on the original device on the new device and I got the same error.

why might this be happening? What can I do to fix it? Thanks!!

CodePudding user response:

Seems like you are getting GoogleAuthException when updating spreadsheet values. GoogleAuthException is caused when the client is invalid.
And because of that the name parameter in android.accounts.Account class is null.
I suggest that you check the google account on both of your test phones (the working one and not working one) and see if you can find any discrepancies.

CodePudding user response:

i figured out the problem.

  1. The Google Sheet needed to be made editable by all those with the link
  2. I changed to following:
private fun requestSignIn(context: Context) {
        val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestScopes(Scope(SheetsScopes.SPREADSHEETS))
            .build()
        val client = GoogleSignIn.getClient(context, signInOptions)

        startActivityForResult(client.signInIntent, REQUEST_SIGN_IN)
    }

to

private fun requestSignIn(context: Context) {
        val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestScopes(Scope(SheetsScopes.SPREADSHEETS))
            .requestEmail()
            .build()
        val client = GoogleSignIn.getClient(context, signInOptions)

        startActivityForResult(client.signInIntent, REQUEST_SIGN_IN)
    }
  • Related