Search code examples
pythonandroidkivygoogle-sheets-apibuildozer

Kivy/Buildozer app using google sheets API crashes upon start


I am trying to run a Kivy app on my android phone (Xiaomi Redmi Note 12 Pro) which uses the google sheets API to write data to a google sheet upon pressing a button. For this I am using buildozer.
I can debug and deploy the app without any problem but upon opening the app it crashes. This does not happen without the google sheets functionality tho.

Here are the code parts related to the google API functionality:

import os
from google.oauth2.credentials import Credentials
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build

# A function used to start the service
def GetService(api_name, api_version, *scopes):
    # Credentials
    SCOPES = [scope for scope in scopes[0]]
    creds = None
    if os.path.exists("token.json"):
        creds = Credentials.from_authorized_user_file("token.json", SCOPES)
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                "credentials.json", SCOPES
            )
            creds = flow.run_local_server(port = 0)
        with open("token.json", "w") as token:
            token.write(creds.to_json())
    
    try:
        service = build(api_name, api_version, credentials = creds)
        print("Successfully connected to the google sheets api.")
        return service
    except Exception as e:
        print("Could not connect to the google sheets api!") 
        print(e)
        return None

# Things initialized upon app start
self.api_name = "sheets"
self.api_version = "v4"
self.scopes = ["https://www.googleapis.com/auth/spreadsheets"]
self.sheet_id = "id of my spreadsheet"
self.sheet_name = "name of my sheet"
self.service = GetService(self.api_name, self.api_version, self.scopes)
self.my_sheet = self.service.spreadsheets().get(spreadsheetId = self.sheet_id).execute()

# A function that adds a row to the sheet upon pressing a button
def AddRow(self, current_date, val1, val2, val3, current_time):
        # Getting the number of rows
        row_numb = self.service.spreadsheets().values().get(
            spreadsheetId = self.sheet_id,
            majorDimension = "ROWS",
            range = f"{self.sheet_name}A1:A1000"
        ).execute()
        row_numb = len(row_numb["values"]) + 1
        # Appending a new row
        insert_vals = (
            (current_date, val1, val2, val3, "", current_time, ""), ()
        )
        value_range_body = {
            "majorDimension": "ROWS",
            "values": insert_vals
        }
        self.service.spreadsheets().values().update(
            spreadsheetId = self.sheet_id, 
            valueInputOption = "USER_ENTERED",
            range = self.sheet_name + f"A{row_numb}",
            body = value_range_body
        ).execute()
        return None

The app makes use of the credentials.json and token.json files as shown in the google API for python demos.

I already tried all possible combinations of requirements and permissions (that I found and could think of) that could relate to this within my buildozer.spec file but I cannot get it to work. I also added json files to the source files to include.
Can this be fixed by only changing the .spec file? If so, what would be the minimum changes to the default file needed to run such an app on my phone? Am I just missing something very obvious here?

Any help on this would be very much appreciated :)


Solution

  • UPDATE:
    My problem was that using ''buildozer android deploy run logcat'' I could not see any usable error messages. However, when using ''buildozer -v android deploy run logcat | grep python'' error messages were shown. From there on I was able to list all necessary dependencies in my .spec file that were shown via the ''ModuleNotFoundError: No module named...'' error.