26

発信が応答されたことを検出するために、この質問から、、、、およびを作成してリッスンしようとしましたが、以下で説明するPhoneStateListenerように、機能していないようです。TelephonyManagerCALL_STATE_RINGINGCALL_STATE_OFFHOOKCALL_STATE_IDLE

まず、マニフェストに次の許可を登録しました。

<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />

次に、発信呼び出しが行われるたびにイベントBroadcastReceiverOutCallLoggerキャッチする呼び出し先:NEW_OUTGOING_CALL

<receiver android:name=".listener.OutCallLogger">
    <intent-filter>
        <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
    </intent-filter>
</receiver>

次に、私の実装OutCallLogger。呼び出されたときはいつでもnewをnoCallListenerYetアタッチしないように、と呼ばれるブール値を設定しました。PhoneStateListenerTelephonyManageronReceive()

public class OutCallLogger extends BroadcastReceiver {

    private static boolean noCallListenerYet = true;

    @Override
    public void onReceive(final Context context, Intent intent) {
        number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
        if (noCallListenerYet) {
            final TelephonyManager tm = (TelephonyManager) context.getSystemService(
                    Context.TELEPHONY_SERVICE);
            tm.listen(new PhoneStateListener() {
                @Override
                public void onCallStateChanged(int state, String incomingNumber) {
                    switch (state) {
                        case TelephonyManager.CALL_STATE_RINGING:
                            Log.d(This.LOG_TAG, "RINGING");
                            break;
                        case TelephonyManager.CALL_STATE_OFFHOOK:
                            Log.d(This.LOG_TAG, "OFFHOOK");
                            break;
                        case TelephonyManager.CALL_STATE_IDLE:
                            Log.d(This.LOG_TAG, "IDLE");
                            break;
                        default:
                            Log.d(This.LOG_TAG, "Default: " + state);
                            break;
                    }
                }
            }, PhoneStateListener.LISTEN_CALL_STATE);
            noCallListenerYet = false;
        }
    }

}

これで、デバイスで発信を行うと、CALL_STATE_RINGING 呼び出されることはありません。私はいつも、他の回線が鳴り始めたときに「IDLE」から「OFFHOOK」までのプリントアウトを取得し、通話に応答したときに何も表示せず、通話が終了したときに再び「IDLE」のプリントアウトを取得します。

Androidで発信コールが応答されたことを確実に検出するにはどうすればよいですか、それとも可能ですか?

4

6 に答える 6

4

着信のみが RINGING 状態になるようです。発信コールは IDLE から OFFHOOK に変化するため、Phone State を確認しても、これを実現できない可能性があります。

内部関数を使用して可能だと思います。これを見てください: Android テレフォニー スタックのさまざまな Cal​​l 状態は何を表していますか?

于 2013-08-13T16:08:27.843 に答える
1

たぶんCallManagerを使用してみてください。http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.3_r1/com/android/internal/telephony/CallManager.javaを確認してください。また、コンピュータのSDKファイルの中にCallManager.javaが見つかりました。リンク先のページからの次のテキストは有望なようです。

Register for getting notifications for change in the Call State Call.State This is 
called PreciseCallState because the call state is more precise than the Phone.State 
which can be obtained using the android.telephony.PhoneStateListener Resulting events 
will have an AsyncResult in Message.obj. AsyncResult.userData will be set to the obj 
argument here. The h parameter is held only by a weak reference.

1051
1052    public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){
1053        mPreciseCallStateRegistrants.addUnique(h, what, obj);
1054    }

私は何もコーディングしようとしたことがないので、それがあなたの望むことを実行できるかどうかは本当にわかりませんが、知りたいです。

于 2012-11-09T22:32:12.127 に答える
-1

あなたは次のことを行うことができます...あまり正確ではありませんが、トリックを行うことができます:

  1. android.intent.action.NEW_OUTGOING_CALLアクションのレシーバーを使用します
  2. レシーバーが呼び出されると、NEW_OUTGOIN_CALL 状態とこれが発生したミリ秒単位の時刻 (つまり、new Date().getTime()) をどこかに保存します (たとえば、静的変数)。
  3. android.intent.action.PHONE_STATEに別のレシーバーを使用し、onReceive で次のことを行います。

    if (intent.getAction().equals("android.intent.action.PHONE_STATE")) {
        TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        telephony.listen(new PhoneStateListener() {
            public void onCallStateChanged(int state, String incomingNumber) {
                  switch(state) {
                    case TelephonyManager.CALL_STATE_IDLE:
                    break;
                    case TelephonyManager.CALL_STATE_OFFHOOK:
                    break;
                    case TelephonyManager.CALL_STATE_RINGING:
                    break;
                   }
            } 
        }, PhoneStateListener.LISTEN_CALL_STATE);
    
    }
    

CALL_STATE_OFFHOOK の場合、最後に保存された状態が NEW_OUTGOING_CALL であり、おおよそ以下であることを確認します。最後の状態変更から 10 秒が経過しました。これは、電話が最大 10 秒前に通話を開始し、現在はアイドル状態または呼び出し音を通過することなくオフフック状態 (アクティブな通話を意味する) にあることを意味します。これは、通話に応答したことを意味する場合があります。

于 2013-01-02T17:04:14.790 に答える
-2

ここであなたの答えは、間違っている OutGoingCallReceiver に CallStateListener を実装したということです。PhoneStateListener に CallStateListener を実装する必要があります

以前のプロジェクトでもこのことを試しましたが、同じ問題に直面していたので、以下のように解決しました。以下の3クラスを受講しました。

  1. AutoCallReceiver: TelephonyManager を登録しますPhoneStateListener.LISTEN_CALL_STATE

  2. TelephonyManager.CALL_STATE_IDLETelephonyManager.CALL_STATE_OFFHOOK、 の3 つの状態をリッスンする CallStateListenerTelephonyManager.CALL_STATE_RINGING

3.発信コールを処理する OutGoingCallReceiver

public class OutGoingCallReceiver extends BroadcastReceiver {  
    /* onReceive will execute on out going call */
    @Override  
    public void onReceive(Context context, Intent intent) {  
        Toast.makeText(context, "OutGoingCallReceiver", Toast.LENGTH_SHORT).show();
    }
}

public class CallStateListener extends PhoneStateListener {  
    String number=""; // variable for storing incoming/outgoing number
    Context mContext; // Application Context

    //Constructor that will accept Application context as argument
    public CallStateListener(Context context) {
        mContext=context;
    }

    // This function will automatically invoke when call state changed
    public void onCallStateChanged(int state,String incomingNumber)
    {
        boolean end_call_state=false; // this variable when true indicate that call is disconnected
        switch(state) {
            case TelephonyManager.CALL_STATE_IDLE:  
                // Handling Call disconnect state after incoming/outgoing call 
                Toast.makeText(mContext, "idle", Toast.LENGTH_SHORT).show();
                break;  

            case TelephonyManager.CALL_STATE_OFFHOOK:     
                // Handling outgoing call  
                Toast.makeText(mContext, "OFFHOOK", Toast.LENGTH_SHORT).show();
                // saving outgoing call state so that after disconnect idle state can act accordingly
                break;  

            case TelephonyManager.CALL_STATE_RINGING: 
                Toast.makeText(mContext, "RINGING", Toast.LENGTH_SHORT).show();     
                break;
        }
    }
}

public class AutoCallReceiver extends BroadcastReceiver {       
    /* onReceive will execute on call state change */
    @Override  
    public void onReceive(Context context, Intent intent) { 

    // Instantiating PhoneStateListener
    CallStateListener phoneListener=new CallStateListener(context);  

    // Instantiating TelephonyManager
        TelephonyManager telephony = (TelephonyManager)   
                         context.getSystemService(Context.TELEPHONY_SERVICE);  

            // Registering the telephony to listen CALL STATE change
        telephony.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);  
    }
}

<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<application ...>
    <receiver android:name=".OutGoingCallReceiver">
        <intent-filter>
            <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
        </intent-filter>
    </receiver>
    <receiver android:name=".AutoCallReceiver">
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
        </intent-filter>
    </receiver>
</application>
于 2012-10-30T07:27:51.567 に答える