원인은 PendingIntent가 설정이 안되었기 때문인데요. 하시려고 하는 게 PendingIntent 없이도 Notification 을 탭하면 Notification이 없어지는거니까, 두가지를 만족하기 위해서 빈껍데기 뿐인 PendingIntent를 하나 만들어 줍니다.
Notification처리를 할 수 있는 간단한 유틸리티 클래스들을 만들어 봤습니다. 님이 원하는 자동 취소가 기본으로 들어가 있습니다.
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import androidx.core.app.TaskStackBuilder;
public class NoOpBroadcastReceiver extends BroadcastReceiver {
public static PendingIntent getPendingIntent(Context context) {
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(new Intent(context, NoOpBroadcastReceiver.class));
return stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
}
@Override
public void onReceive(Context context, Intent intent) {
}
}
NoOpBroadCastReceiver는 아무 것도 안하는 빈껍데기만 있는 클래스입니다. Notification이 PendingIntent가 있어야 눌렀을 때 사라질 수 있기 때문에 필요합니다.
import static android.content.Context.NOTIFICATION_SERVICE;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import androidx.core.app.NotificationCompat;
public class NotificationBuilder {
private static final String CHANNEL_ID = "default";
private static final String CHANNEL_NAME = "기본채널";
private static final long[] DEFAULT_VIBRATE = {0, 100, 200, 300};
private static final int NOTIFICATION_ID = 2;
private String channelId = CHANNEL_ID;
private String channelName = CHANNEL_NAME;
private int notificationId = NOTIFICATION_ID;
private Uri ringtoneUri;
private long[] vibrationPattern = DEFAULT_VIBRATE;
private PendingIntent pendingIntent;
private String title;
private String message;
private boolean autoCancel = true; // 자동 취소를 기본 설정으로 함.
private final Context context;
public NotificationBuilder(Context context) {
this.context = context;
this.ringtoneUri = getDefaultRingtoneUri();
this.pendingIntent = NoOpBroadcastReceiver.getPendingIntent(context);
this.title = context.getString(R.string.app_name); // 기본값은 님이 원하는대로 설정
this.message = context.getString(R.string.app_name); // 기본값은 님이 원하는대로 설정
}
public NotificationBuilder setChannelId(String channelId) {
this.channelId = channelId;
return this;
}
public NotificationBuilder setChannelName(String channelName) {
this.channelName = channelName;
return this;
}
public NotificationBuilder setRingtoneUri(Uri ringtoneUri) {
this.ringtoneUri = ringtoneUri;
return this;
}
public NotificationBuilder setVibrationPattern(long[] vibrationPattern) {
this.vibrationPattern = vibrationPattern;
return this;
}
public NotificationBuilder setPendingIntent(PendingIntent pendingIntent) {
this.pendingIntent = pendingIntent;
return this;
}
public NotificationBuilder setTitle(String title) {
this.title = title;
return this;
}
public NotificationBuilder setMessage(String message) {
this.message = message;
return this;
}
public NotificationBuilder setNotificationId(int notificationId) {
this.notificationId = notificationId;
return this;
}
public NotificationBuilder setAutoCancel(boolean autoCancel) {
this.autoCancel = autoCancel;
return this;
}
public Notification build() {
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId);
builder.setSmallIcon(R.drawable.ic_notifications_black_24dp)
.setContentTitle(title)
.setContentText(message)
.setContentIntent(pendingIntent)
.setSound(ringtoneUri)
.setVibrate(vibrationPattern)
.setAutoCancel(autoCancel);
NotificationManager manager = getNotificationManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
manager.createNotificationChannel(new NotificationChannel(channelId, channelName,
NotificationManager.IMPORTANCE_DEFAULT));
}
Notification notification = builder.build();
manager.notify(notificationId, notification);
return notification;
}
private NotificationManager getNotificationManager() {
return (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
}
private Uri getDefaultRingtoneUri() {
return RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.TYPE_NOTIFICATION);
}
}
NotificationBuilder는 NotficationCompat.Builder를 사용하기 편하게 감싼 클래스입니다. NotficationCompat.Builder를 액티비티에서 직접 사용하게 되면 불필요한 boiler plate코드를 작성하게 되므로 이것을 피하기 위해 만들었습니다.
import android.content.Context;
public class NotificationHelper {
private final Context context;
public NotificationHelper(Context context) {
this.context = context;
}
public void notifyDeliveryArrival() {
NotificationBuilder builder = new NotificationBuilder(context);
builder.setTitle(context.getString(R.string.delivery_arrival_notification_title))
.setMessage(context.getString(R.string.delivery_arrival_notification_message))
.build();
}
}
액비티티에서 위에서 만든 NotificationBuilder클래스를 사용한다고 해도 여전히 boiler plate코드가 생기기 때문에 용도에 맞는 Notification을 관리하는 클래스를 두는 게 좋습니다.
액티비티에서는 NotificationHelper클래스만 사용하면 됩니다.
public class MainActivity extends AppCompatActivity {
private NotificationHelper notificationHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
setContentView(...);
notificationHelper = new NotificationHelper(this); //초기화
}
private void notifyDeliveryArrival() {
notificationHelper.notifyDeliveryArrival();
}
}
도움이 되시길...