为什么 Plyer vibrate 方法会引发异常?

问题描述 投票:0回答:1

我正在编写一个应用程序,目前正在尝试使用 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

python kivy-language kivymd
1个回答
0
投票

为了解决这个问题,我们可以为每个应用程序使用所需的权限请求,该函数不包含错误,它可能是需要在运行时获得权限的应用程序,尽管如此,该功能从 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):

完全没有错误,已从清单和运行时授予权限: 按下按钮时手机会按预期振动

enter image description here

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()
© www.soinside.com 2019 - 2024. All rights reserved.