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

Я работаю над получением журнала последних вызовов, поскольку вызов отключается (исходящий, входящий) либо с ответом, либо без ответа.

Я использую прослушиватель состояния телефона для запуска трансляции при отключении вызова, но он запускается несколько раз для одного вызова, почему так..??

Так что, пожалуйста, скажите мне, как запустить приемник только один раз для одного звонка.

вот мой код

public class BroadcastReceiver  extends android.content.BroadcastReceiver{
    static boolean iscallended= true;
    Context mContext;
    TelephonyManager telephony;
     private static final String TAG = "CustomBroadcastReceiver";
    CustomPhoneStateListener customPhoneStateListener;

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        mContext = context;
        Bundle extras = intent.getExtras();
        if (extras != null) {
            String state = extras.getString(TelephonyManager.EXTRA_STATE);
            Log.w("DEBUG", state);

                telephony = (TelephonyManager)context.getSystemService(context.TELEPHONY_SERVICE);
               if(customPhoneStateListener==null)
               {

                customPhoneStateListener = new   CustomPhoneStateListener();
                telephony.listen(customPhoneStateListener,   PhoneStateListener.LISTEN_CALL_STATE);
               }



        }



    }
    private class CustomPhoneStateListener extends PhoneStateListener
    {
         private static final String TAG = "CustomPhoneStateListener";
         Handler handler=new Handler();

        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            // TODO Auto-generated method stub
            System.out.println(iscallended+  "  value of iscancelled ");
             switch (state) 
             {
             case TelephonyManager.CALL_STATE_RINGING:
                 if(!incomingNumber.equalsIgnoreCase(""))
                 {
                     //YOUR CODE HERE

                 }
                 break;

             case TelephonyManager.CALL_STATE_IDLE:
                 if(iscallended)
                 {
                     iscallended = false;
                 System.out.println("IDLE called");
                 Toast.makeText(mContext, "IDLE", Toast.LENGTH_SHORT).show();
                 Intent it = new Intent(mContext,MainActivity.class);
                 it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                 mContext.startActivity(it);
                 }
                 break;
             default:
                 break;
             }
             super.onCallStateChanged(state, incomingNumber);
             telephony.listen(customPhoneStateListener, PhoneStateListener.LISTEN_NONE);
        }







    }

}

Вот получатель в манифесте

 <receiver android:name="com.example.calllogs.BroadcastReceiver">
            <intent-filter >

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


        </receiver>

person Shivam Nagpal    schedule 09.09.2015    source источник
comment
@Nagpal Нагпал, вы нашли какое-нибудь решение для этого. Если да, то, пожалуйста, напишите, как вы это сделали?   -  person srinivas    schedule 23.03.2016


Ответы (3)


Вот ваш ответ:

https://stackoverflow.com/a/5497316/3479012

также укажите в своем манифесте разрешение на доступ к состоянию телефона.

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

также взгляните на этот http://karanbalkar.com/2014/02/detect-incoming-call-and-call-hangup-event-in-android/

person Jolson Da Costa    schedule 09.09.2015
comment
я использовал тот же код, но я дважды получаю состояние IDLE в приложении - person Shivam Nagpal; 09.09.2015
comment
Это может быть проблема с Lollipop и далее (mmarvick.github. ио/блог/блог/) - person Bugs Happen; 19.01.2016

Да, вы получите это.

 private class MyPhoneStateListener extends PhoneStateListener {

    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        switch (state) {
            //Hangup
            case TelephonyManager.CALL_STATE_IDLE:
                Log.d("IDLE", "Call Idle" + state);

                if (isCallEnded) {
                    isCallEnded = false;
                    AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getActivity());
                                                    .setCancelable(false)
                            .setPositiveButton(getString(R.string.Yes), new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    // your method
                                }
                            })
                            .setNegativeButton(getString(R.string.No), new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {

                                }
                            });
                    alertBuilder.show();
                }
                break;
            //Outgoing
            case TelephonyManager.CALL_STATE_OFFHOOK:
                Log.d("OFFHOOK", "Call OffHook" + state);
                isCallEnded = true;
                break;
            //Incoming
            case TelephonyManager.CALL_STATE_RINGING:
                Log.d("RINGING", "Call Ringing" + state);
                break;
        }
    }
}

Вышеприведенный пример — когда вы смотрите журнал устройства, вы обязательно увидите несколько раз поднятую трубку, а также состояние IDLE.

Попробуй посчитать, должно получиться.

person EngineSense    schedule 09.09.2015
comment
но он не работает каждый раз, когда вызывается приемник, он создает новый экземпляр класса и удаляет старые значения. - person Shivam Nagpal; 09.09.2015
comment
Есть ли другой способ добиться такого же поведения? - person Shivam Nagpal; 09.09.2015
comment
удалить старые значения, что вы подразумеваете под этим? - person EngineSense; 09.09.2015
comment
я тоже сталкиваюсь с той же проблемой, я думаю, что удаление старых значений означает, что значения, хранящиеся в переменных, теряются, т. е. если мы сохраняем состояние в состоянии звонка, значения удаляются при изменении состояния (в состояние IDLE). - person srinivas; 23.03.2016

Чтобы избежать повторяющихся срабатываний, используйте MyPhoneStateListener в качестве объекта и отметьте lastCallState. Позвоните makeMyPhoneStateListener из ServiceReceiver.

class MyPhoneStateListener () : PhoneStateListener() {

    companion object {

        var lastCallState: Int? = null
        lateinit var context: Context

        fun makeMyPhoneStateListener(_context: Context): MyPhoneStateListener
        {
            val myPhoneStateListener = MyPhoneStateListener()
            context = _context
            return myPhoneStateListener
        }
    }

    override fun onCallStateChanged(state: Int, incomingNumber: String) {

        when (state) {
            TelephonyManager.CALL_STATE_IDLE -> {

                if (lastCallState!= TelephonyManager.CALL_STATE_IDLE){
                    // some code for CALL_STATE_IDLE
                    lastCallState = TelephonyManager.CALL_STATE_IDLE
                }
            }
            TelephonyManager.CALL_STATE_OFFHOOK -> {

                if (lastCallState!= TelephonyManager.CALL_STATE_OFFHOOK) {

                    // some code for CALL_STATE_OFFHOOK
                    lastCallState = TelephonyManager.CALL_STATE_OFFHOOK
                }
            }
            TelephonyManager.CALL_STATE_RINGING -> {
                if (lastCallState!= TelephonyManager.CALL_STATE_RINGING) {

                    // some code for CALL_STATE_RINGING
                    lastCallState = TelephonyManager.CALL_STATE_RINGING    
                }
            }    
        }    
    }
person Artem    schedule 08.11.2020