5

I am trying to use BroadcastReceiver with READ_PHONE_STATE permission. I ask user for a permission on the run (Android M), but after all I get following Permission Denial:

W/BroadcastQueue: Permission Denial: receiving Intent { act=android.intent.action.PHONE_STATE flg=0x10 (has extras) } to com.pb.qostest/.network.PhoneStateBroadcastReceiver requires android.permission.READ_PRIVILEGED_PHONE_STATE due to sender android (uid 1000)

For a Permission I am using a code from this link: https://stackoverflow.com/a/38764861

So far wanted my phone state BroadcastReceiver to just print something so it looks like this:

public class PhoneStateBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {   
         Log.d("RECEIEVER", "PhoneStateBroadcastReceiver Receiver started!");
    }
}

Anyway nothing is printed due to permission denial above.

And in manifest it is:

<receiver
    android:name=".network.PhoneStateBroadcastReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.PHONE_STATE" />
    </intent-filter>
</receiver>
...
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

Any idea how should it look alike or what is the problem?

shemekh
  • 426
  • 5
  • 14
  • @shemekh this is a known bug for reading group permissions on android M specially with Phone state. Can you let me know what state you want to achieve? Do you want to do calls and stuff? Explain a bit about your application – Kapil G Aug 04 '17 at 10:44
  • @kapsym I want to detect calls and collect some data during the call, i.e. Signal Strength. I want to use BroadcastReceiver for this prupose because I want app to work even when its not in recent apps. – shemekh Aug 06 '17 at 21:57

1 Answers1

2

To be able to detect phone call, you need:

1 in Manifest.xml, define your receiver and ask for PHONE_STATE permission:

<receiver android:name=".network.PhoneStateBroadcastReceiver">
<intent-filter>
  <action android:name="android.intent.action.PHONE_STATE" />
    </intent-filter>
</receiver>
// ...
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

2 add a class PhoneStateBroadcastReceiver which extends BroadcastReceiver and overwrite onReceive()

3 at runtime, request PHONE_STATE permission upfront

    ActivityCompat.requestPermissions(myMainActivity,
            new String[]{Manifest.permission.READ_PHONE_STATE},
            READ_PHONE_STATE_CODE);

and give it via the system dialog

4 make a phone call

You'll see the intent caught in onReceive():

intent: Intent { act=android.intent.action.READ_PHONE_STATE flg=0x10 cmp=com.myApp.network.PhoneStateBroadcastReceiver (has extras) }
Action: android.intent.action.PHONE_STATE

Hope it helps

Alessio
  • 3,063
  • 1
  • 15
  • 17
  • What do you mean by no event broadcasted? As far as i understand BroadcastReceiver, event on PHONE_STATE should fire on ongoing call. Before that, in my main activity I ask user for READ_PHONE_STATE permission, so I understand it should be granted after accepting it. Should I ask for a permission inside onReceive method? That seem strange to me. – shemekh Aug 12 '17 at 17:22
  • Sorry for 2nd answer, but I cannot edit previous one. What I generally want to do is same thing as on this url: http://www.theappguruz.com/blog/detecting-incoming-phone-calls-in-android Problem is it is not working like that for some reason when its about Android M and permissions on the run. – shemekh Aug 12 '17 at 22:25
  • @shemekh good that you explained what you're trying to do, would have been way easier to tell it from the very beginning. To detect calls, the info in link you provided are enough, I just tested it, and I can get in the receiver ```Action: android.intent.action.PHONE_STATE```, so you're definitely doing something wrong. Simply follow step by step: define receiver in manifest, add permission in manifest, ask for phone permission at runtime and give it via the dialog, make the phone call; you should be good. – Alessio Aug 14 '17 at 05:58
  • Update my answer accordingly with working code, so you can check what you're missing – Alessio Aug 14 '17 at 06:14
  • To be honest I have no idea what made it work, but your information it's working for you made me to give it another shot. Cleared app on phone, changed the way of on the run permission asking and it's working like a charm now. Thanks for all your help! – shemekh Aug 14 '17 at 12:19
  • Ok, Im comming to you with another question. From what Ive read BroadcastReceiver declared in manifest should work after closing the app (removing it from recent apps), but unfrotunately it isn't. It only works when app is in the recent apps. Is there any flag or something else I am missing? Ive found few connected topics, but actually one say that manifest registered BroadcastReceiver should work event the app is close or eventually they say to create a Service. Why I dont want to create a service is actually I dont have any job to do in service apart of keeping ability to receive broadcast – shemekh Aug 14 '17 at 14:28
  • Ok, I am spamming here as hell and sorry for that, but I just wanted to share what Ive found out. BackgroundReceiver is not working on closed app on Redmi Note 4, but in the same conditions it works perfectly on Galaxy Samsung S IV. Can it really be connected with phone vendor? – shemekh Aug 14 '17 at 16:53
  • @shemekh look at where you instantiate your receiver. If it happens in an activity, when user swipes your app from recent apps list, that kills your process entirely; at this point, only Services are started up again by the system, but not the main activity (read about this there's plenty of literature), which is instead created when the user click on the launcher icon the next time. So, in such case, your receiver will not be instantiated again until then. The common approach is to declare a service, and let it start up the receiver (as you wrote). – Alessio Aug 15 '17 at 04:30
  • "Can it really be connected with phone vendor?" -> generally speaking, in Android vendors can change the system quite a lot; but I would bet not this much. Most likely due to the different oses you've in those two phones. – Alessio Aug 15 '17 at 04:32