Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can an activity receive an unordered broadcast(incoming call) intent before system's default receiver?

Tags:

android

Here is the scenario :

An activity is displayed(active). If a phone call comes, the activity should receive the intent (send the "incoming call screen" to the background/hide it from the display) and itself remain visible to the user. I dont necessarily want to suppress the incoming phone call as I have read in a lot of questions that it is not possible with public APIs.

All I want is to somehow make that android's default incoming call screen hidden by my activity on the top.

This behavior is only required when my activity is visible which is NOT EQUAL TO having a PHONE_STATE broadcast receiver to start my activity. The latter question has been answered a number of times on SO.

Please help me. I have been looking for directions for almost a day now.

Thanks for your time.

like image 969
Vikas Singh Avatar asked Mar 26 '12 09:03

Vikas Singh


People also ask

Does broadcast receiver work in background?

ACTION_BOND_STATE_CHANGED)); The alternative is to register the receiver in the AndroidManifest. This ensures that the BroadcastReceiver runs all the time, even when the app is backgrounded. I chose this option because I want my application to receive Bluetooth events even when the app isn't in use (i.e. backgrounded).

What is the difference between intent and broadcast receiver?

An intent is a messaging object, a broadcast receiver is an app component. An intent is used to request some action from some app component, it could be a broadcast receiver, an activity or a service.

What is the specific role of intent receiver and intent filter in broadcast receiver class?

BroadcastReceiver : 'Gateway' with which your app tells to Android OS that, your app is interested in receiving information. Intent-Filter : Works with BroadcastReceiver and tells the 'What' information it is interested to receive in. For example, your app wants to receive information on Battery level.

What is the problem with declaring a broadcast receiver with implicit intents in AndroidManifest XML?

Essentially, the problem in Android Oreo with BroadcastReceivers is that all BroadcastReceivers that we have declared in our AndroidManifest. xml and are listening to implicit intents will no longer receive those broadcasts (there are some cases that are allowed).


2 Answers

This is how I solved it :

Manifest.xml

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
...
<receiver android:name=".MyPhoneBroadcastReceiver">
<intent-filter android:priority="99999">
    <action android:name="android.intent.action.PHONE_STATE" />
    </intent-filter>
</receiver>

<activity android:name=".LockScreenActivity" android:noHistory="true" android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.ANSWER" />
         <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>    
 </activity>

MyPhoneBroadcastReceiver.java

public void onReceive(final Context context, Intent intent) {
    Bundle extras = intent.getExtras();
    ...
    if (extras != null) {
    String state = extras.getString(TelephonyManager.EXTRA_STATE);

     if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
             new Handler().postDelayed(new Runnable() {
          public void run() {
              Intent intentPhoneCall = new Intent("android.intent.action.ANSWER");
                      intentPhoneCall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
          context.startActivity(intentPhoneCall);
                  }
             }, 100);
         }
    }
}

LockScreenActivity.java - A regular activity class with UI that shows up saying your screen is locked. It covers 100% area of your screen i.e. no navigation/status bar. Also the HOME/MENU keys have been disabled. This is how I achieved that : How can I detect user pressing HOME key in my activity?

P.S. : The trick is not the main logic but a 100ms delay. Without it your custom(home) lock screen will be removed by the system default incoming call screen everytime you get a call on the phone!

like image 151
Vikas Singh Avatar answered Oct 25 '22 07:10

Vikas Singh


Ya sanjana is right that code works for me.. but instead of giving postdelay 100msec give more then 1.5 sec.. Bcoz to start incoming screen needs 800 to 1000msec.. I copied her code only but modified a bit.. Try this works fine...

@Override
public void onReceive(final Context context, Intent intent) {

    Bundle extras = intent.getExtras();

    if (extras != null) {
        String state = extras.getString(TelephonyManager.EXTRA_STATE);
        final String incomingNumber = extras.getString("incoming_number");

        Handler callActionHandler = new Handler();

        Runnable runRingingActivity = new Runnable() {

            @Override
            public void run() {
                Intent intentPhoneCall = new Intent("android.intent.action.ANSWER");
                intentPhoneCall.putExtra("INCOMING_NUM", incomingNumber);
                intentPhoneCall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(intentPhoneCall);
            }
        };

        if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
            callActionHandler.postDelayed(runRingingActivity, 2000);

        }

        if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
            callActionHandler.removeCallbacks(runRingingActivity);
            // setResultCode(Activity.RESULT_CANCELED);
        }

    }
}

Then use PhoneStateListener at receiver class side.. I used like this....

/*********** My receiver class onCreate() contains ************/
TelephonyManager telephony = (TelephonyManager)    
getSystemService(getApplicationContext().TELEPHONY_SERVICE);
        telephony.listen(myListener, PhoneStateListener.LISTEN_CALL_STATE);

class MyPhoneStateListener extends PhoneStateListener {

     Activity curActivity;

     public MyPhoneStateListener(Activity _curActivity){
         this.curActivity = _curActivity;

     }

        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
            case TelephonyManager.CALL_STATE_IDLE:
                Log.i("TEST APP", "Cal End");                   
                curActivity.finish();                   
                break;

            case TelephonyManager.CALL_STATE_OFFHOOK:
                Log.i("TEST APP", "Hello");                 
                break;

            case TelephonyManager.CALL_STATE_RINGING:
                Log.i("TEST APP", "Calling...");

                break;
            }

        }
    }
like image 24
Pradeep Avatar answered Oct 25 '22 09:10

Pradeep