Регистрация контекста BroadcastReceiver не работает

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

Полный код доступен здесь: https://github.com/akirby/notificationTest

Изменить: Согласно документации Android ( https://developer.android.com/guide/components/broadcasts.html), это возможно, но у меня возникают проблемы с пониманием, почему это не работает.

BroadcastReciever локальная переменная

public BroadcastReceiver approveReceiver = new BroadcastReceiver(){
    @Override
    public void onReceive(Context context, Intent intent){
        notificationManager.cancel(notificationId);
        String data = intent.getAction();
        Toast.makeText(getApplicationContext(), data, Toast.LENGTH_LONG);
        if(data != null && data.equals("com.myapp.Approve")){
            mainText.setText("Approved");
        }
        else{
            mainText.setText("Denied");
        }
    }
};

Постановка на учет:

registerReceiver(approveReceiver, new IntentFilter("com.myapp.Approve"));

Уведомление:

public void showNotification(){

    Context appContext = getApplicationContext();
    Intent approveIntent = new Intent(appContext, ApprovalReceiver.class);
    approveIntent.setData(Uri.parse("Approve"));
    approveIntent.setAction("com.myapp.Approve");
    PendingIntent pendingIntent = PendingIntent.getBroadcast(appContext, 0, approveIntent, PendingIntent.FLAG_CANCEL_CURRENT);

    Intent denyIntent = new Intent(appContext, ApprovalReceiver.class);
    approveIntent.setData(Uri.parse("deny"));
    denyIntent.setAction("com.myapp.Deny");
    PendingIntent denyPendingIntent = PendingIntent.getBroadcast(appContext, 0, denyIntent, PendingIntent.FLAG_CANCEL_CURRENT);


    NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentTitle("Test Notification")
            .setContentText("Test notification details")
            .setAutoCancel(true)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .addAction(R.drawable.ic_launcher_foreground, getString(R.string.Approved),
                    pendingIntent)
            .addAction(R.drawable.ic_launcher_foreground, getString(R.string.Deny),
                    denyPendingIntent);
    notificationManager.notify(notificationId, builder.build());
}

2 ответа

Решение

Я понял мою проблему. Это был конфликт с тем, как я создавал объекты Intent и мои объекты IntentFilter. Фильтры IntentFilters создавались с помощью действия, и пока я создавал экземпляры Intents с параметром ".setAction", исправление приведено ниже:

Изменить это:

Intent approveIntent = new Intent(appContext, ApprovalReceiver.class);

К этому:

Intent approveIntent = new Intent("com.myapp.Approve");

потому что мой IntentFilter для регистрации BroadcastReceiver таков:

this.registerReceiver(approveReceiver, new IntentFilter("com.myapp.Approve"));

К сожалению, PendingIntent не может быть неявным, поэтому вы не можете получить его таким образом. Хотя есть обходной путь.

Ваша деятельность должна быть объявлена android:launchMode="singleInstance в манифесте.

Создайте пользовательский получатель, который начнет работу:

public class ApprovalReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent){
        Intent activityIntent = new Intent(context, MainActivity.class);
        activityIntent.putExtra("action", intent.getAction());
        context.startActivity(activityIntent);
    }
}

Зарегистрируйте это в манифесте:

<receiver android:name=".ApprovalReceiver">
    <intent-filter>
        <action android:name="ACTION_APPROVE"/>
        <action android:name="ACTION_DENY"/>
    </intent-filter>
</receiver>

А затем обработайте намерение в деятельности:

public class MainActivity extends AppCompatActivity {

    private String CHANNEL_ID = "AlertChannel";
    private TextView mainText;
    private int notificationId = 1;
    private NotificationManagerCompat notificationManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mainText = (TextView) findViewById(R.id.mainText);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        notificationManager = NotificationManagerCompat.from(this);
        createNotificationChannel();

        handleIntent(getIntent());

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showNotification();
            }
        });
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        handleIntent(intent);
    }

    private void handleIntent(Intent intent) {
        if(intent != null) {
            String action = intent.getStringExtra("action");
            if(action != null) {
                notificationManager.cancel(notificationId);
                setText(action);
            }
        }
    }

    private void setText(String action) {
        switch (action) {
            case "ACTION_APPROVE":
                mainText.setText("Approved");
                break;
            case "ACTION_DENY":
                mainText.setText("Denied");
                break;
        }
    }

    private void createNotificationChannel() {
        CharSequence name = getString(R.string.channel_name);
        String description = getString(R.string.channel_description);
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }

    public void showNotification() {
        Intent approveIntent = new Intent(getApplicationContext(), ApprovalReceiver.class);
        approveIntent.setAction("ACTION_APPROVE");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, approveIntent, 0);

        Intent denyIntent = new Intent(getApplicationContext(), ApprovalReceiver.class);
        denyIntent.setAction("ACTION_DENY");
        PendingIntent denyPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, denyIntent, 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_launcher_foreground)
                .setContentTitle("Test Notification")
                .setContentText("Test notification details")
                .setAutoCancel(true)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .addAction(R.drawable.ic_launcher_foreground, getString(R.string.Approved), pendingIntent)
                .addAction(R.drawable.ic_launcher_foreground, getString(R.string.Deny), denyPendingIntent);

        notificationManager.notify(notificationId, builder.build());
    }
}
Другие вопросы по тегам