捕获滑动关闭事件

91
我正在使用安卓通知来告知用户服务的完成情况(成功或失败),并且我想在进程完成后删除本地文件。
我的问题是,如果发生失败 - 我想让用户有“重试”选项。如果他选择不重试和解除通知,则希望删除为处理目的保存的本地文件(图像等)。
有没有办法捕获通知滑动以解除事件?
3个回答

149

DeleteIntent: DeleteIntent是一个可以与通知关联的PendingIntent对象,当通知被删除时会触发它,删除操作可能是由以下原因引起的:

  • 用户特定的操作
  • 用户删除所有通知

您可以将Pending Intent设置为广播接收器,然后执行任何想要的操作。

  Intent intent = new Intent(this, MyBroadcastReceiver.class);
  PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intent, 0);
  Builder builder = new Notification.Builder(this):
 ..... code for your notification
  builder.setDeleteIntent(pendingIntent);

MyBroadcastReceiver

public class MyBroadcastReceiver extends BroadcastReceiver {
      @Override
      public void onReceive(Context context, Intent intent) {
             .... code to handle cancel
         }

  }

8
这有点晚了。我只是想知道是否有类似的方法适用于那些使用了builder.setAutoCancel(true);的通知,因为当用户单击通知并且它被取消时,删除意图不会触发。 - devanshu_kaushik
1
@dev_android 请查看http://developer.android.com/reference/android/app/Notification.Builder.html#setContentIntent(android.app.PendingIntent)。 - Mr.Me
@Peter 为了让它在 Oreo 及以上版本中正常工作,您需要添加以下代码行: Notification note = builder.build(); note.flags |= Notification.FLAG_AUTO_CANCEL; - Dimas Mendes

90
一个完整的答案(感谢Mr. Me提供答案):
1)创建一个接收器来处理滑动删除事件:
public class NotificationDismissedReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
      int notificationId = intent.getExtras().getInt("com.my.app.notificationId");
      /* Your code to handle the event here */
  }
}

2) 在您的清单(Manifest)中添加一个条目:

<receiver
    android:name="com.my.app.receiver.NotificationDismissedReceiver"
    android:exported="false" >
</receiver>

3) 使用待定意图的唯一ID(此处使用通知ID)创建待定意图,否则相同的额外信息将被重用于每个解除事件:

private PendingIntent createOnDismissedIntent(Context context, int notificationId) {
    Intent intent = new Intent(context, NotificationDismissedReceiver.class);
    intent.putExtra("com.my.app.notificationId", notificationId);

    PendingIntent pendingIntent =
           PendingIntent.getBroadcast(context.getApplicationContext(), 
                                      notificationId, intent, 0);
    return pendingIntent;
}

4) 构建您的通知:

Notification notification = new NotificationCompat.Builder(context)
              .setContentTitle("My App")
              .setContentText("hello world")
              .setWhen(notificationTime)
              .setDeleteIntent(createOnDismissedIntent(context, notificationId))
              .build();

NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, notification);

对我来说没有用,总是出现错误“无法实例化接收器....没有零参数构造函数”。只有在我实现了另一个类似的解决方案并注册广播接收器后才解决了问题: https://dev59.com/lWcs5IYBdhLWcg3wOBbl - Alexeev Valeriy
这对我有用。但是当你点击通知时,事件无法被调用。我该如何监听点击事件? - Allen Vork
根据文档,如果使用setAutoCancel(true),那么通知在被点击后将被取消并广播删除意图 [https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#setAutoCancel(boolean)]。 - sven
这个代码是有效的,除了参数传递。即使设置了额外信息,intent.getExtras()总是返回null。为了让它正常工作,你必须像下面这样设置action:resultIntent.setAction(unique_action); - lxknvlk

0
另一个想法:
如果您通常创建通知,还需要其中一个、两个或三个操作。我创建了一个“NotifyManager”,它创建了我需要的所有通知,并接收所有意图调用。 因此,我可以在一个地方管理所有操作,并捕获解除事件。
public class NotifyPerformService extends IntentService {

@Inject NotificationManager notificationManager;

public NotifyPerformService() {
    super("NotifyService");
    ...//some Dagger stuff
}

@Override
public void onHandleIntent(Intent intent) {
    notificationManager.performNotifyCall(intent);
}

要创建deleteIntent,请使用以下代码(在NotificationManager中):

private PendingIntent createOnDismissedIntent(Context context) {
    Intent          intent          = new Intent(context, NotifyPerformMailService.class).setAction("ACTION_NOTIFY_DELETED");
    PendingIntent   pendingIntent   = PendingIntent.getService(context, SOME_NOTIFY_DELETED_ID, intent, 0);

    return pendingIntent;
}

这是我用来设置删除意图的方式(在NotificationManager中):

private NotificationCompat.Builder setNotificationStandardValues(Context context, long when){
    String                          subText = "some string";
    NotificationCompat.Builder      builder = new NotificationCompat.Builder(context.getApplicationContext());


    builder
            .setLights(ContextUtils.getResourceColor(R.color.primary) , 1800, 3500) //Set the argb value that you would like the LED on the device to blink, as well as the rate
            .setAutoCancel(true)                                                    //Setting this flag will make it so the notification is automatically canceled when the user clicks it in the panel.
            .setWhen(when)                                                          //Set the time that the event occurred. Notifications in the panel are sorted by this time.
            .setVibrate(new long[]{1000, 1000})                                     //Set the vibration pattern to use.

            .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher))
            .setSmallIcon(R.drawable.ic_white_24dp)
            .setGroup(NOTIFY_GROUP)
            .setContentInfo(subText)
            .setDeleteIntent(createOnDismissedIntent(context))
    ;

    return builder;
}

最后在同一个NotificationManager中是perform函数:

public void performNotifyCall(Intent intent) {
    String  action  = intent.getAction();
    boolean success = false;

    if(action.equals(ACTION_DELETE)) {
        success = delete(...);
    }

    if(action.equals(ACTION_SHOW)) {
        success = showDetails(...);
    }

    if(action.equals("ACTION_NOTIFY_DELETED")) {
        success = true;
    }


    if(success == false){
        return;
    }

    //some cleaning stuff
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接