/** * Copyright (c) 2015, The CyanogenMod 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 cyanogenmod.app; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; import android.widget.RemoteViews; import cyanogenmod.os.Build; import cyanogenmod.os.Concierge; import cyanogenmod.os.Concierge.ParcelInfo; import java.util.ArrayList; /** * A class that represents a quick settings tile * *

The {@link cyanogenmod.app.CustomTile.Builder} has been added to make it * easier to construct CustomTiles.

*/ public class CustomTile implements Parcelable { /** Max count allowed by PseudoGridView within SystemUi **/ public static final int PSEUDO_GRID_ITEM_MAX_COUNT = 9; private String resourcesPackageName = ""; /** * An optional intent to execute when the custom tile entry is clicked. If * this is an activity, it must include the * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires * that you take care of task management. * * This takes priority over the onClickUri. **/ public PendingIntent onClick; /** * An optional intent to execute when the custom tile entry is long clicked. If * this is an activity, it must include the * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires * that you take care of task management. Activities will also automatically trigger * the host panel to automatically collapse after executing the pending intent. **/ public PendingIntent onLongClick; /** * An optional settings intent to execute when the custom tile's detail is shown * If this is an activity, it must include the * {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK} flag, which requires * that you take care of task management */ public Intent onSettingsClick; /** * The intent to execute when the custom tile is explicitly removed by the user. * * This probably shouldn't be launching an activity since several of those will be sent * at the same time. */ public PendingIntent deleteIntent; /** * An optional Uri to be parsed and broadcast on tile click, if an onClick pending intent * is specified, it will take priority over the uri to be broadcasted. **/ public Uri onClickUri; /** * A label specific to the quick settings tile to be created */ public String label; /** * A content description for the custom tile state */ public String contentDescription; /** * An icon to represent the custom tile */ public int icon; /** * A remote icon to represent the custom tile */ public Bitmap remoteIcon; /** * An expanded style for when the CustomTile is clicked, can either be * a {@link GridExpandedStyle} or a {@link ListExpandedStyle} */ public ExpandedStyle expandedStyle; /** * Boolean that forces the status bar panel to collapse when a user clicks on the * {@link CustomTile} * By default {@link #collapsePanel} is true */ public boolean collapsePanel = true; /** * Indicates whether this tile has sensitive data that have to be hidden on * secure lockscreens. * By default {@link #sensitiveData} is false */ public boolean sensitiveData = false; /** * Unflatten the CustomTile from a parcel. */ public CustomTile(Parcel parcel) { // Read parcelable version via the Concierge ParcelInfo parcelInfo = Concierge.receiveParcel(parcel); int parcelableVersion = parcelInfo.getParcelVersion(); // Pattern here is that all new members should be added to the end of // the writeToParcel method. Then we step through each version, until the latest // API release to help unravel this parcel if (parcelableVersion >= Build.CM_VERSION_CODES.APRICOT) { if (parcel.readInt() != 0) { this.onClick = PendingIntent.CREATOR.createFromParcel(parcel); } if (parcel.readInt() != 0) { this.onSettingsClick = Intent.CREATOR.createFromParcel(parcel); } if (parcel.readInt() != 0) { this.onClickUri = Uri.CREATOR.createFromParcel(parcel); } if (parcel.readInt() != 0) { this.label = parcel.readString(); } if (parcel.readInt() != 0) { this.contentDescription = parcel.readString(); } if (parcel.readInt() != 0) { this.expandedStyle = ExpandedStyle.CREATOR.createFromParcel(parcel); } this.icon = parcel.readInt(); } if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { this.resourcesPackageName = parcel.readString(); this.collapsePanel = (parcel.readInt() == 1); if (parcel.readInt() != 0) { this.remoteIcon = Bitmap.CREATOR.createFromParcel(parcel); } if (parcel.readInt() != 0) { this.deleteIntent = PendingIntent.CREATOR.createFromParcel(parcel); } this.sensitiveData = (parcel.readInt() == 1); } if (parcelableVersion >= Build.CM_VERSION_CODES.DRAGON_FRUIT) { if (parcel.readInt() != 0) { this.onLongClick = PendingIntent.CREATOR.createFromParcel(parcel); } } // Complete parcel info for the concierge parcelInfo.complete(); } /** * Constructs a CustomTile object with default values. * You might want to consider using {@link cyanogenmod.app.CustomTile.Builder} instead. */ public CustomTile() { // Empty constructor } /** @hide **/ public String getResourcesPackageName() { return resourcesPackageName; } @Override public CustomTile clone() { CustomTile that = new CustomTile(); cloneInto(that); return that; } @Override public String toString() { StringBuilder b = new StringBuilder(); String NEW_LINE = System.getProperty("line.separator"); if (onClickUri != null) { b.append("onClickUri=" + onClickUri.toString() + NEW_LINE); } if (onClick != null) { b.append("onClick=" + onClick.toString() + NEW_LINE); } if (onLongClick != null) { b.append("onLongClick=" + onLongClick.toString() + NEW_LINE); } if (onSettingsClick != null) { b.append("onSettingsClick=" + onSettingsClick.toString() + NEW_LINE); } if (!TextUtils.isEmpty(label)) { b.append("label=" + label + NEW_LINE); } if (!TextUtils.isEmpty(contentDescription)) { b.append("contentDescription=" + contentDescription + NEW_LINE); } if (expandedStyle != null) { b.append("expandedStyle=" + expandedStyle + NEW_LINE); } b.append("icon=" + icon + NEW_LINE); b.append("resourcesPackageName=" + resourcesPackageName + NEW_LINE); b.append("collapsePanel=" + collapsePanel + NEW_LINE); if (remoteIcon != null) { b.append("remoteIcon=" + remoteIcon.getGenerationId() + NEW_LINE); } if (deleteIntent != null) { b.append("deleteIntent=" + deleteIntent.toString() + NEW_LINE); } b.append("sensitiveData=" + sensitiveData + NEW_LINE); return b.toString(); } /** * Copy all of this into that * @hide */ public void cloneInto(CustomTile that) { that.resourcesPackageName = this.resourcesPackageName; that.onClick = this.onClick; that.onLongClick = this.onLongClick; that.onSettingsClick = this.onSettingsClick; that.onClickUri = this.onClickUri; that.label = this.label; that.contentDescription = this.contentDescription; that.expandedStyle = this.expandedStyle; that.icon = this.icon; that.collapsePanel = this.collapsePanel; that.remoteIcon = this.remoteIcon; that.deleteIntent = this.deleteIntent; that.sensitiveData = this.sensitiveData; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { // Tell the concierge to prepare the parcel ParcelInfo parcelInfo = Concierge.prepareParcel(out); // ==== APRICOT ===== if (onClick != null) { out.writeInt(1); onClick.writeToParcel(out, 0); } else { out.writeInt(0); } if (onSettingsClick != null) { out.writeInt(1); onSettingsClick.writeToParcel(out, 0); } else { out.writeInt(0); } if (onClickUri != null) { out.writeInt(1); onClickUri.writeToParcel(out, 0); } else { out.writeInt(0); } if (label != null) { out.writeInt(1); out.writeString(label); } else { out.writeInt(0); } if (contentDescription != null) { out.writeInt(1); out.writeString(contentDescription); } else { out.writeInt(0); } if (expandedStyle != null) { out.writeInt(1); expandedStyle.writeToParcel(out, 0); } else { out.writeInt(0); } out.writeInt(icon); // ==== BOYSENBERRY ===== out.writeString(resourcesPackageName); out.writeInt(collapsePanel ? 1 : 0); if (remoteIcon != null) { out.writeInt(1); remoteIcon.writeToParcel(out, 0); } else { out.writeInt(0); } if (deleteIntent != null) { out.writeInt(1); deleteIntent.writeToParcel(out, 0); } else { out.writeInt(0); } out.writeInt(sensitiveData ? 1 : 0); // ==== DRAGONFRUIT ==== if (onLongClick != null) { out.writeInt(1); onLongClick.writeToParcel(out, 0); } else { out.writeInt(0); } // Complete the parcel info for the concierge parcelInfo.complete(); } /** * An object that can apply an expanded view style to a {@link CustomTile.Builder} * object. */ public static class ExpandedStyle implements Parcelable { /** * @hide */ public static final int NO_STYLE = -1; /** * Identifier for a grid style expanded view */ public static final int GRID_STYLE = 0; /** * Identifier for a list style expanded view */ public static final int LIST_STYLE = 1; /** * Identifier for a remote view style expanded view */ public static final int REMOTE_STYLE = 2; private ExpandedStyle() { styleId = NO_STYLE; } private RemoteViews contentViews; private ExpandedItem[] expandedItems; private int styleId; private ExpandedStyle(Parcel parcel) { // Read parcelable version via the Concierge ParcelInfo parcelInfo = Concierge.receiveParcel(parcel); int parcelableVersion = parcelInfo.getParcelVersion(); // Pattern here is that all new members should be added to the end of // the writeToParcel method. Then we step through each version, until the latest // API release to help unravel this parcel if (parcelableVersion >= Build.CM_VERSION_CODES.APRICOT) { if (parcel.readInt() != 0) { expandedItems = parcel.createTypedArray(ExpandedItem.CREATOR); } styleId = parcel.readInt(); } if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { if (parcel.readInt() != 0) { contentViews = RemoteViews.CREATOR.createFromParcel(parcel); } } // Complete parcel info for the concierge parcelInfo.complete(); } /** * @hide */ public void setBuilder(Builder builder) { if (builder != null) { builder.setExpandedStyle(this); } } /** * @hide */ protected void internalSetExpandedItems(ArrayList items) { if (styleId == GRID_STYLE && items.size() > PSEUDO_GRID_ITEM_MAX_COUNT) { Log.w(CustomTile.class.getName(), "Attempted to publish greater than max grid item count"); } expandedItems = new ExpandedItem[items.size()]; items.toArray(expandedItems); } /** * @hide */ protected void internalSetRemoteViews(RemoteViews remoteViews) { contentViews = remoteViews; } /** * @hide */ protected void internalStyleId(int id) { styleId = id; } /** * Retrieve the {@link ExpandedItem}s that have been set on this expanded style * @return array of {@link ExpandedItem} */ public ExpandedItem[] getExpandedItems() { return expandedItems; } /** * Retrieve the RemoteViews that have been set on this expanded style * @return RemoteViews */ public RemoteViews getContentViews() { return contentViews; } /** * Retrieve the style id associated with the {@link ExpandedStyle} * @return id for style */ public int getStyle() { return styleId; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel parcel, int i) { // Tell the concierge to prepare the parcel ParcelInfo parcelInfo = Concierge.prepareParcel(parcel); // ==== APRICOT ==== if (expandedItems != null) { parcel.writeInt(1); parcel.writeTypedArray(expandedItems, 0); } else { parcel.writeInt(0); } parcel.writeInt(styleId); // ==== BOYSENBERRY ==== if (contentViews != null) { parcel.writeInt(1); contentViews.writeToParcel(parcel, 0); } else { parcel.writeInt(0); } // Complete the parcel info for the concierge parcelInfo.complete(); } @Override public String toString() { StringBuilder b = new StringBuilder(); String NEW_LINE = System.getProperty("line.separator"); if (expandedItems != null) { b.append("expandedItems= "+ NEW_LINE); for (ExpandedItem item : expandedItems) { b.append(" item=" + item.toString() + NEW_LINE); } } b.append("styleId=" + styleId + NEW_LINE); return b.toString(); } /** * Parcelable.Creator that instantiates ExpandedStyle objects */ public static final Creator CREATOR = new Creator() { public ExpandedStyle createFromParcel(Parcel in) { return new ExpandedStyle(in); } @Override public ExpandedStyle[] newArray(int size) { return new ExpandedStyle[size]; } }; } /** * An instance of {@link ExpandedStyle} that shows the {@link ExpandedGridItem}s in a * non-scrollable grid. */ public static class GridExpandedStyle extends ExpandedStyle { /** * Constructs a GridExpandedStyle object with default values. */ public GridExpandedStyle() { internalStyleId(GRID_STYLE); } /** * Sets an {@link ArrayList} of {@link ExpandedGridItem}'s to be utilized by * the PseudoGridView for presentation. * * Since the PseudoGridView is not a Grid with an adapter instance, there's a hard * limit specified by {@link #PSEUDO_GRID_ITEM_MAX_COUNT} * @param expandedGridItems an array list of {@link ExpandedGridItem}s */ public void setGridItems(ArrayList expandedGridItems) { internalSetExpandedItems(expandedGridItems); } } /** * An instance of {@link ExpandedStyle} that shows the {@link ExpandedListItem}'s in a * scrollable ListView. */ public static class ListExpandedStyle extends ExpandedStyle { /** * Constructs a ListExpandedStyle object with default values. */ public ListExpandedStyle() { internalStyleId(LIST_STYLE); } /** * Sets an {@link ArrayList} of {@link ExpandedListItem}s to be utilized by * the ListView for presentation. * @param expandedListItems an array list of {@link ExpandedListItem}s */ public void setListItems(ArrayList expandedListItems) { internalSetExpandedItems(expandedListItems); } } /** * An instance of {@link ExpandedStyle} that shows a remote view in the remote process */ public static class RemoteExpandedStyle extends ExpandedStyle { /** * Constructs a RemoteExpandedStyle object with default values. */ public RemoteExpandedStyle() { internalStyleId(REMOTE_STYLE); } /** * Sets the RemoteViews for the {@link RemoteExpandedStyle} * @param remoteViews a remote view */ public void setRemoteViews(RemoteViews remoteViews) { internalSetRemoteViews(remoteViews); } } /** * A container object that is utilized by {@link ExpandedStyle} to show specific items in either * a PseudoGridView or a ListView via {@link GridExpandedStyle} and {@link ListExpandedStyle} */ public static class ExpandedItem implements Parcelable { /** * A {@link PendingIntent} associated with the item. * Triggers a {@link PendingIntent#send()} when the item is clicked. */ public PendingIntent onClickPendingIntent; /** * A drawable resource id associated with the {@link ExpandedItem} */ public int itemDrawableResourceId; /** * A bitmap to be utilized instead of #itemDrawableResourceId */ public Bitmap itemBitmapResource; /** * The title of the item */ public String itemTitle; /** * The summary associated with the item, may be null */ public String itemSummary = null; private ExpandedItem() { // Don't want to have this baseclass be instantiable } /** * @hide */ protected void internalSetItemDrawable(int resourceId) { itemDrawableResourceId = resourceId; } /** * @hide */ protected void internalSetItemBitmap(Bitmap bitmap) { itemBitmapResource = bitmap; } /** * @hide */ protected void internalSetItemSummary(String resourceId) { itemSummary = resourceId; } /** * @hide */ protected void internalSetItemTitle(String title) { itemTitle = title; } /** * @hide */ protected void internalSetOnClickPendingIntent(PendingIntent pendingIntent) { onClickPendingIntent = pendingIntent; } /** * Unflatten the ExpandedItem from a parcel. */ protected ExpandedItem(Parcel parcel) { // Read parcelable version via the Concierge ParcelInfo parcelInfo = Concierge.receiveParcel(parcel); int parcelableVersion = parcelInfo.getParcelVersion(); // Pattern here is that all new members should be added to the end of // the writeToParcel method. Then we step through each version, until the latest // API release to help unravel this parcel if (parcelableVersion >= Build.CM_VERSION_CODES.APRICOT) { if (parcel.readInt() != 0) { onClickPendingIntent = PendingIntent.CREATOR.createFromParcel(parcel); } if (parcel.readInt() != 0) { itemTitle = parcel.readString(); } if (parcel.readInt() != 0) { itemSummary = parcel.readString(); } itemDrawableResourceId = parcel.readInt(); } if (parcelableVersion >= Build.CM_VERSION_CODES.BOYSENBERRY) { if (parcel.readInt() != 0) { itemBitmapResource = Bitmap.CREATOR.createFromParcel(parcel); } } // Complete parcel info for the concierge parcelInfo.complete(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { // Tell the concierge to prepare the parcel ParcelInfo parcelInfo = Concierge.prepareParcel(out); // ==== APRICOT ==== if (onClickPendingIntent != null) { out.writeInt(1); onClickPendingIntent.writeToParcel(out, 0); } else { out.writeInt(0); } if (!TextUtils.isEmpty(itemTitle)) { out.writeInt(1); out.writeString(itemTitle); } else { out.writeInt(0); } if (!TextUtils.isEmpty(itemSummary)) { out.writeInt(1); out.writeString(itemSummary); } else { out.writeInt(0); } out.writeInt(itemDrawableResourceId); // ==== BOYSENBERRY ==== if (itemBitmapResource != null) { out.writeInt(1); itemBitmapResource.writeToParcel(out, 0); } else { out.writeInt(0); } // Complete the parcel info for the concierge parcelInfo.complete(); } @Override public String toString() { StringBuilder b = new StringBuilder(); String NEW_LINE = System.getProperty("line.separator"); if (onClickPendingIntent != null) { b.append("onClickPendingIntent= " + onClickPendingIntent.toString() + NEW_LINE); } if (itemTitle != null) { b.append("itemTitle= " + itemTitle.toString() + NEW_LINE); } if (itemSummary != null) { b.append("itemSummary= " + itemSummary.toString() + NEW_LINE); } b.append("itemDrawableResourceId=" + itemDrawableResourceId + NEW_LINE); if (itemBitmapResource != null) { b.append("itemBitmapResource=" + itemBitmapResource.getGenerationId() + NEW_LINE); } return b.toString(); } public static final Creator CREATOR = new Creator() { @Override public ExpandedItem createFromParcel(Parcel in) { return new ExpandedItem(in); } @Override public ExpandedItem[] newArray(int size) { return new ExpandedItem[size]; } }; } /** * An instance of {@link ExpandedItem} to be utilized within a {@link GridExpandedStyle} */ public static class ExpandedGridItem extends ExpandedItem { /** * Constructor for the ExpandedGridItem */ public ExpandedGridItem() { } /** * Sets the title for the {@link ExpandedGridItem} * @param title a string title */ public void setExpandedGridItemTitle(String title) { internalSetItemTitle(title); } /** * Sets the {@link PendingIntent} associated with the {@link ExpandedGridItem} * @param intent a pending intent to be triggered on click */ public void setExpandedGridItemOnClickIntent(PendingIntent intent) { internalSetOnClickPendingIntent(intent); } /** * Sets the drawable resource id associated with the {@link ExpandedGridItem} * @param resourceId a resource id that maps to a drawable */ public void setExpandedGridItemDrawable(int resourceId) { internalSetItemDrawable(resourceId); } /** * Sets the bitmap associated with the {@link ExpandedGridItem} to be utilized instead of * the {@link ExpandedItem#itemDrawableResourceId} * * Note, sending many items with bitmaps over IPC may result in a * TransactionTooLargeException. * @param bitmap */ public void setExpandedGridItemBitmap(Bitmap bitmap) { internalSetItemBitmap(bitmap); } } /** * An instance of {@link ExpandedItem} to be utilized within a {@link ListExpandedStyle} */ public static class ExpandedListItem extends ExpandedItem { /** * Constructor fot the ExpandedListItem */ public ExpandedListItem() { } /** * Sets the title for the {@link ExpandedListItem} * @param title a string title */ public void setExpandedListItemTitle(String title) { internalSetItemTitle(title); } /** * Sets the title for the {@link ExpandedListItem} * @param summary a string summary */ public void setExpandedListItemSummary(String summary) { internalSetItemSummary(summary); } /** * Sets the {@link PendingIntent} associated with the {@link ExpandedListItem} * @param intent a pending intent to be triggered on click */ public void setExpandedListItemOnClickIntent(PendingIntent intent) { internalSetOnClickPendingIntent(intent); } /** * Sets the drawable resource id associated with the {@link ExpandedListItem} * @param resourceId a resource id that maps to a drawable */ public void setExpandedListItemDrawable(int resourceId) { internalSetItemDrawable(resourceId); } /** * Sets the bitmap associated with the {@link ExpandedListItem} to be utilized instead of * the {@link ExpandedItem#itemDrawableResourceId} * * Note, sending many items with bitmaps over IPC may result in a * TransactionTooLargeException. * @param bitmap */ public void setExpandedListItemBitmap(Bitmap bitmap) { internalSetItemBitmap(bitmap); } } /** * Parcelable.Creator that instantiates CustomTile objects */ public static final Creator CREATOR = new Creator() { public CustomTile createFromParcel(Parcel in) { return new CustomTile(in); } @Override public CustomTile[] newArray(int size) { return new CustomTile[size]; } }; /** * Builder class for {@link cyanogenmod.app.CustomTile} objects. * * Provides a convenient way to set the various fields of a {@link cyanogenmod.app.CustomTile} * *

Example: * *

     * CustomTile customTile = new CustomTile.Builder(mContext)
     *         .setLabel("custom label")
     *         .setContentDescription("custom description")
     *         .setOnClickIntent(pendingIntent)
     *         .setOnSettingsClickIntent(intent)
     *         .setOnClickUri(Uri.parse("custom uri"))
     *         .setIcon(R.drawable.ic_launcher)
     *         .build();
     * 
*/ public static class Builder { private PendingIntent mOnClick; private PendingIntent mOnLongClick; private Intent mOnSettingsClick; private Uri mOnClickUri; private String mLabel; private String mContentDescription; private int mIcon; private Bitmap mRemoteIcon; private Context mContext; private ExpandedStyle mExpandedStyle; private boolean mCollapsePanel = true; private PendingIntent mDeleteIntent; private boolean mSensitiveData = false; /** * Constructs a new Builder with the defaults: */ public Builder(Context context) { mContext = context; } /** * Set the label for the custom tile * @param label a string to be used for the custom tile label * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder setLabel(String label) { mLabel = label; return this; } /** * Set the label for the custom tile * @param id a string resource id to be used for the custom tile label * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder setLabel(int id) { mLabel = mContext.getString(id); return this; } /** * Set the content description for the custom tile * @param contentDescription a string to explain content * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder setContentDescription(String contentDescription) { mContentDescription = contentDescription; return this; } /** * Set the content description for the custom tile * @param id a string resource id to explain content * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder setContentDescription(int id) { mContentDescription = mContext.getString(id); return this; } /** * Set a {@link android.app.PendingIntent} to be fired on custom tile click * @param intent * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder setOnClickIntent(PendingIntent intent) { mOnClick = intent; return this; } /** * Set a {@link android.app.PendingIntent} to be fired on custom tile long press. * Note: if this is an activity, the host panel will automatically collapse. * @param intent * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder setOnLongClickIntent(PendingIntent intent) { mOnLongClick = intent; return this; } /** * Set a settings {@link android.content.Intent} to be fired on custom * tile detail pane click * @param intent * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder setOnSettingsClickIntent(Intent intent) { mOnSettingsClick = intent; return this; } /** * Set a {@link android.net.Uri} to be broadcasted in an intent on custom tile click * @param uri * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder setOnClickUri(Uri uri) { mOnClickUri = uri; return this; } /** * Set an icon for the custom tile to be presented to the user * * @param drawableId * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder setIcon(int drawableId) { mIcon = drawableId; return this; } /** * Set a bitmap icon to the custom tile to be utilized instead of {@link CustomTile#icon} * * This will unset {@link #setIcon(int)} if utilized together. * @see CustomTile#remoteIcon * @param remoteIcon * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder setIcon(Bitmap remoteIcon) { mIcon = 0; // empty mRemoteIcon = remoteIcon; return this; } /** * Set an {@link ExpandedStyle} to to be displayed when a user clicks the custom tile * @param expandedStyle * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder setExpandedStyle(ExpandedStyle expandedStyle) { if (mExpandedStyle != expandedStyle) { mExpandedStyle = expandedStyle; if (mExpandedStyle != null) { expandedStyle.setBuilder(this); } } return this; } /** * Set whether or not the Statusbar Panel should be collapsed when an * {@link #onClick} or {@link #onClickUri} event is fired. * @param bool * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder shouldCollapsePanel(boolean bool) { mCollapsePanel = bool; return this; } /** * Supply a {@link PendingIntent} to send when the custom tile is cleared explicitly * by the user. * * @see CustomTile#deleteIntent * @param intent * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder setDeleteIntent(PendingIntent intent) { mDeleteIntent = intent; return this; } /** * Indicates whether this tile has sensitive data that have to be hidden * on secure lockscreens. * @param bool * @return {@link cyanogenmod.app.CustomTile.Builder} */ public Builder hasSensitiveData(boolean bool) { mSensitiveData = bool; return this; } /** * Create a {@link cyanogenmod.app.CustomTile} object * @return {@link cyanogenmod.app.CustomTile} */ public CustomTile build() { CustomTile tile = new CustomTile(); tile.resourcesPackageName = mContext.getPackageName(); tile.onClick = mOnClick; tile.onLongClick = mOnLongClick; tile.onSettingsClick = mOnSettingsClick; tile.onClickUri = mOnClickUri; tile.label = mLabel; tile.contentDescription = mContentDescription; tile.expandedStyle = mExpandedStyle; tile.icon = mIcon; tile.collapsePanel = mCollapsePanel; tile.remoteIcon = mRemoteIcon; tile.deleteIntent = mDeleteIntent; tile.sensitiveData = mSensitiveData; return tile; } } }