Title: App crashes on Android after successful installation
Tags: python,android,kivy,apk

Question: I have created an app using the Kivy libraries in Python. The purpose of the app is to download music from YouTube using my API. The app works perfectly fine on my desktop when I run the main.py file. However, after building the app into an APK using buildozer and installing it on my Android smartphone, the app crashes immediately after displaying image.
Here is my main.py file:
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from googleapiclient.discovery import build
from pytube import YouTube
from kivymd.app import MDApp
from kivymd.uix.button import MDFillRoundFlatButton
from kivymd.uix.textfield import MDTextField
from kivymd.uix.list import OneLineListItem
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivymd.uix.boxlayout import MDBoxLayout
from kivy.uix.widget import Widget
from kivymd.theming import ThemeManager
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.uix.dialog import MDDialog
from kivy.app import App
import logging
import os


Builder.load_string('''
<RecycleViewRow@OneLineListItem>:
    text: ''
    video_id: ''
    on_release: app.on_video_selected(root.video_id)

<RV>:
    viewclass: 'RecycleViewRow'
    RecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
''')

class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = []

class MusicDownloaderApp(MDApp):
    def build(self):
        logging.info('Building the app')
        self.theme_cls.primary_palette = 'Teal'  
        self.theme_cls.primary_hue = '700'
        self.theme_cls.theme_style = 'Light'
        


        layout = MDBoxLayout(orientation='vertical', padding='32dp', spacing='20dp')

        # Add a BoxLayout at the top for the title/logo
        title_layout = MDBoxLayout(orientation='horizontal', size_hint=(1, None), height="50dp", padding='2dp', spacing='7dp' )
        layout.add_widget(title_layout)

        # Add a label as a title
        title = Label(text="Music Downloader", font_size='20sp')
        title_layout.add_widget(title)

        title_layout.add_widget(Widget())

        # Or add an image as a logo
        logo = Image(source="download.png", size_hint=(None, None), size=("80dp", "80dp"))
        title_layout.add_widget(logo)

        title_layout.add_widget(Widget())

        title_layout.add_widget(Widget())

        self.search_bar = MDTextField(
            hint_text="Enter song title or artist name",
            size_hint=(2, None),
            height="40dp"
        )
        layout.add_widget(self.search_bar)

        self.search_button = MDFillRoundFlatButton(
            text="Search",
            on_release=self.perform_search
        )
        layout.add_widget(self.search_button)

        self.results_list = RV()
        layout.add_widget(self.results_list)

        return layout

    def perform_search(self, instance):
        query = self.search_bar.text
        logging.info(f'Performing search with query {query}')
        if not query.strip():
            return

        api_key = '<my-api-key'
        youtube = build('youtube', 'v3', developerKey=api_key)

        request = youtube.search().list(
            part="snippet",
            maxResults=50,
            q=query
        )
        response = request.execute()

        results = []
        for item in response['items']:
            if item['id']['kind'] == "youtube#video":
                video_title = item['snippet']['title']
                video_id = item['id']['videoId']
                results.append({'text': video_title, 'video_id': video_id})

        self.results_list.data = results

    def on_video_selected(self, video_id):
        logging.info(f'Selected video with id {video_id}')
        youtube_url = f"[https://www.youtube.com/watch?v={video_id}]"
        youtube = YouTube(youtube_url)
         # Get the path to the app's internal storage directory
        app_path = App.get_running_app().user_data_dir

        # Define a subdirectory to save the downloads
        download_dir = os.path.join(app_path, 'downloads')

        # Create the download directory if it doesn't exist
        if not os.path.exists(download_dir):
            os.makedirs(download_dir)

        # Download the video to the download directory
        youtube.streams.filter(only_audio=True).first().download(download_dir)
        
        dialog = MDDialog(title='Finished Downloading', text='Enjoy your music!')
        dialog.open()


        

if __name__ == "__main__":
    MusicDownloaderApp().run()


And here is my buildozer.spec file:
[app]

# (str) Title of your application
title = Music Downloader

# (str) Package name
package.name = musicdownloader

# (str) Package domain (needed for android/ios packaging)
package.domain = org.test

# (str) Source code where the main.py live
source.dir = .

# (list) Source files to include (let empty to include all the files)
source.include_exts = py,png,jpg,kv,atlas

# (str) Application versioning (method 1)
version = 0.1

# (list) Application requirements
# comma separated e.g. requirements = sqlite3,kivy
requirements = python3,kivy,kivymd,pytube,google-api-python-client


# (str) Presplash of the application
presplash.filename = /content/download.png

# (str) Icon of the application
icon.filename = /content/download.png

#
# OSX Specific
#

#
# author = © Copyright Info

# change the major version of python used by the app
osx.python_version = 3

# Kivy version to use
osx.kivy_version = 1.9.1

#
# Android specific
#

# (bool) Indicate if the application should be fullscreen or not
fullscreen = 0


# (list) Permissions
# (See https://python-for-android.readthedocs.io/en/latest/buildoptions/#build-options-1 for all the supported syntaxes and properties)
android.permissions = INTERNET,WRITE_EXTERNAL_STORAGE


#
# iOS specific
#

# (str) Path to a custom kivy-ios folder
#ios.kivy_ios_dir = ../kivy-ios
# Alternately, specify the URL and branch of a git checkout:
ios.kivy_ios_url = https://github.com/kivy/kivy-ios
ios.kivy_ios_branch = master

# Another platform dependency: ios-deploy
# Uncomment to use a custom checkout
#ios.ios_deploy_dir = ../ios_deploy
# Or specify URL and branch
ios.ios_deploy_url = https://github.com/phonegap/ios-deploy
ios.ios_deploy_branch = 1.10.0

# (bool) Whether or not to sign the code
ios.codesign.allowed = false




What I have tried:
I have checked the logcat logs, but I couldn't find any specific error related to the crash.
I have ensured that the necessary permissions (INTERNET and WRITE_EXTERNAL_STORAGE) are declared in the buildozer.spec file.
I have verified that the required libraries (kivy, kivymd, pytube, google-api-python-client) are included in the requirements section of the buildozer.spec file.
I have confirmed that the APK installation was successful without any errors or warnings.
I'm not sure if I need to make any changes to my main.py or buildozer.spec file to resolve this issue.
Any suggestions or guidance would be greatly appreciated.

Answer: Add pillow to your requirements.
requirements = python3,kivy,kivymd,pytube,google-api-python-client,pillow