简体   繁体   English

Android检测(Call Waiting)第二个来电状态

[英]Android detect (Call Waiting) second incoming call state

Hello i am trying to detect call waiting state in android I successfully detecting android call events like CALL_STATE_RINGING , CALL_STATE_IDLE and its working fine but I need to detect 2nd incoming call while there is another active call, for example, 1st call is active on phone and when some other trying to call on this number let 1st number be ABC and second incoming number be XYZ so when ABC call connected to check if ABC is already active then disconnect 1st active call and pick 2nd incoming call.您好,我正在尝试检测 android 中的呼叫等待状态我成功检测到了 android 呼叫事件,如CALL_STATE_RINGINGCALL_STATE_IDLE及其工作正常,但我需要在有另一个活动呼叫时检测第二个来电,例如,第一个电话在电话上处于活动状态,并且当其他人尝试拨打此号码时,让第一个号码为 ABC,第二个来电号码为 XYZ,因此当 ABC 呼叫连接以检查 ABC 是否已处于活动状态时,然后断开第一个活动呼叫并接听第二个来电。

PhonecallReceiver电话接收器

public abstract 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;  //because the passed incoming is only valid in ringing


    @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.
        if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
            savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
        }
        else{
            String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
            String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
            Toast.makeText(context, number, Toast.LENGTH_SHORT).show();
            int state = 0;
            if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
                state = TelephonyManager.CALL_STATE_IDLE;
                Toast.makeText(context, "CALL_STATE_IDLE", Toast.LENGTH_SHORT).show();
            }
            else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
                state = TelephonyManager.CALL_STATE_OFFHOOK;
                Toast.makeText(context, "CALL_STATE_OFFHOOK", Toast.LENGTH_SHORT).show();
            }
            else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
                state = TelephonyManager.CALL_STATE_RINGING;
                Toast.makeText(context, "CALL_STATE_RINGING", Toast.LENGTH_SHORT).show();
            }


            onCallStateChanged(context, state, number);
        }
    }

    //Derived classes should override these to respond to specific events of interest
    protected abstract void onIncomingCallReceived(Context ctx, String number, Date start);
    protected abstract void onIncomingCallAnswered(Context ctx, String number, Date start);
    protected abstract void onIncomingCallEnded(Context ctx, String number, Date start, Date end);

    protected abstract void onOutgoingCallStarted(Context ctx, String number, Date start);
    protected abstract void onOutgoingCallEnded(Context ctx, String number, Date start, Date end);

    protected abstract void onMissedCall(Context ctx, String number, Date start);

    //Deals with actual events

    //Incoming call-  goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
    //Outgoing call-  goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
    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
                if(lastState != TelephonyManager.CALL_STATE_RINGING){
                    isIncoming = false;
                    callStartTime = new Date();
                    onOutgoingCallStarted(context, savedNumber, callStartTime);
                }
                else
                {
                    isIncoming = true;
                    callStartTime = new Date();
                    onIncomingCallAnswered(context, savedNumber, callStartTime);
                }

                break;
            case TelephonyManager.CALL_STATE_IDLE:
                //Went to idle-  this is the end of a call.  What type depends on previous state(s)
                if(lastState == TelephonyManager.CALL_STATE_RINGING){
                    //Ring but no pickup-  a miss
                    onMissedCall(context, savedNumber, callStartTime);
                }
                else if(isIncoming){
                    onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
                }
                else{
                    onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
                }
                break;
        }
        lastState = state;
    }
}

CallReceiver呼叫接收器

public class CallReceiver extends PhonecallReceiver {

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


        Toast.makeText(ctx, "Call Recicevd", Toast.LENGTH_LONG).show();

    }

    @Override
    protected void onIncomingCallAnswered(Context ctx, String number, Date start)
    {
        Toast.makeText(ctx, "Call CallAnswered", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end)
    {
        Toast.makeText(ctx, "Call onIncomingCallEnded", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onOutgoingCallStarted(Context ctx, String number, Date start)
    {
        Toast.makeText(ctx, "Call onOutgoingCallStarted", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end)
    {
        Toast.makeText(ctx, "Call onOutgoingCallEnded", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onMissedCall(Context ctx, String number, Date start)
    {
        Toast.makeText(ctx, "Call onMissedCall", Toast.LENGTH_LONG).show();
    }

}

If you have system permission for you app, you can try to add permission in AndroidManifest.xml.如果您的应用程序有系统权限,您可以尝试在 AndroidManifest.xml 中添加权限。

<uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
public class SystemTelephonyBroadcastReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        if ((intent != null) && (intent.getAction() != null))
        {
            String extraState = null;
            String extraIncomingNumber = null;
            int foregroundState = -3;
            int backgroundState = -3;
            int ringingState = -3;
            switch (intent.getAction())
            {
                case TelephonyManager.ACTION_PHONE_STATE_CHANGED:
                {
                    extraState = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
                    extraIncomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);

                    if (extraState != null)
                    {
                        switch (extraState)
                        {
                            case "IDLE":
                            {
                                Log.d("SystemTelephony", "extraState = " + "IDLE");
                                Log.d("SystemTelephony", "extraIncomingNumber = " + extraIncomingNumber);
                            }
                            break;
                            case "OFFHOOK":
                            {
                                Log.d("SystemTelephony", "extraState = " + "OFFHOOK");
                                Log.d("SystemTelephony", "extraIncomingNumber = " + extraIncomingNumber);
                            }
                            break;
                            case "RINGING":
                            {
                                Log.d("SystemTelephony", "extraState = " + "RINGING");
                                Log.d("SystemTelephony", "extraIncomingNumber = " + extraIncomingNumber);
                            }
                            break;
                        }
                    }
                }
                break;
                case "android.intent.action.PRECISE_CALL_STATE":
                {

                    foregroundState = intent.getIntExtra("foreground_state", -2);
                    backgroundState = intent.getIntExtra("background_state", -2);
                    ringingState = intent.getIntExtra("ringing_state", -2);

                    switch (foregroundState)
                    {
                        case -1:
                            Log.d("SystemTelephony", "foregroundState = " + "PRECISE_CALL_STATE_NOT_VALID");
                            break;
                        case 0:
                            Log.d("SystemTelephony", "foregroundState = " + "PRECISE_CALL_STATE_IDLE");
                            break;
                        case 1:
                            Log.d("SystemTelephony", "foregroundState = " + "PRECISE_CALL_STATE_ACTIVE");
                              PhoneCallManager.getInstance(CustomApplication.getInstance()).onCallAnswer();
                            break;
                        case 2:
                            Log.d("SystemTelephony", "foregroundState = " + "PRECISE_CALL_STATE_HOLDING");
                            break;
                        case 3:
                            Log.d("SystemTelephony", "foregroundState = " + "PRECISE_CALL_STATE_DIALING");
                            break;
                        case 4:
                            Log.d("SystemTelephony", "foregroundState = " + "PRECISE_CALL_STATE_ALERTING");
                            break;
                        case 5:
                            Log.d("SystemTelephony", "foregroundState = " + "PRECISE_CALL_STATE_INCOMING");
                            break;
                        case 6:
                            Log.d("SystemTelephony", "foregroundState = " + "PRECISE_CALL_STATE_WAITING");
                            break;
                        case 7:
                            Log.d("SystemTelephony", "foregroundState = " + "PRECISE_CALL_STATE_DISCONNECTED");
                            break;
                        case 8:
                            Log.d("SystemTelephony", "foregroundState = " + "PRECISE_CALL_STATE_DISCONNECTING");
                            break;
                    }

                    switch (backgroundState)
                    {
                        case -1:
                            Log.d("SystemTelephony", "backgroundState = " + "PRECISE_CALL_STATE_NOT_VALID");
                            break;
                        case 0:
                            Log.d("SystemTelephony", "backgroundState = " + "PRECISE_CALL_STATE_IDLE");
                            break;
                        case 1:
                            Log.d("SystemTelephony", "backgroundState = " + "PRECISE_CALL_STATE_ACTIVE");
                            break;
                        case 2:
                            Log.d("SystemTelephony", "backgroundState = " + "PRECISE_CALL_STATE_HOLDING");
                            break;
                        case 3:
                            Log.d("SystemTelephony", "backgroundState = " + "PRECISE_CALL_STATE_DIALING");
                            break;
                        case 4:
                            Log.d("SystemTelephony", "backgroundState = " + "PRECISE_CALL_STATE_ALERTING");
                            break;
                        case 5:
                            Log.d("SystemTelephony", "backgroundState = " + "PRECISE_CALL_STATE_INCOMING");
                            break;
                        case 6:
                            Log.d("SystemTelephony", "backgroundState = " + "PRECISE_CALL_STATE_WAITING");
                            break;
                        case 7:
                            Log.d("SystemTelephony", "backgroundState = " + "PRECISE_CALL_STATE_DISCONNECTED");
                            break;
                        case 8:
                            Log.d("SystemTelephony", "backgroundState = " + "PRECISE_CALL_STATE_DISCONNECTING");
                            break;
                    }

                    switch (ringingState)
                    {
                        case -1:
                            Log.d("SystemTelephony", "ringingState = " + "PRECISE_CALL_STATE_NOT_VALID");
                            break;
                        case 0:
                            Log.d("SystemTelephony", "ringingState = " + "PRECISE_CALL_STATE_IDLE");
                            break;
                        case 1:
                            Log.d("SystemTelephony", "ringingState = " + "PRECISE_CALL_STATE_ACTIVE");
                            break;
                        case 2:
                            Log.d("SystemTelephony", "ringingState = " + "PRECISE_CALL_STATE_HOLDING");
                            break;
                        case 3:
                            Log.d("SystemTelephony", "ringingState = " + "PRECISE_CALL_STATE_DIALING");
                            break;
                        case 4:
                            Log.d("SystemTelephony", "ringingState = " + "PRECISE_CALL_STATE_ALERTING");
                            break;
                        case 5:
                            Log.d("SystemTelephony", "ringingState = " + "PRECISE_CALL_STATE_INCOMING");
                            break;
                        case 6:
                            Log.d("SystemTelephony", "ringingState = " + "PRECISE_CALL_STATE_WAITING");
                            break;
                        case 7:
                            Log.d("SystemTelephony", "ringingState = " + "PRECISE_CALL_STATE_DISCONNECTED");
                            break;
                        case 8:
                            Log.d("SystemTelephony", "ringingState = " + "PRECISE_CALL_STATE_DISCONNECTING");
                            break;
                    }
                }
                break;
            }
        }
    }
}

In Android R we have open permisison for READ_PRECISE_PHONE_STATE , and also for special-use applications such as dialers, carrier applications, or ims applications, you can have a try.在Android的[R,我们有开放permisison READ_PRECISE_PHONE_STATE ,也可用于特殊用途的应用程序,如拨号器,运营商应用,或者IMS应用程序,你可以试试。

Possibly I might put here on SO about my little project on detecting all I can with the 3 states (did everything I could with 1 and 2 calls already, just missing 3 or more calls now, which is the same case), but you need to check if there is any call already in CALL_STATE_OFFHOOK.可能我可能会把我的小项目放在我的小项目上,用 3 个状态检测我所能做的一切(已经用 1 个和 2 个调用做了我能做的一切,现在只是错过了 3 个或更多的调用,这是相同的情况),但是你需要检查 CALL_STATE_OFFHOOK 中是否已经有任何呼叫。 Would happen like this:会像这样发生:

RINGING (ABC) --> OFFHOOK (ABC) --> RINGING (XYZ) == 2nd call is waiting RINGING (ABC) --> OFFHOOK (ABC) --> RINGING (XYZ) == 2nd call is waiting

So you need to check if there is another call with the state OFFHOOK --> you need to store the last state for each call in order to do this, I guess - at least that's how I'm doing it to detect various things, like call lost, waiting, finished, ..... The list you could put it on SharedPreferences or something, or let the class instanciated (in memory) like I did.因此,您需要检查是否有另一个状态为 OFFHOOK 的呼叫-> 您需要存储每个呼叫的最后一个状态才能执行此操作,我想-至少我是这样做以检测各种事情的,就像呼叫丢失,等待,完成,..... 你可以把它放在 SharedPreferences 或其他东西上的列表,或者像我一样让类实例化(在内存中)。

If I didn't explain right, I can try again, just say!如果我没有解释正确,我可以再试一次,就说吧!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM