My application starts and runs on the computer, but when you open it on your phone, it just crashes without downloading anything. Help me solve the problem.
import httpx
import schedule
from datetime import datetime
from bs4 import BeautifulSoup
import json
import asyncio
from concurrent.futures import ThreadPoolExecutor
from kivy.lang import Builder
from kivy.clock import Clock
from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.card import MDSeparator
from plyer import notification
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class Example(MDApp):
def __init__(self):
super().__init__()
self.executor = ThreadPoolExecutor(max_workers=5)
self.screen = Builder.load_file('interface_app.kv')
self.observer = None
self.search_query = ""
self.load_data()
def build(self):
self.theme_cls.theme_style = "Light"
return self.screen
def handle_search(self, query):
"""Processing the search button click"""
self.search_query = query
self.search_data()
def load_data(self):
"""Downloading data from a JSON file"""
try:
with open('data.json', 'r', encoding='utf-8') as f:
self.data = json.load(f)
self.run_parser_script()
except FileNotFoundError:
# print("Error loading data...")
self.run_parser_in_background()
def second_load_data(self):
with open('data.json', 'r', encoding='utf-8') as f:
self.data = json.load(f)
async def run_other_script(self):
# The script launch code
await self.run_parser()
self.second_load_data()
def check_time(self):
now = datetime.now()
if now.minute % 5 == 0:
asyncio.run(self.run_other_script())
def run_parser_script(self):
# Calling run_other_script once immediately after launching the application
# asyncio.run(self.run_other_script())
# Scheduling a task for every 10 seconds
schedule.every(10).seconds.do(self.check_time)
Clock.schedule_interval(lambda dt: schedule.run_pending(), 10)
async def run_parser_in_background(self):
"""Launching the parser"""
self.show_loading_message()
asyncio.run(self.run_parser())
self.load_data()
self.hide_loading_message()
async def find_files_links(self, source_url):
# The function finds links to files using the source URL.
async with httpx.AsyncClient() as client:
response = await client.get(source_url) # receives an HTTP response from the server
soup = BeautifulSoup(response.text,
'html.parser') # analyzes the resulting HTML code using
files_links = [a['href'] for a in soup.find_all('a', href=True) if, a['href'].startswith('files/')] # extracts links to files from found elements <a>
return files_links
async def combine_base_url_with_files_links(self, base_url, files_links):
# combines the base URL with each link to a file from the files_links list
combined_links = [base_url + link for link in files_links]
return combined_links
async def parse_combined_links(self, links):
# the function processes the combined URLs and extracts data from the HTML code
data = []
async with httpx.AsyncClient() as client:
for link in links:
response = await client.get(link) # receives an HTTP response from the server URL
soup = BeautifulSoup(response.text, 'html.parser') # analyzes the resulting HTML code.
rows = soup.find_all('tr') # finds all rows of the table
# iterates through each row of the table
for row in rows:
cols = row.find_all('td')
cell_data = {}
for col in cols:
if col.text != '':
# We check the presence and value of the attributes of interest
if 'id' in col.attrs:
col_id = col['id']
col_id = col_id.rstrip()[:-1]
cell_data['id'] = col_id
if 'para' in col.attrs:
cell_data['para'] = col['para']
if 'day' in col.attrs:
cell_data['day'] = col['day']
if 'data' in col.attrs:
cell_data['data'] = col['data']
# We add the text of the cell if all the attributes of interest are present
if all(key in cell_data for key in ['id', 'day', 'data', 'para']):
cell_data['text'] = col.text
data.append(cell_data)
cell_data = {}
# Saving the data
with open('data.json', 'w', encoding='utf-8') as file:
json.dump(data, file, ensure_ascii=False, indent=4)
return data
async def run_parser(self):
source_url = 'https://nfuunit.ru/timetable/fulltime/'
files_links = await self.find_files_links(source_url)
combined_links = await self.combine_base_url_with_files_links(source_url, files_links)
await self.parse_combined_links(combined_links)
def show_loading_message(self):
"""Displaying a message about downloading data"""
self.loading_label = MDLabel(
text="Wait for the data to load...",
halign="center",
size_hint_y=None
)
self.screen.ids.list_result.add_widget(self.loading_label)
def hide_loading_message(self):
"""Hiding the data download message"""
if self.loading_label:
self.screen.ids.list_result.remove_widget(self.loading_label)
def search_data(self):
"""Search for data on requestу"""
grouped_results = {}
for item in self.data:
if self.search_query == "":
error_label = MDLabel(
text="Enter the search data",
size_hint_y=None,
theme_text_color="Custom",
text_color=(1, 0, 0, 1)
)
self.screen.ids.list_result.add_widget(error_label)
else:
if self.search_query.lower() == item['id'].lower() or self.search_query.lower() in item['id'].lower() or self.search_query.lower() in item['text'].lower():
id_item = item['id']
day = item['day']
data = item['data']
para = item['para']
text = item['text']
if day.strip():
key = f"{day} - {data}"
if key not in grouped_results:
grouped_results[key] = []
grouped_results[key].append({
"day": day,
"data": data,
"para": para,
"class": id_item,
"text": text
})
self.screen.ids.list_result.clear_widgets()
if not grouped_results:
message_label = MDLabel(
text="Nothing was found",
size_hint_y=None,
halign='center',
theme_text_color="Custom",
text_color=(1, 0, 0, 1)
)
self.screen.ids.list_result.add_widget(message_label)
else:
for (date_day, classes) in grouped_results.items():
label_date_day = MDLabel(
text=date_day,
size_hint_y=None,
halign='center',
theme_text_color="Custom",
text_color=(1, 0, 0, 1)
)
self.screen.ids.list_result.add_widget(label_date_day)
separator_day = MDSeparator(height="10dp")
self.screen.ids.list_result.add_widget(separator_day)
for class_ in classes:
label_class = MDLabel(
text=f"{class_['para']} : {class_['class']}",
adaptive_height=True,
theme_text_color="Custom",
text_color=(0, 0, 1, 1)
)
self.screen.ids.list_result.add_widget(label_class)
label_text = MDLabel(
text=f"{class_['text']}",
size_hint_y=None,
theme_text_color="Custom",
text_color=(0, 0, 0, 1)
)
self.screen.ids.list_result.add_widget(label_text)
separator = MDSeparator(height="10dp")
self.screen.ids.list_result.add_widget(separator)
def monitor_json_changes(self, filepath='data.json'):
event_handler = FileSystemEventHandler()
event_handler.on_modified = lambda event: self.reload_data_and_notify(event.src_path)
if self.observer:
self.observer.stop()
self.observer.join()
observer = Observer()
observer.schedule(event_handler, filepath, recursive=False)
observer.start()
def reload_data_and_notify(self, filepath):
self.load_data(filepath)
self.send_notification("Schedule changes")
def send_notification(self, message):
notification_title = "NF UUNiT Schedule"
notification_text = message
notification.notify(title=notification_title, message=notification_text)
if __name__ == "__main__":
Example().run()
Everything works fine on the computer, but on the phone after installing the apk file of the application, a black screen appears and crashes
To convert a project to an apk file, I use buildozer.
# This .spec config file tells Buildozer an app's requirements for being built.
#
# It largely follows the syntax of an .ini file.
# See the end of the file for more details and warnings about common mistakes.
[app]
# (str) Title of your application
title = Schedule
# (str) Package name
package.name = myapp
# (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 (leave empty to include all the files)
source.include_exts = py,png,jpg,kv
# (list) List of inclusions using pattern matching
#source.include_patterns = assets/*,images/*.png
# (list) Source files to exclude (leave empty to not exclude anything)
#source.exclude_exts = spec
# (list) List of directory to exclude (leave empty to not exclude anything)
#source.exclude_dirs = tests, bin, venv
# (list) List of exclusions using pattern matching
# Do not prefix with './'
#source.exclude_patterns = license,images/*/*.jpg
# (str) Application versioning (method 1)
version = 3.4
# (str) Application versioning (method 2)
# version.regex = __version__ = ['"](.*)['"]
# version.filename = %(source.dir)s/main.py
# (list) Application requirements
# comma separated e.g. requirements = sqlite3,kivy
requirements = python3,kivy,kivymd,beautifulsoup4,plyer,httpx,schedule,watchdog,asyncio
Can you help with solving the problem
1