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());
}
}
我正在做一个项目,我需要注册一个 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());
}
}