2

我正在做一个项目,我需要注册一个 BroadcastReceiver 并从通知操作向它发送广播。请告诉我是否有明显的地方我做错了。我不希望接收者在清单中注册,因为我想要访问多个局部变量的自定义 onRecieve 方法。

此处提供完整代码:https ://github.com/akirby/notificationTest

编辑: 根据 Android 文档(https://developer.android.com/guide/components/broadcasts.html),这是可能的,但我无法理解为什么这不起作用。

广播接收器局部变量

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

2 回答 2

2

我发现了我的问题。这与我如何实例化 Intent 对象和我的 IntentFilter 对象存在冲突。IntentFilters 正在用一个动作实例化,当我用“.setAction”选项实例化 Intents 时,修复如下:

改变这个:

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

对此:

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

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

this.registerReceiver(approveReceiver, new IntentFilter("com.myapp.Approve"));
于 2019-03-15T16:37:37.403 回答
2

不幸的是,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());
    }
}
于 2019-03-15T16:59:13.363 回答