wake-up-neo.com

Broadcast-Empfänger funktioniert nicht in Android oreo

Mein Broadcast-Empfänger funktioniert nicht auf oreo, aber unterhalb von oreo funktioniert er einwandfrei. Ich habe viel darüber gesucht, konnte aber keine passende Lösung finden. Steht jemand vor dem gleichen Problem? Hier ist mein Code zu meinem Dienst, in dem Broadcast implementiert wurde. Ich bitte um Verständnis, wie ich in oreo arbeiten kann.

Hier ist die Klasse

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

Beachten Sie, dass sich jemand im Empfang befindet. Kann mir jemand dabei helfen?

Neue Ergänzungen laut Diskussion  

Manifestdaten : -

Verwendete Erlaubnis : - 

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

Empfänger : -

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

Meine BroadCast-Empfängerklasse : -

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

Rest desselben Dienstes wird den Anruf erhalten, aber das Problem ist, dass ich immer noch keinen Anruf im Empfänger bekomme. Und der primäre Punkt ist, dass der Dienst nur dann angerufen werden sollte, wenn der Benutzer auf die Schaltfläche tippt, und nicht automatisch, da ich einige Werte in der Bedienung.

Vielen Dank

7
Era Singla

Broadcast-Einschränkungen

Wenn sich eine App für den Empfang von Broadcasts registriert, verbraucht der Empfänger der App bei jedem Broadcast-Versand Ressourcen. Dies kann zu Problemen führen, wenn sich zu viele Apps registrieren, um Broadcasts basierend auf Systemereignissen zu empfangen. Ein Systemereignis, das einen Broadcast auslöst, kann dazu führen, dass all diese Apps in rascher Folge Ressourcen verbrauchen und die Benutzererfahrung beeinträchtigen. Um dieses Problem zu verringern, hat Android 7.0 (API-Level 25) Broadcasts Beschränkungen auferlegt, wie unter Hintergrundoptimierung beschrieben. Android 8.0 (API Level 26) macht diese Einschränkungen strenger.

  1. Apps, die auf Android 8.0 oder höher abzielen, können Broadcast-Empfänger nicht mehr für implizite Broadcasts in ihrem Manifest registrieren. Eine implizite Übertragung ist eine Übertragung, die diese App nicht speziell anspricht. Beispielsweise ist ACTION_PACKAGE_REPLACED eine implizite Rundsendung, da sie an alle registrierten Listener gesendet wird und ihnen mitteilt, dass ein Paket auf dem Gerät ersetzt wurde. ACTION_MY_PACKAGE_REPLACED ist jedoch keine implizite Übertragung, da sie nur an die App gesendet wird, deren Paket ersetzt wurde, unabhängig davon, wie viele andere Benutzer Listener für diese Übertragung registriert haben.

  2. Apps können sich weiterhin für explizite Übertragungen in ihren Manifesten registrieren.

  3. Apps können Context.registerReceiver () zur Laufzeit verwenden, um einen Empfänger für jede Broadcast zu registrieren, egal ob implizit oder explizit.

  4. Broadcasts, für die eine Signaturberechtigung erforderlich ist, sind von dieser Einschränkung ausgenommen, da diese Broadcasts nur an Apps gesendet werden, die mit demselben Zertifikat signiert sind, nicht an alle Apps auf dem Gerät.

Offizielle Dokumentation hier prüfen

Hoffe das hilft.

9

Das Problem besteht darin, dass der Dienst, den Sie ausführen möchten, nicht ausgeführt wird. Dienste oder permanente Hintergrunddienste dürfen für Apps, die auf Oreo oder höher abzielen, nicht lange ausgeführt werden. 

Überprüfen Sie diese Anleitung und auch dies für die Migration Ihrer App zur Unterstützung von Oreo.

3
MadScientist

Ich hatte auch diese Art von Problem, fand aber eine bessere Lösung:

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

    }
}

Klasse Hauptaktivität

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

Für vollständige Referenz können Sie auch https://github.com/devggaurav/BroadcastReceiver-For-Naught-und-Oreo-devices

2
Akshay Kumar

Android 8.0 bietet mehrere Verbesserungen an JobScheduler, die das Ersetzen von Diensten und Rundfunkempfängern durch geplante Jobs erleichtern:

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

1
Danial Pordel

Registrieren Sie Ihren Rundfunkempfänger in der Aktivität für die Erstellungsmethode und nicht für die Manifestmethode, und heben Sie die Registrierung für die Zerstörungsmethode auf. Ich hoffe, das funktioniert auf Android 9.

0