BroadcastReceiver 上下文注册不起作用

BroadcastReceiver context registration not working

我正在做一个项目,我需要注册一个 BroadcastReceiver 并从一个 Notification Action 向它发送一个广播。如果我做错了什么,请告诉我。我不希望接收器在清单中注册,因为我想要自定义 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());
}

我想通了我的问题。这与我实例化 Intent 对象和 IntentFilter 对象的方式有冲突。 IntentFilters 正在用一个动作实例化,而当我用“.setAction”选项实例化 Intent 时,修复如下:

改变这个:

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

为此:

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

因为我的 BroadcastReceiver 注册 IntentFilter 是这样的:

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

不幸的是,PendingIntent 不能是隐式的,因此您无法像那样接收它。不过有一个解决方法。

您的 activity 必须在清单中声明 android:launchMode="singleInstance

创建将启动 activity 的自定义接收器:

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>

然后在activity中处理意图:

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