web-dev-qa-db-ja.com

Android oreoでブロードキャストレシーバーが機能しない

私の放送受信機は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;
    }
}

残りの同じサービスは呼び出しを取得しますが、問題はまだ受信機で呼び出しを取得しないことです。そして、mの主要な点は、ユーザーがボタンをタップしたときに呼び出されるだけで、自動的にではなくいくつかの値を渡す必要があるということですサービス。

ありがとう

12
Era Singla

ブロードキャストの制限

アプリがブロードキャストを受信するように登録すると、アプリの受信者はブロードキャストが送信されるたびにリソースを消費します。これは、システムイベントに基づいてブロードキャストを受信するために登録するアプリが多すぎる場合に問題を引き起こす可能性があります。ブロードキャストをトリガーするシステムイベントにより、これらのアプリがすべて連続してリソースを消費し、ユーザーエクスペリエンスが損なわれる可能性があります。この問題を軽減するために、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. 署名の許可が必要なブロードキャストは、デバイス上のすべてのアプリではなく、同じ証明書で署名されたアプリにのみ送信されるため、この制限から免除されます。

公式ドキュメントはこちら

お役に立てれば。

11

問題は、実行しようとしているサービスに付属しています。サービスまたは永続的なバックグラウンドサービスは、Oreo以上を対象とするアプリでは長時間実行できません。

Oreoをサポートするためにアプリを移行するには、 このガイド および これも を確認してください。

4
MadScientist

私もこの種の問題を抱えていましたが、より良い解決策を見つけました。

クラス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

3
Akshay Kumar

Android 8.0ではJobSchedulerにいくつかの改良が加えられ、サービスとブロードキャストレシーバーをスケジュールされたジョブに簡単に置き換えることができます。

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

1
Danial Pordel

マニフェストではなくcreateメソッドのアクティビティでブロードキャストレシーバーを登録し、destroyメソッドで登録解除します。これがAndroid 9で機能することを願っています。

0