2

每次我开始通话或每次接到电话时,我都会尝试显示一条消息。我制作了一个适用于传入呼叫但不适用于传出呼叫的代码。我确实阅读了关于这个主题的不同帖子。

谁能告诉我为什么下面的代码向我展示了(当然,这段代码并没有做我之前提到的所有事情):
- 当我接到电话时是
“外出” - 当我开始通话时是“来电”然后是“外出”

/* 来自 MainActivity */

protected void onCreate(Bundle savedInstanceState) 
 {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  context = getApplicationContext();
  context.startService(new Intent(context, SvcCall.class));
 }

/* 来自 SvcCall */

public class SvcCall extends Service 
 {
  private static final String ACTION_OUT = "android.intent.action.PHONE_STATE";
  private static final String ACTION_IN = "android.intent.action.NEW_OUTGOING_CALL";
  private CallBr br_call;

  @Override
  public void onCreate()
   {
    super.onCreate();   
   }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId)
   {
    final IntentFilter filter = new IntentFilter();
    filter.addAction(ACTION_OUT);
    filter.addAction(ACTION_IN); 
    this.br_call = new CallBr();
    this.registerReceiver(this.br_call, filter);
    return (START_STICKY);
   }

  public class CallBr extends BroadcastReceiver  
   {
    @Override
    public void onReceive(Context context, Intent intent) 
 {
  if (intent.getAction().equals(ACTION_IN))
       Toast.makeText(context, "INCOMING", Toast.LENGTH_LONG).show();       
  else if (intent.getAction().equals(ACTION_OUT))
   Toast.makeText(context, "OUTGOING", Toast.LENGTH_LONG).show();
     }
   }

 @Override
 public IBinder onBind(Intent intent) 
 {
  return null;
 }
} 

/* 来自清单 */

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

3 回答 3

9

这是我用来对来电和去电做出反应的类。它的设置让你只需要派生和覆盖你关心的那些。它还告诉您呼叫是开始、结束还是未接听:

package com.gabesechan.android.reusable.receivers;

import java.util.Date;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

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
    static PhonecallStartEndDetector listener;
    String outgoingSavedNumber;
    protected Context savedContext;


    @Override
    public void onReceive(Context context, Intent intent) {
        savedContext = context;
        if(listener == null){
            listener = new PhonecallStartEndDetector();
        }

        //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")) {
            listener.setOutgoingNumber(intent.getExtras().getString("android.intent.extra.PHONE_NUMBER"));
            return;
        }

        //The other intent tells us the phone state changed.  Here we set a listener to deal with it
        TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 
        telephony.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
    }

    //Derived classes should override these to respond to specific events of interest
    protected abstract void onIncomingCallStarted(String number, Date start);
    protected abstract void onOutgoingCallStarted(String number, Date start);
    protected abstract void onIncomingCallEnded(String number, Date start, Date end); 
    protected abstract void onOutgoingCallEnded(String number, Date start, Date end);
    protected abstract void onMissedCall(String number, Date start);

    //Deals with actual events
    public class PhonecallStartEndDetector extends PhoneStateListener {
        int lastState = TelephonyManager.CALL_STATE_IDLE;
        Date callStartTime;
        boolean isIncoming;
        String savedNumber;  //because the passed incoming is only valid in ringing

        public PhonecallStartEndDetector() {}

        //The outgoing number is only sent via a separate intent, so we need to store it out of band
        public void setOutgoingNumber(String number){
            savedNumber = number;
        }

        //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
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);
            if(lastState == state){
                //No change, debounce extras
                return;
            }
            switch (state) {
                case TelephonyManager.CALL_STATE_RINGING:
                    isIncoming = true;
                    callStartTime = new Date();
                    savedNumber = incomingNumber;
                    onIncomingCallStarted(incomingNumber, callStartTime);
                    break;
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    //Transition of ringing->offhook are pickups of incoming calls.  Nothing donw on them
                    if(lastState != TelephonyManager.CALL_STATE_RINGING){
                        isIncoming = false;
                        callStartTime = new Date();
                        onOutgoingCallStarted(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(savedNumber, callStartTime);
                    }
                    else if(isIncoming){
                        onIncomingCallEnded(savedNumber, callStartTime, new Date());                        
                    }
                    else{
                        onOutgoingCallEnded(savedNumber, callStartTime, new Date());                                                
                    }
                    break;
            }
            lastState = state;
        }

    }



}
于 2013-06-03T00:40:06.220 回答
1

这是我的更新。

实际上,我尝试了两种方式(一个 BR 与两个 BR)并且由于您的回答,两者都运行良好。此刻一切都不完美。我正在做。我将向您展示我如何使用一个 BR(因为它是我的问题的对象)。

public class SvcCall extends Service 
 {
  Context _context;
  private static final String ACTION_IN = "android.intent.action.PHONE_STATE";
  private static final String ACTION_OUT = "android.intent.action.NEW_OUTGOING_CALL";
  private CallBr br_call;

  @Override
  public void onCreate()
   {
    super.onCreate();
    this._context = getApplicationContext();   
   }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId)
   {
    final IntentFilter filter = new IntentFilter();
    filter.addAction(ACTION_OUT);
    filter.addAction(ACTION_IN); 
    this.br_call = new CallBr();
    this.registerReceiver(this.br_call, filter);
    return (START_STICKY);
   }

  public class CallBr extends BroadcastReceiver  
   {
    Bundle bundle;
    String state;
    String inCall, outCall;
    public boolean wasRinging = false;

   @Override
   public void onReceive(Context context, Intent intent) 
    {
     if (intent.getAction().equals(ACTION_IN))
      {
       if ((bundle = intent.getExtras()) != null)
        {
         state = bundle.getString(TelephonyManager.EXTRA_STATE);
         if (state.equals(TelephonyManager.EXTRA_STATE_RINGING))
          {          
           inCall = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
           wasRinging = true;
           Toast.makeText(context, "IN : " + inCall, Toast.LENGTH_LONG).show();        
          }
         else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
          {        
           if (wasRinging == true)
            Toast.makeText(context, "ANSWERED", Toast.LENGTH_LONG).show();
          }
         else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE))
          {
           wasRinging = false;
           Toast.makeText(context, "REJECT || DISCO", Toast.LENGTH_LONG).show();
          }
        }
      }
     else if (intent.getAction().equals(ACTION_OUT))
      {
       if ((bundle = intent.getExtras()) != null)
        {  
         outCall = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
         Toast.makeText(context, "OUT : " + outCall, Toast.LENGTH_LONG).show();
        }
      }
     }
    }

   @Override
   public IBinder onBind(Intent intent)
    {
     return null;
    }
  }
于 2013-06-03T00:40:44.553 回答
-2
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:                      
    //CALL_STATE_IDLE;
    Toast.makeText(getApplicationContext(), "CALL_STATE_IDLE", Toast.LENGTH_LONG).show();
    break;
case TelephonyManager.CALL_STATE_OFFHOOK:
    //CALL_STATE_OFFHOOK;
    Toast.makeText(getApplicationContext(), "CALL_STATE_OFFHOOK", Toast.LENGTH_LONG).show();
    break;
case TelephonyManager.CALL_STATE_RINGING:
    //CALL_STATE_RINGING
    Toast.makeText(getApplicationContext(), incomingNumber, Toast.LENGTH_LONG).show();   
    Toast.makeText(getApplicationContext(), "CALL_STATE_RINGING", Toast.LENGTH_LONG).show();
     break;
default:
     break;
}

别忘了授权..

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
于 2014-07-28T11:01:45.287 回答