1

I have the following manifest.xml:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

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

    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

</application>

The listener receives data while the main activity is running. However when the main activity is killed, the receiver stops to output information.

The receiver is an example class:

public class PhoneStateBroadcastReceiver extends BroadcastReceiver {

    private static final String TAG = "PhoneReceiver";
    Context mContext;
    String incoming_number;
    private int prev_state;

    @Override
    public void onReceive(Context context, Intent intent) {
        TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); //TelephonyManager object
        CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();
        telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE); //Register our listener with TelephonyManager

        Bundle bundle = intent.getExtras();
        String phoneNr = bundle.getString("incoming_number");
        Log.v(TAG, phoneNr);
        Log.d( TAG, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
        mContext = context;
    }

    /* Custom PhoneStateListener */
    public class CustomPhoneStateListener extends PhoneStateListener {

        private static final String TAG = "CustomStateListener";

        @Override
        public void onCallStateChanged(int state, String incomingNumber){

            if( incomingNumber != null && incomingNumber.length() > 0 )
                incoming_number = incomingNumber;

            switch(state){
                case TelephonyManager.CALL_STATE_RINGING:
                    Log.d(TAG, "CALL_STATE_RINGING");
                    prev_state=state;
                    break;

                case TelephonyManager.CALL_STATE_OFFHOOK:
                    Log.d(TAG, "CALL_STATE_OFFHOOK");
                    prev_state=state;
                    break;

                case TelephonyManager.CALL_STATE_IDLE:

                    Log.d(TAG, "CALL_STATE_IDLE==>"+incoming_number);

                    if((prev_state == TelephonyManager.CALL_STATE_OFFHOOK)){
                        prev_state=state;
                        //Answered Call which is ended
                    }
                    if((prev_state == TelephonyManager.CALL_STATE_RINGING)){
                        prev_state=state;
                        //Rejected or Missed call
                    }
                    break;
            }
        }
    }
}

As far as I understood the android principles, when a receiver is registered in manifest then it should receive data even if its app is killed, if so, what am I doing wrong?

Aaron
  • 7,000
  • 2
  • 21
  • 37
Kristian Ivanov
  • 111
  • 1
  • 9

3 Answers3

1

Add the following to your <receiver> in the manifest:

 android:enabled="true"
 android:exported="true">

Furthermore according to this thread, it seems that you have to manually start one of your activities before the broadcast receiver will start working, i.e. the application has to have been launched at least once before any broadcast receiver will work.

Additionally declare the permission outside of the <application> tag. So you should have something like this:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.app.myapp" >
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <application ...
...
</manifest>

Of course these implies that you should remove the permission parameter in your receiver.

Community
  • 1
  • 1
REG1
  • 486
  • 4
  • 15
  • addint enabled and exported didnt help. May I ask how am I supposed to manually launch an activity before registering the listener, since it is registered in the manifest, and is also working while the app isn't killed? thank you in advance – Kristian Ivanov Jun 20 '16 at 19:02
  • Well I don't mean that you have to launch the app before registering. What I understood from the link in my answer is that you have to have launched your app at least once before the broadcast receiver is going to work. So after launching and then subsequently closing the app once, the receiver should work. Look at the link I provided in my answer as your problem seems pretty similar. I can't see any issues with your code. – REG1 Jun 20 '16 at 19:18
  • I understood the same at first but it doesn't work like that. NO matter how many time I start it it only works, while the app is running. – Kristian Ivanov Jun 20 '16 at 19:30
  • @KristianIvanov So I updated my question. I noticed that you declared your permission inside of the ``, generally one declares permissions outside of the `application` tag. This change might not be the solution, but I couldn't think of anything else, so it's worth giving it a try. – REG1 Jun 20 '16 at 22:31
  • They are also declared outside of the application tag and asked for in the main activity to handle android 6 and newer. I will try to remove it from the receiver to see if this will help. – Kristian Ivanov Jun 21 '16 at 05:40
  • Nope, removing the permission from the receiver tag doesn't help. – Kristian Ivanov Jun 21 '16 at 08:22
  • Can you place the following line of code into your `onReceive` method (as the first line in `onReceive()`): `Log.i("PhoneStateBroadcastReceiver", "---reached onReceive method---")`. And then test it again, just to make sure that `onReceive` is never reached (when the app is closed). – REG1 Jun 21 '16 at 09:44
  • Adding a debug or info log at the start of onReceive didn't help. I did however noticed (by pure chance) that there is a broadcast send when the phone state change and the following error is received Permission Denial: receiving Intent { act=android.intent.action.PHONE_STATE flg=0x10 (has extras) } to PhoneStateBroadcastReceiver requires android.permission.READ_PRIVILEGED_PHONE_STATE due to sender android (uid 1000) – Kristian Ivanov Jun 21 '16 at 18:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/115239/discussion-between-reg1-and-kristian-ivanov). – REG1 Jun 21 '16 at 20:31
0

OK. After banging my head against the wall for more than a week, I decided to create a new project with the minimum functionality and it worked from the first try. I don't know whether it was caused by something in my old code, which I doubt, since I copied it method by method to the new project and it still works, or the newer versions of Android Studio and their build tools.

Huge thanks to REG1 for having the patience and desire to give ideas.

Regards

Kristian Ivanov
  • 111
  • 1
  • 9
0

Add these lines to the android studio manifest file ... You just not register the broadcast class

<receiver android:name=".PhoneStateBroadcastReceiver"
        android:exported="true"
        android:enabled="true">
    <intent-filter>
        <action android:name="android.intent.action.PHONE_STATE"/>
    </intent-filter>
</receiver>
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Sohaib Aslam
  • 1,245
  • 17
  • 27