com.dspot.declex.actions.NotificationActionHolder.java Source code

Java tutorial

Introduction

Here is the source code for com.dspot.declex.actions.NotificationActionHolder.java

Source

/**
 * Copyright (C) 2016-2019 DSpot Sp. z o.o
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.dspot.declex.actions;

import java.io.IOException;

import org.androidannotations.annotations.RootContext;
import org.androidannotations.annotations.SystemService;
import org.androidannotations.api.BackgroundExecutor;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Style;
import android.widget.RemoteViews;

import com.dspot.declex.annotation.action.ActionFor;
import com.dspot.declex.annotation.action.FormattedExpression;
import com.dspot.declex.annotation.action.StopOn;
import com.squareup.picasso.Picasso;

/**
 * An Action that represents how a persistent notification is to be presented to
 * the user using the {@link NotificationManager}.
 *
 * <div class="special reference">
 * <h3>Developer Guides</h3>
 * <p>For a guide to creating notifications, read the
 * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
 * developer guide.</p>
 * </div>
 */

@ActionFor("Notification")
public class NotificationActionHolder {

    NotificationCompat.Builder builder;

    @RootContext
    Context context;

    @SystemService
    NotificationManager manager;

    private boolean cancelPrevious = true;

    private int notificationId;
    private String pendingLargeIconLoad;

    private Runnable Shown;

    /**
     * @param notificationId An identifier for this notification unique within your
     *        application.
     */
    void init(int notificationId) {
        builder = new NotificationCompat.Builder(context);
        this.notificationId = notificationId;
    }

    /**
     * @param Shown <i><b>(default)</b></i> This Action Selector will be executed when the Notification is shown 
     * with the NotificationManager
     */
    void build(final Runnable Shown) {
        if (cancelPrevious) {
            manager.cancel(notificationId);
        }
        this.Shown = Shown;
    };

    void execute() {

        final Runnable execute = new Runnable() {

            @Override
            public void run() {
                manager.notify(notificationId, builder.build());
                if (Shown != null)
                    Shown.run();
            }
        };

        if (pendingLargeIconLoad != null) {
            BackgroundExecutor.execute(new Runnable() {

                @Override
                public void run() {
                    try {
                        Bitmap bitmap = Picasso.with(context).load(pendingLargeIconLoad).get();
                        pendingLargeIconLoad = null;
                        builder.setLargeIcon(bitmap);
                    } catch (IOException ignored) {
                    }

                    Handler mainHandler = new Handler(context.getMainLooper());
                    mainHandler.post(execute);
                }
            });
        } else {
            execute.run();
        }

    }

    /**
     * @return Android Builder layer to access the underlying Notifications Builder object
     * 
     * @see NotificationCompat.Builder Notifications Builder
     */
    @StopOn("build")
    public NotificationCompat.Builder builder() {
        return this.builder;
    }

    /**
     * Add a timestamp pertaining to the notification (usually the time the event occurred).
     * It will be shown in the notification content view by default; use
     * {@link #showWhen(boolean) showWhen} to control this.
     *
     * @see Notification#when
     */
    public NotificationActionHolder when(long when) {
        builder.setWhen(when);
        return this;
    }

    /**
     * Show the {@link Notification#when} field as a stopwatch.
     *
     * Instead of presenting <code>when</code> as a timestamp, the notification will show an
     * automatically updating display of the minutes and seconds since <code>when</code>.
     *
     * Useful when showing an elapsed time (like an ongoing phone call).
     *
     * @see android.widget.Chronometer
     * @see Notification#when
     */
    public NotificationActionHolder usesChronometer(boolean usesChronometer) {
        builder.setUsesChronometer(usesChronometer);
        return this;
    }

    /**
     * Set the small icon resource, which will be used to represent the notification in the
     * status bar.
     *
        
     * The platform template for the expanded view will draw this icon in the left, unless a
     * {@link #largeIcon(Bitmap) large icon} has also been specified, in which case the small
     * icon will be moved to the right-hand side.
     *
        
     * @param icon
     *            A resource ID in the application's package of the drawable to use.
     * @see Notification#icon
     */
    public NotificationActionHolder smallIcon(@DrawableRes int icon) {
        builder.setSmallIcon(icon);
        return this;
    }

    /**
     * A variant of {@link #smallIcon(int) smallIcon(int)} that takes an additional
     * level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable
     * LevelListDrawable}.
     *
     * @param icon A resource ID in the application's package of the drawable to use.
     * @param level The level to use for the icon.
     *
     * @see Notification#icon
     * @see Notification#iconLevel
     */
    public NotificationActionHolder smallIcon(@DrawableRes int icon, int level) {
        builder.setSmallIcon(icon, level);
        return this;
    }

    /**
     * Set the first line of text in the platform notification template.
     */
    public NotificationActionHolder contentTitle(@FormattedExpression String contentTitle) {
        builder.setContentTitle(contentTitle);
        return this;
    }

    /**
     * Set the second line of text in the platform notification template.
     */
    public NotificationActionHolder contentText(@FormattedExpression String contentText) {
        builder.setContentTitle(contentText);
        return this;
    }

    /**
     * Set the third line of text in the platform notification template.
     * Don't use if you're also using {@link #progress(int, int, boolean)}; they occupy the
     * same location in the standard template.
     */
    public NotificationActionHolder subText(@FormattedExpression String subText) {
        builder.setContentTitle(subText);
        return this;
    }

    /**
     * Set the large number at the right-hand side of the notification.  This is
     * equivalent to setContentInfo, although it might show the number in a different
     * font size for readability.
     */
    public NotificationActionHolder number(int number) {
        builder.setNumber(number);
        return this;
    }

    /**
     * A small piece of additional information pertaining to this notification.
     *
     * The platform template will draw this on the last line of the notification, at the far
     * right (to the right of a smallIcon if it has been placed there).
     */
    public NotificationActionHolder contentInfo(@FormattedExpression String contentInfo) {
        builder.setContentInfo(contentInfo);
        return this;
    }

    /**
     * Set the progress this notification represents.
     *
     * The platform template will represent this using a {@link ProgressBar}.
     */
    public NotificationActionHolder progress(int max, int progress, boolean indeterminate) {
        builder.setProgress(max, progress, indeterminate);
        return this;
    }

    /**
     * Supply a custom RemoteViews to use instead of the platform template.
     *
     * @see Notification#contentView
     */
    public NotificationActionHolder content(RemoteViews content) {
        builder.setContent(content);
        return this;
    }

    /**
     * Set the "ticker" text which is sent to accessibility services.
     *
     * @see Notification#tickerText
     */
    public NotificationActionHolder ticker(@FormattedExpression String ticker) {
        builder.setTicker(ticker);
        return this;
    }

    /**
     * Add a large icon to the notification content view.
     *
     * In the platform template, this image will be shown on the left of the notification view
     * in place of the {@link #smallIcon(Icon) small icon} (which will be placed in a small
     * badge atop the large icon).
     */
    public NotificationActionHolder largeIcon(Bitmap icon) {
        builder.setLargeIcon(icon);
        return this;
    }

    /**
     * Add a large icon to the notification content view.
     *
     * In the platform template, this image will be shown on the left of the notification view
     * in place of the {@link #smallIcon(Icon) small icon} (which will be placed in a small
     * badge atop the large icon).
     */
    public NotificationActionHolder largeIcon(@FormattedExpression String icon) {
        if (icon == null || icon.isEmpty())
            return this;

        if (Looper.myLooper() == Looper.getMainLooper()) {
            //Call should not be in main thread
            pendingLargeIconLoad = icon;
            return this;
        }

        try {
            Bitmap bitmap = Picasso.with(context).load(icon).get();
            builder.setLargeIcon(bitmap);
        } catch (IOException ignored) {
        }

        return this;
    }

    /**
     * Set the sound to play.
     *
     * It will be played using the {@link #AUDIO_ATTRIBUTES_DEFAULT default audio attributes}
     * for notifications.
     *
     * <p>
     * A notification that is noisy is more likely to be presented as a heads-up notification.
     * </p>
     *
     * @see Notification#sound
     */
    public NotificationActionHolder sound(Uri sound) {
        builder.setSound(sound);
        return this;
    }

    /**
     * Set the vibration pattern to use.
     *
     * See {@link android.os.Vibrator#vibrate(long[], int)} for a discussion of the
     * <code>pattern</code> parameter.
     *
     * <p>
     * A notification that vibrates is more likely to be presented as a heads-up notification.
     * </p>
     *
     * @see Notification#vibrate
     */
    public NotificationActionHolder vibrate(long[] pattern) {
        builder.setVibrate(pattern);
        return this;
    }

    /**
     * Set the desired color for the indicator LED on the device, as well as the
     * blink duty cycle (specified in milliseconds).
     *
        
     * Not all devices will honor all (or even any) of these values.
     *
        
     * @see Notification#ledARGB
     * @see Notification#ledOnMS
     * @see Notification#ledOffMS
     */
    public NotificationActionHolder lights(@ColorInt int argb, int onMs, int offMs) {
        builder.setLights(argb, onMs, offMs);
        return this;
    }

    /**
     * Set whether this is an "ongoing" notification.
     *
        
     * Ongoing notifications cannot be dismissed by the user, so your application or service
     * must take care of canceling them.
     *
        
     * They are typically used to indicate a background task that the user is actively engaged
     * with (e.g., playing music) or is pending in some way and therefore occupying the device
     * (e.g., a file download, sync operation, active network connection).
     *
        
     * @see Notification#FLAG_ONGOING_EVENT
     * @see Service#setForeground(boolean)
     */
    public NotificationActionHolder ongoing(boolean ongoing) {
        builder.setOngoing(ongoing);
        return this;
    }

    /**
     * Set this flag if you would only like the sound, vibrate
     * and ticker to be played if the notification is not already showing.
     *
     * @see Notification#FLAG_ONLY_ALERT_ONCE
     */
    public NotificationActionHolder onlyAlertOnce(boolean onlyAlertOnce) {
        builder.setOnlyAlertOnce(onlyAlertOnce);
        return this;
    }

    /**
     * Make this notification automatically dismissed when the user touches it. The
     * PendingIntent set with {@link #deleteIntent} will be sent when this happens.
     *
     * @see Notification#FLAG_AUTO_CANCEL
     */
    public NotificationActionHolder autoCancel(boolean autoCancel) {
        builder.setAutoCancel(autoCancel);
        return this;
    }

    /**
     * Set which notification properties will be inherited from system defaults.
     * <p>
     * The value should be one or more of the following fields combined with
     * bitwise-or:
     * {@link #DEFAULT_SOUND}, {@link #DEFAULT_VIBRATE}, {@link #DEFAULT_LIGHTS}.
     * <p>
     * For all default values, use {@link #DEFAULT_ALL}.
     */
    public NotificationActionHolder defaults(int defaults) {
        builder.setDefaults(defaults);
        return this;
    }

    /**
     * Set the priority of this notification.
     *
     * @see Notification#priority
     */
    public NotificationActionHolder priority(int priority) {
        builder.setPriority(priority);
        return this;
    }

    public NotificationActionHolder cancelPrevious(boolean cancelPrevious) {
        this.cancelPrevious = cancelPrevious;
        return this;
    }

    /**
     * Supply a {@link PendingIntent} to be sent when the notification is clicked.
     *
     * As of {@link android.os.Build.VERSION_CODES#HONEYCOMB}, if this field is unset and you
     * have specified a custom RemoteViews with {@link #setContent(RemoteViews)}, you can use
     * {@link RemoteViews#setOnClickPendingIntent RemoteViews.setOnClickPendingIntent(int,PendingIntent)}
     * to assign PendingIntents to individual views in that custom layout (i.e., to create
     * clickable buttons inside the notification view).
     *
     * @see Notification#contentIntent Notification.contentIntent
     */
    public NotificationActionHolder contentIntent(PendingIntent intent) {
        builder.setContentIntent(intent);
        return this;
    }

    /**
     * Supply a {@link PendingIntent} to send when the notification is cleared explicitly by the user.
     *
     * @see Notification#deleteIntent
     */
    public NotificationActionHolder deleteIntent(PendingIntent intent) {
        builder.setDeleteIntent(intent);
        return this;
    }

    /**
     * An intent to launch instead of posting the notification to the status bar.
     * Only for use with extremely high-priority notifications demanding the user's
     * <strong>immediate</strong> attention, such as an incoming phone call or
     * alarm clock that the user has explicitly set to a particular time.
     * If this facility is used for something else, please give the user an option
     * to turn it off and use a normal notification, as this can be extremely
     * disruptive.
     *
     * <p>
     * The system UI may choose to display a heads-up notification, instead of
     * launching this intent, while the user is using the device.
     * </p>
     *
     * @param intent The pending intent to launch.
     * @param highPriority Passing true will cause this notification to be sent
     *          even if other notifications are suppressed.
     *
     * @see Notification#fullScreenIntent
     */
    public NotificationActionHolder fullScreenIntent(PendingIntent intent, boolean highPriority) {
        builder.setFullScreenIntent(intent, highPriority);
        return this;
    }

    /**
     * Add a rich notification style to be applied at build time.
     * <br>
     * If the platform does not provide rich notification styles, this method has no effect. The
     * user will always see the normal notification style.
     *
     * @param style Object responsible for modifying the notification style.
     */
    public NotificationActionHolder style(Style style) {
        builder.setStyle(style);
        return this;
    }
}