我正在编写一个应用程序,目前正在尝试使用 Plyer 提供的
vibrate
方法。
这是我的Python代码:
class SplashScreen(MDScreen):
def __init__(self, **kwargs):
super(SplashScreen, self).__init__(**kwargs)
self.main_app = MDApp.get_running_app()
self.splash_screen_counter = 0
def on_enter(self):
msg = ""
if vibrator.exists():
msg = "Device has a vibrator!"
vibrator.pattern(pattern=(0, 1), repeat=-1)
vibrator.vibrate(time=2)
# after 2 seconds, add the label
Clock.schedule_once( partial(self.add_label_to_splash_screen, msg if msg else "Gettings things ready for you." ) , 2 )
# increase the counter
self.splash_screen_counter += 2
这是 buildozer.spec 文件的相关部分
# (list) Application requirements
# comma separated e.g. requirements = sqlite3,kivy
requirements = python3,kivy,plyer
# change the major version of python used by the app
osx.python_version = 3
# Kivy version to use
osx.kivy_version = 2.2.0
#android.permissions = android.permission.INTERNET, (name=android.permission.WRITE_EXTERNAL_STORAGE;maxSdkVersion=18)
android.permissions = WAKE_LOCK, VIBRATE
# (int) Target Android API, should be as high as possible.
android.api = 31
# (int) Minimum API your APK / AAB will support.
android.minapi = 21
当我运行代码时,即使在 buildozer.spec 文件中授予了权限,我也会收到此错误。问题可能出在哪里?
这是文本形式的错误消息
文件“/storage/emulated/0/bluetooth/splash_page_tutorial-7.py”,第 83 行,on_enter 振动器.pattern(模式=(0, 1), 重复=-1) 文件“/data/user/0/ru.iiec.pydroid3/files/arm-linux-androideabi/lib/python3.11/site-packages/plyer/facades/vibrator.py”,第 70 行,模式 self._pattern(模式=模式,重复=重复) 文件“/data/user/0/ru.iiec.pydroid3/files/arm-linux-androideabi/lib/python3.11/site-packages/plyer/platforms/android/vibrator.py”,第 41 行,在 _pattern 中 振动器.振动( 文件“jnius/jnius_export_class.pxi”,第 1164 行,位于 jnius.jnius.JavaMultipleMethod。call 文件“jnius/jnius_export_class.pxi”,第 878 行,位于 jnius.jnius.JavaMethod.call 文件“jnius/jnius_export_class.pxi”,第 972 行,位于 jnius.jnius.JavaMethod.call_method 中 文件“jnius/jnius_utils.pxi”,第 79 行,位于 jnius.jnius.check_exception jnius.jnius.JavaException:发生 JVM 异常:需要 VIBRATE 权限 java.lang.SecurityException
为了解决这个问题,我们可以为每个应用程序使用所需的权限请求,该函数不包含错误,它可能是需要在运行时获得权限的应用程序,尽管如此,该功能从 API Level 1 开始就可用,执行以下代码的一些测试并使用 buildozer 编译为 APK,我们得到:
Python 脚本(应用程序正在运行):
from kivy.lang import Builder
from kivymd.app import MDApp
KV = '''
Screen:
BoxLayout:
padding: dp(90)
orientation: "vertical"
MDLabel:
id: infos
text: "Press the button"
MDIconButton:
icon: "pencil"
text: "Test device"
on_release: app.ask_permission(root.ids.infos),app.ask2(root.ids.infos),app.on_enter2(root.ids.infos)'''
class Examplejbsidis(MDApp):
def __init__(self):
super().__init__()
def build(self):
self.theme_cls.primary_palette = "Green"
return Builder.load_string(KV)
def on_enter2(self,inform):
try:
from plyer import vibrator
msg = ""
if vibrator.exists():
msg = "Device has a vibrator!"
vibrator.pattern(pattern=(0, 1), repeat=-1)
vibrator.vibrate(time=2)
except Exception as e:
j=inform.text
inform.text=str(e) + str(j)
def ask2(self,inform):
try:
from jnius import autoclass
from android import activity
activity = activity.current_activity
Vibrator = autoclass('android.os.Vibrator')
permission = 'android.permission.VIBRATE' #per Android developer documentation states this is needed
if not activity.checkSelfPermission(permission):
# If not, request permission
if not activity.shouldShowRequestPermissionRationale(permission):
activity.requestPermissions([permission], 1)
else:
print("Permission already granted.")
else:
print("Permission already granted.")
# Wait for the result
activity.onActivityResult = self.on_permission_result
except Exception as e:
j=inform.text
inform.text=str(e) + str(j)
def on_permission_result(self,requestCode, resultCode, data):
if requestCode == 1 and resultCode == 0:
print("Permission denied.")
elif requestCode == 1 and resultCode == -1:
print("Permission granted.")
else:
print("Unknown result.")
def ask_permission(self,inform):
try:
from jnius import autoclass
from android.permissions import request_permissions, Permission
#get permission from user
request_permissions([Permission.VIBRATE])
except Exception as e:
j=inform.text
inform.text=str(e) + str(j)
Examplejbsidis().run()
Android 10(A10):
完全没有错误,已从清单和运行时授予权限: 按下按钮时手机会按预期振动
Android 12(A31):
发生错误:
#JVM exception occurred: vibrate: Neither user 10532 nor current process has android.permission.VIBRATE java.lang.SecurityException
发生这种情况是因为 buildozer 项目在清单中没有包含 android.permission.VIBRATE,但后来它做到了:
新错误:
module **'android.activity'** has no attribute **'current_activity'**, this error does not exist in Android 10.
修正代码,现在振动正常了:
from kivy.lang import Builder
from kivymd.app import MDApp
KV = '''
Screen:
BoxLayout:
padding: dp(90)
orientation: "vertical"
MDLabel:
id: infos
text: "Press the button"
MDIconButton:
icon: "pencil"
text: "Test device" #app.ask2(root.ids.infos)
on_release: app.ask_permission(root.ids.infos),app.on_enter2(root.ids.infos)'''
class Example(MDApp):
def __init__(self):
super().__init__()
def build(self):
self.theme_cls.primary_palette = "Green"
return Builder.load_string(KV)
def on_enter2(self,inform):
try:
from plyer import vibrator
msg = ""
if vibrator.exists():
msg = "Device has a vibrator!"
vibrator.pattern(pattern=(0, 1), repeat=-1)
vibrator.vibrate(time=2)
except Exception as e:
j=inform.text
inform.text=str(e) + str(j)
def ask2(self,inform):
try:
from jnius import autoclass
from android import activity
activity = activity.current_activity
Vibrator = autoclass('android.os.Vibrator')
permission = 'android.permission.VIBRATE' #per Android developer documentation states this is needed
if not activity.checkSelfPermission(permission):
# If not, request permission
if not activity.shouldShowRequestPermissionRationale(permission):
activity.requestPermissions([permission], 1)
else:
print("Permission already granted.")
else:
print("Permission already granted.")
# Wait for the result
activity.onActivityResult = self.on_permission_result
except Exception as e:
j=inform.text
inform.text=str(e) + str(j)
def on_permission_result(self,requestCode, resultCode, data):
if requestCode == 1 and resultCode == 0:
print("Permission denied.")
elif requestCode == 1 and resultCode == -1:
print("Permission granted.")
else:
print("Unknown result.")
def ask_permission(self,inform):
try:
from jnius import autoclass
from android.permissions import request_permissions, Permission
#get permission from user
request_permissions([Permission.VIBRATE])
except Exception as e:
j=inform.text
inform.text=str(e) + str(j)
Example().run()