在拨打电话时结束拨出电话

时间:2015-01-14 07:04:59

标签: java android

我需要在铃声结束后结束通话(有点像未接来电)。我使用BroadcastReceiverPhoneStateListener来监控状态。

问题是我正在接收广播以及phonenumber,并且听众工作得很好 - 它进入switch并执行case预期,但它没有' t执行endCall接口的ITelephony方法。这是我的代码:

清单:

<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"
    tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<receiver
    android:name=".EndCall"
    android:enabled="true" >
    <intent-filter>
        <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
    </intent-filter>
</receiver>

EndCall.java

public class EndCall extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("Debug", "Received a broadcast...");
        String phonenumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
        Log.i("Debug", "Phone number: " + phonenumber);
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        EndCallListener callListener = new EndCallListener(context, tm);
        tm.listen(callListener, PhoneStateListener.LISTEN_CALL_STATE);
    }
}

EndCallListener.java:

public class EndCallListener extends PhoneStateListener {
    Context context;
    TelephonyManager tm;
    public EndCallListener(Context context, TelephonyManager tm) {
        this.context = context;
        this.tm = tm;
    }
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        switch (state) {
            case TelephonyManager.CALL_STATE_OFFHOOK:
                Log.i("Debug", "OFFHOOK");
                try {
                    Log.i("Debug", "Inside try...");
                    Class c = Class.forName(tm.getClass().getName());
                    Method m = c.getDeclaredMethod("getITelephony");
                    ITelephony telephonyService = (ITelephony) m.invoke(tm);
                    //nothing happens after this...
                    if(telephonyService.endCall()) {
                        Log.i("Debug", "Call ended...");
                    } else {
                        Log.i("Debug", "Call not ended...");
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case TelephonyManager.CALL_STATE_IDLE:
                Log.i("Debug", "IDLE");
                break;
        }
    }
}

ITelephony.aidl

package com.android.internal.telephony;    
interface ITelephony {
    boolean endCall();
    void answerRingingCall();
    void silenceRinger();
}

3 个答案:

答案 0 :(得分:1)

最后一条评论让事情不清楚(在问题帖子中)..“它确实结束了通话,但问题是我想在通话时或者通话结束后的一段时间结束通话。”< / p>

所以通话已经结束,但你希望它在响铃时或一段时间后结束? 这里有2个案例: - 响铃时:您需要检查CALL_STATE_RINGING然后转到How to reject a call programatically android并检查那里的技术

  • 调用完成后的一段时间:只需稍后从Runnable(或其他机制)调用endCall()方法,只需在处理程序上postDelayed()并设置某种延迟时间。 在Runnable中运行的代码中,我将检查呼叫是否仍在进行中

我可能不合时宜,我建议你澄清你的评论/问题

答案 1 :(得分:1)

您仅监控清单中的拨出电话。您还可以在清单接收器中监控电话状态。

基本上你想在几声(例如10秒)响铃或被拣选后结束外拨电话。

由于Android没有发送任何更新,因此没有任何方式可以知道外出呼叫是否已收到回复或仍然响铃。

但是,因为,你需要在几秒钟之后结束传出呼叫,你的EndCallListener代码应该是这样的: -

public class EndCallListener extends PhoneStateListener {
    Context context;
    TelephonyManager tm;
    public EndCallListener(Context context, TelephonyManager tm) {
        this.context = context;
        this.tm = tm;
    }
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        switch (state) {
            case TelephonyManager.CALL_STATE_OFFHOOK:
                   handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            Log.i("Debug", "OFFHOOK");   
                            try {
                                 Log.i("Debug", "Inside try...");
                                 Class c = Class.forName(tm.getClass().getName());
                                 Method m = c.getDeclaredMethod("getITelephony");
                                 ITelephony telephonyService = (ITelephony) m.invoke(tm);
                                 //nothing happens after this...
                                 if(telephonyService.endCall()) {
                                    Log.i("Debug", "Call ended...");
                                 } else {
                                    Log.i("Debug", "Call not ended...");
                                 }
                             } catch (ClassNotFoundException e) {
                                 e.printStackTrace();
                             } catch (NoSuchMethodException e) {
                                 e.printStackTrace();
                             } catch (InvocationTargetException e) {
                                 e.printStackTrace();
                             } catch (IllegalAccessException e) {
                                 e.printStackTrace();
                             } catch (RemoteException e) {
                                 e.printStackTrace();
                             }
                       }
                }, 10000);
                break;
            case TelephonyManager.CALL_STATE_IDLE:
                Log.i("Debug", "IDLE");
                break;
        }
    }
}

答案 2 :(得分:1)

您只能检测到电话何时开始拨打电话以及何时拨打电话,但您无法确定何时拨打电话&#34;开始了。

唯一的解决方法是在拨出电话开始后挂断并通过几秒钟,但是,您再也不能保证手机会响铃:

public class EndCallListener extends PhoneStateListener {
        int lastState = TelephonyManager.CALL_STATE_IDLE;
        boolean isIncoming;

    //Incoming call-   IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when hung up
    //Outgoing call-  from IDLE to OFFHOOK when dialed out, to IDLE when hunged up

    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        super.onCallStateChanged(state, incomingNumber);
        if(lastState == state){
            //No change
            return;
        }
        switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                isIncoming = true;
                 //incoming call started
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                //Transition of ringing->offhook are pickups of incoming calls.  Nothing down on them
                if(lastState != TelephonyManager.CALL_STATE_RINGING){
                    isIncoming = false;
                   //outgoing call started
             new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            Log.i("Debug", "OFFHOOK");   
                            try {
                                 Log.i("Debug", "Inside try...");
                                 Class c = Class.forName(tm.getClass().getName());
                                 Method m = c.getDeclaredMethod("getITelephony");
                                 ITelephony telephonyService = (ITelephony) m.invoke(tm);
                                 //nothing happens after this...
                                 if(telephonyService.endCall()) {
                                    Log.i("Debug", "Call ended...");
                                 } else {
                                    Log.i("Debug", "Call not ended...");
                                 }
                             } catch (ClassNotFoundException e) {
                                 e.printStackTrace();
                             } catch (NoSuchMethodException e) {
                                 e.printStackTrace();
                             } catch (InvocationTargetException e) {
                                 e.printStackTrace();
                             } catch (IllegalAccessException e) {
                                 e.printStackTrace();
                             } catch (RemoteException e) {
                                 e.printStackTrace();
                             }
                       }
                }, 10000);
                }
                break;
            case TelephonyManager.CALL_STATE_IDLE:
                //End of call(Idle).  The type depends on the previous state(s)
                if(lastState == TelephonyManager.CALL_STATE_RINGING){
                    // missed call
                }
                else if(isIncoming){
                      //incoming call ended
                }
                else{
                   //outgoing call ended                                              
                }
                break;
        }
        lastState = state;
    }

}

}