为什么在一次调用中多次调用Android上的onCallStateChanged()?

时间:2011-04-05 09:01:25

标签: android

我想实现一个防止像防火墙这样的通话的应用。当我调试我的应用程序时,我发现当有一个调用时,接口 PhoneStateListener 中的 onCallStateChanged()函数被调用三次。因此,阻止一个呼叫可能会导致三个日志。我很困惑!!

我的代码:

    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        try {
            if (state == TelephonyManager.CALL_STATE_RINGING && 
                PhoneUtil.getITelephony(tpm).isRinging()) {
                String flag = isBlockCall(myContext, myHelper, myTypes, incomingNumber);
                if (flag.length() > 0) {
                    blockCall();
                    myHelper.insertLog(new String[] { flag, incomingNumber, String.valueOf(System.currentTimeMillis()), null });
                    showNotification(myContext, incomingNumber, System.currentTimeMillis());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        super.onCallStateChanged(state, incomingNumber);
    }
}, PhoneStateListener.LISTEN_CALL_STATE);

5 个答案:

答案 0 :(得分:11)

答案在于您创建TelephonyManager然后使用它注册监听器的代码。每次启动一个新的调用时都会注册一个监听器,因此多个监听器连接到同一个电话管理器,导致每个监听器都有一个onCallStateChanged()。 尝试创建新的Telephony Manager并将其注册只执行一次。(构造函数)。

  

TelephonyManager tmanager =(TelephonyManager)this.getSystemService(TELEPHONY_SERVICE);

     

tmanager.listen(new CallListener(),PhoneStateListener.LISTEN_CALL_STATE);

答案 1 :(得分:8)

为了更好地说出Aakash的答案,onCallStateChanged()被多次调用,因为TelephonyManager.listen()位于onReceive()内。这样,只要广播一个事件,就会实例化一个新PhoneStateListener并注册到TelephonyManager,因此有很多这样的事件。

我个人在我的代码中做了类似的事情:

if (noCallListenerYet) { // noCallListenerYet is static boolean
    TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    tm.listen(new OutgoingCallListener(), PhoneStateListener.LISTEN_CALL_STATE);
    noCallListenerYet = false;
}

答案 2 :(得分:7)

现在好了,我一直在遭遇同样的事情,但不知何故,我找到了办法。

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;

public class CallActionsReceiver extends BroadcastReceiver {
    static ThePhoneStateListener phoneStateListener;

    @Override
    public void onReceive(Context arg0, Intent arg1) {
        TelephonyManager manager = (TelephonyManager) arg0
                .getSystemService(arg0.TELEPHONY_SERVICE);
        if (phoneStateListener == null) {
            phoneStateListener = new ThePhoneStateListener(arg0);
            manager.listen(phoneStateListener,
                    android.telephony.PhoneStateListener.LISTEN_CALL_STATE);
        }

    }

}

通过这种方式,TelephonyManager只会收听一次。干杯。 。 。

答案 3 :(得分:0)

PinkyJie,

onCallStateChanged()正在使用BroadcastReceiver。所以每当调用状态改变时,总会调用onCallStateChanged()。有三种呼叫状态。

TelephonyManager.CALL_STATE_IDLE:电话处于空闲模式,没有呼叫操作 TelephonyManager.CALL_STATE_OFFHOOK:至少有一个呼叫处于活动状态 TelephonyManager.CALL_STATE_RINGING:新呼叫到达并正在振铃或等待。 TelephonyManager。

系统永远不会超越它。请参阅此链接http://developer.android.com/reference/android/telephony/TelephonyManager.html

public class TestPhoneStateListener extends PhoneStateListener{

  public void onCallStateChanged(int state, String incomingNumber) {
    // TODO Auto-generated method stub
    System.out.println("aaaaaaaaaaaaaaa----------------------------------"+state);
    try {
        if (state == TelephonyManager.CALL_STATE_RINGING ) {
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    super.onCallStateChanged(state, incomingNumber);
  }
}

答案 4 :(得分:0)

根据 official documents

  

当设备调用状态发生变化时调用回调。

  • 这意味着每当来电响铃您的手机时,都会这样 改变状态。
  • 来电被拒绝,这也会调用状态更改
  • 接听来电,状态发生变化!
  • 最后没有动作,也会导致状态改变

据说,一旦一个国家改变了,在任何由此产生的反应中被视为被解雇两次是有意义的。