当我尝试使用 open 函数和 kivy 从 /storage/emulated/0/Download/ 读取图片时,出现错误 13 权限被拒绝。
应用程序在配备 Android 12 的 motorola g32 上正常工作,但无法在配备 Android 10 的 Honor 10 lite 和配备 Android 12 的 Redmi 上工作
我添加了 buildozer.spec 权限: android.permissions = WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE
# https://github.com/HeaTTheatR/KivyMD/blob/master/kivymd/icon_definitions.py
from kivymd.app import MDApp
# from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from plyer import filechooser
import sys
from kivy.utils import platform
from datetime import datetime
kv = """
<Demo>
orientation: "vertical"
MDBottomNavigation:
panel_color: "#800080"
text_color_active: "F5F5F5"
MDBottomNavigationItem:
name: "screen 1"
text: "Головна"
icon: "google-earth"
MDLabel:
id: Vitalii
text: "@created by "
pos_hint: {"center_x": 0.7,"center_y":0.03}
MDLabel:
id: descr
text: "Цей додаток працює із зображеннями фомату bmp(bitmap), та символами таблиці ACII(Англійський алфавіт), якщо виникли питання зверніться телеграм"
pos_hint: {"center_x": 0.55,"center_y":0.5}
size_hint: (0.8,0.5)
MDBottomNavigationItem:
name: "screen 2"
text: "Зашифрувати"
icon: "file-code"
MDLabel:
id: selected_path
text: "Введіть текст"
pos_hint: {"center_x": 0.6,"center_y":0.88}
MDLabel:
id: seria1
text: "seria 1"
pos_hint: {"center_x": 0.7,"center_y":0.5}
MDCheckbox:
group: "Encrypt_seria"
pos_hint: {"center_x": 0.12,"center_y":0.5}
size_hint: (0.1,0.07)
on_active: root.Encrypt_checkbox_click(self, self.active, "seria1")
MDLabel:
id: seria2
text: "seria 2"
pos_hint: {"center_x": 1,"center_y":0.5}
MDCheckbox:
group: "Encrypt_seria"
size_hint: (0.1,0.07)
pos_hint: {"center_x": 0.425,"center_y":0.5}
on_active: root.Encrypt_checkbox_click(self, self.active, "seria2")
MDLabel:
id: seria3
text: "seria 3"
pos_hint: {"center_x": 1.3,"center_y":0.5}
MDCheckbox:
group: "Encrypt_seria"
size_hint: (0.1,0.07)
pos_hint: {"center_x": 0.725,"center_y":0.5}
on_active: root.Encrypt_checkbox_click(self, self.active, "seria3")
TextInput:
id: inp1
size_hint: (0.8,0.3)
pos_hint: {"center_x": 0.5,"center_y":0.7}
Button:
text: "Обрати файл"
bold: True
background_color:'00FFCE'
size_hint: (0.8,0.2)
pos_hint: {"center_x": 0.5,"center_y":0.34}
on_press: root.callback()
Button:
text: "Зашифрувати"
bold: True
background_color:'00FFCE'
size_hint: (0.8,0.2)
pos_hint: {"center_x": 0.5,"center_y":0.12}
on_press: root.encrypt()
MDBottomNavigationItem:
name: "screen 3"
text: "Розшифрувати"
icon: "file-document"
MDLabel:
id: selected_path
text:
pos_hint: {"center_x": 0.6,"center_y":0.98}
MDLabel:
id: seria1
text: "seria 1"
pos_hint: {"center_x": 0.7,"center_y":0.5}
MDCheckbox:
group: "Decrypt_seria"
pos_hint: {"center_x": 0.12,"center_y":0.5}
size_hint: (0.1,0.07)
on_active: root.Decrypt_checkbox_click(self, self.active, "seria1")
MDLabel:
id: seria2
text: "seria 2"
pos_hint: {"center_x": 1,"center_y":0.5}
MDCheckbox:
group: "Decrypt_seria"
size_hint: (0.1,0.07)
pos_hint: {"center_x": 0.425,"center_y":0.5}
on_active: root.Decrypt_checkbox_click(self, self.active, "seria2")
MDLabel:
id: seria3
text: "seria 3"
pos_hint: {"center_x": 1.3,"center_y":0.5}
MDCheckbox:
group: "Decrypt_seria"
size_hint: (0.1,0.07)
pos_hint: {"center_x": 0.725,"center_y":0.5}
on_active: root.Decrypt_checkbox_click(self, self.active, "seria3")
TextInput:
id: inp2
text:
size_hint: (0.8,0.4)
pos_hint: {"center_x": 0.5,"center_y":0.76}
Button:
text: "Обрати файл"
bold: True
background_color:'00FFCE'
size_hint: (0.8,0.2)
pos_hint: {"center_x": 0.5,"center_y":0.34}
on_press: root.callback()
Button:
text: "Розкодувати"
bold: True
background_color:'00FFCE'
size_hint: (0.8,0.2)
pos_hint: {"center_x": 0.5,"center_y":0.12}
on_press: root.decrypt()
"""
class Demo(BoxLayout):
global degree
degree = 1
Encrypt_checks = []
Decrypt_checks = []
def converter_to_bmp(self,path):
from PIL import Image
Image.open("sample1.png").save("sample1.bmp")
def Encrypt_checkbox_click(self, instance, value, topping):
if value == True:
Demo.Encrypt_checks.append(topping)
else:
Demo.Encrypt_checks.remove(topping)
def Decrypt_checkbox_click(self, instance, value, topping):
if value == True:
Demo.Decrypt_checks.append(topping)
else:
Demo.Decrypt_checks.remove(topping)
def decrypt(self):
try:
encoded_bmp = open(choice_picture, "rb")
except:
self.ids.inp2.text = str(sys.exc_info()[1])
def encrypt(self):
try:
text = self.ids.inp1.text + "!"
start_bmp = open(choice_picture, 'rb')
if platform == "android":
encode_bmp = open(f'/storage/emulated/0/Download/encoded_{time_now}.bmp', 'wb')
encode_bmp.write(start_bmp.read())
start_bmp.close()
encode_bmp.close()
self.ids.inp1.text = f"Файл збережено у папку Download під назвою: encoded_{time_now}.bmp"
except:
self.ids.inp1.text = str(sys.exc_info()[1])
def callback(self):
filechooser.open_file(on_selection=self.selected)
def selected(self, selection):
# try:
if selection:
global choice_picture
choice_picture = selection[0]
self.ids.selected_path.text = choice_picture
# except:
# self.ids.inp2.text = str(sys.exc_info()[1])
class Main(MDApp):
def build(self):
Builder.load_string(kv)
return Demo()
def on_start(self):
if platform == 'android':
from android.permissions import request_permissions, Permission
request_permissions([Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE])
def process1(self):
text = self.root.ids.Inp1.text
if __name__ == "__main__":
Main().run()
我的问题通过反编译 apk 文件并添加: application android:requestLegacyExternalStorage="true" 到 AndroidMainfest.xml 文件来解决 如何反编译 apk 文件然后将其编译回来可以在这个视频中看到 https://www.youtube.com/watch?v=M9fWezuvTUM&t=211s