web-dev-qa-db-fra.com

Récepteur de diffusion ne fonctionne pas dans Android oreo

Mon récepteur de diffusion ne fonctionne pas sur oreo mais son fonctionnement en dessous de oreo fonctionne très bien. J'ai beaucoup cherché à ce sujet, mais je n'ai pas trouvé la solution appropriée. Est-ce que quelqu'un a le même problème, voici mon code concernant mon service dans lequel la diffusion a été mise en œuvre. Suggère de bien vouloir comprendre comment je peux travailler pour oreo.

Voici la classe

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);
    }

Constatant qu'il entre dans le récepteur, est-ce que quelqu'un peut m'aider dans ce domaine?

Nouveaux ajouts selon discussion  

Données manifestes : -

Permission utilisée : - 

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

Reciver : -

<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>

Ma classe de récepteurs 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;
    }
}

Restez le même service obtiendra l'appel, mais le problème est que je ne reçois toujours pas d'appel dans le récepteur. Et le point principal est que le service ne devrait être appelé qu'une fois l'utilisateur clique sur le bouton, pas automatiquement car je dois transmettre certaines valeurs un service.

Merci

7
Era Singla

Limites de diffusion

Si une application s'enregistre pour recevoir des émissions, le récepteur de l'application consomme des ressources chaque fois que l'émission est envoyée. Cela peut poser problème si trop d'applications s'enregistrent pour recevoir des émissions en fonction d'événements système. un événement système qui déclenche une diffusion peut amener toutes ces applications à consommer des ressources en succession rapide, ce qui nuit à l'expérience utilisateur. Pour résoudre ce problème, Android 7.0 (API niveau 25) a limité les diffusions, comme décrit dans Optimisation en arrière-plan. Android 8.0 (API niveau 26) rend ces limitations plus strictes.

  1. Les applications qui ciblent Android 8.0 ou version ultérieure ne peuvent plus enregistrer les récepteurs de diffusion pour les diffusions implicites dans leur manifeste. Une diffusion implicite est une diffusion qui ne cible pas spécifiquement cette application. Par exemple, ACTION_PACKAGE_REPLACED est une diffusion implicite, car elle est envoyée à tous les écouteurs enregistrés, leur indiquant qu'un paquet sur le périphérique a été remplacé. Cependant, ACTION_MY_PACKAGE_REPLACED n'est pas une diffusion implicite, car elle est envoyée uniquement à l'application dont le package a été remplacé, quel que soit le nombre d'applications ayant enregistré des écouteurs pour cette diffusion.

  2. Les applications peuvent continuer à s'inscrire pour des émissions explicites dans leurs manifestes.

  3. Les applications peuvent utiliser Context.registerReceiver () lors de l'exécution pour enregistrer un récepteur pour toute diffusion, qu'elle soit implicite ou explicite.

  4. Les diffusions nécessitant une autorisation de signature sont exemptées de cette restriction, car elles ne sont envoyées qu'aux applications signées avec le même certificat, et non à toutes les applications de l'appareil.

Consultez la documentation officielle ici

J'espère que cela t'aides.

9
Mayank Bhatnagar

Le problème vient du service que vous essayez d'exécuter. Les services ou les services d'arrière-plan persistants ne sont pas autorisés à s'exécuter longtemps pour les applications ciblant Oreo et les versions ultérieures. 

Consultez ce guide et cela aussi pour la migration de votre application afin de prendre en charge Oreo.

3
MadScientist

J'ai aussi eu ce genre de problème, mais j'ai trouvé une meilleure solution:

Classe 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());
    }
}

Class 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);

    }
}

Classe 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();
    }
}

Pour une référence complète, vous pouvez aussi consulter https://github.com/devggaurav/BroadcastReceiver-For-Naught-and-Oreo-devices

2
Akshay Kumar

Android 8.0 offre plusieurs améliorations à JobScheduler qui facilitent le remplacement de services et la diffusion de récepteurs par des tâches planifiées:

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

1
Danial Pordel