Приемник вещания для состояния телефона изменен, не работает - PullRequest
0 голосов
/ 17 сентября 2018

Я создал широковещательный приемник для изменения состояния телефона.но трансляция не работает.Я пытался от пары часов и попробовал 2,3 решения, но все еще не работает.другие парни через Интернет имеют такой же код, и он работает нормально для них.Я не знаю, где я делаю ошибку.нужна ваша помощь!Вот мой файл манифеста

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="veclar.map.callandsmsblocking">
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>
        </activity>
        <receiver android:name=".PhoneCallReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
            </intent-filter>
        </receiver>
    </application>
</manifest> 

, а вот мой класс PhoneCallReceiver

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

    private static int lastState = TelephonyManager.CALL_STATE_IDLE;
    private static Date callStartTime;
    private static boolean isIncoming;
    private static String savedNumber;  //because the passed incoming is only valid in ringing

    @Override
    public void onReceive(Context context, Intent intent) {

        //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")) {
            savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
        }
        else{
            String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
            String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
            int state = 0;
            if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
                state = TelephonyManager.CALL_STATE_IDLE;
            }
            else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
                state = TelephonyManager.CALL_STATE_OFFHOOK;
            }
            else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
                state = TelephonyManager.CALL_STATE_RINGING;
            }

            onCallStateChanged(context, state, 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
    public void onCallStateChanged(Context context, int state, String number) {
        if(lastState == state){
            //No change, debounce extras
            return;
        }
        switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                isIncoming = true;
                callStartTime = new Date();
                savedNumber = number;

                Toast.makeText(context, "Incoming Call Ringing" , Toast.LENGTH_SHORT).show();
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                //Transition of ringing->offhook are pickups of incoming calls.  Nothing done on them
                if(lastState != TelephonyManager.CALL_STATE_RINGING){
                    isIncoming = false;
                    callStartTime = new Date();
                    Toast.makeText(context, "Outgoing Call Started" , Toast.LENGTH_SHORT).show();
                }

                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
                    Toast.makeText(context, "Ringing but no pickup" + savedNumber + " Call time " + callStartTime +" Date " + new Date() , Toast.LENGTH_SHORT).show();
                }
                else if(isIncoming){

                    Toast.makeText(context, "Incoming " + savedNumber + " Call time " + callStartTime  , Toast.LENGTH_SHORT).show();
                }
                else{

                    Toast.makeText(context, "outgoing " + savedNumber + " Call time " + callStartTime +" Date " + new Date() , Toast.LENGTH_SHORT).show();

                }

                break;
        }

        lastState = state;
    }
}

Ответы [ 2 ]

0 голосов
/ 04 мая 2019

Мне не хватило разрешения состояния телефона в моем случае (android.permission.READ_PHONE_STATE), определенного в манифесте, поэтому, когда я даю разрешение приложению вручную из настройки приложения, оно начинает получать широковещательную рассылку Phone_State.Я думаю, что от пользователя требуется разрешение во время выполнения.

0 голосов
/ 17 сентября 2018

Вы больше не можете получать трансляцию PHONE_STATE_CHANGED таким образом.

Из официального руководства разработчика Android https://developer.android.com/guide/components/broadcasts:

Начиная с Android 8.0 (уровень API 26),система налагает дополнительные ограничения на получателей, объявленных манифестом.

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

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

public class ToastDisplay extends Activity {

    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(getApplicationContext(), "received", Toast.LENGTH_SHORT);
        }
    };

    @Override
    protected void onResume() {
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.intent.action.PHONE_STATE");
        registerReceiver(receiver, filter);
        super.onResume();
    }

    @Override
    protected void onPause() {
        unregisterReceiver(receiver);
        super.onPause();
    }
}

Кроме того, кроме того, что вы декларируете в манифесте необходимые разрешения, такие как android.permission.READ_PHONE_STATE, android.permission.PROCESS_OUTGOING_CALLS, вы должны явно получить эти разрешения от пользователя во время выполнения.В противном случае вы не получите некоторые (большинство) системных трансляций.В руководстве для разработчиков Android есть хорошее объяснение того, как запрашивать разрешения у пользователя, и пример кода.https://developer.android.com/training/permissions/requesting

...