如何使用Kivy处理Android运行时权限

问题描述:

我发现kivy非常适合构建跨平台应用程序的Google框架,并且我对kivy感兴趣,因为我认为在kivy中既简单又舒适,所以我只想做android应用程序.

I found that kivy is very google framework to build cross platform application and I am very interested in kivy just to do android application as I think is easy and comfortable in kivy.

尝试了几个示例之后,我很想知道如何处理kivy应用程序的android运行时权限.

After trying few examples, I am interested to know how should handle android run time permission for the kivy app.

实际上,我已经在google上搜索过,但没有一个单独的工作示例.我应该回到android/java还是有kivy和其他一些python库的可能.

Actually I had searched on google, but no single working example out there. Should I go back to android / java or it possible with kivy and some other python libs.

pyjnius是必经之路.您必须使用pyjnius移植这些说明.这涉及以下步骤:

pyjnius is the way to go. You have to port these instructions using pyjnius. This involves the following steps:

  • 不幸的是,对ContextCompat.checkSelfPermission的api调用是在android sdk支持库中实现的,该库必须单独下载, 因此,请获取具有与您的Android API级别最匹配的版本的.aar.
  • Unfortunately the api call to ContextCompat.checkSelfPermission is implemented in the android sdk support library which has to be downloaded seperately, so get the .aar with the version best matching your android API level for example here.
  • copy it into your project dir and reference it from your buildozer.spec:

android.add_aars = support-v4-26.0.0-alpha1.aar  

  • 确保jinius符合buildozer.spec的要求

  • make sure jinius is in the requirements in buildozer.spec

    使用以下代码段

    注意:这是一个阻止功能,它会一直等待到回答权限对话框为止.如果该应用程序已经具有该功能的权限,则该函数将立即返回.因此,例如,如果您想获得写入SD卡和相机的权限,它们都是危险权限",请致电:

    Note: this is a blocking function which waits until the permissions dialog is answered. If the app already has the permission the function returns immediately. So for example if you want to get the permissions for writing to the SD card and for the camera, which are both "dangerous permissions", call:

    perms = ["android.permission.READ_EXTERNAL_STORAGE",
             "android.permission.WRITE_EXTERNAL_STORAGE",
             "android.permission.CAMERA"]
    
    haveperms = acquire_permissions(perms)
    

    这里是获取权限的功能:

    And here the function for acquiring the permissions:

    import time
    import functools
    import jnius
    
    def acquire_permissions(permissions, timeout=30):
        """
        blocking function for acquiring storage permission
    
        :param permissions: list of permission strings , e.g. ["android.permission.READ_EXTERNAL_STORAGE",]
        :param timeout: timeout in seconds
        :return: True if all permissions are granted
        """
    
        PythonActivity = jnius.autoclass('org.kivy.android.PythonActivity')
        Compat = jnius.autoclass('android.support.v4.content.ContextCompat')
        currentActivity = jnius.cast('android.app.Activity', PythonActivity.mActivity)
    
        checkperm = functools.partial(Compat.checkSelfPermission, currentActivity)
    
        def allgranted(permissions):
            """
            helper function checks permissions
            :param permissions: list of permission strings
            :return: True if all permissions are granted otherwise False
            """
            return reduce(lambda a, b: a and b,
                        [True if p == 0 else False for p in map(checkperm, permissions)]
                        )
    
        haveperms = allgranted(permissions)
        if haveperms:
            # we have the permission and are ready
            return True
    
        # invoke the permissions dialog
        currentActivity.requestPermissions(permissions, 0)
    
        # now poll for the permission (UGLY but we cant use android Activity's onRequestPermissionsResult)
        t0 = time.time()
        while time.time() - t0 < timeout and not haveperms:
            # in the poll loop we could add a short sleep for performance issues?
            haveperms = allgranted(permissions)
    
        return haveperms
    

    也许最干净的方法是将p4a的PythonActivity.java皮条客化,但这是现在为我做的.

    Probably the cleanest way would be to pimp p4a's PythonActivity.java to do that but this one does it for me for now.