我正在尝试使用NotificationManager将自定义内置通知替换为内置日历提醒通知。
我添加了一个截获日历提醒通知的BroadCastReceiver,如下所示:
<receiver
android:name=".receivers.CalendarNotificationBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.EVENT_REMINDER"/>
<data android:scheme="content"/>
<data android:host="com.android.calendar"/>
</intent-filter>
</receiver>
问题1:如何使用ContentResolver API查找有关触发通知的事件的信息(例如,我需要TITLE字段来构建新通知)?
Q2:如何取消意图,以便不触发日历事件的提醒通知? 我已经尝试过这篇文章中的推荐,但无济于事: How to cancel this repeating alarm? 此外,我尝试过(没有成功):
PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT).cancel();
编辑 ******************
在遵循Ovidiu Latcu的提案之后,我提供了NotificationListenerService的实现,该实现还具有用于新通知的BroadcastReceiver
AndroidManifest
<service android:name=".service.CalendarNotificationListenerService"
android:label="@string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
NotificationListenerService
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
/**
* Due to an android bug: https://stackoverflow.com/questions/17911883/cannot-get-the-notificationlistenerservice-class-to-work
* This class' name should be changed before each debug use, because if not, onReceive will never get called.
*/
public class CalendarNotificationListenerService extends NotificationListenerService {
private String TAG = this.getClass().getSimpleName();
private CalendarNotificationBroadcastReceiver receiver;
@Override
public void onCreate() {
Log.i(TAG,"********** Service is created");
super.onCreate();
receiver = new CalendarNotificationBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter("android.intent.action.EVENT_REMINDER");
intentFilter.addDataScheme("content");
registerReceiver(receiver, intentFilter);
}
@Override
public void onDestroy() {
Log.i(TAG,"********** Service is destroyed");
super.onDestroy();
unregisterReceiver(receiver);
}
@Override
public IBinder onBind(Intent mIntent) {
IBinder mIBinder = super.onBind(mIntent);
Log.i(TAG, "********** onBind");
return mIBinder;
}
@Override
public boolean onUnbind(Intent mIntent) {
boolean mOnUnbind = super.onUnbind(mIntent);
Log.i(TAG, "********** onUnbind");
return mOnUnbind;
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
Log.i(TAG,"********** onNotificationPosted");
Log.i(TAG,"ID :" + sbn.getId() + "\t" + sbn.getNotification().tickerText + "\t" + sbn.getPackageName());
Notification currentNotification = sbn.getNotification();
String notificationTitle = (String) sbn.getNotification().extras.get("android.title");
if(notificationTitle == null || !notificationTitle.startsWith("CALLERQ:")){
return;
}
//Seem to only be able to cancel a notification after it is posted.
CalendarNotificationListenerService.this.cancelNotification(sbn.getKey());
Intent i = new Intent("com.enginizer.NOTIFICATION_LISTENER_EXAMPLE");
i.putExtra("notification_event","onNotificationPosted :" + sbn.getPackageName() + "\n");
sendBroadcast(i);
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn) {
Log.i(TAG,"********** onNOtificationRemoved");
Log.i(TAG,"ID :" + sbn.getId() + "\t" + sbn.getNotification().tickerText +"\t" + sbn.getPackageName());
Intent i = new Intent("com.enginizer.NOTIFICATION_LISTENER_EXAMPLE");
i.putExtra("notification_event","onNotificationRemoved :" + sbn.getPackageName() + "\n");
sendBroadcast(i);
}
class CalendarNotificationBroadcastReceiver extends BroadcastReceiver {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "********** Notification received");
String intentAction = intent.getAction();
Log.i(TAG, "********** " + intentAction);
intent.getBundleExtra(CalendarContract.EXTRA_CUSTOM_APP_URI);
ContentResolver contentResolver = context.getContentResolver();
//This throws an java.lang.IllegalArgumentException
Cursor cursor = contentResolver.query(intent.getData(), new String[]{CalendarContract.Events.DESCRIPTION}, null, null, null);
CalendarNotificationListenerService.this.cancelAllNotifications();
}
}
@Override
public void onListenerConnected() {
Log.i(TAG,"********** Listener connected");
super.onListenerConnected();
}
}
对于Q1中的回答,我试图查询mData字段中记录的事件的日历。这样做时,我收到以下内容:
java.lang.IllegalArgumentException: Unknown URL content://com.android.calendar/1491653055193
对于Q2,我无法从onReceive方法中取消通知,因为我无法在意图中找到它。我只能在onNotificationPosted方法中取消通知,这比预期的要晚。
是否真的如此纠结于取消日历提醒通知并将其替换为自定义通知?
答案 0 :(得分:0)
Q1:mData
字段包含该事件的URI
。您应该查询URI
并查找有关该事件的所有信息。
Q2:自API 18起,您可以在发布通知时使用NotificationListenerService
拦截,并使用cancelNotification(String key)
取消