kivyを使用したbuildozerによるAndroidアプリケーションのビルドとクラッシュ
解決したいこと
PythonでローカルのミュージックフォルダとYouTubeのある再生リストの動画IDを照合し不足していたら不足している動画をダウンロードするプログラムを作ろうと思いました。
VSCodeで実行すると問題なく起動・動作するのですがapkにビルドしAndroid端末で起動しようとするとLoading...と表示された後アプリがクラッシュしてしまいます。
解決方法を教えてください。
発生している問題・エラー
ビルド時のエラーは無し
該当するソースコード
Python
main.py
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
import logging
from Verification import Search
from Verification import Comparison
from kivy.config import Config
logging.getLogger().setLevel(logging.INFO)
class MyWidget(Widget):
pass
class MyApp(App):
def build(self):
layout = BoxLayout(orientation="vertical", padding=10)
self.log_text = TextInput(
size_hint_x=1.0,
size_hint_y=0.8, # 垂直方向に伸縮する
readonly=True,
multiline=True,
hint_text="Press Search button",
)
self.button = Button(
on_press=self.press,
on_release=self.release,
text="Search",
size_hint_x=1.0,
size_hint_y=0.2, # 垂直方向に伸縮する
)
layout.add_widget(self.log_text)
layout.add_widget(self.button)
return layout
def press(self, btn):
self.log_text.text += "Search start\n"
self.button.text = "Sarching..."
self.log_text.text += "Get local Music files...\n"
print("Music:")
global Music_result
Music_result = Search.Music()
self.log_text.text += "Get YouTube video_id...\n"
print("\nyoutube:")
def release(self, btn):
playlist_id = "PLOEBIV1zsMI9oXXeEti-3AZtyz8u8Znw4"
YouTube_result = Search.YouTube(playlist_id)
print(YouTube_result)
self.log_text.text += "Processing information...\n"
Comparison.comparison(Music_result, YouTube_result, self)
self.button.text = "Finished"
if name == "main":
MyApp().run()
Verification.py
import os
import re
from YouTubeDL import Download
from apiclient.discovery import build
API_SERVICE_NAME = "youtube"
API_VERSION = "v3"
API_KEY = "API_KEY"
playlist_id = "PLOEBIV1zsMI9oXXeEti-3AZtyz8u8Znw4"
class Search:
youtube = build(API_SERVICE_NAME, API_VERSION, developerKey=API_KEY)
@classmethod
def Music(cls):
dir_path = "/home/akito"
#dir_path = "/storage/D80C-D7EA/Music/Neuro-sama"
files = os.listdir(dir_path)
Music_result = files
print(Music_result)
return Music_result
@classmethod
def YouTube(cls, playlist_id):
videos = []
# プレイリスト内の動画一覧を取得
request = cls.youtube.playlistItems().list(
part="contentDetails",
playlistId=playlist_id,
maxResults=50, # 一度に取得する動画の数 (最大50まで)
)
while request:
response = request.execute()
for item in response.get("items", []):
videos.append(item["contentDetails"]["videoId"])
request = cls.youtube.playlistItems().list_next(request, response)
if request:
request = cls.youtube.playlistItems().list_next(request, response)
return videos
search_instance = Search()
class Comparison:
@classmethod
def comparison(cls, Music_result, YouTube_result, self):
# 正規表現パターンをコンパイル
pattern = re.compile(r"[([^]]+)]")
music_string = ", ".join(str(item) for item in Music_result)
matches = pattern.findall(music_string)
Music_result_str = "\n".join(matches) # リストを文字列に変換
YouTube_result_str = "\n".join(YouTube_result) # リストを文字列に変換
Music_result_set = set(Music_result_str.split("\n"))
YouTube_result_set = set(YouTube_result_str.split("\n"))
YouTube_result_set_count = len(YouTube_result_set)
print("\nTotal videoid count:")
print(YouTube_result_set_count)
# YouTubeにはあって、Musicにはないアイテム
youtube_only = YouTube_result_set - Music_result_set
common_elements = Music_result_set.intersection(YouTube_result_set)
result = list(common_elements)
print("\nVideo count:")
YouTube_result_set_count_copy = YouTube_result_set_count - len(result)
print(YouTube_result_set_count_copy)
print("\nAnd:\n" + str(result) + "\n")
youtube_only_videoId = len(youtube_only)
if youtube_only_videoId > 0:
count = 0
self.log_text.text += "Downloading...\n"
for youtube_only_count in youtube_only:
count = count + 1
print(youtube_only_count)
url = "https://www.youtube.com/watch?v=" + youtube_only_count
Download(count, url)
self.log_text.text += "Success!"
else:
return
YouTubeDL.py
from yt_dlp import YoutubeDL
def Download(count, url):
print(str(count) + "." + url)
ydl_video_opts = {
#動作チェック用
"outtmpl": "D:\Picture" + "\%(title)s[%(id)s].m4a",
#"outtmpl": r"/storage/D80C-D7EA/Music" + "/%(title)s[%(id)s].m4a",
"format": "bestaudio",
}
with YoutubeDL(ydl_video_opts) as ydl:
result = ydl.download(url)
return result
buildozer.spec
#変更点のみ記載
(list) Application requirements
comma separated e.g. requirements = sqlite3,kivy
requirements = python3,kivy,yt-dlp,google-api-python-client
(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,READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE
自分で試したこと
main.pyのみでの動作チェック
buildozer.specの編集
⇒何も変わらず
adb logcatの実行
⇒どこを読めば良いか分かりませんでした