kivy / plyer

Plyer is a platform-independent Python wrapper for platform-dependent APIs
https://plyer.readthedocs.io
MIT License
1.57k stars 424 forks source link

Plyer stt not working on my android device #621

Open nandamtejas opened 3 years ago

nandamtejas commented 3 years ago

I have build a kivy app to android apk with kivy following the example from this source (https://github.com/kivy/plyer/blob/master/examples/speech2text/main.py)

the app is working good by when I click the button the plyer is not showing any output.

As per the following code https://github.com/kivy/plyer/blob/master/plyer/facades/stt.py "after execute start method you can hear BEEP!" , but I am not able to hear anything even though My device microphone works fine

AM-ash-OR-AM-I commented 3 years ago

@nandamtejas I saw your stack exchange answer https://stackoverflow.com/a/67483202/13714716 you seemed to have got the solution but that doesn't seem to be working in my case even though I had used same buildozer.spec and .py as in the example (https://github.com/kivy/plyer/blob/master/examples/speech2text/main.py), I also tried giving permissions to my app manually and also using runtime permissions but still it didn't show anything in the text field. While trying to debug the stt.result showed blank list [] . Can you share your main.py and buildozer.spec so that I can see whether it works in my case or not...

AM-ash-OR-AM-I commented 3 years ago

@nandamtejas I saw your stack exchange answer https://stackoverflow.com/a/67483202/13714716 you seemed to have got the solution but that doesn't seem to be working in my case even though I had used same buildozer.spec and .py as in the example (https://github.com/kivy/plyer/blob/master/examples/speech2text/main.py), I also tried giving permissions to my app manually and also using runtime permissions but still it didn't show anything in the text field. While trying to debug the stt.result showed blank list [] . Can you share your main.py and buildozer.spec so that I can see whether it works in my case or not...

Now I got the answer whoever has the same problem you can use this repo https://github.com/AM-ash-OR-AM-I/SR/blob/main/main.py that I forked from https://github.com/Abhishek-op/SR basically I added the dialog asking for microphone permission to user...

akshayaurora commented 3 years ago

so we should probably add requesting permissions on android into plyer

tshirtman commented 3 years ago

yes, i think adding check_permission/ask_permission code in each android plyer module would make sense, the dev can still ask beforehand if they don’t want users to be asked each permission independently.

nandamtejas commented 3 years ago

yes, i think adding check_permission/ask_permission code in each android plyer module would make sense, the dev can still ask beforehand if they don’t want users to be asked each permission independently.

yes I actually added this small code in my main.py

for android.permissions import request_permissions, Permission

# on kivy app class
def on_start(self):
    request_permissions([Permission.RECORD_AUDIO]) # RECORD_AUDIO is for microphone usage for your android device.
RobertFlatt commented 3 years ago

Really not a good idea to integrate run time permissions into Plyer, it will result in unexpected behavior.

There can only be one call to request_permissions() and it must be in the build() method.

AndiEcker commented 3 years ago

@RobertF: I learned a lot from your great investigations related to Kivy Android apps - big thanks for that!!!

Only want to confirm to you, that calling request_permission() earlier, at the top of the main module of an app - directly after the Kivy module imports - is also working (at least on Android V 5, 6, and 7).

Am So., 6. Juni 2021 um 03:37 Uhr schrieb RobertF @.***

:

Really not a good idea to integrate run time permissions into Plyer, it will result in unexpected behavior.

There can only be one call to request_permissions() and it must be in the build() method.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/kivy/plyer/issues/621#issuecomment-855327191, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA4U63RTICC5HGNUAO6Q7W3TRLNNLANCNFSM44UU3R6Q .

tshirtman commented 3 years ago

Really not a good idea to integrate run time permissions into Plyer, it will result in unexpected behavior.

There can only be one call to request_permissions() and it must be in the build() method.

oh, i'm surprised by that, i though it was common for apps to ask permissions as they need them, not in bulk at start, and to handle refusal of permission in a granular way if possible.

tshirtman commented 3 years ago

According to https://developer.android.com/guide/topics/permissions/overview#associate-with-actions

Associate runtime permissions with specific actions Request permissions as late into the flow of your app's use cases as possible. For example, if your app allows users to send audio messages to others, wait until the user has navigated to the messaging screen and has pressed the Send audio message button. After the user presses the button, your app can then request access to the microphone.

the app should ask for the permission as late as possible, which would contradict the idea that "There can only be one call to request_permissions() and it must be in the build() method."

RobertFlatt commented 3 years ago

request_permissions() generates Android pause/resume events. Called during Kivy build() this is not an issue. Called during Kivy on_start() the pause occurs during on_start (not an issue) but a Kivy on_resume() is generated at a later time. This is an issue because the app code will see an on_resume() with no prior on_pause(). It is reasonable to expect a pause/resume pair, and is commonly used in setting app state; but this assumption can lead to unexpected behavior in the request_permissions() case.
Here are my original experiments https://github.com/kivy/python-for-android/issues/2309 Given the documentation the issue may be Kivy specific, on_start() quite reasonably inhibiting the generation of an on_pause(). In which case my 'must be in build()', should be 'must not be in on_start()'. I prefer documenting the former.

Separately, multiple calls to request_permissions() can lead to a single dialog with missing approvals, in the one test case I looked at (Xcamera + user specified permission) the missing permissions were automatically approved. That was enough I did not dig deeper. Given the documents, perhaps the issue is overlapping calls. User transparent calls of request_permissions() have the potential to be overlapping and lead to unexpected behavior.

Bottom line: there can be undocumented side effects, testing is required.

Thanks for listening to my 2 cents worth.

akshayaurora commented 3 years ago

@RobertFlatt

This is the intended design by Android ::

In Kivy if permissions don't work that way or prevent anything from working that way, then this would qualify as a bug in Kivy & needs fixing. Please raise appropriate issues.

Thus permissions should not be called in on_start or in build but later.

for player, I am suggesting a helper function ->

>> from player import module
>> module.do_whatever()
Warning:: [Plyer][module] This <module> requires xxx permissions
You  should probably call it like so::

from player import module

def callback(has_permissions):
    if has_permission:
        module.do_whatever()

module.request_permissions(callback)
tshirtman commented 3 years ago

i started implementing a require_permissions decorator on my side, to transparently request the permissions before calling the actual method if all the permissions haven’t been set already, i still need to test it a bit more, and there are subtleties that could make that route harder to ride than i expected, but i think it can work.

tshirtman commented 3 years ago

https://github.com/kivy/plyer/pull/629/files

RobertFlatt commented 3 years ago

1) If my understanding of the proposed change is correct if the user first accesses a Plyer module in on_start() the Kivy lifecycle is broken.

2) I tried the following on Android 11 as a test of multiple Plyer modules requiring permissions, or Plyer and user permissions occurring at build time.

from kivy.app import App
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.uix.label import Label
from android.permissions import request_permissions, check_permission, \
    Permission

class MyApp(App):
    def build(self):
        request_permissions([Permission.CAMERA])
        request_permissions([Permission.RECORD_AUDIO])
        self.label = Label(text = 'Greetings Earthlings\n\nWait 5.....')
        return self.label

    def on_start(self):
        Clock.schedule_once(self.status,5)

    def status(self,dt):
        self.label.text = 'Camera permission = ' +\
            str(check_permission(Permission.CAMERA)) +\
            '\nRecord Audio permission = ' +\
            str(check_permission(Permission.RECORD_AUDIO))

MyApp().run()

I got no dialog and no permission granted. In the logcat:

06-14 13:14:03.753 27698 27739 W Activity: Can request only one set of permissions at a time

So the good news is Android's huge security hole is patched. But if I understand from the point of view of the change this is really bad news.

I suggest that until a mechanism that works reliably is found, that documentation is a temporary and reliable solution.

tshirtman commented 3 years ago
  1. If my understanding of the proposed change is correct if the user first accesses a Plyer module in on_start() the Kivy lifecycle is broken.

I think it's a specific enough problem that it shouldn't prevent us from making the right thing easier to do. We can document to avoid calling these functions specifically in on_start if it's a problem (or to fix on resume).

  1. I tried the following on Android 11 as a test of multiple Plyer modules requiring permissions, or Plyer and user permissions occurring at build time. […]

So the good news is Android's huge security hole is patched. But if I understand from the point of view of the change this is really bad news.

I suggest that until a mechanism that works reliably is found, that documentation is a temporary and reliable solution.

Hm, so you mean, calling multiple methods of plyer that require permissions, in the same frame, with my patch, would not actually get the permission dialog to the user, and just silently fail?

I guess i'll need to try that.

RobertFlatt commented 3 years ago

I have a different preconception about what is the "right thing". But I'm not writing the code, so it matters little.

RobertFlatt commented 3 years ago

I occurred to me that if this is the case: 06-14 13:14:03.753 27698 27739 W Activity: Can request only one set of permissions at a time Then there may be xcamera https://github.com/kivy-garden/xcamera applications out there that are now broken, but the good news is they wont find out till a new install.

nandamtejas commented 2 years ago

Speech button is not working even after the permissions(RECORD_AUDIO) are allowed. I am using plyer stt. Recently I have updated my android phone. Its version is 9. And I have tried the same application but stt is not working even after allowing the runtime permission.

ignamendi21 commented 1 year ago

For me neither... in android 11

NikitaKokarev commented 4 weeks ago

Hope this solution to send Android notifications using Plyer can be helpful to someone: https://github.com/NikitaKokarev/PlyerNotification I changed the plyer notification logic depending on api_version >= 31.