1

I am trying to perform some implementation against the phone call. by following this link. Everything works fine except the onReceive method from PhonecallReceiver doesn't get called on the first launch of the application, afterward, it works fine. Thanks for your time and help.

PhonecallReceiver

public class PhonecallReceiver extends BroadcastReceiver {

//The receiver will be recreated whenever android feels like it.  We need a static variable to remember data between instantiations

private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber;  

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

    //We listen to two intents.  The new outgoing call only tells us of an outgoing call.  We use it to get the number.

        String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
        String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
        int state = 0;
        if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
            state = TelephonyManager.CALL_STATE_IDLE;
        }
        else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
            state = TelephonyManager.CALL_STATE_OFFHOOK;
        }
        else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
            state = TelephonyManager.CALL_STATE_RINGING;
        }


        onCallStateChanged(context, state, number);

}

//Derived classes should override these to respond to specific events of interest

protected void onIncomingCallReceived(Context ctx, String number, Date start){}

public void onCallStateChanged(Context context, int state, String number) {
    if(lastState == state){
        //No change, debounce extras
        return;
    }
    switch (state) {
        case TelephonyManager.CALL_STATE_RINGING:
            isIncoming = true;
            callStartTime = new Date();
            savedNumber = number;
            onIncomingCallReceived(context, number, callStartTime);
            break;
        case TelephonyManager.CALL_STATE_OFFHOOK:
            //Transition of ringing->offhook are pickups of incoming calls.  Nothing done on them
            break;

        case TelephonyManager.CALL_STATE_IDLE:
            //Went to idle-  this is the end of a call.  What type depends on previous state(s)
            break;
    }
    lastState = state;
}

}

CallReceiver

public class CallReceiver extends PhonecallReceiver {

private static CallListener mCallListener;

public static void bindListener(CallListener callListener) {
    mCallListener = callListener;
}

@Override
protected void onIncomingCallReceived(final Context ctx, final String number, Date start) {
    try {
        if (mCallListener != null) {

                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        stopRinging(ctx);
                        mCallListener.displayNumber(number);
                    }
                }, 2000);
            }
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

Manifest

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name="com.example.expphonecall.MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

    <receiver android:name="com.example.expphonecall.CallReceiver" android:enabled="true">
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
        </intent-filter>
        <!--<intent-filter>
            <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
        </intent-filter>-->
    </receiver>

</application>

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
shehzy
  • 2,215
  • 3
  • 25
  • 45

2 Answers2

0

My English expression may not be very good, I hope you can understand

You can make it as `

PhoneStateReceiver phoneStateReceiver = new PhoneStateReceiver();
    IntentFilter intentFilter = new IntentFilter();
    for (String action : actions) {
        intentFilter.addAction(action);
    }
    c.registerReceiver(phoneStateReceiver,intentFilter);

`

but not register as static,It well be work?

Or

If your application implement InCallService.

Use call.registerCallback(Call.Callback),the Callback worked No abnormality

lantian
  • 176
  • 7
0

Required permissions(READ_PHONE_STATE, CALL_PHONE) were being asked separately in the activity(not a better way)

if (Build.VERSION.SDK_INT >= 23) {
        if (getApplicationContext().checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
                != PackageManager.PERMISSION_GRANTED) {
            // Permission has not been granted, therefore prompt the user to grant permission
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.READ_PHONE_STATE},
                    //MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
                    11);
        }

        if (getApplicationContext().checkSelfPermission(Manifest.permission.CALL_PHONE)
                != PackageManager.PERMISSION_GRANTED) {
            // Permission has not been granted, therefore prompt the user to grant permission
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CALL_PHONE},
                    //MY_PERMISSIONS_REQUEST_PROCESS_OUTGOING_CALLS);
                    12);
        }
    }

And as the request for these permissions is asked collectively then the receiver started to invoke on the first launch of the application

int PERMISSION_ALL = 1;
String[] PERMISSIONS = {
        Manifest.permission.CALL_PHONE,
        Manifest.permission.READ_PHONE_STATE,
};

private void checkPermissions(){

    if (!hasPermissions(this, PERMISSIONS)) {
        ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
    }
}

public static boolean hasPermissions(Context context, String... permissions) {
    if (context != null && permissions != null) {
        for (String permission : permissions) {
            if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
    }
    return true;
}
shehzy
  • 2,215
  • 3
  • 25
  • 45