public class

PreviewChannel

extends java.lang.Object

 java.lang.Object

↳androidx.tvprovider.media.tv.PreviewChannel

Gradle dependencies

compile group: 'androidx.tvprovider', name: 'tvprovider', version: '1.1.0-alpha01'

  • groupId: androidx.tvprovider
  • artifactId: tvprovider
  • version: 1.1.0-alpha01

Artifact androidx.tvprovider:tvprovider:1.1.0-alpha01 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.tvprovider:tvprovider com.android.support:support-tv-provider

Androidx class mapping:

androidx.tvprovider.media.tv.PreviewChannel android.support.media.tv.PreviewChannel

Overview

Since API 26, all TV apps may create preview channels and publish them to the home screen. We call these App Channels (as distinct from the Live Channels row on the home screen). To help you create App Channels, the support library provides a number of classes prefixed by the word Preview-. This is a convenience class for mapping your app's content into a TvProvider Channel for publication. Use the provided PreviewChannel.Builder for creating your preview channel object. Once you create a preview channel, you can use PreviewChannelHelper to publish it and add programs to it.

Summary

Methods
public booleanequals(java.lang.Object other)

public static PreviewChannelfromCursor(Cursor cursor)

Used by PreviewChannelHelper to transduce a TvProvider channel row into a PreviewChannel Java object.

public IntentgetAppLinkIntent()

public UrigetAppLinkIntentUri()

public java.lang.CharSequencegetDescription()

public java.lang.CharSequencegetDisplayName()

public longgetId()

public byte[]getInternalProviderDataByteArray()

public java.lang.LonggetInternalProviderFlag1()

public java.lang.LonggetInternalProviderFlag2()

public java.lang.LonggetInternalProviderFlag3()

public java.lang.LonggetInternalProviderFlag4()

public java.lang.StringgetInternalProviderId()

public BitmapgetLogo(Context context)

This method should be called on a worker thread since decoding Bitmap is an expensive operation and therefore should not be performed on the main thread.

public java.lang.StringgetPackageName()

public java.lang.StringgetType()

public booleanhasAnyUpdatedValues(PreviewChannel update)

Indicates whether some other PreviewChannel has any set attribute that is different from this PreviewChannel's respective attributes.

public inthashCode()

public booleanisBrowsable()

public ContentValuestoContentValues()

Used by PreviewChannelHelper to communicate PreviewChannel CRUD operations to the TvProvider.

public java.lang.StringtoString()

from java.lang.Objectclone, finalize, getClass, notify, notifyAll, wait, wait, wait

Methods

public static PreviewChannel fromCursor(Cursor cursor)

Used by PreviewChannelHelper to transduce a TvProvider channel row into a PreviewChannel Java object. You never need to use this method unless you want to convert database rows to PreviewChannel objects yourself.

This method assumes the cursor was obtained using .PreviewChannel.Columns#PROJECTION. This way, all indices are known beforehand.

Parameters:

cursor: a cursor row from the TvProvider

Returns:

a PreviewChannel whose values come from the cursor row

public long getId()

Returns:

the ID the system assigns to this preview channel upon publication.

public java.lang.String getPackageName()

Returns:

package name of the app that created this channel

public java.lang.String getType()

Returns:

what type of channel this is. For preview channels, the type is always TvContractCompat.Channels.TYPE_PREVIEW

public java.lang.CharSequence getDisplayName()

Returns:

The name users see when this channel appears on the home screen

public java.lang.CharSequence getDescription()

Returns:

The value of TvContractCompat.Channels.COLUMN_DESCRIPTION for the channel. A short text explaining what this channel contains.

public Uri getAppLinkIntentUri()

Returns:

The value of TvContractCompat.Channels.COLUMN_APP_LINK_INTENT_URI for the channel.

public Intent getAppLinkIntent()

Returns:

The value of TvContractCompat.Channels.COLUMN_APP_LINK_INTENT_URI for the program.

public Bitmap getLogo(Context context)

This method should be called on a worker thread since decoding Bitmap is an expensive operation and therefore should not be performed on the main thread.

Returns:

The logo associated with this preview channel

public byte[] getInternalProviderDataByteArray()

Returns:

The value of TvContractCompat.Channels.COLUMN_INTERNAL_PROVIDER_DATA for the channel.

public java.lang.Long getInternalProviderFlag1()

Returns:

The value of TvContractCompat.Channels.COLUMN_INTERNAL_PROVIDER_FLAG1 for the channel.

public java.lang.Long getInternalProviderFlag2()

Returns:

The value of TvContractCompat.Channels.COLUMN_INTERNAL_PROVIDER_FLAG2 for the channel.

public java.lang.Long getInternalProviderFlag3()

Returns:

The value of TvContractCompat.Channels.COLUMN_INTERNAL_PROVIDER_FLAG3 for the channel.

public java.lang.Long getInternalProviderFlag4()

Returns:

The value of TvContractCompat.Channels.COLUMN_INTERNAL_PROVIDER_FLAG4 for the channel.

public java.lang.String getInternalProviderId()

Returns:

The value of TvContractCompat.Channels.COLUMN_INTERNAL_PROVIDER_ID for the channel.

public boolean isBrowsable()

Returns:

The value of TvContractCompat.Channels.COLUMN_BROWSABLE for the channel. A preview channel is BROWABLE when it is visible on the TV home screen.

public int hashCode()

public boolean equals(java.lang.Object other)

public boolean hasAnyUpdatedValues(PreviewChannel update)

Indicates whether some other PreviewChannel has any set attribute that is different from this PreviewChannel's respective attributes. An attribute is considered "set" if its key is present in the ContentValues vector.

public java.lang.String toString()

public ContentValues toContentValues()

Used by PreviewChannelHelper to communicate PreviewChannel CRUD operations to the TvProvider. You never need to use this method unless you want to communicate to the TvProvider directly.

Source

/*
 * Copyright 2018 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.tvprovider.media.tv;

import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;

import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.tv.TvContract;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.WorkerThread;
import androidx.tvprovider.media.tv.TvContractCompat.Channels;
import androidx.tvprovider.media.tv.TvContractCompat.Channels.Type;

import java.io.FileNotFoundException;
import java.net.URISyntaxException;
import java.util.Objects;
import java.util.Set;

/**
 * Since API 26, all TV apps may create preview channels and publish them to the home screen.
 * We call these App Channels (as distinct from the Live Channels row on the home screen). To help
 * you create App Channels, the support library provides a number of classes prefixed by the word
 * Preview-.
 *
 * This is a convenience class for mapping your app's content into a
 * {@link TvContractCompat TvProvider Channel} for publication. Use the provided {@link Builder}
 * for creating your preview channel object. Once you create a preview channel, you can
 * use {@link PreviewChannelHelper} to publish it and add {@link PreviewProgram programs} to it.
 */
public class PreviewChannel {

    private static final String TAG = "PreviewChannel";
    private static final long INVALID_CHANNEL_ID = -1;
    private static final int IS_BROWSABLE = 1;

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    ContentValues mValues;
    private volatile Bitmap mLogoImage;

    private Uri mLogoUri;
    private boolean mLogoChanged;

    /**
     * Logo is fetched when it is explicitly asked for. mLogoFetched prevents repeated calls in
     * case there is no logo in fact.
     */
    private volatile boolean mLogoFetched;

    PreviewChannel(Builder builder) {
        mValues = builder.mValues;
        mLogoImage = builder.mLogoBitmap;
        mLogoUri = builder.mLogoUri;
        mLogoChanged = (mLogoImage != null || mLogoUri != null);
    }

    /**
     * Used by {@link PreviewChannelHelper} to transduce a TvProvider channel row into a
     * PreviewChannel Java object. You never need to use this method unless you want to convert
     * database rows to PreviewChannel objects yourself.
     * <p/>
     * This method assumes the cursor was obtained using {@link androidx.tvprovider.media.tv
     * .PreviewChannel.Columns#PROJECTION}. This way, all indices are known
     * beforehand.
     *
     * @param cursor a cursor row from the TvProvider
     * @return a PreviewChannel whose values come from the cursor row
     */
    public static PreviewChannel fromCursor(Cursor cursor) {
        Builder builder = new Builder();
        builder.setId(cursor.getInt(Columns.COL_ID));
        builder.setPackageName(cursor.getString(Columns.COL_PACKAGE_NAME));
        builder.setType(cursor.getString(Columns.COL_TYPE));
        builder.setDisplayName(cursor.getString(Columns.COL_DISPLAY_NAME));
        builder.setDescription(cursor.getString(Columns.COL_DESCRIPTION));
        builder.setAppLinkIntentUri(Uri.parse(cursor.getString(Columns.COL_APP_LINK_INTENT_URI)));
        builder.setInternalProviderId(cursor.getString(Columns.COL_INTERNAL_PROVIDER_ID));
        builder.setInternalProviderData(cursor.getBlob(Columns.COL_INTERNAL_PROVIDER_DATA));
        builder.setInternalProviderFlag1(cursor.getLong(Columns.COL_INTERNAL_PROVIDER_FLAG1));
        builder.setInternalProviderFlag2(cursor.getLong(Columns.COL_INTERNAL_PROVIDER_FLAG2));
        builder.setInternalProviderFlag3(cursor.getLong(Columns.COL_INTERNAL_PROVIDER_FLAG3));
        builder.setInternalProviderFlag4(cursor.getLong(Columns.COL_INTERNAL_PROVIDER_FLAG4));
        return builder.build();
    }

    /**
     * @return the ID the system assigns to this preview channel upon publication.
     */
    public long getId() {
        Long l = mValues.getAsLong(Channels._ID);
        return l == null ? INVALID_CHANNEL_ID : l;
    }

    /**
     * @return package name of the app that created this channel
     */
    public String getPackageName() {
        return mValues.getAsString(Channels.COLUMN_PACKAGE_NAME);
    }

    /**
     * @return what type of channel this is. For preview channels, the type is always
     * TvContractCompat.Channels.TYPE_PREVIEW
     */
    @Type
    public String getType() {
        return mValues.getAsString(Channels.COLUMN_TYPE);
    }

    /**
     * @return The name users see when this channel appears on the home screen
     */
    public CharSequence getDisplayName() {
        return mValues.getAsString(Channels.COLUMN_DISPLAY_NAME);
    }

    /**
     * @return The value of {@link Channels#COLUMN_DESCRIPTION} for the channel. A short text
     * explaining what this channel contains.
     */
    public CharSequence getDescription() {
        return mValues.getAsString(Channels.COLUMN_DESCRIPTION);
    }

    /**
     * @return The value of {@link Channels#COLUMN_APP_LINK_INTENT_URI} for the channel.
     */
    public Uri getAppLinkIntentUri() {
        String uri = mValues.getAsString(Channels.COLUMN_APP_LINK_INTENT_URI);
        return uri == null ? null : Uri.parse(uri);
    }

    /**
     * @return The value of {@link Channels#COLUMN_APP_LINK_INTENT_URI} for the program.
     */
    public Intent getAppLinkIntent() throws URISyntaxException {
        String uri = mValues.getAsString(Channels.COLUMN_APP_LINK_INTENT_URI);
        return uri == null ? null : Intent.parseUri(uri.toString(), Intent.URI_INTENT_SCHEME);
    }

    /**
     * This method should be called on a worker thread since decoding Bitmap is an expensive
     * operation and therefore should not be performed on the main thread.
     *
     * @return The logo associated with this preview channel
     */
    @WorkerThread
    public Bitmap getLogo(Context context) {
        if (!mLogoFetched && mLogoImage == null) {
            try {
                mLogoImage = BitmapFactory.decodeStream(
                        context.getContentResolver().openInputStream(
                                TvContract.buildChannelLogoUri(getId())
                        ));
            } catch (FileNotFoundException | SQLiteException e) {
                Log.e(TAG, "Logo for preview channel (ID:" + getId() + ") not found.", e);
            }
            mLogoFetched = true;
        }
        return mLogoImage;
    }

    /**
     * @hide
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    boolean isLogoChanged() {
        return mLogoChanged;
    }

    /**
     * @hide
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    Uri getLogoUri() {
        return mLogoUri;
    }

    /**
     * @return The value of {@link Channels#COLUMN_INTERNAL_PROVIDER_DATA} for the channel.
     */
    public byte[] getInternalProviderDataByteArray() {
        return mValues.getAsByteArray(Channels.COLUMN_INTERNAL_PROVIDER_DATA);
    }

    /**
     * @return The value of {@link Channels#COLUMN_INTERNAL_PROVIDER_FLAG1} for the channel.
     */
    public Long getInternalProviderFlag1() {
        return mValues.getAsLong(Channels.COLUMN_INTERNAL_PROVIDER_FLAG1);
    }

    /**
     * @return The value of {@link Channels#COLUMN_INTERNAL_PROVIDER_FLAG2} for the channel.
     */
    public Long getInternalProviderFlag2() {
        return mValues.getAsLong(Channels.COLUMN_INTERNAL_PROVIDER_FLAG2);
    }

    /**
     * @return The value of {@link Channels#COLUMN_INTERNAL_PROVIDER_FLAG3} for the channel.
     */
    public Long getInternalProviderFlag3() {
        return mValues.getAsLong(Channels.COLUMN_INTERNAL_PROVIDER_FLAG3);
    }

    /**
     * @return The value of {@link Channels#COLUMN_INTERNAL_PROVIDER_FLAG4} for the channel.
     */
    public Long getInternalProviderFlag4() {
        return mValues.getAsLong(Channels.COLUMN_INTERNAL_PROVIDER_FLAG4);
    }

    /**
     * @return The value of {@link Channels#COLUMN_INTERNAL_PROVIDER_ID} for the channel.
     */
    public String getInternalProviderId() {
        return mValues.getAsString(Channels.COLUMN_INTERNAL_PROVIDER_ID);
    }

    /**
     * @return The value of {@link Channels#COLUMN_BROWSABLE} for the channel. A preview channel
     * is BROWABLE when it is visible on the TV home screen.
     */
    public boolean isBrowsable() {
        Integer i = mValues.getAsInteger(Channels.COLUMN_BROWSABLE);
        return i != null && i == IS_BROWSABLE;
    }

    @Override
    public int hashCode() {
        return mValues.hashCode();
    }

    @Override
    public boolean equals(Object other) {
        if (!(other instanceof PreviewChannel)) {
            return false;
        }
        return mValues.equals(((PreviewChannel) other).mValues);
    }

    /**
     * Indicates whether some other PreviewChannel has any set attribute that is different from
     * this PreviewChannel's respective attributes. An attribute is considered "set" if its key
     * is present in the ContentValues vector.
     */
    public boolean hasAnyUpdatedValues(PreviewChannel update) {
        Set<String> updateKeys = update.mValues.keySet();
        for (String key : updateKeys) {
            Object updateValue = update.mValues.get(key);
            Object currValue = mValues.get(key);
            if (!Objects.deepEquals(updateValue, currValue)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String toString() {
        return "Channel{" + mValues.toString() + "}";
    }

    /**
     * Used by {@link PreviewChannelHelper} to communicate PreviewChannel CRUD operations
     * to the TvProvider. You never need to use this method unless you want to communicate to the
     * TvProvider directly.
     *
     * @hide
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    public ContentValues toContentValues() {
        ContentValues values = new ContentValues(mValues);
        return values;
    }

    /**
     * @hide
     */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    public static class Columns {
        public static final String[] PROJECTION = {
                Channels._ID,
                Channels.COLUMN_PACKAGE_NAME,
                Channels.COLUMN_TYPE,
                Channels.COLUMN_DISPLAY_NAME,
                Channels.COLUMN_DESCRIPTION,
                Channels.COLUMN_APP_LINK_INTENT_URI,
                Channels.COLUMN_INTERNAL_PROVIDER_ID,
                Channels.COLUMN_INTERNAL_PROVIDER_DATA,
                Channels.COLUMN_INTERNAL_PROVIDER_FLAG1,
                Channels.COLUMN_INTERNAL_PROVIDER_FLAG2,
                Channels.COLUMN_INTERNAL_PROVIDER_FLAG3,
                Channels.COLUMN_INTERNAL_PROVIDER_FLAG4
        };

        public static final int COL_ID = 0;
        public static final int COL_PACKAGE_NAME = 1;
        public static final int COL_TYPE = 2;
        public static final int COL_DISPLAY_NAME = 3;
        public static final int COL_DESCRIPTION = 4;
        public static final int COL_APP_LINK_INTENT_URI = 5;
        public static final int COL_INTERNAL_PROVIDER_ID = 6;
        public static final int COL_INTERNAL_PROVIDER_DATA = 7;
        public static final int COL_INTERNAL_PROVIDER_FLAG1 = 8;
        public static final int COL_INTERNAL_PROVIDER_FLAG2 = 9;
        public static final int COL_INTERNAL_PROVIDER_FLAG3 = 10;
        public static final int COL_INTERNAL_PROVIDER_FLAG4 = 11;

        private Columns() {
        }
    }

    /**
     * This builder makes it easy to create a PreviewChannel object by allowing you to chain
     * setters. Even though this builder provides a no-arg constructor, certain fields are
     * required or the {@link #build()} method will throw an exception. The required fields are
     * displayName and appLinkIntentUri; use the respective methods to set them.
     */
    public static final class Builder {
        ContentValues mValues;
        Bitmap mLogoBitmap;
        Uri mLogoUri;

        public Builder() {
            mValues = new ContentValues();
        }

        public Builder(PreviewChannel other) {
            mValues = new ContentValues(other.mValues);
        }

        Builder setId(long id) {
            mValues.put(Channels._ID, id);
            return this;
        }

        /**
         * Sets the package name of the Channel.
         *
         * @param packageName The value of {@link Channels#COLUMN_PACKAGE_NAME} for the channel.
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @hide
         */
        @RestrictTo(LIBRARY_GROUP_PREFIX)
        Builder setPackageName(String packageName) {
            mValues.put(Channels.COLUMN_PACKAGE_NAME, packageName);
            return this;
        }

        // Not public because this is always the same: setType(TvContractCompat.Channels.TYPE_PREVIEW)
        Builder setType(@Type String type) {
            mValues.put(Channels.COLUMN_TYPE, type);
            return this;
        }

        /**
         * This is the name user sees when your channel appears on their TV home screen. For
         * example "New Arrivals." This field is required.
         *
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see TvContractCompat.Channels#COLUMN_DISPLAY_NAME
         */
        public Builder setDisplayName(CharSequence displayName) {
            mValues.put(Channels.COLUMN_DISPLAY_NAME, displayName.toString());
            return this;
        }

        /**
         * It's good practice to include a general description of the programs in this channel.
         *
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see TvContractCompat.Channels#COLUMN_DESCRIPTION
         */
        @NonNull
        public Builder setDescription(@Nullable CharSequence description) {
            if (description == null) {
                mValues.remove(Channels.COLUMN_DESCRIPTION);
            } else {
                mValues.put(Channels.COLUMN_DESCRIPTION, description.toString());
            }
            return this;
        }

        /**
         * When user clicks on this channel's logo, the system will send an Intent for your app to
         * open an Activity with contents relevant to this channel. Hence, the Intent data you
         * provide here must point to content relevant to this channel.
         *
         * @return This Builder object to allow for chaining of calls to builder methods.
         */
        public Builder setAppLinkIntent(Intent appLinkIntent) {
            return setAppLinkIntentUri(Uri.parse(appLinkIntent.toUri(Intent.URI_INTENT_SCHEME)));
        }

        /**
         * When user clicks on this channel's logo, the system will send an Intent for your app to
         * open an Activity with contents relevant to this channel. Hence, the Uri you provide here
         * must point to content relevant to this channel.
         *
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see TvContractCompat.Channels#COLUMN_APP_LINK_INTENT_URI
         */
        public Builder setAppLinkIntentUri(Uri appLinkIntentUri) {
            mValues.put(Channels.COLUMN_APP_LINK_INTENT_URI,
                    null == appLinkIntentUri ? null : appLinkIntentUri.toString());
            return this;
        }

        /**
         * It is expected that your app or your server has its own internal representation
         * (i.e. data structure) of channels. It is highly recommended that you store your
         * app/server's channel ID here; so that you may easily relate this published preview
         * channel with the corresponding channel from your server.
         *
         * The {@link PreviewChannelHelper#publishChannel(PreviewChannel) publish} method check this
         * field to verify whether a preview channel being published would result in a duplicate.
         * :
         *
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see TvContractCompat.Channels#COLUMN_INTERNAL_PROVIDER_ID
         */
        public Builder setInternalProviderId(String internalProviderId) {
            mValues.put(Channels.COLUMN_INTERNAL_PROVIDER_ID, internalProviderId);
            return this;
        }

        /**
         * This is one of the optional fields that your app may set. Use these fields at your
         * discretion to help you remember important information about this channel.
         *
         * For example, if this channel needs a byte array that is expensive for your app to
         * construct, you may choose to save it here.
         *
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see TvContractCompat.Channels#COLUMN_INTERNAL_PROVIDER_DATA
         */
        public Builder setInternalProviderData(byte[] internalProviderData) {
            mValues.put(Channels.COLUMN_INTERNAL_PROVIDER_DATA, internalProviderData);
            return this;
        }

        /**
         * This is one of the optional fields that your app may set. Use these fields at your
         * discretion to help you remember important information about this channel.
         *
         * For example, you may use this flag to track additional data about this particular
         * channel.
         *
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see TvContractCompat.Channels#COLUMN_INTERNAL_PROVIDER_FLAG1
         */
        public Builder setInternalProviderFlag1(long flag) {
            mValues.put(Channels.COLUMN_INTERNAL_PROVIDER_FLAG1, flag);
            return this;
        }

        /**
         * This is one of the optional fields that your app may set. Use these fields at your
         * discretion to help you remember important information about this channel.
         *
         * For example, you may use this flag to track additional data about this particular
         * channel.
         *
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see TvContractCompat.Channels#COLUMN_INTERNAL_PROVIDER_FLAG2
         */
        public Builder setInternalProviderFlag2(long flag) {
            mValues.put(Channels.COLUMN_INTERNAL_PROVIDER_FLAG2, flag);
            return this;
        }

        /**
         * This is one of the optional fields that your app may set. Use these fields at your
         * discretion to help you remember important information about this channel.
         *
         * For example, you may use this flag to track additional data about this particular
         * channel.
         *
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see TvContractCompat.Channels#COLUMN_INTERNAL_PROVIDER_FLAG3
         */
        public Builder setInternalProviderFlag3(long flag) {
            mValues.put(Channels.COLUMN_INTERNAL_PROVIDER_FLAG3, flag);
            return this;
        }

        /**
         * This is one of the optional fields that your app may set. Use these fields at your
         * discretion to help you remember important information about this channel.
         *
         * For example, you may use this flag to track additional data about this particular
         * channel.
         *
         * @return This Builder object to allow for chaining of calls to builder methods.
         * @see TvContractCompat.Channels#COLUMN_INTERNAL_PROVIDER_FLAG4
         */
        public Builder setInternalProviderFlag4(long flag) {
            mValues.put(Channels.COLUMN_INTERNAL_PROVIDER_FLAG4, flag);
            return this;
        }

        /**
         * A logo visually identifies your channel. Hence, you should consider adding a unique logo
         * to every channel you create, so user can quickly identify your channel.
         *
         * @return This Builder object to allow for chaining of calls to builder methods.
         */
        public Builder setLogo(@NonNull Bitmap logoImage) {
            mLogoBitmap = logoImage;
            mLogoUri = null;
            return this;
        }

        /**
         * A logo visually identifies your channel. Hence, you should consider adding a unique logo
         * to every channel you create, so user can quickly identify your channel.
         *
         * @return This Builder object to allow for chaining of calls to builder methods.
         */
        public Builder setLogo(@NonNull Uri logoUri) {
            mLogoUri = logoUri;
            mLogoBitmap = null;
            return this;
        }

        /**
         * Takes the values of the Builder object and creates a PreviewChannel object.
         *
         * @return PreviewChannel object with values from the Builder.
         */
        public PreviewChannel build() {
            setType(Channels.TYPE_PREVIEW);

            if (TextUtils.isEmpty(mValues.getAsString(Channels.COLUMN_DISPLAY_NAME))) {
                throw new IllegalStateException("Need channel name."
                        + " Use method setDisplayName(String) to set it.");
            }

            if (TextUtils.isEmpty(mValues.getAsString(Channels.COLUMN_APP_LINK_INTENT_URI))) {
                throw new IllegalStateException("Need app link intent uri for channel."
                        + " Use method setAppLinkIntent or setAppLinkIntentUri to set it.");
            }

            PreviewChannel previewChannel = new PreviewChannel(this);
            return previewChannel;
        }
    }
}