public final class

CarAppExtender

extends java.lang.Object

implements NotificationCompat.Extender

 java.lang.Object

↳androidx.car.app.notification.CarAppExtender

Gradle dependencies

compile group: 'androidx.car.app', name: 'app', version: '1.2.0-rc01'

  • groupId: androidx.car.app
  • artifactId: app
  • version: 1.2.0-rc01

Artifact androidx.car.app:app:1.2.0-rc01 it located at Google repository (https://maven.google.com/)

Overview

Helper class to add car app extensions to notifications.

By default, notifications in a car screen have the properties provided by . This helper class provides methods to override those properties for the car screen. However, notifications only show up in the car screen if it is extended with CarAppExtender, even if the extender does not override any properties. To create a notification with car extensions:

  1. Create a , setting any desired properties.
  2. Create a CarAppExtender.Builder.
  3. Set car-specific properties using the set methods of CarAppExtender.Builder.
  4. Create a CarAppExtender by calling CarAppExtender.Builder.build().
  5. Call to apply the extensions to a notification.
  6. Post the notification to the notification system with the CarNotificationManager.notify(...) methods. Do not use the NotificationManager.notify(...), nor the NotificationManagerCompat.notify(...)} methods.
 Notification notification = new NotificationCompat.Builder(context)
         ...
         .extend(new CarAppExtender.Builder()
                 .set*(...)
                 .build())
         .build();
 

Car extensions can be accessed on an existing notification by using the CarAppExtender(Notification) constructor, and then using the get methods to access values.

The car screen UI is affected by the notification channel importance (Android O and above) or notification priority (below Android O) in the following ways:

Calling CarAppExtender.Builder.setImportance(int) will override the importance for the notification in the car screen.

Calling NotificationCompat.Builder#setOnlyAlertOnce(true) will alert a high-priority notification only once in the HUN. Updating the same notification will not trigger another HUN event.

Navigation

For a navigation app's turn-by-turn (TBT) notifications, which update the same notification frequently with navigation information, the notification UI has a slightly different behavior. The app can post a TBT notification by calling NotificationCompat.Builder#setOngoing(true) and NotificationCompat.Builder#setCategory(NotificationCompat.CATEGORY_NAVIGATION).

TBT notifications behave the same as regular notifications with the following exceptions:

  • The notification will not be displayed if the navigation app is not the currently active navigation app, or if the app is already displaying routing information in the navigation template.
  • The heads-up-notification (HUN) can be customized with a background color through CarAppExtender.Builder.setColor(CarColor).
  • The notification will not be displayed in the notification center.

In addition to that, the information in the navigation notification will be displayed in the rail widget at the bottom of the screen when the app is in the background.

Note that frequent HUNs distract the driver. The recommended practice is to update the TBT notification regularly on distance changes, which updates the rail widget, but call NotificationCompat.Builder#setOnlyAlertOnce(true) unless there is a significant navigation turn event.

Summary

Constructors
publicCarAppExtender(Notification notification)

Creates a CarAppExtender from the CarAppExtender of an existing notification.

Methods
public NotificationCompat.Builderextend(NotificationCompat.Builder builder)

Applies car extensions to a notification that is being built.

public java.util.List<Action>getActions()

Returns the list of present on this car notification.

public java.lang.StringgetChannelId()

Returns the channel id of the notification channel to use in the car.

public CarColorgetColor()

Returns the background color of the notification or null if a default color is to be used.

public PendingIntentgetContentIntent()

Returns the PendingIntent to send when the notification is clicked in the car or null if not set.

public java.lang.CharSequencegetContentText()

Returns the content text of the notification or null if not set.

public java.lang.CharSequencegetContentTitle()

Returns the content title for the notification or null if not set.

public PendingIntentgetDeleteIntent()

Returns the PendingIntent to send when the notification is cleared by the user or null if not set.

public intgetImportance()

Returns the importance of the notification in the car screen.

public BitmapgetLargeIcon()

Returns the large icon bitmap to display in the notification or null if not set.

public intgetSmallIcon()

Returns the resource ID of the small icon drawable to use.

public static booleanisExtended(Notification notification)

Returns whether the given notification was extended with CarAppExtender.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

public CarAppExtender(Notification notification)

Creates a CarAppExtender from the CarAppExtender of an existing notification.

Methods

Applies car extensions to a notification that is being built.

This is typically called by .

public static boolean isExtended(Notification notification)

Returns whether the given notification was extended with CarAppExtender.

public java.lang.CharSequence getContentTitle()

Returns the content title for the notification or null if not set.

See also: CarAppExtender.Builder.setContentTitle(CharSequence)

public java.lang.CharSequence getContentText()

Returns the content text of the notification or null if not set.

See also: CarAppExtender.Builder.setContentText(CharSequence)

public int getSmallIcon()

Returns the resource ID of the small icon drawable to use.

See also: CarAppExtender.Builder.setSmallIcon(int)

public Bitmap getLargeIcon()

Returns the large icon bitmap to display in the notification or null if not set.

See also: CarAppExtender.Builder.setLargeIcon(Bitmap)

public PendingIntent getContentIntent()

Returns the PendingIntent to send when the notification is clicked in the car or null if not set.

See also: CarAppExtender.Builder.setContentIntent(PendingIntent)

public PendingIntent getDeleteIntent()

Returns the PendingIntent to send when the notification is cleared by the user or null if not set.

See also: CarAppExtender.Builder.setDeleteIntent(PendingIntent)

public java.util.List<Action> getActions()

Returns the list of present on this car notification.

See also: CarAppExtender.Builder.addAction(int, CharSequence, PendingIntent)

public int getImportance()

Returns the importance of the notification in the car screen.

See also: CarAppExtender.Builder.setImportance(int)

public CarColor getColor()

Returns the background color of the notification or null if a default color is to be used.

See also: CarAppExtender.Builder.setColor(CarColor)

public java.lang.String getChannelId()

Returns the channel id of the notification channel to use in the car.

See also: CarAppExtender.Builder.setChannelId(String)

Source

/*
 * Copyright 2020 The Android Open Source Project
 *
 * 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 androidx.car.app.notification;

import static java.util.Objects.requireNonNull;

import android.app.Notification;
import android.app.Notification.Action;
import android.app.PendingIntent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.car.app.model.CarColor;
import androidx.car.app.serialization.Bundler;
import androidx.car.app.serialization.BundlerException;
import androidx.car.app.utils.CollectionUtils;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;

import java.util.ArrayList;
import java.util.List;

/**
 * Helper class to add car app extensions to notifications.
 *
 * <p>By default, notifications in a car screen have the properties provided by
 * {@link NotificationCompat.Builder}. This helper class provides methods to
 * override those properties for the car screen. However, notifications only show up in the car
 * screen if it is extended with {@link CarAppExtender}, even if the extender does not override any
 * properties. To create a notification with car extensions:
 *
 * <ol>
 *   <li>Create a {@link NotificationCompat.Builder}, setting any desired properties.
 *
 *   <li>Create a {@link CarAppExtender.Builder}.
 *
 *   <li>Set car-specific properties using the {@code set} methods of {@link
 *       CarAppExtender.Builder}.
 *
 *   <li>Create a {@link CarAppExtender} by calling {@link Builder#build()}.
 *
 *   <li>Call {@link NotificationCompat.Builder#extend} to apply the extensions to a notification.
 *
 *   <li>Post the notification to the notification system with the {@code
 *       CarNotificationManager.notify(...)} methods. Do not use the {@code
 *       NotificationManager.notify(...)}, nor the NotificationManagerCompat.notify(...)}  methods.
 * </ol>
 *
 * <pre class="prettyprint">
 * Notification notification = new NotificationCompat.Builder(context)
 *         ...
 *         .extend(new CarAppExtender.Builder()
 *                 .set*(...)
 *                 .build())
 *         .build();
 * </pre>
 *
 * <p>Car extensions can be accessed on an existing notification by using the {@code
 * CarAppExtender(Notification)} constructor, and then using the {@code get} methods to access
 * values.
 *
 * <p>The car screen UI is affected by the notification channel importance (Android O and above) or
 * notification priority (below Android O) in the following ways:
 *
 * <ul>
 *   <li>A heads-up-notification (HUN) will show if the importance is set to
 *   {@link NotificationManagerCompat#IMPORTANCE_HIGH}, or the priority is set
 *       to {@link NotificationCompat#PRIORITY_HIGH} or above.
 *
 *   <li>The notification center icon, which opens a screen with all posted notifications when
 *       tapped, will show a badge for a new notification if the importance is set to
 *       {@link NotificationManagerCompat#IMPORTANCE_DEFAULT} or above, or the
 *       priority is set to {@link NotificationCompat#PRIORITY_DEFAULT} or above.
 *   <li>The notification entry will show in the notification center for all priority levels.
 * </ul>
 *
 * Calling {@link Builder#setImportance(int)} will override the importance for the notification in
 * the car screen.
 *
 * <p>Calling {@code NotificationCompat.Builder#setOnlyAlertOnce(true)} will alert a high-priority
 * notification only once in the HUN. Updating the same notification will not trigger another HUN
 * event.
 *
 * <h4>Navigation</h4>
 *
 * <p>For a navigation app's turn-by-turn (TBT) notifications, which update the same notification
 * frequently with navigation information, the notification UI has a slightly different behavior.
 * The app can post a TBT notification by calling {@code
 * NotificationCompat.Builder#setOngoing(true)} and {@code
 * NotificationCompat.Builder#setCategory(NotificationCompat.CATEGORY_NAVIGATION)}.
 * <p>TBT notifications behave the same as regular notifications with the following
 * exceptions:
 *
 * <ul>
 *     <li>The notification will not be displayed if the navigation app is not the currently active
 *     navigation app, or if the app is already displaying routing information in the navigation
 *     template.
 *
 *     <li>The heads-up-notification (HUN) can be customized with a background color through
 *     {@link Builder#setColor}.
 *
 *     <li>The notification will not be displayed in the notification center.
 * </ul>
 *
 * <p>In addition to that, the information in the navigation notification will be displayed in the
 * rail widget at the bottom of the screen when the app is in the background.
 *
 * <p>Note that frequent HUNs distract the driver. The recommended practice is to update the TBT
 * notification regularly on distance changes, which updates the rail widget, but call {@code
 * NotificationCompat.Builder#setOnlyAlertOnce(true)} unless there is a significant navigation turn
 * event.
 */
public final class CarAppExtender implements NotificationCompat.Extender {
    private static final String TAG = "CarAppExtender";

    private static final String EXTRA_CAR_EXTENDER = "androidx.car.app.EXTENSIONS";
    private static final String EXTRA_CONTENT_TITLE = "content_title";
    private static final String EXTRA_CONTENT_TEXT = "content_text";
    private static final String EXTRA_SMALL_RES_ID = "small_res_id";
    private static final String EXTRA_LARGE_BITMAP = "large_bitmap";
    private static final String EXTRA_CONTENT_INTENT = "content_intent";
    private static final String EXTRA_DELETE_INTENT = "delete_intent";
    private static final String EXTRA_ACTIONS = "actions";
    private static final String EXTRA_IMPORTANCE = "importance";
    private static final String EXTRA_COLOR = "color";
    private static final String EXTRA_CHANNEL_ID = "channel_id";

    @Nullable
    private CharSequence mContentTitle;
    @Nullable
    private CharSequence mContentText;
    private int mSmallIconResId;
    @Nullable
    private Bitmap mLargeIconBitmap;
    @Nullable
    private PendingIntent mContentIntent;
    @Nullable
    private PendingIntent mDeleteIntent;
    @Nullable
    private ArrayList<Action> mActions;
    private int mImportance;
    @Nullable
    private CarColor mColor;
    @Nullable
    private String mChannelId;

    /**
     * Creates a {@link CarAppExtender} from the {@link CarAppExtender} of an existing notification.
     */
    @SuppressWarnings("deprecation")
    public CarAppExtender(@NonNull Notification notification) {
        Bundle extras = NotificationCompat.getExtras(notification);
        if (extras == null) {
            return;
        }

        Bundle carBundle = extras.getBundle(EXTRA_CAR_EXTENDER);
        if (carBundle == null) {
            return;
        }

        mContentTitle = carBundle.getCharSequence(EXTRA_CONTENT_TITLE);
        mContentText = carBundle.getCharSequence(EXTRA_CONTENT_TEXT);
        mSmallIconResId = carBundle.getInt(EXTRA_SMALL_RES_ID);
        mLargeIconBitmap = carBundle.getParcelable(EXTRA_LARGE_BITMAP);
        mContentIntent = carBundle.getParcelable(EXTRA_CONTENT_INTENT);
        mDeleteIntent = carBundle.getParcelable(EXTRA_DELETE_INTENT);
        ArrayList<Action> actions = carBundle.getParcelableArrayList(EXTRA_ACTIONS);
        mActions = actions == null ? new ArrayList<>() : actions;
        mImportance =
                carBundle.getInt(EXTRA_IMPORTANCE,
                        NotificationManagerCompat.IMPORTANCE_UNSPECIFIED);

        Bundle colorBundle = carBundle.getBundle(EXTRA_COLOR);
        if (colorBundle != null) {
            try {
                mColor = (CarColor) Bundler.fromBundle(colorBundle);
            } catch (BundlerException e) {
                Log.e(TAG, "Failed to deserialize the notification color", e);
            }
        }

        mChannelId = carBundle.getString(EXTRA_CHANNEL_ID);
    }

    CarAppExtender(Builder builder) {
        mContentTitle = builder.mContentTitle;
        mContentText = builder.mContentText;
        mSmallIconResId = builder.mSmallIconResId;
        mLargeIconBitmap = builder.mLargeIconBitmap;
        mContentIntent = builder.mContentIntent;
        mDeleteIntent = builder.mDeleteIntent;
        mActions = builder.mActions;
        mImportance = builder.mImportance;
        mColor = builder.mColor;
        mChannelId = builder.mChannelId;
    }

    /**
     * Applies car extensions to a notification that is being built.
     *
     * <p>This is typically called by
     * {@link NotificationCompat.Builder#extend(NotificationCompat.Extender)}.
     *
     * @throws NullPointerException if {@code builder} is {@code null}
     */
    @NonNull
    @Override
    public NotificationCompat.Builder extend(@NonNull NotificationCompat.Builder builder) {
        requireNonNull(builder);
        Bundle carExtensions = new Bundle();

        if (mContentTitle != null) {
            carExtensions.putCharSequence(EXTRA_CONTENT_TITLE, mContentTitle);
        }

        if (mContentText != null) {
            carExtensions.putCharSequence(EXTRA_CONTENT_TEXT, mContentText);
        }

        if (mSmallIconResId != Resources.ID_NULL) {
            carExtensions.putInt(EXTRA_SMALL_RES_ID, mSmallIconResId);
        }

        if (mLargeIconBitmap != null) {
            carExtensions.putParcelable(EXTRA_LARGE_BITMAP, mLargeIconBitmap);
        }

        if (mContentIntent != null) {
            carExtensions.putParcelable(EXTRA_CONTENT_INTENT, mContentIntent);
        }

        if (mDeleteIntent != null) {
            carExtensions.putParcelable(EXTRA_DELETE_INTENT, mDeleteIntent);
        }

        if (mActions != null && !mActions.isEmpty()) {
            carExtensions.putParcelableArrayList(EXTRA_ACTIONS, mActions);
        }

        carExtensions.putInt(EXTRA_IMPORTANCE, mImportance);

        if (mColor != null) {
            try {
                Bundle bundle = Bundler.toBundle(mColor);
                carExtensions.putBundle(EXTRA_COLOR, bundle);
            } catch (BundlerException e) {
                Log.e(TAG, "Failed to serialize the notification color", e);
            }
        }

        if (mChannelId != null) {
            carExtensions.putString(EXTRA_CHANNEL_ID, mChannelId);
        }

        builder.getExtras().putBundle(EXTRA_CAR_EXTENDER, carExtensions);
        return builder;
    }

    /**
     * Returns whether the given notification was extended with {@link CarAppExtender}.
     *
     * @throws NullPointerException if {@code notification} is {@code null}
     */
    public static boolean isExtended(@NonNull Notification notification) {
        Bundle extras = NotificationCompat.getExtras(requireNonNull(notification));
        if (extras == null) {
            return false;
        }

        return extras.getBundle(EXTRA_CAR_EXTENDER) != null;
    }

    /**
     * Returns the content title for the notification or {@code null} if not set.
     *
     * @see Builder#setContentTitle
     */
    @Nullable
    public CharSequence getContentTitle() {
        return mContentTitle;
    }

    /**
     * Returns the content text of the notification or {@code null} if not set.
     *
     * @see Builder#setContentText
     */
    @Nullable
    public CharSequence getContentText() {
        return mContentText;
    }

    /**
     * Returns the resource ID of the small icon drawable to use.
     *
     * @see Builder#setSmallIcon(int)
     */
    @DrawableRes
    public int getSmallIcon() {
        return mSmallIconResId;
    }

    /**
     * Returns the large icon bitmap to display in the notification or {@code null} if not set.
     *
     * @see Builder#setLargeIcon(Bitmap)
     */
    @Nullable
    public Bitmap getLargeIcon() {
        return mLargeIconBitmap;
    }

    /**
     * Returns  the {@link PendingIntent} to send when the notification is clicked in the car or
     * {@code null} if not set.
     *
     * @see Builder#setContentIntent(PendingIntent)
     */
    @Nullable
    public PendingIntent getContentIntent() {
        return mContentIntent;
    }

    /**
     * Returns the {@link PendingIntent} to send when the notification is cleared by the user or
     * {@code null} if not set.
     *
     * @see Builder#setDeleteIntent(PendingIntent)
     */
    @Nullable
    public PendingIntent getDeleteIntent() {
        return mDeleteIntent;
    }

    /**
     * Returns the list of {@link Action} present on this car notification.
     *
     * @see Builder#addAction(int, CharSequence, PendingIntent)
     */
    @NonNull
    public List<Action> getActions() {
        return CollectionUtils.emptyIfNull(mActions);
    }

    /**
     * Returns the importance of the notification in the car screen.
     *
     * @see Builder#setImportance(int)
     */
    public int getImportance() {
        return mImportance;
    }

    /**
     * Returns the background color of the notification or {@code null} if a default color is to
     * be used.
     *
     * @see Builder#setColor(CarColor)
     */
    @Nullable
    public CarColor getColor() {
        return mColor;
    }

    /**
     * Returns the channel id of the notification channel to use in the car.
     *
     * @see Builder#setChannelId(String)
     */
    @Nullable
    public String getChannelId() {
        return mChannelId;
    }

    /** A builder of {@link CarAppExtender}. */
    public static final class Builder {
        @Nullable
        CharSequence mContentTitle;
        @Nullable
        CharSequence mContentText;
        int mSmallIconResId;
        @Nullable
        Bitmap mLargeIconBitmap;
        @Nullable
        PendingIntent mContentIntent;
        @Nullable
        PendingIntent mDeleteIntent;
        final ArrayList<Action> mActions = new ArrayList<>();
        int mImportance = NotificationManagerCompat.IMPORTANCE_UNSPECIFIED;
        @Nullable
        CarColor mColor;
        @Nullable
        String mChannelId;

        /**
         * Sets the title of the notification in the car screen.
         *
         * <p>This will be the most prominently displayed text in the car notification.
         *
         * <p>This method is equivalent to
         * {@link NotificationCompat.Builder#setContentTitle(CharSequence)} for the car
         * screen.
         *
         * <p>Spans are not supported in the input string and will be ignored.
         *
         * @throws NullPointerException if {@code contentTitle} is {@code null}
         */
        @NonNull
        public Builder setContentTitle(@NonNull CharSequence contentTitle) {
            mContentTitle = requireNonNull(contentTitle);
            return this;
        }

        /**
         * Sets the content text of the notification in the car screen.
         *
         * <p>This method is equivalent to
         * {@link NotificationCompat.Builder#setContentText(CharSequence)} for the car screen.
         *
         * <p>Spans are not supported in the input string and will be ignored.
         *
         * @param contentText override for the notification's content text. If set to an empty
         *                    string, it will be treated as if there is no context text
         * @throws NullPointerException if {@code contentText} is {@code null}
         */
        @NonNull
        public Builder setContentText(@NonNull CharSequence contentText) {
            mContentText = requireNonNull(contentText);
            return this;
        }

        /**
         * Sets the small icon of the notification in the car screen.
         *
         * <p>This is used as the primary icon to represent the notification.
         *
         * <p>This method is equivalent to {@link NotificationCompat.Builder#setSmallIcon(int)} for
         * the car screen.
         */
        @NonNull
        public Builder setSmallIcon(int iconResId) {
            mSmallIconResId = iconResId;
            return this;
        }

        /**
         * Sets the large icon of the notification in the car screen.
         *
         * <p>This is used as the secondary icon to represent the notification in the notification
         * center.
         *
         * <p>This method is equivalent to {@link NotificationCompat.Builder#setLargeIcon(Bitmap)}
         * for the car screen.
         *
         * <p>The large icon will be shown in the notification badge. If the large icon is not
         * set in the {@link CarAppExtender} or the notification, the small icon will show instead.
         *
         * @throws NullPointerException if {@code bitmap} is {@code null}
         */
        @NonNull
        public Builder setLargeIcon(@NonNull Bitmap bitmap) {
            mLargeIconBitmap = requireNonNull(bitmap);
            return this;
        }

        /**
         * Supplies a {@link PendingIntent} to send when the notification is clicked in the car.
         *
         * <p>If not set, the notification's content intent will be used.
         *
         * <p>In the case of navigation notifications in the rail widget, this intent will be
         * sent when the user taps on the rail widget.
         *
         * <p>This method is equivalent to
         * {@link NotificationCompat.Builder#setContentIntent(PendingIntent)} for the car screen.
         *
         * @param contentIntent override for the notification's content intent.
         * @throws NullPointerException if {@code contentIntent} is {@code null}
         */
        @NonNull
        public Builder setContentIntent(@NonNull PendingIntent contentIntent) {
            mContentIntent = requireNonNull(contentIntent);
            return this;
        }

        /**
         * Supplies a {@link PendingIntent} to send when the user clears the notification by either
         * using the "clear all" functionality in the notification center, or tapping the individual
         * "close" buttons on the notification in the car screen.
         *
         * <p>If not set, the notification's content intent will be used.
         *
         * <p>This method is equivalent to
         * {@link NotificationCompat.Builder#setDeleteIntent(PendingIntent)} for the car screen.
         *
         * @param deleteIntent override for the notification's delete intent
         * @throws NullPointerException if {@code deleteIntent} is {@code null}
         */
        @NonNull
        public Builder setDeleteIntent(@NonNull PendingIntent deleteIntent) {
            mDeleteIntent = requireNonNull(deleteIntent);
            return this;
        }

        /**
         * Adds an action to this notification.
         *
         * <p>Actions are typically displayed by the system as a button adjacent to the notification
         * content.
         *
         * <p>A notification may offer up to 2 actions. The system may not display some actions
         * in the compact notification UI (e.g. heads-up-notifications).
         *
         * <p>If one or more action is added with this method, any action added by
         * {@link NotificationCompat.Builder#addAction(int, CharSequence, PendingIntent)} will be
         * ignored.
         *
         * <p>This method is equivalent to
         * {@link NotificationCompat.Builder#addAction(int, CharSequence, PendingIntent)} for the
         * car screen.
         *
         * @param icon   resource ID of a drawable that represents the action. In order to
         *               display the actions properly, a valid resource id for the icon must be
         *               provided
         * @param title  text describing the action
         * @param intent {@link PendingIntent} to send when the action is invoked. In the case of
         *               navigation notifications in the rail widget, this intent will be sent
         *               when the user taps on the action icon in the rail
         *               widget
         * @throws NullPointerException if {@code title} or {@code intent} are {@code null}
         */
        @SuppressWarnings("deprecation")
        @NonNull
        public Builder addAction(
                @DrawableRes int icon, @NonNull CharSequence title, @NonNull PendingIntent intent) {
            mActions.add(new Action(icon, requireNonNull(title), requireNonNull(intent)));
            return this;
        }

        /**
         * For Android Auto only, sets the importance of the notification in the car screen.
         *
         * <p>The default value is {@link NotificationManagerCompat#IMPORTANCE_UNSPECIFIED},
         * and will not be used to override.
         *
         * <p>The importance is used to determine whether the notification will show as a HUN on
         * the car screen. See the class description for more details.
         *
         * <p>See {@link NotificationManagerCompat} for all supported importance values.
         *
         * @see #setChannelId(String)
         */
        @NonNull
        public Builder setImportance(int importance) {
            mImportance = importance;
            return this;
        }

        /**
         * Sets the background color of the notification in the car screen.
         *
         * <p>This method is equivalent to {@link NotificationCompat.Builder#setColor(int)} for
         * the car screen.
         *
         * <p>This color is only used for navigation notifications. See the "Navigation" section
         * of {@link CarAppExtender} for more details.
         *
         * @throws NullPointerException if {@code color} is {@code null}
         */
        @NonNull
        public Builder setColor(@NonNull CarColor color) {
            mColor = requireNonNull(color);
            return this;
        }

        /**
         * For Android Automotive OS only, sets the channel id of the notification channel to be
         * used in the car.
         *
         * <p>This is used in the case where your notification is to have a different importance
         * in the car then it does on the phone.
         *
         * <p>It is used for the same purposes you'd use {@link #setImportance(int)} for
         * Auto.
         *
         * @see #setImportance(int)
         */
        @NonNull
        public Builder setChannelId(@NonNull String channelId) {
            mChannelId = channelId;
            return this;
        }

        /**
         * Constructs the {@link CarAppExtender} defined by this builder.
         */
        @NonNull
        public CarAppExtender build() {
            return new CarAppExtender(this);
        }

        /** Creates an empty {@link Builder} instance. */
        public Builder() {
        }
    }
}