Android-来电和呼出电话

ia2d9nvy  于 2022-10-09  发布在  Android
关注(0)|答案(4)|浏览(154)

每次开始呼叫或每次收到呼叫时,我都会尝试显示一条消息。我做了一个代码,对来电有效,但对呼出不起作用。我确实读过关于这个主题的不同帖子。

有人能告诉我为什么下面这段代码显示给我看(当然这段代码不能完成我前面提到的所有事情):
--当我接到电话时“呼出”
-当我开始呼叫时,先是“来电”,然后是“去电”

/来自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" />
deikduxw

deikduxw1#

这是我用来对传入和传出电话呼叫做出React的类。它的设置使您只需派生和覆盖您所关心的内容。它还会告诉您呼叫是开始、结束还是未被接听:

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;
        }

    }

}
ippsafx7

ippsafx72#

这是我的最新消息。

事实上,我尝试了两种方法(一个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;
    }
  }
lb3vh1jj

lb3vh1jj3#

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

import java.util.Date;

public abstract class PhoneCallReceiver2 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(context);
        }

        //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);

        //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;
        }

    }

    //Derived classes should override these to respond to specific events of interest
    protected abstract void onIncomingCallStarted(Context context, String number, Date start);

    protected abstract void onOutgoingCallStarted(Context context, String number, Date start);

    protected abstract void onIncomingCallEnded(Context context, String number, Date start, Date end);

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

    protected abstract void onMissedCall(Context context, 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
        Context savedContext;

        public PhonecallStartEndDetector(Context savedContext) {
            this.savedContext = savedContext;
        }

        //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(savedContext, 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(savedContext, 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(savedContext, savedNumber, callStartTime);
                    } else if (isIncoming) {
                        onIncomingCallEnded(savedContext, savedNumber, callStartTime, new Date());
                    } else {
                        onOutgoingCallEnded(savedContext, savedNumber, callStartTime, new Date());
                    }
                    break;
            }
            lastState = state;
        }

    }

}
j8yoct9x

j8yoct9x4#

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"/>

相关问题