Приемник вещания не работает в Android Oreo

Мой приемник Broadcast не работает на oreo, но работает ниже или работает нормально, я много искал по этому поводу, но не смог найти подходящего решения. Кто-нибудь сталкивается с той же проблемой, вот мой код, касающийся моего сервиса, в котором была реализована трансляция. Будь добр, подсказывает мне, что я могу сделать, работая в oreo.

Вот класс

public int onStartCommand(Intent intent, int flags, int startId) {
        mContext = this;
        mAppPreferences = new AppPreferences(mContext);
        if (intent.getExtras() != null) {
            data = (String) intent.getExtras().get("showPopUp");
            phoneNumber= (String) intent.getExtras().get("dialNumber");
        }
        final IntentFilter intentFilter = new IntentFilter();
        if (data.equalsIgnoreCase("true")) {
            showPopup(getApplicationContext());
            Utils.ApiHit(phoneNumber,getApplicationContext());
        }
        intentFilter.setPriority(2147483647);
        intentFilter.addAction("android.intent.action.PHONE_STATE");
        callExplicitReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
                    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);
                        phoneNumber = 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, phoneNumber);
                    }
                }
            }
        };
        mContext.registerReceiver(callExplicitReceiver, intentFilter);
        return START_NOT_STICKY;
    }


    public void onIncomingCallReceived(Context ctx, String number, Date start) {
    }

    public void onIncomingCallAnswered(Context ctx, String number, Date start) {
        if (popupView.getVisibility() == View.GONE) {
            popupView.setVisibility(View.VISIBLE);
        }
    }

    public void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                DeleteCallLogByNumber(number);
            }
        }, 2000);
        if (popupView.getVisibility() == View.VISIBLE) {
            popupView.setVisibility(View.GONE);
        }
    }

    public void onOutgoingCallStarted(Context ctx, String number, Date start) {
//        mAppPreferences.setPrefrenceString("busy", "yes");
//        if (data.equalsIgnoreCase("true")) {
            mediaPlayer = MediaPlayer.create(ctx, R.raw.speech_audio);
//        } else {
//            mediaPlayer = MediaPlayer.create(ctx, R.raw.speech_audio);
//        }

        mediaPlayer.start();
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                    mediaPlayer.stop();
                    mediaPlayer.release();
                }
            }
        }, 12000);
        if (popupView.getVisibility() == View.GONE) {
            popupView.setVisibility(View.VISIBLE);
        }
    }


    public void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
        mAppPreferences.setPrefrenceString("busy", "no");
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
        }
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                DeleteCallLogByNumber(phoneNumber);
            }
        }, 2000);
        if (popupView.getVisibility() == View.VISIBLE) {
            popupView.setVisibility(View.GONE);
        }
    }

    public void onMissedCall(Context ctx, String number, Date start) {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                DeleteCallLogByNumber(phoneNumber);
            }
        }, 2000);
        if (popupView.getVisibility() == View.VISIBLE) {
            popupView.setVisibility(View.GONE);
        }
    }




public void onCallStateChanged(Context context, int state, String number) {
        if (lastState == state) {
            return;
        }
        switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                isIncoming = true;
                callStartTime = new Date();
                savedNumber = number;
                onIncomingCallReceived(context, number, callStartTime);
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                if (lastState != TelephonyManager.CALL_STATE_RINGING) {
                    isIncoming = false;
                    callStartTime = new Date();
                    onOutgoingCallStarted(context, savedNumber, callStartTime);
                } else {
                    isIncoming = true;
                    callStartTime = new Date();
                    onIncomingCallAnswered(context, savedNumber, callStartTime);
                }
                break;
            case TelephonyManager.CALL_STATE_IDLE:
                if (popupView.getVisibility() == View.VISIBLE) {
                    popupView.setVisibility(View.GONE);
                }
                if (lastState == TelephonyManager.CALL_STATE_RINGING) {
                    onMissedCall(context, savedNumber, callStartTime);
                } else if (isIncoming) {
                    onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
                } else {
                    onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
                }
                break;
        }
        lastState = state;
    }

    @Override
    public void onDestroy() {
        mContext.unregisterReceiver(callExplicitReceiver);
    }

Отмечая, что я пришел в приемник, Кто-нибудь может мне помочь в этом?

Новые дополнения согласно обсуждению

Данные манифеста: -

Разрешение использовано: -

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

Получатель: -

<receiver android:name="com.example.dialer.AppUtils.StartUpBootReceiver" android:enabled="true" android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>

Мой класс приемника BroadCast: -

public class StartUpBootReceiver extends BroadcastReceiver {

    private Context mContext;

    @Override
    public void onReceive(Context context, Intent intent) {
        mContext= context;
        String action = "START";

        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            {
                context.startForegroundService(new Intent(context, PhoneStateService.class));
            }
            else
            {
                context.startService(new Intent(context, PhoneStateService.class));
            }
        }
    }


    private boolean isServiceRunning(Class<?> serviceClass) {
        ActivityManager manager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceClass.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }
}

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

Спасибо

Ответ 1

Ограничения на трансляцию

Если приложение регистрируется для получения широковещательных сообщений, получатель приложения потребляет ресурсы при каждой отправке широковещательной рассылки. Это может вызвать проблемы, если слишком много приложений регистрируется для приема трансляций на основе системных событий; системное событие, запускающее широковещательную рассылку, может привести к тому, что все эти приложения будут использовать ресурсы в быстрой последовательности, что ухудшит взаимодействие с пользователем. Чтобы решить эту проблему, Android 7.0 (уровень API 25) наложил ограничения на широковещательные рассылки, как описано в Фоновой оптимизации. Android 8.0 (уровень API 26) делает эти ограничения более строгими.

  1. Приложения, предназначенные для Android 8.0 или выше, больше не могут регистрировать приемники широковещания для неявных трансляций в своем манифесте. Неявная трансляция - это трансляция, которая не предназначена специально для этого приложения. Например, ACTION_PACKAGE_REPLACED - это неявная широковещательная рассылка, поскольку она отправляется всем зарегистрированным слушателям, давая им знать, что какой-то пакет на устройстве был заменен. Однако ACTION_MY_PACKAGE_REPLACED не является неявной трансляцией, поскольку она отправляется только приложению, пакет которого был заменен, независимо от того, сколько других приложений зарегистрировали прослушиватели для этой трансляции.

  2. Приложения могут продолжать регистрироваться для явных трансляций в своих манифестах.

  3. Приложения могут использовать Context.registerReceiver() во время выполнения, чтобы зарегистрировать получателя для любой трансляции, неявной или явной.

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

Проверьте официальную документацию здесь

Надеюсь это поможет.

Ответ 2

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

Проверьте это руководство и это также для переноса вашего приложения для поддержки Oreo.

Ответ 3

У меня тоже была такая проблема, но я нашел лучшее решение:

Класс MyReceiver

@BroadcastReceiverActions({
        "android.intent.action.SCREEN_ON",
        "android.intent.action.SCREEN_OFF",
        "android.intent.action.DREAMING_STARTED",
        "android.intent.action.DREAMING_STOPPED",
        "android.intent.action.ACTION_POWER_DISCONNECTED",
        "android.intent.action.ACTION_POWER_CONNECTED",
        "android.net.conn.CONNECTIVITY_CHANGE"
})
public class MyReceiver extends BroadcastReceiver {

    public MyReceiver() {
        super();
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Session.getGlobalReceiverCallBack(context, intent);

        //Log.e("dfd", "" + intent.getAction());
    }
}

Класс AppController

public class AppController extends Application {

    private BroadcastReceiver receiver;
    MyReceiver mR;

    @Override
    public void onCreate() {
        super.onCreate();
        mR = new MyReceiver();
        receiver = DynamicReceiver.with(mR)
                .register(this);

    }
}

Класс MainActivity

public class MainActivity extends AppCompatActivity implements GlobalReceiverCallBack {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Session.setmGlobalReceiverCallback(this);

    }

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

        Toast.makeText(context, "" + intent.getAction(), Toast.LENGTH_LONG).show();
    }
}

Для полной справки вы можете увидеть также https://github.com/devggaurav/BroadcastReceiver-For-Naught-and-Oreo-devices

Ответ 4

Android 8.0 предлагает несколько улучшений JobScheduler, которые упрощают замену служб и приемников вещания запланированными заданиями:

https://developer.android.com/about/versions/oreo/background

Ответ 5

Зарегистрируйте получателя вещания в действии при создании метода, а не в манифесте, и отмените его регистрацию при уничтожении. Надеюсь, что это будет работать на Android 9.