Как определить, когда телефон отвечает или отклонен

Мне удалось подготовить мероприятие, когда звонит телефон. Теперь мне нужно знать, как отменить эту активность, когда я прошу телефон или отклонить вызов. Я вызываю EXTRA_STATE_IDLE? EXTRA_STATE_OFFHOOK?

Любые идеи?

<receiver android:name=".IncomingBroadcastReceiver">                     
        <intent-filter>                                                   
            <action android:name="android.intent.action.PHONE_STATE"/>   
        </intent-filter>
    </receiver> 



public class IncomingBroadcastReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
    // If an incoming call arrives
    if (state.equals(TelephonyManager.EXTRA_STATE_RINGING))
    { //Did my work }

Ответ 1

в вашем onReceive:

PhoneStateChangeListener pscl = new PhoneStateChangeListener;
TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE);

отдельный класс:

private class PhoneStateChangeListener extends PhoneStateListener {
    public static boolean wasRinging;
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        switch(state){
            case TelephonyManager.CALL_STATE_RINGING:
                 Log.i(LOG_TAG, "RINGING");
                 wasRinging = true;
                 break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                 Log.i(LOG_TAG, "OFFHOOK");

                 if (!wasRinging) {
                     // Start your new activity
                 } else {
                     // Cancel your old activity
                 }

                 // this should be the last piece of code before the break
                 wasRinging = true;
                 break;
            case TelephonyManager.CALL_STATE_IDLE:
                 Log.i(LOG_TAG, "IDLE");
                 // this should be the last piece of code before the break
                 wasRinging = false;
                 break;
        }
    }
}

Все, что вам нужно сделать, это написать код, чтобы проверить, было ли предыдущее состояние "звонком". Если текущее состояние неактивно, а предыдущее состояние звонит, они отменили вызов. Если текущее состояние отключено и предыдущее состояние звонит, они ответили на звонок.

Ответ 2

Вышеприведенный ответ полностью неверен в случае исходящих вызовов. В Android нет способа, с помощью которого можно определить, действительно ли был вызван вызов (в случае исходящих вызовов). Когда вы набираете номер, состояние off_hook запускается. Это один из недостатков в программировании для Android.

Ответ 3

Ниже приведены состояния, которые он проходит в разных сценариях:

1) Ответ на входящий вызов

CALL_STATE_RINGING => CALL_STATE_OFFHOOK (After Answering call) => CALL_STATE_IDLE (After End call) 

2) Отклонение/Неответ (Пропущенный) Принятый вызов

CALL_STATE_RINGING => CALL_STATE_IDLE (After End call)  

3) Наберите

CALL_STATE_OFFHOOK (After dialing) => CALL_STATE_IDLE (After End call) 



int prev_state=0;


  public class CustomPhoneStateListener extends PhoneStateListener {  

        private static final String TAG = "CustomPhoneStateListener";  

        @Override  
        public void onCallStateChanged(int state, String incomingNumber){  

            if(incomingNumber!=null&&incomingNumber.length()>0) incoming_nr=incomingNumber;   

            switch(state){  
                case TelephonyManager.CALL_STATE_RINGING:  
                        Log.d(TAG, "CALL_STATE_RINGING");  
                        prev_state=state;  
                        break;  
                case TelephonyManager.CALL_STATE_OFFHOOK:  
                Log.d(TAG, "CALL_STATE_OFFHOOK");  
                prev_state=state;  
                break;  
                case TelephonyManager.CALL_STATE_IDLE:  
                    Log.d(TAG, "CALL_STATE_IDLE==>"+incoming_nr);  
                    NumberDatabase database=new NumberDatabase(mContext);  
                    if((prev_state==TelephonyManager.CALL_STATE_OFFHOOK)){  
                        prev_state=state;  
                        //Answered Call which is ended  
                    }  
                    if((prev_state==TelephonyManager.CALL_STATE_RINGING)){  
                        prev_state=state;  
                        //Rejected or Missed call  
                    }  
                    break;  

            }  
        }  
    }  

В вашем приемнике

onReceive(Context context, Intent intent) {  
        TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); //TelephonyManager object  
        CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();  
        telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);          //Register our listener with TelephonyManager  

        Bundle bundle = intent.getExtras();  
        String phoneNr= bundle.getString("incoming_number");  

        mContext=context;  
    }  

Ответ 4

ниже - код обнаружения исходящего вызова по событиям доступности -

Добавьте класс, который расширяет AccessibilityService в ваших проектах -

public class CallDetection extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
     acquireLock(this);
    Log.d("myaccess","after lock");
    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
        Log.d("myaccess","in window changed");
        AccessibilityNodeInfo info = event.getSource();
        if (info != null && info.getText() != null) {
            String duration = info.getText().toString();
            String zeroSeconds = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(0)});
            String firstSecond = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(1)});
            Log.d("myaccess","after calculation - "+ zeroSeconds + " --- "+ firstSecond + " --- " + duration);
            if (zeroSeconds.equals(duration) || firstSecond.equals(duration)) {
                Toast.makeText(getApplicationContext(),"Call answered",Toast.LENGTH_SHORT).show();
               // Your Code goes here
            }
            info.recycle();
        }
    }
}


@Override
protected void onServiceConnected() {
    super.onServiceConnected();
    Toast.makeText(this,"Service connected",Toast.LENGTH_SHORT).show();
    AccessibilityServiceInfo info = new AccessibilityServiceInfo();
    info.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
    info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
    info.notificationTimeout = 0;
    info.packageNames = null;
    setServiceInfo(info);
}

@Override
public void onInterrupt() {

}
}

Но для того, чтобы работать с функцией event.getSource(), вам нужно указать некоторую конфигурацию своей службы через xml, поэтому создайте в своем проекте папку xml и добавьте XML файл с именем serviceconfig. xml (вы можете указать любое имя, которое вы хотите.

Содержимое serviceconfig находится ниже -

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/callDetection"
android:accessibilityEventTypes="typeWindowContentChanged"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
/>

Подробнее о serviceconfig вы можете найти в здесь

Теперь добавьте свою службу в свой Манифест, как это -

<service android:name=".CallDetection"
        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
        android:label="@string/callDetection">
        <intent-filter>
            <action android:name="android.accessibilityservice.AccessibilityService" />
        </intent-filter>
        <meta-data
            android:name="android.accessibilityservice"
            android:resource="@xml/serviceconfig" />
</service>

И вы сделали, просто запустите приложение и перейдите в Настройки специальных возможностей на своем телефоне, вы найдете опцию с именем обнаружение (или другое имя, которое вы указали как ваше описание сервиса), включите это, чтобы предоставить разрешения на доступ для вашего приложения.

Теперь вы увидите тост, когда на вызов будет дан ответ.

вы можете закодировать любой код, который вы хотите там, также вы можете вызвать функцию обратного вызова в своей деятельности.

Самое важное. Не звоните в окно вызовов (окно дозвона андроида) до ответа на вызов, иначе это не сработает.

Примечание. Поскольку андроид не предоставляет никакого решения для обнаружения ответа на вызов или нет, это лучшая альтернатива, которую я сделал, надеюсь, что это сработает для вас.