以编程方式取消(并隐藏)Android 通知
Cancel (and hide) Android notification programmatically
我有一项服务 运行 与通知(系统)结合使用。当服务停止时(and/or 应用程序停止),通知应该被取消(即不再显示在状态栏上)。
通过提供 Android Dev guide of Notifications,我没有找到任何关于如何关闭通知的信息。
转到SO,我发现了很多问题。
1.
总结 @nipun.birla's 应该如何取消 Android 通知:
要取消通知,请按顺序尝试:
NotifcationManager.cancel(int) 与 notificationID
NotificationManager.cancel(String, int) 与 notificationID
和 notificationTag
但没有提到的是,如果 none 这些工作应该做什么。
2.
应该使用
3.
contains a good example of a Started Service example with an associate notification implemented into the service lifecycle (where the notification is also killed) - See here for Started Service details
4.
a suggestion was made to delete the PendingIntent 与通知关联
5.
反映上述相同信息的更多问题和解决方案:
查看 this, and ,以及更多...
6.
关于以编程方式在状态栏中隐藏通知图标的
我的问题
现在应该很明显了,我的通知并没有取消自己要求这样做。
实施:
请参阅下面的完整实现,尽管我会 post 帮助程序 class 和核心功能的一般用法
- 创建通知
private Context context;
private NotificationManager notificationManager;
private NotificationChannel notificationChannel;
private NotificationCompat.Builder notificationBuilder;
public NotificationHelper(Context context) {
this.context = context;
// Init notification
// onNotificationCreate()
{
// get notification manager system service
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create notification channel
createNotificationChannel();
//Register notification channel with notification manager
notificationManager.createNotificationChannel(notificationChannel);
}
}
// Init Notification Builder
// createNotificationChannel()
{
Log.d(TAG, "createNotificationChannel: Creating notification channel");
// Define notification channel ID, Channel Name and description
String channelName = BuildConfig.FLAVOR.concat(" Notifier");
String channelDescription = context.getString(R.string.notification_description);
// Create notification channel
notificationChannel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
// Set description of notification channel
notificationChannel.setDescription(channelDescription);
}
}
这由 new NotificationHelper(getApplicationContext)
调用,其中上下文是使用的 Application 上下文(它也用作许多其他函数的上下文)
我的助手 class 背后的方法是简单地使用 method chaining 允许更 eye-candy'ish 方法来创建、修改和取消一个通知。
- NotificationHelper 用法:
设置通知 contentText
通过调用 setTextContent(String)
:
public NotificationHelper setTextContent(String text){
notificationBuilder.setContentText(text);
return this;
}
通过 `setTitle(String):
设置 contentTitle
public NotificationHelper setTitle(String format) {
notificationBuilder.setContentTitle(format);
return this;
}
并通过调用 setStatusIcon(int)
:
设置 smallIcon
(状态图标)
public NotificationHelper setStatusIcon(int res_id) {
notificationBuilder.setSmallIcon(res_id);
return this;
}
最后,通过以下方式更新通知以显示结果设置:
public void update() {
Log.d(TAG, "update: Updating notification");
Notification notification = notificationBuilder.build();
// Set notification flags
notification.flags |= Notification.FLAG_NO_CLEAR;
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
// Notify update
notificationManager.notify(TAG, notificationId, notification);
}
- 取消通知
正如预期的那样,取消通知就像调用 cancelNotification()
:
一样简单
public void cancelNotification() {
Log.d(TAG, "cancelNotification: Cancelling notification");
notificationManager.cancel(TAG, notificationId);
}
但这对取消通知没有影响。
取消通知后,在取消之前发生了以下情况。
- 应用程序出口已启动。
- Bound Service 未绑定 - 确保没有客户端绑定到它。
unbindService
在拥有的上下文中用 getApplicationContext()
调用,就像 unbindService(ServiceConnection) using the same ServiceConnection 最初绑定的那样。
完成所有这些后,通知仍然存在。
我尝试了什么
notificationManger.cancel(int)
notificationManger.cancel(String, int)
notificationManger.cancelAll
这个不行,所以我有创意:
此外:
为 post 这些更新创建一个单独的 NotificationManager
方法(即这里没有设置标志,但使用相同的 notificationmanager
)
public void updateCancelable() {
Log.d(TAG, "update: Updating notification to cancel");
Notification notification = notificationBuilder
.setContentIntent(null)
.setOngoing(false)
.setAutoCancel(true)
.build();
// Notify update
notificationManager.notify(TAG, notificationId, notification);
}
通过调用setContentIntent(null)
清除setContentIntent()并重新通知更新
我还尝试创建一个新通知 cancelable with setAutoCancel(true)
, and setting the ongoing state 和 setOngoing(false)
并重新通知更新
这也没有帮助。有什么我可能遗漏的吗?
我还应该提一下:在调试我的应用程序时,我注意到当我退出应用程序时(停止绑定服务并调用 cancelNotification()
,应用程序应该不会运行 虽然 Android Studio 仍然保持活跃的调试会话打开,就像人们期望的那样,当应用程序仍然 running.Not 确定这是否与它有关
NotificationHelper class(完整实现)
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.connectedover.BuildConfig;
import com.connectedover.R;
import com.connectedover.listeners.NotificationUpdateListener;
/**
* Class aimed at providing helper method for creating, maintaining and destroying notifications in conjunction with {@link de.blinkt.openvpn.core.OpenVPNService}
*
* @author cybex
* @since 1.5.1
*/
public class NotificationHelper implements NotificationUpdateListener {
private static final String TAG = NotificationManager.class.getSimpleName();
private static final String channelId = BuildConfig.APPLICATION_ID.concat(".").concat(TAG);
private static final int notificationId = 42;
private Context context;
private NotificationManager notificationManager;
private NotificationChannel notificationChannel;
private NotificationCompat.Builder notificationBuilder;
public NotificationHelper(Context context) {
this.context = context;
// Init notification
onNotificationCreate();
// Init Notification Builder
createBasicNotification();
}
/**
* Initialize {@link NotificationChannel} and register channel with {@link NotificationManager} service if API is Android Orea (API 26 or higher), else initializes the notification manager
*/
private void onNotificationCreate() {
Log.d(TAG, "onNotificationCreate: Initializing notification helper");
// get notification manager system service
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create notification channel
createNotificationChannel();
//Register notification channel with notification manager
notificationManager.createNotificationChannel(notificationChannel);
}
}
/**
* Creates a notification channel required by devices running Android SDK 26 and higher.
* The notification channel is set to {@link NotificationManager#IMPORTANCE_LOW} which should have no sound and appear right at the top of the status bar
*/
@RequiresApi(api = Build.VERSION_CODES.O)
private void createNotificationChannel() {
Log.d(TAG, "createNotificationChannel: Creating notification channel");
// Define notification channel ID, Channel Name and description
String channelName = BuildConfig.FLAVOR.concat(" Notifier");
String channelDescription = context.getString(R.string.notification_description);
// Create notification channel
notificationChannel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
// Set description of notification channel
notificationChannel.setDescription(channelDescription);
}
/**
* Creates a basic notification using {@link android.support.v4.app.NotificationCompatBuilder} for use throughout the application
*/
private void createBasicNotification() {
// Instantiate Notification Builder
notificationBuilder = new NotificationCompat
.Builder(context, channelId)
.setContentTitle(context.getString(R.string.app_name))
.setSmallIcon(R.drawable.ic_logo_disconnected)
.setWhen(System.currentTimeMillis())
.setAutoCancel(false)
.setOngoing(true);
}
/**
* Set the pending intent of a clickable {@link android.app.Notification} held by {@link NotificationHelper#notificationBuilder}
* @param pendingIntent Pending intent to connect to activity
* @return returns an instance of {@link NotificationHelper}
*/
public NotificationHelper setPendingIntent(PendingIntent pendingIntent){
Log.d(TAG, "setPendingIntent: Setting notification Pending intent");
notificationBuilder.setContentIntent(pendingIntent);
return this;
}
/**
* Updates the notification which is displayed for the user.
*/
public void update() {
Log.d(TAG, "update: Updating notification");
Notification notification = notificationBuilder.build();
// Set notification flags
notification.flags |= Notification.FLAG_NO_CLEAR;
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
// Notify update
notificationManager.notify(TAG, notificationId, notification);
}
/**
* Updates the notification {@link NotificationHelper#notificationBuilder} with new text and displays it to the user
*
* @param text new text to display
* @return returns current {@link NotificationHelper} instance for method chaining.
*/
public NotificationHelper setTextContent(String text){
notificationBuilder.setContentText(text);
return this;
}
@Override
public void onUpdate(String update) {
Log.d(TAG, "onUpdate: updating notification via callback");
this.setTextContent(update)
.update();
}
/**
* Sets a new icon for the notification displayed to the user
* @param res_id icon resource
* @return current instance
*/
public NotificationHelper setLargeIcon(int res_id) {
notificationBuilder.setLargeIcon(ImageUtils.toBitmap(context, res_id));
return this;
}
/**
* Sets a new icon for the notification displayed to the user show in the status bar (i.e. the small icon)
* @param res_id icon resource
* @return current instance
*/
public NotificationHelper setStatusIcon(int res_id) {
notificationBuilder.setSmallIcon(res_id);
return this;
}
public NotificationHelper setTitle(String format) {
notificationBuilder.setContentTitle(format);
return this;
}
/**
* Cancels the application notification
*/
public void cancelNotification() {
Log.d(TAG, "cancelNotification: Cancelling notification");
notificationManager.cancelAll();
}
}
如果您想将 Notification
用作前台服务的一部分,而不是直接操作标志,请在 Service
上使用 startForeground()
和 stopForeground()
。
我有一项服务 运行 与通知(系统)结合使用。当服务停止时(and/or 应用程序停止),通知应该被取消(即不再显示在状态栏上)。
通过提供 Android Dev guide of Notifications,我没有找到任何关于如何关闭通知的信息。
转到SO,我发现了很多问题。
1.
总结 @nipun.birla's
要取消通知,请按顺序尝试:
NotifcationManager.cancel(int) 与
notificationID
NotificationManager.cancel(String, int) 与
notificationID
和notificationTag
但没有提到的是,如果 none 这些工作应该做什么。
2.
应该使用
3.
4.
5.
反映上述相同信息的更多问题和解决方案:
查看 this, and
6.
关于以编程方式在状态栏中隐藏通知图标的
我的问题
现在应该很明显了,我的通知并没有取消自己要求这样做。
实施:
请参阅下面的完整实现,尽管我会 post 帮助程序 class 和核心功能的一般用法
- 创建通知
private Context context;
private NotificationManager notificationManager;
private NotificationChannel notificationChannel;
private NotificationCompat.Builder notificationBuilder;
public NotificationHelper(Context context) {
this.context = context;
// Init notification
// onNotificationCreate()
{
// get notification manager system service
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create notification channel
createNotificationChannel();
//Register notification channel with notification manager
notificationManager.createNotificationChannel(notificationChannel);
}
}
// Init Notification Builder
// createNotificationChannel()
{
Log.d(TAG, "createNotificationChannel: Creating notification channel");
// Define notification channel ID, Channel Name and description
String channelName = BuildConfig.FLAVOR.concat(" Notifier");
String channelDescription = context.getString(R.string.notification_description);
// Create notification channel
notificationChannel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
// Set description of notification channel
notificationChannel.setDescription(channelDescription);
}
}
这由 new NotificationHelper(getApplicationContext)
调用,其中上下文是使用的 Application 上下文(它也用作许多其他函数的上下文)
我的助手 class 背后的方法是简单地使用 method chaining 允许更 eye-candy'ish 方法来创建、修改和取消一个通知。
- NotificationHelper 用法:
设置通知 contentText
通过调用 setTextContent(String)
:
public NotificationHelper setTextContent(String text){
notificationBuilder.setContentText(text);
return this;
}
通过 `setTitle(String):
设置contentTitle
public NotificationHelper setTitle(String format) {
notificationBuilder.setContentTitle(format);
return this;
}
并通过调用 setStatusIcon(int)
:
smallIcon
(状态图标)
public NotificationHelper setStatusIcon(int res_id) {
notificationBuilder.setSmallIcon(res_id);
return this;
}
最后,通过以下方式更新通知以显示结果设置:
public void update() {
Log.d(TAG, "update: Updating notification");
Notification notification = notificationBuilder.build();
// Set notification flags
notification.flags |= Notification.FLAG_NO_CLEAR;
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
// Notify update
notificationManager.notify(TAG, notificationId, notification);
}
- 取消通知
正如预期的那样,取消通知就像调用 cancelNotification()
:
public void cancelNotification() {
Log.d(TAG, "cancelNotification: Cancelling notification");
notificationManager.cancel(TAG, notificationId);
}
但这对取消通知没有影响。
取消通知后,在取消之前发生了以下情况。
- 应用程序出口已启动。
- Bound Service 未绑定 - 确保没有客户端绑定到它。
unbindService
在拥有的上下文中用getApplicationContext()
调用,就像 unbindService(ServiceConnection) using the same ServiceConnection 最初绑定的那样。
完成所有这些后,通知仍然存在。
我尝试了什么
notificationManger.cancel(int)
notificationManger.cancel(String, int)
notificationManger.cancelAll
这个不行,所以我有创意:
此外:
为 post 这些更新创建一个单独的 NotificationManager
方法(即这里没有设置标志,但使用相同的 notificationmanager
)
public void updateCancelable() {
Log.d(TAG, "update: Updating notification to cancel");
Notification notification = notificationBuilder
.setContentIntent(null)
.setOngoing(false)
.setAutoCancel(true)
.build();
// Notify update
notificationManager.notify(TAG, notificationId, notification);
}
通过调用
setContentIntent(null)
清除setContentIntent()并重新通知更新我还尝试创建一个新通知 cancelable with
setAutoCancel(true)
, and setting the ongoing state 和setOngoing(false)
并重新通知更新
这也没有帮助。有什么我可能遗漏的吗?
我还应该提一下:在调试我的应用程序时,我注意到当我退出应用程序时(停止绑定服务并调用 cancelNotification()
,应用程序应该不会运行 虽然 Android Studio 仍然保持活跃的调试会话打开,就像人们期望的那样,当应用程序仍然 running.Not 确定这是否与它有关
NotificationHelper class(完整实现)
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.connectedover.BuildConfig;
import com.connectedover.R;
import com.connectedover.listeners.NotificationUpdateListener;
/**
* Class aimed at providing helper method for creating, maintaining and destroying notifications in conjunction with {@link de.blinkt.openvpn.core.OpenVPNService}
*
* @author cybex
* @since 1.5.1
*/
public class NotificationHelper implements NotificationUpdateListener {
private static final String TAG = NotificationManager.class.getSimpleName();
private static final String channelId = BuildConfig.APPLICATION_ID.concat(".").concat(TAG);
private static final int notificationId = 42;
private Context context;
private NotificationManager notificationManager;
private NotificationChannel notificationChannel;
private NotificationCompat.Builder notificationBuilder;
public NotificationHelper(Context context) {
this.context = context;
// Init notification
onNotificationCreate();
// Init Notification Builder
createBasicNotification();
}
/**
* Initialize {@link NotificationChannel} and register channel with {@link NotificationManager} service if API is Android Orea (API 26 or higher), else initializes the notification manager
*/
private void onNotificationCreate() {
Log.d(TAG, "onNotificationCreate: Initializing notification helper");
// get notification manager system service
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create notification channel
createNotificationChannel();
//Register notification channel with notification manager
notificationManager.createNotificationChannel(notificationChannel);
}
}
/**
* Creates a notification channel required by devices running Android SDK 26 and higher.
* The notification channel is set to {@link NotificationManager#IMPORTANCE_LOW} which should have no sound and appear right at the top of the status bar
*/
@RequiresApi(api = Build.VERSION_CODES.O)
private void createNotificationChannel() {
Log.d(TAG, "createNotificationChannel: Creating notification channel");
// Define notification channel ID, Channel Name and description
String channelName = BuildConfig.FLAVOR.concat(" Notifier");
String channelDescription = context.getString(R.string.notification_description);
// Create notification channel
notificationChannel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
// Set description of notification channel
notificationChannel.setDescription(channelDescription);
}
/**
* Creates a basic notification using {@link android.support.v4.app.NotificationCompatBuilder} for use throughout the application
*/
private void createBasicNotification() {
// Instantiate Notification Builder
notificationBuilder = new NotificationCompat
.Builder(context, channelId)
.setContentTitle(context.getString(R.string.app_name))
.setSmallIcon(R.drawable.ic_logo_disconnected)
.setWhen(System.currentTimeMillis())
.setAutoCancel(false)
.setOngoing(true);
}
/**
* Set the pending intent of a clickable {@link android.app.Notification} held by {@link NotificationHelper#notificationBuilder}
* @param pendingIntent Pending intent to connect to activity
* @return returns an instance of {@link NotificationHelper}
*/
public NotificationHelper setPendingIntent(PendingIntent pendingIntent){
Log.d(TAG, "setPendingIntent: Setting notification Pending intent");
notificationBuilder.setContentIntent(pendingIntent);
return this;
}
/**
* Updates the notification which is displayed for the user.
*/
public void update() {
Log.d(TAG, "update: Updating notification");
Notification notification = notificationBuilder.build();
// Set notification flags
notification.flags |= Notification.FLAG_NO_CLEAR;
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
// Notify update
notificationManager.notify(TAG, notificationId, notification);
}
/**
* Updates the notification {@link NotificationHelper#notificationBuilder} with new text and displays it to the user
*
* @param text new text to display
* @return returns current {@link NotificationHelper} instance for method chaining.
*/
public NotificationHelper setTextContent(String text){
notificationBuilder.setContentText(text);
return this;
}
@Override
public void onUpdate(String update) {
Log.d(TAG, "onUpdate: updating notification via callback");
this.setTextContent(update)
.update();
}
/**
* Sets a new icon for the notification displayed to the user
* @param res_id icon resource
* @return current instance
*/
public NotificationHelper setLargeIcon(int res_id) {
notificationBuilder.setLargeIcon(ImageUtils.toBitmap(context, res_id));
return this;
}
/**
* Sets a new icon for the notification displayed to the user show in the status bar (i.e. the small icon)
* @param res_id icon resource
* @return current instance
*/
public NotificationHelper setStatusIcon(int res_id) {
notificationBuilder.setSmallIcon(res_id);
return this;
}
public NotificationHelper setTitle(String format) {
notificationBuilder.setContentTitle(format);
return this;
}
/**
* Cancels the application notification
*/
public void cancelNotification() {
Log.d(TAG, "cancelNotification: Cancelling notification");
notificationManager.cancelAll();
}
}
如果您想将 Notification
用作前台服务的一部分,而不是直接操作标志,请在 Service
上使用 startForeground()
和 stopForeground()
。