代码之家  ›  专栏  ›  技术社区  ›  CybeX

通过编程取消(和隐藏)Android通知

  •  1
  • CybeX  · 技术社区  · 6 年前

    我有一个与通知(系统)一起运行的服务。当服务停止(和/或应用程序停止)时,应取消通知(即不再显示在状态栏上)。

    通过提供 Android Dev guide of Notifications ,我没有找到有关如何关闭通知的任何信息。

    这样,我发现了许多问题。

    1。

    总结 @nipun.birla answer 如何取消Android通知:

    取消通知 按顺序尝试:

    1. NotifcationManager.cancel(int) 具有 notificationID

    2. NotificationManager.cancel(String, int) 具有 通知通知号 notificationTag

    3. NotificationManager.cancelAll() 作为最后的尝试

    然而,没有提到的是,如果这些都不起作用,应该怎么做。

    2。

    一个人应该用 cancelAll suggestion

    三。

    This SO thread 包含已启动的服务示例的一个很好的示例,其中关联通知在服务生命周期中实现(在该生命周期中通知也被终止)-请参见此处了解 Started Service details

    4。

    Here 建议删除 PendingIntent 与通知关联

    5。

    另外几个问题和解决方案反映了上述相同的信息: 见 this this 还有更多…

    6。

    very interesting question and solution 在状态栏中以编程方式隐藏通知图标时


    我的问题

    到目前为止,这应该是相当明显的 ,我的通知不会取消自己要求的。

    实施:

    请参阅下面的完整实现,尽管我将发布助手类和核心函数的一般用法

    -创建通知

    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 上下文使用 它还用作许多其他函数的上下文 )

    帮助类背后的方法是简单地使用 method chaining 允许更多 眼烛光 创建、修改和取消通知的方法。

    -通知帮助程序用法:

    设置通知 contentText 通过呼叫 setTextContent(String) :

    public NotificationHelper setTextContent(String text){
        notificationBuilder.setContentText(text);
        return this;
    }
    

    设置 contentTitle by`settitle(字符串):

    public NotificationHelper setTitle(String format) {
        notificationBuilder.setContentTitle(format);
        return this;
    }
    

    设置 smallIcon (状态图标)通过调用 setStatusIcon(int) :

    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);
    }
    

    但是,这对取消通知没有影响。

    取消通知时 ,以下事件发生在取消之前。

    完成所有这些操作后,通知仍然有效。

    我试过什么

    • notificationManger.cancel(int)
    • notificationManger.cancel(String, int)
    • notificationManger.cancelAll

    这不起作用,所以我有了创意:

    此外: 创建单独的 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);
    }
    

    这也无济于事。有什么我可能找不到的吗?

    我还应该提到:在调试我的应用程序时,我注意到当我退出应用程序时(使绑定服务停止并调用 取消通知() ,应用程序不应该再运行了,尽管Android Studio仍然保持一个活动的调试会话打开,就像应用程序仍在运行时所期望的那样。不确定这是否与它有关。


    NotificationHelper类(完整实现)

    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();
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   CommonsWare    6 年前

    如果你想用你的 Notification 作为前台服务的一部分,不要直接操作标志,而是使用 startForeground() stopForeground() 对你 Service .