1

I want to add a BroadCastReciver in a service. The BroadCastReceiver listens to phone calling. My problem is that the broadcast doesn't work in service (when I run the app it worked but when I go out of my app it didn't work).

MainActiviy.java:

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

   startService(new Intent(MainActivity.this,FirstService.class));

  }
}

PhoneStateBrodcastRecevier.java:

public class PhoneStateBrodcastRecevier extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {

    try {
      TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(context.TELEPHONY_SERVICE);
      MyPhoneStateListener myPhoneStateListener = new MyPhoneStateListener(context);
      telephonyManager.listen(myPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
    } catch (Exception e){}
  }
}

FirstService.java:

public class FirstService extends Service  {

  BroadcastReceiver myreciReceiver;

  @Nullable
  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    myreciReceiver=new PhoneStateBrodcastRecevier();
    IntentFilter intentFilter=new IntentFilter();
    intentFilter.addAction("android.intent.action.PHONE_STATE");
    registerReceiver(myreciReceiver, intentFilter);
  }

  @Override
  public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
    Log.d("ddddddd", "start");

  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    Log.d("ddddddd", "finish");
  }
}

And my manifest:

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme" >
    <activity android:name=".MainActivity" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

    <receiver android:name=".PhoneStateBrodcastRecevier">
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE"/>
        </intent-filter>
    </receiver>

    <service android:name=".FirstService"/>
</application>
ישו אוהב אותך
  • 28,609
  • 11
  • 78
  • 96
abolfazl-sh
  • 25
  • 1
  • 11

2 Answers2

1

When your target is to listen for phone state changes in the Service class itself. You can try to define it internally within the Service. This will decrease resource usage too as the system is not burdened with handling the lifecycle of another component. In your Service:

private final PhoneStateListener mPhoneListener = new PhoneStateListener() {
    public void onCallStateChanged(int state, String incomingNumber) {
        super.onCallStateChanged(state, incomingNumber);

            // Call receive state 
            if (state != TelephonyManager.CALL_STATE_IDLE) {
                // Do something
            } 
        } 
    };

Then you can register it to listen as (probably in onStartCommand()):

TelephonyManager mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
mTelephonyManager.listen(mPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);

And then unregister it from listening in onDestroy() (or whenever you are done):

mTelephonyManager.listen(mPhoneListener, PhoneStateListener.LISTEN_NONE);
Shaishav
  • 5,282
  • 2
  • 22
  • 41
  • thanks.it's working very well.but where is my code problem that it didn't work? – abolfazl-sh Aug 10 '16 at 09:17
  • @ABOLFAZLSHARIFI ... I'm having trouble understanding: `intentFilter.addAction("android.intent.action.PHONE_STATE"); registerReceiver(myreciReceiver, intentFilter);`...where are you initialising `myreciReceiver`? – Shaishav Aug 10 '16 at 09:46
  • in the onCreate(): `myreciReceiver=new PhoneStateBrodcastRecevier();` – abolfazl-sh Aug 10 '16 at 12:50
  • @ABOLFAZLSHARIFI Yeah, i don't believe thats the right way of registering for a receiver that also has an entry in the manifest – Shaishav Aug 10 '16 at 13:03
  • and this link was helpful:http://stackoverflow.com/questions/9092134/broadcast-receiver-within-a-service – abolfazl-sh Aug 11 '16 at 07:46
  • @ABOLFAZLSHARIFI Yeah...thats almost exactly to what I did above :) – Shaishav Aug 11 '16 at 07:49
0

Do something when the phone rings

Solution

This can be achieved by implementing a Broadcast Receiver and listening for a TelephonyManager.ACTION_PHONE_STATE_CHANGED action.

Discussion

If you want to do something when the phone rings you have to implement a broadcast receiver which listens for the TelephonyManager.ACTION_PHONE_STATE_CHANGED intent action. This is a broadcast intent action indicating that the call state (cellular) on the device has changed.

  1. Create a class IncomingCallInterceptor which extends BroadcastReceiver.

  2. Override the onReceive method to handle incoming broadcast messages.

  3. The EXTRA_STATE intent extra in this case indicates the new call state.

  4. If (and only if) the new state is RINGING, a second intent extra EXTRA_INCOMING_NUMBER provides the incoming phone number as a String.

  5. We extract the number information from the EXTRA_INCOMING_NUMBER intent extra.

Note: Additionally you can act on a state change to OFFHOOK or IDLE when the user picks up the phone or ends/rejects the phone call respectively.

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.widget.Toast;

public class IncomingCallInterceptor extends BroadcastReceiver {                                  

@Override
public void onReceive(Context context, Intent intent) {                                         
    String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);                        
    String msg = "Phone state changed to " + state;

    if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {                                   
        String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);  
        msg += ". Incoming number is " + incomingNumber;

        // TODO This would be a good place to "Do something when the phone rings" <img src="http://androidlabs.org/wp-includes/images/smilies/icon_wink.gif" alt=";-)" class="wp-smiley"> 

    }

    Toast.makeText(context, msg, Toast.LENGTH_LONG).show();

}

}
  1. We have to register our IncomingCallInterceptor as a within the element in the AndroidManifest.xml file.

  2. We register an 'intent-filter'…

  3. and an action value which registers our receiver to listen for TelephonyManager.ACTION_PHONE_STATE_CHANGED broadcast messages.

  4. Finally we have to register a so we are allowed to listen to phone state changes.

    <receiver android:name="IncomingCallInterceptor">                  
        <intent-filter>                                                   
             <action android:name="android.intent.action.PHONE_STATE"/>   
        </intent-filter>
    </receiver>
    

Patrick R
  • 6,621
  • 1
  • 24
  • 27