Как определить, когда на телефон ответили или отклонили - PullRequest
23 голосов
/ 13 марта 2012

Мне удалось подготовить занятие, когда телефон звонит. Теперь мне нужно знать, как отменить это действие, когда я отвечаю по телефону или отклоняю вызов. Я звоню 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 }

Ответы [ 4 ]

24 голосов
/ 16 февраля 2014

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

21 голосов
/ 13 марта 2012

в вашем 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;
    String LOG_TAG = "PhoneListener";
    @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;
        }
    }
}

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

7 голосов
/ 13 марта 2012

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

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;  
 }  
1 голос
/ 12 июля 2017

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

Добавьте класс, который расширяет 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>

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

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

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

Самое важное - Не вызывайте окно вызова (окно набора номера Android), пока на вызов не будет получен ответ, иначе это не будет работать.

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

...