python-requestskivykivymddeeplstorage-access-api

DeepL API not working on KivyMD 1.1.1 android app


I'm building a KivyMD python app for Android. I try to access the DeepL API. It works perfectly on my desktop and on my android device (when compiled with buildozer) when I use 'requests'. But it works on my desktop but not on my android device when I use the 'deepl' library instead of 'requests'. I want to use the 'deepl' library because the translations are better than when I use the 'requests' library.

My android device is Xiaomi Mi 9T

MIUI version : MIUI Global 12.0.5 Stable 12.0.5.0(QFJEUXM)

Android version : 10 QKQ1.190825.002

I'm using :

kivy 2.1.0

kivymd 1.1.1

deepl 1.14.0

Here is my code :

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import traceback

import requests
import deepl
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

class DeeplTranslator:
    def __init__(self):
        self.auth_key = "my_auth_key"
        self.url = 'https://api-free.deepl.com/v2/translate'
        self.translator = deepl.Translator(self.auth_key)

    def translate(self, text_to_translate, target_lang, source_lang):
        # Requests method
        """
        params = {
            'auth_key': self.auth_key,
            'text': text_to_translate,
            'target_lang': target_lang
        }
        
        try:
            response = requests.post(self.url, data=params)
            response.raise_for_status()  # Raise an exception for 4xx or 5xx response status codes
            source_lang = response.json()['translations'][0]['detected_source_language']
            translation = response.json()['translations'][0]['text']
            return source_lang, translation
        except (requests.exceptions.RequestException, KeyError, IndexError) as e:
            print(f"An error occurred while translating the text: {e}")
            return None, None
        """

        # DeepL method
        try:
            result = self.translator.translate_text(text_to_translate, target_lang=target_lang, source_lang=source_lang, formality='less')
            translation = result.text
            return source_lang, translation
        except Exception as e:
            traceback.print_exc()
            print(str(e))
            return None, None


class FlasholatorApp(MDApp):
    def build(self):
        return Builder.load_file("main.kv")


    def on_start(self):
        self.deepl_translator = DeeplTranslator()

        if platform == 'android':
          from android.permissions import request_permissions, Permission
          request_permissions([
            Permission.WRITE_EXTERNAL_STORAGE, 
            Permission.READ_EXTERNAL_STORAGE,
            Permission.INTERNET
          ])
        

        self.device_root_path = "/storage/emulated/0" if platform=='android' else os.environ['HOME']

    def translate(self, text_to_translate, target_lang, source_lang):
        if text_to_translate!=self.text_to_translate and text_to_translate!="":
            self.translate_tab.ids.translate_button.disabled = True
            source_lang, translation = self.deepl_translator.translate(text_to_translate, target_lang, source_lang)
            self.translate_tab.ids.translate_button.disabled = False
        else:
            source_lang, translation = None, None

        if source_lang and translation:
            self.translate_tab.ids.translated_text.text = translation
            self.text_to_translate, self.target_lang = text_to_translate, target_lang
            self.translation, self.source_lang = translation, source_lang

        

Here is my buildozer.spec file permissions :

android.permissions = WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE, INTERNET, SSL

Here is the error I'm getting :

Traceback (most recent call last):
04-26 01:08:16.114  5121  5497 D PowerCheckerService: onBatteryChanged, mBatteryLevel = 58, status = 2, level = 58, plug = 2, scale = 100
04-26 01:08:16.115  3396  3396 I BatteryInfoReceiver: ACTION_BATTERY_CHANGED
04-26 01:08:16.115 23866 24365 I python  :    File "/media/felix/2bbafeba-9213-47d8-8cff-0f44dd5ad585/home/felix/Documents/Informatique/Python/Flasholator/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/flasholatorApp/armeabi-v7a/deepl/http_client.py", line 110, in request_with_backoff
04-26 01:08:16.115 23866 24365 I python  :    File "/media/felix/2bbafeba-9213-47d8-8cff-0f44dd5ad585/home/felix/Documents/Informatique/Python/Flasholator/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/flasholatorApp/armeabi-v7a/deepl/http_client.py", line 251, in _generate_user_agent
04-26 01:08:16.115 23866 24365 I python  :    File "/media/felix/2bbafeba-9213-47d8-8cff-0f44dd5ad585/home/felix/Documents/Informatique/Python/Flasholator/.buildozer/android/platform/build-armeabi-v7a/build/other_builds/python3/armeabi-v7a__ndk_target_21/python3/Lib/platform.py", line 1235, in platform
04-26 01:08:16.115 23866 24365 I python  :    File "/media/felix/2bbafeba-9213-47d8-8cff-0f44dd5ad585/home/felix/Documents/Informatique/Python/Flasholator/.buildozer/android/platform/build-armeabi-v7a/build/other_builds/python3/armeabi-v7a__ndk_target_21/python3/Lib/platform.py", line 196, in libc_ver
04-26 01:08:16.115 23866 24365 I python  :  IsADirectoryError: [Errno 21] Is a directory: '/data/data/org.felixmortas.flasholatorapp/files/app'
04-26 01:08:16.115 23866 24365 I python  :  
04-26 01:08:16.115 23866 24365 I python  :  The above exception was the direct cause of the following exception:
04-26 01:08:16.115 23866 24365 I python  :  
04-26 01:08:16.116 23866 24365 I python  :  Traceback (most recent call last):
04-26 01:08:16.116 23866 24365 I python  :    File "/media/felix/2bbafeba-9213-47d8-8cff-0f44dd5ad585/home/felix/Documents/Informatique/Python/Flasholator/.buildozer/android/app/DeeplTranslator.py", line 44, in translate
04-26 01:08:16.116 23866 24365 I python  :    File "/media/felix/2bbafeba-9213-47d8-8cff-0f44dd5ad585/home/felix/Documents/Informatique/Python/Flasholator/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/flasholatorApp/armeabi-v7a/deepl/translator.py", line 823, in translate_text
04-26 01:08:16.116 23866 24365 I python  :    File "/media/felix/2bbafeba-9213-47d8-8cff-0f44dd5ad585/home/felix/Documents/Informatique/Python/Flasholator/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/flasholatorApp/armeabi-v7a/deepl/translator.py", line 535, in _api_call
04-26 01:08:16.116 23866 24365 I python  :    File "/media/felix/2bbafeba-9213-47d8-8cff-0f44dd5ad585/home/felix/Documents/Informatique/Python/Flasholator/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/flasholatorApp/armeabi-v7a/deepl/http_client.py", line 121, in request_with_backoff
04-26 01:08:16.116 23866 24365 I python  :  deepl.exceptions.DeepLException: Error occurred while preparing request: [Errno 21] Is a directory: '/data/data/org.felixmortas.flasholatorapp/files/app'
04-26 01:08:16.116 23866 24365 I python  : Error occurred while preparing request: [Errno 21] Is a directory: '/data/data/org.felixmortas.flasholatorapp/files/app'

Here are my android logs :

04-25 00:00:22.639 12716 12716 V GrantPermissionsActivity: Permission grant result requestId=292789256274468049 callingUid=10501 callingPackage=org.felixmortas.flasholatorapp permission=android.permission.WRITE_EXTERNAL_STORAGE isImplicit=false result=5
04-25 00:00:22.641  1686  1935 W ActivityManager: setHasOverlayUi called on unknown pid: 12318
04-25 00:00:22.642  1686  2303 I MiuiNetworkPolicy: removeUidState uid = 10501
04-25 00:00:22.642  1686  2303 I MiuiNetworkPolicy: updateMLUid uid:10501,old:2,new:20
04-25 00:00:22.642  1686  2303 I MiuiNetworkPolicy: isMLEnabled state:2,uid:10501,connect:CONNECTED
04-25 00:00:22.642  1686  2303 I MiuiNetworkPolicy: isMLEnabled state:20,uid:10501,connect:CONNECTED
04-25 00:00:22.642  1686  2303 I MiuiNetworkPolicy: updateUidState uid = 10096, uidState = 2
04-25 00:00:22.642  1686  2303 I MiuiNetworkPolicy: updateMLUid uid:10096,old:6,new:2
04-25 00:00:22.642  1686  2303 I MiuiNetworkPolicy: isMLEnabled state:6,uid:10096,connect:CONNECTED
04-25 00:00:22.642  1686  2303 I MiuiNetworkPolicy: isMLEnabled state:2,uid:10096,connect:CONNECTED
04-25 00:00:22.643  2509  2509 D EventBus: [2509, u0] send(AppTransitionFinishedEvent)
04-25 00:00:22.643  2509  2509 D EventBus: [2509, u0]  -> ForcedResizableInfoActivityController [0x77137cc, P1] onBusEvent(AppTransitionFinishedEvent)
04-25 00:00:22.643   522   522 I hwservicemanager: getTransport: Cannot find entry vendor.qti.hardware.servicetracker@1.0::IServicetracker/default in either framework or device manifest.
04-25 00:00:22.643  2509  2509 D EventBus: [2509, u0] onBusEvent(AppTransitionFinishedEvent) duration: 48 microseconds, avg: 60
04-25 00:00:22.647  1686  4701 V LocSvc_HIDL_IzatProvider_jni: [onRemoveRequest][180] [HC] =>> [HS]
04-25 00:00:22.647   718   718 V LocSvc_HIDL_IzatProvider: [onRemoveRequest][210] [HS] <<<<= [HC]
04-25 00:00:22.647   718   718 I IzatSvc_IzatManager: LocTech-Label :: IZATMANAGER :: Remove Request In
04-25 00:00:22.647   718   718 I IzatSvc_IzatManager: LocTech-Value :: Provider: 2, Num Updates: 2147483647, TTFF: 0, Interval: 1000, Displacement: 0.000000, Horizontal Accuracy: 1, Altitude Accuracy: 2, Bearing Accuracy: 2
04-25 00:00:22.647  1686  1946 V LocSvc_HIDL_OsNpGlue_jni: [onStopRequest][73] [HC] <<= [HS]
04-25 00:00:22.654  1686  1936 I Timeline: Timeline: App_transition_ready time:781897641
04-25 00:00:22.655  4784  5146 I FusedLocationProvider: onSetRequest
04-25 00:00:22.655  4784  5189 I AbsoluteLocationDispatcher: request type:0
04-25 00:00:22.655 12716 12716 V GrantPermissionsActivity: Permission grant result requestId=292789256274468049 callingUid=10501 callingPackage=org.felixmortas.flasholatorapp permission=android.permission.READ_EXTERNAL_STORAGE isImplicit=false result=5

When building the app on my android device, it asks me if I'm OK to give access to my storage and I say yes.

Also, my MDFileManager is not opening on my android device but is on my desktop. Maybe the problem is related ?

Here is the code for my MDFileManager in my class FlasholatorApp(MDApp):

class FlasholatorApp(MDApp):
    ...
    def open_save_database_folder_selector(self):
        def save_database(path):    
            print("Sauvegarde du paquet de carte ...")
            # Pass the file path to save_database() method
            self.flashcard_collection.save_database(path)
            print("Paquet de cartes sauvegardé avec succès !")

            # Close the file manager
            file_manager.close()

        # Create a file manager instance
        file_manager = MDFileManager(
            exit_manager=lambda x: file_manager.close(),
            select_path=save_database,
            ext=[".db"],
            selector="folder"
        )

        # Open the file manager
        file_manager.show(self.device_root_path) # Starting path

When I try to open my MDFileManager by clicking on a button, it doesn't crash but doesn't do anything.

Does anyone knows what is really causing the problem ?

Also, based on this post : https://stackoverflow.com/questions/64849485/why-is-filemanager-not-working-on-android-kivymd

I changed the self.device_root_path of my MDFileManager to self.primary_ext_storage.

self.primary_ext_storage is defined as this :

from android.storage import primary_external_storage_path
self.primary_ext_storage = os.environ['HOME'] if platform!='android' else primary_external_storage_path()

But that doesn't change anything. When I try to open my MDFileManager by clicking on a button, it doesn't crash but doesn't do anything.

Thank you


Solution

  • The library is trying to figure out which platform is running on, which causes the issue you observed (platform.platform() is throwing). Changing the way you instantiate your deepl.Translator should fix the issue.

    From

    self.translator = deepl.Translator(self.auth_key)

    to

    self.translator = deepl.Translator(self.auth_key, send_platform_info=False)