Setup Google Sheets API for Android (Java/Kotlin)

April 6, 2019

You can use Google Sheets API to:

  • Read/write cell values
  • Read/update spreadsheet properties (e.g. frozen column, protected cells, cell format, etc.)

Although it is recommended that G Suite APIs are called from a server using server-side authentication, these APIs can also be called using the Android SDK.

Note: It is highly recommended to call G Suite APIs from a server environment rather than a mobile environment.

Source

Dependencies

dependencies {
    implementation 'com.google.android.gms:play-services-auth:16.0.1'

    // https://developers.google.com/gsuite/guides/android
    // https://mvnrepository.com/artifact/com.google.api-client/google-api-client-android
    implementation('com.google.api-client:google-api-client-android:1.28.0') {
        exclude group: 'org.apache.httpcomponents'
        exclude module: 'guava-jdk5'
    }
    // https://mvnrepository.com/artifact/com.google.apis/google-api-services-sheets
    implementation('com.google.apis:google-api-services-sheets:v4-rev571-1.25.0') {
        exclude group: 'org.apache.httpcomponents'
        exclude module: 'guava-jdk5'
    }
}

NOTE: If you bump into Error: Program type already present: com.google.common.annotations.GwtCompatible, you need exclude module: 'guava-jdk5'.

Google Cloud Platform Project and Enable API

You need to create a new or use existing Google Cloud Platform project.

Enable Sheets API in API Library.

Make sure Credential - OAuth 2.0 client IDs contain an entry with

Sometimes this entry is auto created by Google Service. If the entry does not exist, you need to create an entry.

NOTE: Refer to Connecting and Authorizing the Google Drive Android API.

Code

The following sample will

  • Sign-in to request Google Sheets permission
  • Create a new Spreadsheet
  • Utilize kotlin coroutines to launch job in background thread
  • User Timber to log output
class TestSheetsApiActivity : AppCompatActivity(), CoroutineScope by MainScope() {
    companion object {
        private const val REQUEST_SIGN_IN = 1
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.testsheetsapi)

        requestSignIn()
    }

    override fun onDestroy() {
        super.onDestroy()
        cancel()
    }

    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(context, scopes)
                        credential.selectedAccount = account.account

                        val jsonFactory = JacksonFactory.getDefaultInstance()
                        // GoogleNetHttpTransport.newTrustedTransport()
                        val httpTransport =  AndroidHttp.newCompatibleTransport()
                        val service = Sheets.Builder(httpTransport, jsonFactory, credential)
                            .setApplicationName(getString(R.string.app_name))
                            .build()

                        createSpreadsheet(service)
                    }
                    .addOnFailureListener { e ->
                        Timber.e(e)
                    }
            }
        }
    }

    private fun requestSignIn(context: Context) {
        /*
        GoogleSignIn.getLastSignedInAccount(context)?.also { account ->
            Timber.d("account=${account.displayName}")
        }
         */

        val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            // .requestEmail()
            // .requestScopes(Scope(SheetsScopes.SPREADSHEETS_READONLY))
            .requestScopes(Scope(SheetsScopes.SPREADSHEETS))
            .build()
        val client = GoogleSignIn.getClient(context, signInOptions)

        startActivityForResult(client.signInIntent, REQUEST_SIGN_IN)
    }

    private fun createSpreadsheet(service: Sheets) {
        var spreadsheet = Spreadsheet()
            .setProperties(
                SpreadsheetProperties()
                    .setTitle("CreateNewSpreadsheet")
            )

        launch(Dispatchers.Default) {
            spreadsheet = service.spreadsheets().create(spreadsheet).execute()
            Timber.d("ID: ${spreadsheet.spreadsheetId}")
        }
    }
}

References:

This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.