From d878376c09d6cf65b0af051dd4241deab66bbf3d Mon Sep 17 00:00:00 2001 From: Justin Koh Date: Wed, 27 Feb 2013 15:31:29 -0800 Subject: Updated Gallery2 with Pano. Updated Gallery2 with Pano. Bug: 8263808 Change-Id: Iedaba9dc478fb20480f3b37e9708bc8d67cf6003 --- src/com/android/photos/canvas/CanvasActivity.java | 4 +- src/com/android/photos/canvas/CanvasProvider.java | 6 +- .../android/photos/canvas/CanvasProviderBase.java | 62 +- src/com/google/android/canvas/data/Cluster.java | 195 ---- .../google/android/canvas/data/util/UriUtils.java | 124 --- .../android/canvas/provider/CanvasContract.java | 895 ---------------- src/com/google/android/pano/data/Cluster.java | 309 ++++++ .../google/android/pano/data/util/UriUtils.java | 134 +++ .../google/android/pano/provider/PanoContract.java | 1087 ++++++++++++++++++++ 9 files changed, 1566 insertions(+), 1250 deletions(-) delete mode 100644 src/com/google/android/canvas/data/Cluster.java delete mode 100644 src/com/google/android/canvas/data/util/UriUtils.java delete mode 100644 src/com/google/android/canvas/provider/CanvasContract.java create mode 100644 src/com/google/android/pano/data/Cluster.java create mode 100644 src/com/google/android/pano/data/util/UriUtils.java create mode 100644 src/com/google/android/pano/provider/PanoContract.java (limited to 'src/com') diff --git a/src/com/android/photos/canvas/CanvasActivity.java b/src/com/android/photos/canvas/CanvasActivity.java index 17afdb8b4..ad3cb638b 100644 --- a/src/com/android/photos/canvas/CanvasActivity.java +++ b/src/com/android/photos/canvas/CanvasActivity.java @@ -20,14 +20,14 @@ import android.app.Activity; import android.content.Intent; import android.os.Bundle; -import com.google.android.canvas.provider.CanvasContract; +import com.google.android.pano.provider.PanoContract; public class CanvasActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Intent intent = CanvasContract.getBrowseIntent( + Intent intent = PanoContract.getBrowseIntent( CanvasProvider.BROWSER_ROOT_URI, 0); startActivity(intent); finish(); diff --git a/src/com/android/photos/canvas/CanvasProvider.java b/src/com/android/photos/canvas/CanvasProvider.java index 1ed6cd461..1bc55669a 100644 --- a/src/com/android/photos/canvas/CanvasProvider.java +++ b/src/com/android/photos/canvas/CanvasProvider.java @@ -42,8 +42,8 @@ import com.android.gallery3d.util.Future; import com.android.gallery3d.util.ThreadPool.CancelListener; import com.android.gallery3d.util.ThreadPool.Job; import com.android.gallery3d.util.ThreadPool.JobContext; -import com.google.android.canvas.data.Cluster; -import com.google.android.canvas.provider.CanvasContract; +import com.google.android.pano.data.Cluster; +import com.google.android.pano.provider.PanoContract; import java.io.FileNotFoundException; import java.io.IOException; @@ -142,7 +142,7 @@ public class CanvasProvider extends CanvasProviderBase { Cluster.Builder bob = new Cluster.Builder(); bob.id(i); bob.displayName(set.getName()); - Intent intent = CanvasContract.getBrowseIntent(BROWSER_ROOT_URI, i); + Intent intent = PanoContract.getBrowseIntent(BROWSER_ROOT_URI, i); bob.intent(intent); bob.imageCropAllowed(true); bob.cacheTimeMs(CACHE_TIME_MS); diff --git a/src/com/android/photos/canvas/CanvasProviderBase.java b/src/com/android/photos/canvas/CanvasProviderBase.java index 4438c5398..a38aae5ce 100644 --- a/src/com/android/photos/canvas/CanvasProviderBase.java +++ b/src/com/android/photos/canvas/CanvasProviderBase.java @@ -26,8 +26,8 @@ import android.net.Uri; import android.os.Binder; import android.provider.BaseColumns; -import com.google.android.canvas.data.Cluster; -import com.google.android.canvas.provider.CanvasContract; +import com.google.android.pano.data.Cluster; +import com.google.android.pano.provider.PanoContract; import java.util.ArrayList; import java.util.HashMap; @@ -45,10 +45,10 @@ public abstract class CanvasProviderBase extends ContentProvider { protected static final String PATH_IMAGE = "image"; protected static final String PATH_LAUNCHER = "launcher"; protected static final String PATH_LAUNCHER_ITEM = PATH_LAUNCHER + "/" - + CanvasContract.PATH_LAUNCHER_ITEM; + + PanoContract.PATH_LAUNCHER_ITEM; protected static final String PATH_BROWSE = "browse"; protected static final String PATH_BROWSE_HEADERS = PATH_BROWSE + "/" - + CanvasContract.PATH_BROWSE_HEADERS; + + PanoContract.PATH_BROWSE_HEADERS; public static final Uri BROWSER_ROOT_URI = Uri.parse("content://" + AUTHORITY + "/" + PATH_BROWSE); @@ -91,19 +91,19 @@ public abstract class CanvasProviderBase extends ContentProvider { static { LAUNCHER_COLUMN_CASES.put(BaseColumns._ID, LAUNCHER_CASE_ID); LAUNCHER_COLUMN_CASES.put(BaseColumns._COUNT, LAUNCHER_CASE_COUNT); - LAUNCHER_COLUMN_CASES.put(CanvasContract.Launcher.NAME, + LAUNCHER_COLUMN_CASES.put(PanoContract.Launcher.NAME, LAUNCHER_CASE_NAME); - LAUNCHER_COLUMN_CASES.put(CanvasContract.Launcher.IMPORTANCE, + LAUNCHER_COLUMN_CASES.put(PanoContract.Launcher.IMPORTANCE, LAUNCHER_CASE_IMPORTANCE); - LAUNCHER_COLUMN_CASES.put(CanvasContract.Launcher.DISPLAY_NAME, + LAUNCHER_COLUMN_CASES.put(PanoContract.Launcher.DISPLAY_NAME, LAUNCHER_CASE_DISPLAY_NAME); - LAUNCHER_COLUMN_CASES.put(CanvasContract.Launcher.VISIBLE_COUNT, + LAUNCHER_COLUMN_CASES.put(PanoContract.Launcher.VISIBLE_COUNT, LAUNCHER_CASE_VISIBLE_COUNT); - LAUNCHER_COLUMN_CASES.put(CanvasContract.Launcher.IMAGE_CROP_ALLOWED, + LAUNCHER_COLUMN_CASES.put(PanoContract.Launcher.IMAGE_CROP_ALLOWED, LAUNCHER_CASE_CROP_ALLOWED); - LAUNCHER_COLUMN_CASES.put(CanvasContract.Launcher.CACHE_TIME_MS, + LAUNCHER_COLUMN_CASES.put(PanoContract.Launcher.CACHE_TIME_MS, LAUNCHER_CASE_CACHE_TIME); - LAUNCHER_COLUMN_CASES.put(CanvasContract.Launcher.INTENT_URI, + LAUNCHER_COLUMN_CASES.put(PanoContract.Launcher.INTENT_URI, LAUNCHER_CASE_INTENT_URI); LAUNCHER_PROJECTION_ALL = LAUNCHER_COLUMN_CASES.keySet().toArray( @@ -120,9 +120,9 @@ public abstract class CanvasProviderBase extends ContentProvider { static { CLUSTER_COLUMN_CASES.put(BaseColumns._ID, CLUSTER_CASE_ID); CLUSTER_COLUMN_CASES.put(BaseColumns._COUNT, CLUSTER_CASE_COUNT); - CLUSTER_COLUMN_CASES.put(CanvasContract.LauncherItem.PARENT_ID, + CLUSTER_COLUMN_CASES.put(PanoContract.LauncherItem.PARENT_ID, CLUSTER_CASE_PARENT_ID); - CLUSTER_COLUMN_CASES.put(CanvasContract.LauncherItem.IMAGE_URI, + CLUSTER_COLUMN_CASES.put(PanoContract.LauncherItem.IMAGE_URI, CLUSTER_CASE_IMAGE_URI); CLUSTER_PROJECTION_ALL = CLUSTER_COLUMN_CASES.keySet().toArray( @@ -149,33 +149,33 @@ public abstract class CanvasProviderBase extends ContentProvider { BROWSE_HEADER_COLUMN_CASES.put(BaseColumns._ID, BROWSE_HEADER_CASE_ID); BROWSE_HEADER_COLUMN_CASES.put(BaseColumns._COUNT, BROWSE_HEADER_CASE_COUNT); - BROWSE_HEADER_COLUMN_CASES.put(CanvasContract.BrowseHeaders.NAME, + BROWSE_HEADER_COLUMN_CASES.put(PanoContract.BrowseHeaders.NAME, BROWSE_HEADER_CASE_NAME); BROWSE_HEADER_COLUMN_CASES.put( - CanvasContract.BrowseHeaders.DISPLAY_NAME, + PanoContract.BrowseHeaders.DISPLAY_NAME, BROWSE_HEADER_CASE_DISPLAY_NAME); - BROWSE_HEADER_COLUMN_CASES.put(CanvasContract.BrowseHeaders.ICON_URI, + BROWSE_HEADER_COLUMN_CASES.put(PanoContract.BrowseHeaders.ICON_URI, BROWSE_HEADER_CASE_ICON_URI); - BROWSE_HEADER_COLUMN_CASES.put(CanvasContract.BrowseHeaders.BADGE_URI, + BROWSE_HEADER_COLUMN_CASES.put(PanoContract.BrowseHeaders.BADGE_URI, BROWSE_HEADER_CASE_BADGE_URI); - BROWSE_HEADER_COLUMN_CASES.put(CanvasContract.BrowseHeaders.COLOR_HINT, + BROWSE_HEADER_COLUMN_CASES.put(PanoContract.BrowseHeaders.COLOR_HINT, BROWSE_HEADER_CASE_COLOR_HINT); BROWSE_HEADER_COLUMN_CASES.put( - CanvasContract.BrowseHeaders.TEXT_COLOR_HINT, + PanoContract.BrowseHeaders.TEXT_COLOR_HINT, BROWSE_HEADER_CASE_TEXT_COLOR_HINT); BROWSE_HEADER_COLUMN_CASES.put( - CanvasContract.BrowseHeaders.BG_IMAGE_URI, + PanoContract.BrowseHeaders.BG_IMAGE_URI, BROWSE_HEADER_CASE_BG_IMAGE_URI); BROWSE_HEADER_COLUMN_CASES.put( - CanvasContract.BrowseHeaders.EXPAND_GROUP, + PanoContract.BrowseHeaders.EXPAND_GROUP, BROWSE_HEADER_CASE_EXPAND_GROUP); - BROWSE_HEADER_COLUMN_CASES.put(CanvasContract.BrowseHeaders.WRAP_ITEMS, + BROWSE_HEADER_COLUMN_CASES.put(PanoContract.BrowseHeaders.WRAP_ITEMS, BROWSE_HEADER_CASE_WRAP); BROWSE_HEADER_COLUMN_CASES.put( - CanvasContract.BrowseHeaders.DEFAULT_ITEM_WIDTH, + PanoContract.BrowseHeaders.DEFAULT_ITEM_WIDTH, BROWSE_HEADER_CASE_DEFAULT_ITEM_WIDTH); BROWSE_HEADER_COLUMN_CASES.put( - CanvasContract.BrowseHeaders.DEFAULT_ITEM_HEIGHT, + PanoContract.BrowseHeaders.DEFAULT_ITEM_HEIGHT, BROWSE_HEADER_CASE_DEFAULT_ITEM_HEIGHT); BROWSE_HEADER_PROJECTION_ALL = BROWSE_HEADER_COLUMN_CASES.keySet() @@ -197,19 +197,19 @@ public abstract class CanvasProviderBase extends ContentProvider { static { BROWSE_COLUMN_CASES.put(BaseColumns._ID, BROWSE_CASE_ID); BROWSE_COLUMN_CASES.put(BaseColumns._COUNT, BROWSE_CASE_COUNT); - BROWSE_COLUMN_CASES.put(CanvasContract.BrowseItems.PARENT_ID, + BROWSE_COLUMN_CASES.put(PanoContract.BrowseItems.PARENT_ID, BROWSE_CASE_PARENT_ID); - BROWSE_COLUMN_CASES.put(CanvasContract.BrowseItems.DISPLAY_NAME, + BROWSE_COLUMN_CASES.put(PanoContract.BrowseItems.DISPLAY_NAME, BROWSE_CASE_DISPLAY_NAME); - BROWSE_COLUMN_CASES.put(CanvasContract.BrowseItems.DISPLAY_DESCRIPTION, + BROWSE_COLUMN_CASES.put(PanoContract.BrowseItems.DISPLAY_DESCRIPTION, BROWSE_CASE_DISPLAY_DESCRIPTION); - BROWSE_COLUMN_CASES.put(CanvasContract.BrowseItems.IMAGE_URI, + BROWSE_COLUMN_CASES.put(PanoContract.BrowseItems.IMAGE_URI, BROWSE_CASE_IMAGE_URI); - BROWSE_COLUMN_CASES.put(CanvasContract.BrowseItems.WIDTH, + BROWSE_COLUMN_CASES.put(PanoContract.BrowseItems.WIDTH, BROWSE_CASE_WIDTH); - BROWSE_COLUMN_CASES.put(CanvasContract.BrowseItems.HEIGHT, + BROWSE_COLUMN_CASES.put(PanoContract.BrowseItems.HEIGHT, BROWSE_CASE_HEIGHT); - BROWSE_COLUMN_CASES.put(CanvasContract.BrowseItems.INTENT_URI, + BROWSE_COLUMN_CASES.put(PanoContract.BrowseItems.INTENT_URI, BROWSE_CASE_INTENT_URI); BROWSE_PROJECTION_ALL = BROWSE_COLUMN_CASES.keySet().toArray( diff --git a/src/com/google/android/canvas/data/Cluster.java b/src/com/google/android/canvas/data/Cluster.java deleted file mode 100644 index ab6aaedcc..000000000 --- a/src/com/google/android/canvas/data/Cluster.java +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. - -package com.google.android.canvas.data; - -import android.content.Intent; -import android.net.Uri; - -import java.util.ArrayList; -import java.util.List; - -/** - * Represents a home screen cluster. - */ -public class Cluster { - - private long mId; - private String mName; - private CharSequence mDisplayName; - private int mImportance; - private int mVisibleCount; - private boolean mImageCropAllowed; - private long mCacheTimeMs; - private Intent mIntent; - - private List mClusterItems; - - /** - * An item displayed inside a cluster. - */ - public static class ClusterItem { - private Uri mImageUri; - - ClusterItem(Uri imageUri) { - mImageUri = imageUri; - } - - public Uri getImageUri() { - return mImageUri; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("imageUri: ").append(mImageUri); - return builder.toString(); - } - } - - public Cluster() { - mClusterItems = new ArrayList(); - mImageCropAllowed = true; - } - - public long getId() { - return mId; - } - - public String getName() { - return mName; - } - - public CharSequence getDisplayName() { - return mDisplayName; - } - - public int getImportance() { - return mImportance; - } - - public int getVisibleCount() { - return mVisibleCount; - } - - public boolean isImageCropAllowed() { - return mImageCropAllowed; - } - - public long getCacheTimeMs() { - return mCacheTimeMs; - } - - public Intent getIntent() { - return mIntent; - } - - public int getItemCount() { - return mClusterItems.size(); - } - - public ClusterItem getItem(int position) { - if (position >= 0 && position < mClusterItems.size()) { - return mClusterItems.get(position); - } - return null; - } - - void addClusterItem(ClusterItem item) { - mClusterItems.add(item); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("id: ").append(mId) - .append(", name: ").append(mName) - .append(", displayName: ").append(mDisplayName) - .append(", importance: ").append(mImportance) - .append(", visibleCount: ").append(mVisibleCount) - .append(", imageCropAllowed: ").append(mImageCropAllowed) - .append(", cacheTimeMs: ").append(mCacheTimeMs) - .append(", intent: ").append(mIntent.toUri(0)); - return builder.toString(); - } - - /** - * Builds cluster objects. - */ - public static class Builder { - private long mId; - private String mName; - private CharSequence mDisplayName; - private int mImportance; - private int mVisibleCount; - private boolean mImageCropAllowed; - private long mCacheTimeMs; - private Intent mIntent; - - private List mClusterItems; - - public Cluster build() { - Cluster cluster = new Cluster(); - cluster.mId = mId; - cluster.mName = mName; - cluster.mDisplayName = mDisplayName; - cluster.mImportance = mImportance; - cluster.mVisibleCount = mVisibleCount; - cluster.mImageCropAllowed = mImageCropAllowed; - cluster.mIntent = mIntent; - cluster.mCacheTimeMs = mCacheTimeMs; - cluster.mClusterItems.addAll(mClusterItems); - return cluster; - } - - public Builder() { - mClusterItems = new ArrayList(); - mImageCropAllowed = true; - } - - public Builder id(long id) { - mId = id; - return this; - } - - public Builder name(String name) { - mName = name; - return this; - } - - public Builder displayName(CharSequence displayName) { - mDisplayName = displayName; - return this; - } - - public Builder importance(int importance) { - mImportance = importance; - return this; - } - - public Builder visibleCount(int visibleCount) { - mVisibleCount = visibleCount; - return this; - } - - public Builder imageCropAllowed(boolean allowed) { - mImageCropAllowed = allowed; - return this; - } - - public Builder cacheTimeMs(long cacheTimeMs) { - mCacheTimeMs = cacheTimeMs; - return this; - } - - public Builder intent(Intent intent) { - mIntent = intent; - return this; - } - - public Builder addItem(Uri imageUri) { - ClusterItem item = new ClusterItem(imageUri); - mClusterItems.add(item); - return this; - } - } -} diff --git a/src/com/google/android/canvas/data/util/UriUtils.java b/src/com/google/android/canvas/data/util/UriUtils.java deleted file mode 100644 index 7b7b73cb5..000000000 --- a/src/com/google/android/canvas/data/util/UriUtils.java +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. - -package com.google.android.canvas.data.util; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent.ShortcutIconResource; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import android.net.Uri; - -/** - * Utilities for working with URIs. - */ -public final class UriUtils { - - private static final String SCHEME_SHORTCUT_ICON_RESOURCE = "shortcut.icon.resource"; - private static final String SCHEME_DELIMITER = "://"; - private static final String URI_PATH_DELIMITER = "/"; - private static final String URI_PACKAGE_DELIMITER = ":"; - private static final String HTTP_PREFIX = "http"; - private static final String HTTPS_PREFIX = "https"; - - /** - * Non instantiable. - */ - private UriUtils() {} - - /** - * get resource uri representation for a resource of a package - */ - public static String getAndroidResourceUri(Context context, int resourceId) { - return getAndroidResourceUri(context.getResources(), resourceId); - } - - /** - * get resource uri representation for a resource - */ - public static String getAndroidResourceUri(Resources resources, int resourceId) { - return ContentResolver.SCHEME_ANDROID_RESOURCE - + SCHEME_DELIMITER + resources.getResourceName(resourceId) - .replace(URI_PACKAGE_DELIMITER, URI_PATH_DELIMITER); - } - - /** - * load drawable from resource - * TODO: move to a separate class to handle bitmap and drawables - */ - public static Drawable getDrawable(Context context, ShortcutIconResource r) - throws NameNotFoundException { - Resources resources = context.getPackageManager().getResourcesForApplication(r.packageName); - if (resources == null) { - return null; - } - final int id = resources.getIdentifier(r.resourceName, null, null); - return resources.getDrawable(id); - } - - /** - * Gets a URI with short cut icon scheme. - */ - public static Uri getShortcutIconResourceUri(ShortcutIconResource iconResource) { - return Uri.parse(SCHEME_SHORTCUT_ICON_RESOURCE + SCHEME_DELIMITER + iconResource.packageName - + URI_PATH_DELIMITER - + iconResource.resourceName.replace(URI_PACKAGE_DELIMITER, URI_PATH_DELIMITER)); - } - - /** - * Gets a URI with scheme = {@link ContentResolver#SCHEME_ANDROID_RESOURCE}. - */ - public static Uri getAndroidResourceUri(String resourceName) { - Uri uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + SCHEME_DELIMITER - + resourceName.replace(URI_PACKAGE_DELIMITER, URI_PATH_DELIMITER)); - return uri; - } - - /** - * Checks if the URI refers to an Android resource. - */ - public static boolean isAndroidResourceUri(Uri uri) { - return ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme()); - } - - /** - * Checks if the URI refers to an shortcut icon resource. - */ - public static boolean isShortcutIconResourceUri(Uri uri) { - return SCHEME_SHORTCUT_ICON_RESOURCE.equals(uri.getScheme()); - } - - /** - * Creates a shortcut icon resource object from an Android resource URI. - */ - public static ShortcutIconResource getIconResource(Uri uri) { - if(isAndroidResourceUri(uri)) { - ShortcutIconResource iconResource = new ShortcutIconResource(); - iconResource.packageName = uri.getAuthority(); - // Trim off the scheme + 3 extra for "://", then replace the first "/" with a ":" - iconResource.resourceName = uri.toString().substring( - ContentResolver.SCHEME_ANDROID_RESOURCE.length() + SCHEME_DELIMITER.length()) - .replaceFirst(URI_PATH_DELIMITER, URI_PACKAGE_DELIMITER); - return iconResource; - } else if(isShortcutIconResourceUri(uri)) { - ShortcutIconResource iconResource = new ShortcutIconResource(); - iconResource.packageName = uri.getAuthority(); - iconResource.resourceName = uri.toString().substring( - SCHEME_SHORTCUT_ICON_RESOURCE.length() + SCHEME_DELIMITER.length() - + iconResource.packageName.length() + URI_PATH_DELIMITER.length()) - .replaceFirst(URI_PATH_DELIMITER, URI_PACKAGE_DELIMITER); - return iconResource; - } else { - throw new IllegalArgumentException("Invalid resource URI. " + uri); - } - } - - /** - * Returns {@code true} if this is a web URI. - */ - public static boolean isWebUri(Uri resourceUri) { - String scheme = resourceUri.getScheme().toLowerCase(); - return HTTP_PREFIX.equals(scheme) || HTTPS_PREFIX.equals(scheme); - } -} diff --git a/src/com/google/android/canvas/provider/CanvasContract.java b/src/com/google/android/canvas/provider/CanvasContract.java deleted file mode 100644 index f6a1741c4..000000000 --- a/src/com/google/android/canvas/provider/CanvasContract.java +++ /dev/null @@ -1,895 +0,0 @@ -package com.google.android.canvas.provider; - -import android.content.ContentUris; -import android.content.Intent; -import android.net.Uri; -import android.provider.BaseColumns; - -/** - * The contract between Canvas and ContentProviders that allow access to Canvas - * browsing data. All apps that wish to interact with Canvas should use these - * definitions. - * - * TODO add more details - */ -public final class CanvasContract { - - // Base for content uris - public static final String CONTENT = "content://"; - /** - * Path to items within a single cluster in the launcher. This can be used - * when setting up a UriMatcher. Queries will use the form - * content:////<#> where the # is the _id of the cluster - * being queried - */ - public static final String PATH_LAUNCHER_ITEM = "items"; - /** - * Path to the header meta-data. This can be used when setting up a - * UriMatcher. Queries will use the form content:/// - */ - public static final String PATH_BROWSE_HEADERS = "headers"; - - /** - * This tag is used to identify the authority to be used for a canvas - * launcher app. - * - * TODO: this is obsolete: remove. - */ - public static final String METADATA_TAG = "com.google.android.canvas.data.launcher"; - - /** - * This tag is used to identify the launcher info data file to be used for a canvas - * launcher app. - */ - public static final String METADATA_LAUNCHER_INFO_TAG = - "com.google.android.canvas.data.launcher_info"; - - /** - * This tag is used to denote a background color hint for the activity. - *

- * This can either be a reference to an @color or else a string (e.g. #ff001100). - * - * TODO: this is obsolete: remove. - */ - public static final String METADATA_COLOR_HINT = - "com.google.android.canvas.ui.launcher_color_hint"; - - /** - * An intent action for browsing app content in Canvas. Apps receiving this - * intent should call {@link Intent#getData()} to retrieve the base Uri and - * {@link #EXTRA_START_INDEX} or {@link #EXTRA_START_ID} to find which header - * to start at (default 0). - */ - public static final String ACTION_BROWSE = "com.google.android.canvas.action.BROWSE"; - - /** - * The index of the header to focus on initially when the browse is launched. - * This extra is optional and defaults to 0. If {@link #EXTRA_START_ID} is present - * this value will not be used. - */ - public static final String EXTRA_START_INDEX = "start_index"; - - /** - * The _id of the header to focus on initially when the browse is launched. - * This extra is optional and {@link #EXTRA_START_ID} is used by default. - */ - public static final String EXTRA_START_ID = "start_id"; - - /** - * An intent action for viewing detail content in Canvas. Apps receiving this - * intent should call {@link Intent#getData()} to retrieve the base Uri. - */ - public static final String ACTION_DETAIL = "com.google.android.canvas.action.DETAIL"; - - /** - * Path for querying details for an item. - */ - public static final String PATH_DETAIL_ITEM = "details"; - - /** - * Path for querying sections for a detail item. This can be used when setting up a - * UriMatcher. Queries will use the form content:///details//sections. - */ - public static final String PATH_DETAIL_SECTIONS = "sections"; - - /** - * Path for querying detail actions. This can be used when setting up a UriMatcher. Queries will - * use the form content:///details//actions. - */ - public static final String PATH_DETAIL_ACTIONS = "actions"; - - /** - * Action for searching a Canvas provider. Apps receiving this - * intent should call {@link Intent#getData()} to retrieve the base Uri and - * {@link #EXTRA_QUERY} to find query. - */ - public static final String ACTION_SEARCH = "com.google.android.canvas.action.SEARCH"; - - /** - * The query to be executed when search activity is launched - * This extra is optional and defaults to null. - */ - public static final String EXTRA_QUERY = "query"; - - /** - * Optional int extra for setting the display mode of the search activity. - * - * @see #DISPLAY_MODE_ROW - * @see #DISPLAY_MODE_GRID - */ - public static final String EXTRA_DISPLAY_MODE = "display_mode"; - - public static final int DISPLAY_MODE_ROW = 0; - public static final int DISPLAY_MODE_GRID = 1; - - /** - * Value for the root Canvas URI when this activity should be excluded from the Canvas top level - * and the legacy apps area. - * - * TODO: this is obsolete: remove. - */ - public static final String EXCLUDED_ROOT_URI = "excluded"; - - protected interface LauncherColumns { - - /** - * The name of the cluster. Generally used for debugging and not shown - * to the user. - * - *

Type: String

- */ - public static final String NAME = "name"; - - /** - * An optional name to display with the cluster. This value will be user - * visible. Example: "Recently Watched" - * - *

Type: String

- */ - public static final String DISPLAY_NAME = "display_name"; - - /** - * How important this cluster is. The higher the value the more important - * it will be relative to other clusters. The importance is a relative - * weighting and not an absolute priority. If this value is left blank - * it will default to 0 (not important). - * - *

Type: INTEGER

- */ - public static final String IMPORTANCE = "importance"; - - /** - * The number of items that should be shown in this cluster. If this - * value is more than there is space for fewer items may be shown. - * - *

Type: INTEGER

- */ - public static final String VISIBLE_COUNT = "visible_count"; - - /** - * Whether or not the image may be cropped to fit the display area - * better. 1 means cropping is allowed, 0 means the item should be - * shrunk or stretched to fit instead. - * - *

Type: INTEGER (0 or 1)

- */ - public static final String IMAGE_CROP_ALLOWED = "image_crop_allowed"; - - /** - * The amount of time it is safe to assume the data for this - * cluster will remain valid. For example, if this cluster is - * advertising a daily special this should return the time until the - * special ends. A best effort will be made to not display data past - * this point but some data may not be requeried immediately. - * - *

Type: INTEGER (long)

- */ - public static final String CACHE_TIME_MS = "cache_time_ms"; - - /** - * A standard Intent Uri to be launched when this cluster is selected. - * This may be a {@link CanvasContract#ACTION_BROWSE} intent or an - * intent to launch directly into an app. You can also use - * {@link CanvasContract#getBrowseIntent(Uri, int)} to generate a - * browse intent for a given root Uri. Use {@link Intent#toUri(int)} - * with a flag of {@link Intent#URI_INTENT_SCHEME}. - * - *

Type: String (Uri)

- */ - public static final String INTENT_URI = "intent_uri"; - - /** - * A String to display as a notification on the launcher. This may also - * cause a visual indication to be shown on the launcher when this app - * is not in view. - * - *

Type: String

- */ - public static final String NOTIFICATION_TEXT = "notification_text"; - - /** - * An optional Uri for querying progresss for any ongoing actions, such - * as an active download. - * - *

Type: String (Uri)

- */ - public static final String PROGRESS_URI = "progress_uri"; - - } - - public static final class Launcher implements BaseColumns, LauncherColumns { - - /** - * This utility class cannot be instantiated - */ - private Launcher() {} - } - - protected interface ProgressColumns { - /** - * The current progress as an integer in the range [0-100] inclusive. - * - *

Type: INTEGER

- */ - public static final String PROGRESS = "progress"; - } - - public static final class Progress implements BaseColumns, ProgressColumns { - /** - * This utility class cannot be instantiated - */ - private Progress() {} - } - - protected interface LauncherItemColumns { - /** - * The _id of the cluster this item is a member of. - * - *

Type: INTEGER (long)

- */ - public static final String PARENT_ID = "parent_id"; - - /** - * The uri for retrieving the image to show for this item. This - * String should be generated using {@link Uri#toString()} - * - *

Type: String (Uri)

- */ - public static final String IMAGE_URI = "image_uri"; - - } - - public static final class LauncherItem implements BaseColumns, LauncherItemColumns { - - /** - * Returns a Uri that can be used to query the individual items in a - * cluster. - * - * @param root The Uri base path to query against. - * @param clusterId the _id of the cluster returned by querying the Launcher - * Uri for this provider. - */ - public static final Uri getLauncherItemsUri(Uri root, long clusterId) { - return Uri.withAppendedPath(root, PATH_LAUNCHER_ITEM + "/" + clusterId); - } - - /** - * Returns a Uri that can be used to query the all items across clusters. - * - * @param root The ContentProvider authority that this Uri should query - * against. - */ - public static final Uri getLauncherItemsUri(Uri root) { - return Uri.withAppendedPath(root, PATH_LAUNCHER_ITEM); - } - - /** - * This utility class cannot be instantiated - */ - private LauncherItem() {}; - } - - protected interface BrowseHeadersColumns { - /** - * Reference name of the header, not used for display to the users. - * - *

Type: String

- */ - public static final String NAME = "name"; - - /** - * The name to show for the header. User visible. - * - *

Type: String

- */ - public static final String DISPLAY_NAME = "display_name"; - - /** - * Uri pointing to an icon to be used as part of the header. This - * String should be generated using {@link Uri#toString()} - * - *

Type: String (Uri)

- */ - public static final String ICON_URI = "icon_uri"; - - /** - * Uri pointing to an icon to be used for app branding on this tab. - * This String should be generated using {@link Uri#toString()} - * - *

Type: String (Uri)

- */ - public static final String BADGE_URI = "badge_uri"; - - /** - * A 0xAARRGGBB color that should be applied to the background when on - * this tab. - * - *

Type: INTEGER

- */ - public static final String COLOR_HINT = "color_hint"; - - /** - * A 0xAARRGGBB color that should be applied to the text when on this - * tab. - * - *

Type: INTEGER

- */ - public static final String TEXT_COLOR_HINT = "text_color_hint"; - - /** - * Uri pointing to an image to display in the background when on this - * tab. Be sure the image contrasts enough with the text color hint and - * is of high enough quality to be displayed at 1080p. This String - * should be generated using {@link Uri#toString()}. The URI will be either - * a resource uri in format of android:resource:// or an external URL - * like file://, http://, https://. - * - *

Type: String (Uri)

- */ - public static final String BG_IMAGE_URI = "bg_image_uri"; - - /** - * The default width of the expanded image - * - *

Type: INTEGER

- */ - public static final String DEFAULT_ITEM_WIDTH = "default_item_width"; - - /** - * The default height of the expanded image - * - *

Type: INTEGER

- */ - public static final String DEFAULT_ITEM_HEIGHT = "default_item_height"; - - /** - * 1 to show a lane below images for description, 0 to hide. - * Default value is 1. - * - *

Type: INTEGER (0 or 1)

- */ - public static final String SHOW_DESCRIPTIONS = "show_descriptions"; - - /** - * A group id. If this is not 0, contiguous headers with the same - * expand group will be expanded together. Non-contiguous headers with - * the same expand group is an error. - * - *

Type: INTEGER

- */ - public static final String EXPAND_GROUP = "expand_group"; - - /** - * Controls whether the items in this row will wrap around back to the - * beginning when the user scrolls to the last item. 0 to not wrap items, - * 1 to wrap. - * - *

Type: INTEGER (0 or 1)

- */ - public static final String WRAP_ITEMS = "wrap_items"; - - } - - public static final class BrowseHeaders implements BaseColumns, BrowseHeadersColumns { - /** - * Returns a uri for retrieving a list of browse header meta-data items that - * describe the categories for this browse path (name, badge, color hint, - * background image, etc.) - * - * @param root The base content Uri to browse. - * @return - */ - public static final Uri getBrowseHeadersUri(Uri root) { - return Uri.withAppendedPath(root, PATH_BROWSE_HEADERS); - } - - /** - * This utility class cannot be instantiated - */ - private BrowseHeaders(){} - } - - protected interface BrowseItemsColumns { - /** - * The _id of the header this item belongs to. - * - *

Type: INTEGER (long)

- */ - public static final String PARENT_ID = "parent_id"; - - /** - * Text that may be shown to the user along with the image or instead - * of an image if no image was specified. - * - *

Type: String

- */ - public static final String DISPLAY_NAME = "display_name"; - - /** - * Long description text of this item. - * - *

Type: String

- */ - public static final String DISPLAY_DESCRIPTION = "display_description"; - - /** - * The uri for retrieving the image to show for this item. This string - * should be created using {@link Uri#toString()}. - * - *

Type: String (Uri)

- */ - public static final String IMAGE_URI = "image_uri"; - - /** - * The width of the image for this item in pixels. - * - *

Type: INTEGER

- */ - public static final String WIDTH = "width"; - - /** - * The height of the image for this item in pixels. - * - *

Type: INTEGER

- */ - public static final String HEIGHT = "height"; - - /** - * An intent to launch when this item is selected. It may be another - * browse intent or a deep link into the app. This String should be - * generated using {@link Intent#toUri(int)} with - * {@link Intent#URI_INTENT_SCHEME}. - * - *

Type: String (Uri)

- */ - public static final String INTENT_URI = "intent_uri"; - } - - public static final class BrowseItems implements BaseColumns, BrowseItemsColumns { - /** - * Returns a Uri that can be used to query the items within a browse - * category. - * - * @param root The base content Uri that is being browsed. - * @param headerId The _id of the header that will be queried. - * @return - */ - public static final Uri getBrowseItemsUri(Uri root, long headerId) { - return ContentUris.withAppendedId(root, headerId); - } - } - - protected interface UserRatingColumns { - /** - * The average rating for this item. (Optional) - * - *

Type: Double

- */ - public static final String USER_RATING_AVERAGE = "user_rating_average"; - - /** - * A simple rating for this item as an integer in the range - * [0-10] inclusive. (Optional) - * - *

Type: INTEGER

- */ - public static final String USER_RATING_SIMPLE = "user_rating_simple"; - - /** - * The number of reviews included in the average rating. (Optional) - * - *

Type: INTEGER

- */ - public static final String USER_RATING_COUNT = "user_rating_count"; - } - - protected interface DetailItemColumns { - - /** - * Title of the item. - * - *

Type: String

- */ - public static final String DISPLAY_NAME = "display_name"; - - /** - * Long description text of this item. - * - *

Type: String

- */ - public static final String DISPLAY_DESCRIPTION = "display_description"; - - /** - * The uri for retrieving the foreground image to show for this item. This string - * should be created using {@link Uri#toString()}. - * - *

Type: String (Uri)

- */ - public static final String FOREGROUND_IMAGE_URI = "foreground_image_uri"; - - /** - * The uri for retrieving the background image to show for this item. This string - * should be created using {@link Uri#toString()}. - * - *

Type: String (Uri)

- */ - public static final String BACKGROUND_IMAGE_URI = "background_image_uri"; - - /** - * A 0xAARRGGBB color that should be applied to the background. - * - *

Type: INTEGER

- */ - public static final String COLOR_HINT = "color_hint"; - - /** - * The uri for the badge - */ - public static final String BADGE_URI = "badge_uri"; - - /** - * A 0xAARRGGBB color that should be applied to rendered text so as no - * not conflict with the {@link #COLOR_HINT} or - * {@link #BACKGROUND_IMAGE_URI}. - * - *

Type: INTEGER

- */ - public static final String TEXT_COLOR_HINT = "text_color_hint"; - } - - public static final class DetailItem implements BaseColumns, DetailItemColumns { - - /** - * Non instantiable. - */ - private DetailItem() {} - } - - protected interface DetailSectionsColumns { - - /** - * Text that will be shown to the user for navigating between sections. - * - *

Type: String

- */ - public static final String DISPLAY_HEADER = "display_header"; - - /** - * Primary text for display when a section is visible, such as - * an artist name or movie title. (Optional) - *

- * This is only valid if {@link #SECTION_TYPE} is - * {@link #SECTION_TYPE_LIST} or {@link #SECTION_TYPE_SECTIONS}. - * - *

Type: String

- */ - public static final String DISPLAY_NAME = "display_name"; - - /** - * Secondary text for display when a section is visible, such as - * a release date or album title. (Optional) - *

- * This is only valid if {@link #SECTION_TYPE} is - * {@link #SECTION_TYPE_LIST} or {@link #SECTION_TYPE_SECTIONS}. - * - *

Type: String

- */ - public static final String DISPLAY_SUBNAME = "display_subname"; - - /** - * Type of item. - *

- * One of {@link #SECTION_TYPE_BLOB}, {@link #SECTION_TYPE_LIST}, - * {@link #SECTION_TYPE_BLURB}, {@link #SECTION_TYPE_REVIEWS}, or - * {@link #SECTION_TYPE_SECTIONS}. - * - *

Type: Integer

- */ - public static final String SECTION_TYPE = "section_type"; - - /** - * Value for {@link #SECTION_TYPE} if this section has HTML content. - * This should only be used as a last resort if the other formats can't - * be made to work. - */ - public static final int SECTION_TYPE_BLOB = 0; - - /** - * Value for {@link #SECTION_TYPE} if this section uses the default list - * formatting for its content. - */ - public static final int SECTION_TYPE_LIST = 1; - - /** - * Value for {@link #SECTION_TYPE} if this section uses the default - * formatting for its content. - */ - public static final int SECTION_TYPE_BLURB = 2; - - /** - * Value for {@link #SECTION_TYPE} if this section has review style - * formatting for its content. - */ - public static final int SECTION_TYPE_REVIEWS = 3; - - /** - * Value for {@link #SECTION_TYPE} if this section is multiple related - * sections that can be grouped. For example, seasons of a TV show - * should use this type. - */ - public static final int SECTION_TYPE_SECTIONS = 4; - - /** - * Blob content, either a string or HTML. - *

- * If HTML, this will be sanitized before displaying in a web view. - *

- * JavaScript is not allowed. - * - *

Type: String

- */ - public static final String BLOB_CONTENT = "blob_content"; - - /** - * Action or list of actions available for this section. - *

- * Only valid if {@link #SECTION_TYPE} = {@link #SECTION_TYPE_BLOB}. - *

- * This is either a single intent URI or a content URI pointing to a list of - * {@link DetailActions}. - */ - public static final String ACTION_URI = "action_uri"; - - /** - * Content URI. This must be nested under the detail item ID. - *

- * Only valid if {@link #SECTION_TYPE} is one of - * {@link #SECTION_TYPE_LIST}, {@link #SECTION_TYPE_REVIEWS}, - * {@link #SECTION_TYPE_SECTIONS}. - */ - public static final String CONTENT_URI = "content_uri"; - } - - /** - * A top level listing of the sections for this item, such as "Ratings" or - * "Related." The BLOB_CONTENT column is only valid if - * {@link DetailSectionsColumns#SECTION_TYPE} = - * {@link DetailSectionsColumns#SECTION_TYPE_BLOB}. USER_RATING columns are - * only valid if {@link DetailSectionsColumns#SECTION_TYPE} = - * {@link DetailSectionsColumns#SECTION_TYPE_REVIEWS}. - */ - public static final class DetailSections - implements BaseColumns, DetailSectionsColumns, UserRatingColumns { - /** - * Non instantiable. - */ - private DetailSections() {} - - /** - * Gets a content URI suitable for loading the sections for an item. - */ - public static Uri getSectionsUri(Uri itemUri) { - return itemUri.buildUpon().appendPath(PATH_DETAIL_SECTIONS).build(); - } - } - - protected interface DetailBlurbColumns { - /** - * Primary text that will be shown to the user, generally the title. - * (Optional) - * - *

Type: String

- */ - public static final String DISPLAY_NAME = "display_name"; - - /** - * A secondary title with more importance than the description, such as - * the artist or director. (Optional) - * - *

Type: String

- */ - public static final String DISPLAY_SUBNAME = "display_subname"; - - /** - * Long description text of this item. (Optional) - * - *

Type: String

- */ - public static final String DISPLAY_DESCRIPTION = "display_description"; - - /** - * The category of the item to show to the user, such as "Apps" or - * "Folk". (Optional) - * - *

Type: String

- */ - public static final String DISPLAY_CATEGORY = "display_category"; - - /** - * The URI for retrieving an image to show. This should be a rating - * badge or other similar icon. This string should be created using - * {@link Uri#toString()}. (Optional) - * - *

Type: String (Uri)

- */ - public static final String BADGE_URI = "badge_uri"; - } - - public static final class DetailBlurb - implements BaseColumns, DetailBlurbColumns, UserRatingColumns { - /** - * Non instantiable. - */ - private DetailBlurb() {} - } - - protected interface ItemChildrenColumns { - /** - * Primary text that will be shown to the user, generally the title. - * (Optional) - * - *

Type: String

- */ - public static final String DISPLAY_NAME = "display_name"; - - /** - * A secondary title with more importance than the description, such as - * the artist or director. (Optional) - * - *

Type: String

- */ - public static final String DISPLAY_SUBNAME = "display_subname"; - - /** - * Long description text of this item. (Optional) - * - *

Type: String

- */ - public static final String DISPLAY_DESCRIPTION = "display_description"; - - /** - * A number to display next to the item, such as the track or - * episode number. 0 is not allowed. (Optional) - * - *

Type: INTEGER

- */ - public static final String DISPLAY_NUMBER = "display_number"; - - /** - * The uri for retrieving the image to show for this item. This string - * should be created using {@link Uri#toString()}. (Optional) - * - *

Type: String (Uri)

- */ - public static final String IMAGE_URI = "image_uri"; - - /** - * Either an intent URI for an intent that should be triggered or else a content URI - * pointing to a list of actions for this item. - *

- * If the list has only 1 action per item, it is more efficient to supply an intent URI - * here. (Optional) - * - *

Type: String (Uri)

- */ - public static final String ACTION_URI = "action_uri"; - } - - public static final class DetailChildren - implements BaseColumns, ItemChildrenColumns, UserRatingColumns { - - /** - * Non instantiable. - */ - private DetailChildren() {} - } - - public static final class SearchResults - implements BaseColumns, ItemChildrenColumns, UserRatingColumns { - - /** - * Non instantiable. - */ - private SearchResults() {} - } - - protected interface DetailActionsColumns { - - /** - * Text that will be shown to the user. - * - *

Type: String

- */ - public static final String DISPLAY_NAME = "display_name"; - - /** - * Secondary text that will be shown to the user, such as "from $2.99". - * (Optional) - * - *

Type: String

- */ - public static final String DISPLAY_SUBNAME = "display_subname"; - - /** - * Intent URI of the form intent:// which will be triggered. - * - *

Type: String (Uri)

- */ - public static final String INTENT_URI = "intent_uri"; - } - - public static final class DetailActions implements BaseColumns, DetailActionsColumns { - - /** - * Non instantiable. - */ - private DetailActions() {} - } - - /** - * Returns a browse intent with the root included. The root should be a - * base Uri that the browse queries can build off of. - * - * Example: "content://com.google.movies/browse/action" - * - * @param root The authority + path that will be browsed on. - * @param start The index of the header to display expanded first. - * @return - */ - public static Intent getBrowseIntent(Uri root, int start) { - Intent intent = new Intent(ACTION_BROWSE); - intent.setData(root); - intent.putExtra(EXTRA_START_INDEX, start); - return intent; - } - - /** - * Returns a browse intent with the root included. The root should be a - * base Uri that the browse queries can build off of. - * - * Example: "content://com.google.movies/browse/action" - * - * @param root The authority + path that will be browsed on. - * @param startId The _id of the header to display expanded first. - * @return - */ - public static Intent getBrowseIntentById(Uri root, long startId) { - Intent intent = new Intent(ACTION_BROWSE); - intent.setData(root); - intent.putExtra(EXTRA_START_ID, startId); - return intent; - } - - /** - * Returns a details intent for the given root URI. The root should be a URI - * specific to the item being viewed that can be appended to for details - * queries. - * - * Example: "content://com.google.movies/details/75289" - */ - public static Intent getDetailsIntent(Uri root) { - Intent intent = new Intent(ACTION_DETAIL); - intent.setData(root); - return intent; - } -} \ No newline at end of file diff --git a/src/com/google/android/pano/data/Cluster.java b/src/com/google/android/pano/data/Cluster.java new file mode 100644 index 000000000..d4a2c1c08 --- /dev/null +++ b/src/com/google/android/pano/data/Cluster.java @@ -0,0 +1,309 @@ +// Copyright 2012 Google Inc. All Rights Reserved. + +package com.google.android.pano.data; + +import android.content.Intent; +import android.net.Uri; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a home screen cluster. + */ +public class Cluster { + + private long mId; + private String mName; + private CharSequence mDisplayName; + private int mImportance; + private int mVisibleCount; + private boolean mImageCropAllowed; + private long mCacheTimeMs; + private Intent mIntent; + private Uri mBrowseItemsUri; + + private List mClusterItems; + + /** + * An item displayed inside a cluster. + */ + public static class ClusterItem { + private Uri mImageUri; + + public ClusterItem(Uri imageUri) { + mImageUri = imageUri; + } + + public Uri getImageUri() { + return mImageUri; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("imageUri: ").append(mImageUri); + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((mImageUri == null) ? 0 : mImageUri.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ClusterItem other = (ClusterItem) obj; + if (mImageUri == null) { + if (other.mImageUri != null) + return false; + } else if (!mImageUri.equals(other.mImageUri)) + return false; + return true; + } + } + + public Cluster() { + mClusterItems = new ArrayList(); + mImageCropAllowed = true; + } + + public long getId() { + return mId; + } + + public String getName() { + return mName; + } + + public CharSequence getDisplayName() { + return mDisplayName; + } + + public int getImportance() { + return mImportance; + } + + public int getVisibleCount() { + return mVisibleCount; + } + + public boolean isImageCropAllowed() { + return mImageCropAllowed; + } + + public long getCacheTimeMs() { + return mCacheTimeMs; + } + + public Intent getIntent() { + return mIntent; + } + + public Uri getBrowseItemsUri() { + return mBrowseItemsUri; + } + + public int getItemCount() { + return mClusterItems.size(); + } + + public ClusterItem getItem(int position) { + if (position >= 0 && position < mClusterItems.size()) { + return mClusterItems.get(position); + } + return null; + } + + public void addClusterItem(ClusterItem item) { + mClusterItems.add(item); + } + + public void clearItems() { + mClusterItems.clear(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (int) (mCacheTimeMs ^ (mCacheTimeMs >>> 32)); + if (mClusterItems == null) { + result = prime * result; + } else { + for (ClusterItem ci : mClusterItems) { + result = prime * result + ci.hashCode(); + } + } + result = prime * result + ((mDisplayName == null) ? 0 : mDisplayName.toString().hashCode()); + result = prime * result + (int) (mId ^ (mId >>> 32)); + result = prime * result + (mImageCropAllowed ? 1231 : 1237); + result = prime * result + mImportance; + result = prime * result + ((mIntent == null) ? 0 : mIntent.hashCode()); + result = prime * result + ((mName == null) ? 0 : mName.hashCode()); + result = prime * result + mVisibleCount; + result = prime * result + ((mBrowseItemsUri == null) ? 0 : mBrowseItemsUri.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Cluster other = (Cluster) obj; + if (mCacheTimeMs != other.mCacheTimeMs) + return false; + if (mClusterItems == null) { + if (other.mClusterItems != null) + return false; + } else if (!mClusterItems.equals(other.mClusterItems)) + return false; + if (mDisplayName == null) { + if (other.mDisplayName != null) + return false; + } else if (!mDisplayName.equals(other.mDisplayName)) + return false; + if (mId != other.mId) + return false; + if (mImageCropAllowed != other.mImageCropAllowed) + return false; + if (mImportance != other.mImportance) + return false; + if (mIntent == null) { + if (other.mIntent != null) + return false; + } else if (!mIntent.equals(other.mIntent)) + return false; + if (mName == null) { + if (other.mName != null) + return false; + } else if (!mName.equals(other.mName)) + return false; + if (mVisibleCount != other.mVisibleCount) + return false; + if (mBrowseItemsUri == null) { + if (other.mBrowseItemsUri != null) + return false; + } else if (!mBrowseItemsUri.equals(other.mBrowseItemsUri)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("id: ").append(mId) + .append(", name: ").append(mName) + .append(", displayName: ").append(mDisplayName) + .append(", importance: ").append(mImportance) + .append(", visibleCount: ").append(mVisibleCount) + .append(", imageCropAllowed: ").append(mImageCropAllowed) + .append(", cacheTimeMs: ").append(mCacheTimeMs) + .append(", clusterItems: ").append(mClusterItems) + .append(", intent: ").append(mIntent != null ? mIntent.toUri(0) : "") + .append(", browseItems: ").append(mBrowseItemsUri != null ? mBrowseItemsUri : ""); + return builder.toString(); + } + + /** + * Builds cluster objects. + */ + public static class Builder { + private long mId; + private String mName; + private CharSequence mDisplayName; + private int mImportance; + private int mVisibleCount; + private boolean mImageCropAllowed; + private long mCacheTimeMs; + private Intent mIntent; + private Uri mBrowseItemsUri; + + private List mClusterItems; + + public Cluster build() { + Cluster cluster = new Cluster(); + cluster.mId = mId; + cluster.mName = mName; + cluster.mDisplayName = mDisplayName; + cluster.mImportance = mImportance; + cluster.mVisibleCount = mVisibleCount; + cluster.mImageCropAllowed = mImageCropAllowed; + cluster.mIntent = mIntent; + cluster.mCacheTimeMs = mCacheTimeMs; + cluster.mClusterItems.addAll(mClusterItems); + cluster.mBrowseItemsUri = mBrowseItemsUri; + return cluster; + } + + public Builder() { + mClusterItems = new ArrayList(); + mImageCropAllowed = true; + } + + public Builder id(long id) { + mId = id; + return this; + } + + public Builder name(String name) { + mName = name; + return this; + } + + public Builder displayName(CharSequence displayName) { + mDisplayName = displayName; + return this; + } + + public Builder importance(int importance) { + mImportance = importance; + return this; + } + + public Builder visibleCount(int visibleCount) { + mVisibleCount = visibleCount; + return this; + } + + public Builder imageCropAllowed(boolean allowed) { + mImageCropAllowed = allowed; + return this; + } + + public Builder cacheTimeMs(long cacheTimeMs) { + mCacheTimeMs = cacheTimeMs; + return this; + } + + public Builder intent(Intent intent) { + mIntent = intent; + return this; + } + + public Builder browseItemsUri(Uri uri) { + mBrowseItemsUri = uri; + return this; + } + + public Builder addItem(Uri imageUri) { + ClusterItem item = new ClusterItem(imageUri); + mClusterItems.add(item); + return this; + } + } +} diff --git a/src/com/google/android/pano/data/util/UriUtils.java b/src/com/google/android/pano/data/util/UriUtils.java new file mode 100644 index 000000000..5d973c16c --- /dev/null +++ b/src/com/google/android/pano/data/util/UriUtils.java @@ -0,0 +1,134 @@ +// Copyright 2012 Google Inc. All Rights Reserved. + +package com.google.android.pano.data.util; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent.ShortcutIconResource; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.net.Uri; + +/** + * Utilities for working with URIs. + */ +public final class UriUtils { + + private static final String SCHEME_SHORTCUT_ICON_RESOURCE = "shortcut.icon.resource"; + private static final String SCHEME_DELIMITER = "://"; + private static final String URI_PATH_DELIMITER = "/"; + private static final String URI_PACKAGE_DELIMITER = ":"; + private static final String HTTP_PREFIX = "http"; + private static final String HTTPS_PREFIX = "https"; + + /** + * Non instantiable. + */ + private UriUtils() {} + + /** + * get resource uri representation for a resource of a package + */ + public static String getAndroidResourceUri(Context context, int resourceId) { + return getAndroidResourceUri(context.getResources(), resourceId); + } + + /** + * get resource uri representation for a resource + */ + public static String getAndroidResourceUri(Resources resources, int resourceId) { + return ContentResolver.SCHEME_ANDROID_RESOURCE + + SCHEME_DELIMITER + resources.getResourceName(resourceId) + .replace(URI_PACKAGE_DELIMITER, URI_PATH_DELIMITER); + } + + /** + * load drawable from resource + * TODO: move to a separate class to handle bitmap and drawables + */ + public static Drawable getDrawable(Context context, ShortcutIconResource r) + throws NameNotFoundException { + Resources resources = context.getPackageManager().getResourcesForApplication(r.packageName); + if (resources == null) { + return null; + } + final int id = resources.getIdentifier(r.resourceName, null, null); + return resources.getDrawable(id); + } + + /** + * Gets a URI with short cut icon scheme. + */ + public static Uri getShortcutIconResourceUri(ShortcutIconResource iconResource) { + return Uri.parse(SCHEME_SHORTCUT_ICON_RESOURCE + SCHEME_DELIMITER + iconResource.packageName + + URI_PATH_DELIMITER + + iconResource.resourceName.replace(URI_PACKAGE_DELIMITER, URI_PATH_DELIMITER)); + } + + /** + * Gets a URI with scheme = {@link ContentResolver#SCHEME_ANDROID_RESOURCE}. + */ + public static Uri getAndroidResourceUri(String resourceName) { + Uri uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + SCHEME_DELIMITER + + resourceName.replace(URI_PACKAGE_DELIMITER, URI_PATH_DELIMITER)); + return uri; + } + + /** + * Checks if the URI refers to an Android resource. + */ + public static boolean isAndroidResourceUri(Uri uri) { + return ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme()); + } + + /** + * Returns {@code true} if the URI refers to a content URI which can be opened via + * {@link ContentResolver#openInputStream(Uri)}. + */ + public static boolean isContentUri(Uri uri) { + return ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) || + ContentResolver.SCHEME_FILE.equals(uri.getScheme()); + } + + /** + * Checks if the URI refers to an shortcut icon resource. + */ + public static boolean isShortcutIconResourceUri(Uri uri) { + return SCHEME_SHORTCUT_ICON_RESOURCE.equals(uri.getScheme()); + } + + /** + * Creates a shortcut icon resource object from an Android resource URI. + */ + public static ShortcutIconResource getIconResource(Uri uri) { + if(isAndroidResourceUri(uri)) { + ShortcutIconResource iconResource = new ShortcutIconResource(); + iconResource.packageName = uri.getAuthority(); + // Trim off the scheme + 3 extra for "://", then replace the first "/" with a ":" + iconResource.resourceName = uri.toString().substring( + ContentResolver.SCHEME_ANDROID_RESOURCE.length() + SCHEME_DELIMITER.length()) + .replaceFirst(URI_PATH_DELIMITER, URI_PACKAGE_DELIMITER); + return iconResource; + } else if(isShortcutIconResourceUri(uri)) { + ShortcutIconResource iconResource = new ShortcutIconResource(); + iconResource.packageName = uri.getAuthority(); + iconResource.resourceName = uri.toString().substring( + SCHEME_SHORTCUT_ICON_RESOURCE.length() + SCHEME_DELIMITER.length() + + iconResource.packageName.length() + URI_PATH_DELIMITER.length()) + .replaceFirst(URI_PATH_DELIMITER, URI_PACKAGE_DELIMITER); + return iconResource; + } else { + throw new IllegalArgumentException("Invalid resource URI. " + uri); + } + } + + /** + * Returns {@code true} if this is a web URI. + */ + public static boolean isWebUri(Uri resourceUri) { + String scheme = resourceUri.getScheme() == null ? null + : resourceUri.getScheme().toLowerCase(); + return HTTP_PREFIX.equals(scheme) || HTTPS_PREFIX.equals(scheme); + } +} diff --git a/src/com/google/android/pano/provider/PanoContract.java b/src/com/google/android/pano/provider/PanoContract.java new file mode 100644 index 000000000..cfce17a17 --- /dev/null +++ b/src/com/google/android/pano/provider/PanoContract.java @@ -0,0 +1,1087 @@ +package com.google.android.pano.provider; + +import android.content.ContentUris; +import android.content.Intent; +import android.net.Uri; +import android.provider.BaseColumns; + +/** + * The contract between Pano and ContentProviders that allow access to Pano + * browsing data. All apps that wish to interact with Pano should use these + * definitions. + * + * TODO add more details + */ +public final class PanoContract { + + // Base for content uris + public static final String CONTENT = "content://"; + /** + * Path to items within a single cluster in the launcher. This can be used + * when setting up a UriMatcher. Queries will use the form + * content:////<#> where the # is the _id of the cluster + * being queried + */ + public static final String PATH_LAUNCHER_ITEM = "items"; + /** + * Path to the header meta-data. This can be used when setting up a + * UriMatcher. Queries will use the form content:/// + */ + public static final String PATH_BROWSE_HEADERS = "headers"; + + /** + * Pano will search for activities with the action {@link Intent#ACTION_MAIN} and this + * category in order to find the activities for the home screen. + */ + public static final String CATEGORY_BROWSE_LAUNCHER = + "com.google.android.pano.category.BROWSE_LAUNCHER"; + + /** + * This tag is used to identify the launcher info data file to be used for a Pano + * launcher app. + */ + public static final String METADATA_LAUNCHER_INFO_TAG = + "com.google.android.pano.data.launcher_info"; + + /** + * An intent action for browsing app content in Pano. Apps receiving this + * intent should call {@link Intent#getData()} to retrieve the base Uri and + * {@link #EXTRA_START_INDEX} or {@link #EXTRA_START_ID} to find which header + * to start at (default 0). + */ + public static final String ACTION_BROWSE = "com.google.android.pano.action.BROWSE"; + + /** + * An intent action for picking app content in Pano. + *

+ * Any intents launched from here will be returned to the calling activity instead of being + * directly launched. + *

+ * This can be used to select an item. + */ + public static final String ACTION_BROWSE_PICKER = + "com.google.android.pano.action.BROWSE_PICKER"; + + /** + * An intent action for picking app content while keeping the launching app running. + *

+ * Pano Browse will appear over the app. + *

+ * Any intents launched from here will be returned to the calling activity instead of being + * directly launched. + *

+ * This can be used to select an item. + */ + public static final String ACTION_BROWSE_PICKER_TRANSLUCENT = + "com.google.android.pano.action.BROWSE_PICKER_TRANSLUCENT"; + + /** + * The index of the header to focus on initially when the browse is launched. + * This extra is optional and defaults to 0. If {@link #EXTRA_START_ID} is present + * this value will not be used. + */ + public static final String EXTRA_START_INDEX = "start_index"; + + /** + * The _id of the header to focus on initially when the browse is launched. + * This extra is optional and {@link #EXTRA_START_ID} is used by default. + */ + public static final String EXTRA_START_ID = "start_id"; + + /** + * An intent action for viewing detail content in Pano. Apps receiving this + * intent should call {@link Intent#getData()} to retrieve the base Uri. + */ + public static final String ACTION_DETAIL = "com.google.android.pano.action.DETAIL"; + + /** + * The name of the section to focus on initially when {@link #ACTION_DETAIL} is launched. + *

+ * Using name allows targeting a sub section. + */ + public static final String EXTRA_START_NAME = "start_name"; + + /** + * Index of a child to focus on initially when {@link #ACTION_DETAIL} is launched. + *

+ * Requires a start section to be specified using {@link #EXTRA_START_INDEX} or + * {@link #EXTRA_START_NAME}. + */ + public static final String EXTRA_START_CHILD_INDEX = "start_child_index"; + + /** + * Path for querying details for an item. + */ + public static final String PATH_DETAIL_ITEM = "details"; + + /** + * Path for querying sections for a detail item. This can be used when setting up a + * UriMatcher. Queries will use the form content:///details//sections. + */ + public static final String PATH_DETAIL_SECTIONS = "sections"; + + /** + * Path for querying detail actions. This can be used when setting up a UriMatcher. Queries will + * use the form content:///details//actions. + */ + public static final String PATH_DETAIL_ACTIONS = "actions"; + + /** + * Action for searching a Pano provider. Apps receiving this + * intent should call {@link Intent#getData()} to retrieve the base Uri and + * {@link #EXTRA_QUERY} to find query. + */ + public static final String ACTION_SEARCH = "com.google.android.pano.action.SEARCH"; + + /** + * Action for searching a Pano provider. + *

+ * Any intent selected off this activity will be returned to the calling activity instead of + * being launched directly. + */ + public static final String ACTION_SEARCH_PICKER = + "com.google.android.pano.action.SEARCH_PICKER"; + + /** + * An intent action for searching app content while keeping the launching app running. + *

+ * Pano Search will appear over the app. + *

+ * Any intents launched from here will be returned to the calling activity instead of being + * directly launched. + *

+ * This can be used to select an item. + */ + public static final String ACTION_SEARCH_PICKER_TRANSLUCENT = + "com.google.android.pano.action.SEARCH_PICKER_TRANSLUCENT"; + + /** + * The query to be executed when search activity is launched + * This extra is optional and defaults to null. + */ + public static final String EXTRA_QUERY = "query"; + + /** + * Optional String extra for meta information. This must be supplied as a string, but must be a valid URI. + *

+ * Used with {@link #ACTION_SEARCH}. + */ + public static final String EXTRA_META_URI = "meta_uri"; + + /** + * Optional int extra for setting the display mode of the search activity. + * + * @see #DISPLAY_MODE_ROW + * @see #DISPLAY_MODE_GRID + */ + public static final String EXTRA_DISPLAY_MODE = "display_mode"; + + public static final int DISPLAY_MODE_ROW = 0; + public static final int DISPLAY_MODE_GRID = 1; + public static final int DISPLAY_MODE_BROWSE = 2; + + /** + * Value for the root Pano URI when this activity should be excluded from the Pano top level + * and the legacy apps area. + * + * TODO: this is obsolete: remove. + */ + public static final String EXCLUDED_ROOT_URI = "excluded"; + + protected interface LauncherColumns { + + /** + * The name of the cluster. Generally used for debugging and not shown + * to the user. + * + *

Type: String

+ */ + public static final String NAME = "name"; + + /** + * An optional name to display with the cluster. This value will be user + * visible. Example: "Recently Watched" + * + *

Type: String

+ */ + public static final String DISPLAY_NAME = "display_name"; + + /** + * How important this cluster is. The higher the value the more important + * it will be relative to other clusters. The importance is a relative + * weighting and not an absolute priority. If this value is left blank + * it will default to 0 (not important). + * + *

Type: INTEGER

+ */ + public static final String IMPORTANCE = "importance"; + + /** + * The number of items that should be shown in this cluster. If this + * value is more than there is space for fewer items may be shown. + * + *

Type: INTEGER

+ */ + public static final String VISIBLE_COUNT = "visible_count"; + + /** + * Whether or not the image may be cropped to fit the display area + * better. 1 means cropping is allowed, 0 means the item should be + * shrunk or stretched to fit instead. + * + *

Type: INTEGER (0 or 1)

+ */ + public static final String IMAGE_CROP_ALLOWED = "image_crop_allowed"; + + /** + * The amount of time it is safe to assume the data for this + * cluster will remain valid. For example, if this cluster is + * advertising a daily special this should return the time until the + * special ends. A best effort will be made to not display data past + * this point but some data may not be requeried immediately. + * + *

Type: INTEGER (long)

+ */ + public static final String CACHE_TIME_MS = "cache_time_ms"; + + /** + * Content URI pointing to a list of items in the {@link PanoContract.BrowseItemsColumns} + * schema. + *

+ * This is optional but highly recommended if the cluster represents a browse row. + *

+ * In this case, the cluster items will be read from this URI instead of from the cluster + * items. + *

+ * If this is filled in, the intent_uri must have the action + * {@link PanoContract#ACTION_BROWSE}. The row with this URI will automatically be + * selected when the activity starts up. + * + *

Type: String (Uri)

+ */ + public static final String BROWSE_ITEMS_URI = "browse_items_uri"; + + /** + * A standard Intent Uri to be launched when this cluster is selected. + * This may be a {@link PanoContract#ACTION_BROWSE} intent or an + * intent to launch directly into an app. You can also use + * {@link PanoContract#getBrowseIntent(Uri, int)} to generate a + * browse intent for a given root Uri. Use {@link Intent#toUri(int)} + * with a flag of {@link Intent#URI_INTENT_SCHEME}. + * + *

Type: String (Uri)

+ */ + public static final String INTENT_URI = "intent_uri"; + + /** + * A String to display as a notification on the launcher. This may also + * cause a visual indication to be shown on the launcher when this app + * is not in view. + * + *

Type: String

+ */ + public static final String NOTIFICATION_TEXT = "notification_text"; + + /** + * An optional Uri for querying progress for any ongoing actions, such + * as an active download. + * + *

Type: String (Uri)

+ */ + public static final String PROGRESS_URI = "progress_uri"; + + } + + public static final class Launcher implements BaseColumns, LauncherColumns { + + /** + * This utility class cannot be instantiated + */ + private Launcher() {} + } + + protected interface ProgressColumns { + /** + * The current progress as an integer in the range [0-100] inclusive. + * + *

Type: INTEGER

+ */ + public static final String PROGRESS = "progress"; + + /** + * The smallest value that is a valid {@link #PROGRESS}. + */ + public static final int PROGRESS_MIN = 0; + + /** + * The largest value that is a valid {@link #PROGRESS}. + */ + public static final int PROGRESS_MAX = 100; + } + + public static final class Progress implements BaseColumns, ProgressColumns { + /** + * This utility class cannot be instantiated + */ + private Progress() {} + } + + protected interface LauncherItemColumns { + /** + * The _id of the cluster this item is a member of. + * + *

Type: INTEGER (long)

+ */ + public static final String PARENT_ID = "parent_id"; + + /** + * The uri for retrieving the image to show for this item. This + * String should be generated using {@link Uri#toString()} + * + *

Type: String (Uri)

+ */ + public static final String IMAGE_URI = "image_uri"; + + } + + public static final class LauncherItem implements BaseColumns, LauncherItemColumns { + + /** + * Returns a Uri that can be used to query the individual items in a + * cluster. + * + * @param root The Uri base path to query against. + * @param clusterId the _id of the cluster returned by querying the Launcher + * Uri for this provider. + */ + public static final Uri getLauncherItemsUri(Uri root, long clusterId) { + return Uri.withAppendedPath(root, PATH_LAUNCHER_ITEM + "/" + clusterId); + } + + /** + * Returns a Uri that can be used to query the all items across clusters. + * + * @param root The ContentProvider authority that this Uri should query + * against. + */ + public static final Uri getLauncherItemsUri(Uri root) { + return Uri.withAppendedPath(root, PATH_LAUNCHER_ITEM); + } + + /** + * This utility class cannot be instantiated + */ + private LauncherItem() {}; + } + + protected interface BrowseHeadersColumns { + /** + * Reference name of the header, not used for display to the users. + * + *

Type: String

+ */ + public static final String NAME = "name"; + + /** + * The name to show for the header. User visible. + * + *

Type: String

+ */ + public static final String DISPLAY_NAME = "display_name"; + + /** + * Optional Uri pointing to the data for the items for this header. + *

+ * If this is not provided, a Uri will be constructed using + * {@link BrowseItems#getBrowseItemsUri(Uri, long)}. + * + *

Type: String

+ */ + public static final String ITEMS_URI = "items_uri"; + + /** + * Uri pointing to an icon to be used as part of the header. This + * String should be generated using {@link Uri#toString()} + * + *

Type: String (Uri)

+ */ + public static final String ICON_URI = "icon_uri"; + + /** + * Uri pointing to an icon to be used for app branding on this tab. + * This String should be generated using {@link Uri#toString()} + * + *

Type: String (Uri)

+ */ + public static final String BADGE_URI = "badge_uri"; + + /** + * A 0xAARRGGBB color that should be applied to the background when on + * this tab. + * + *

Type: INTEGER

+ */ + public static final String COLOR_HINT = "color_hint"; + + /** + * A 0xAARRGGBB color that should be applied to the text when on this + * tab. + * + *

Type: INTEGER

+ */ + public static final String TEXT_COLOR_HINT = "text_color_hint"; + + /** + * Uri pointing to an image to display in the background when on this + * tab. Be sure the image contrasts enough with the text color hint and + * is of high enough quality to be displayed at 1080p. This String + * should be generated using {@link Uri#toString()}. The URI will be either + * a resource uri in format of android:resource:// or an external URL + * like file://, http://, https://. + * + *

Type: String (Uri)

+ */ + public static final String BACKGROUND_IMAGE_URI = "background_image_uri"; + + /** + * Uri pointing to an image to display in the background when on this + * tab. Be sure the image contrasts enough with the text color hint and + * is of high enough quality to be displayed at 1080p. This String + * should be generated using {@link Uri#toString()}. The URI will be either + * a resource uri in format of android:resource:// or an external URL + * like file://, http://, https://. + * + *

Type: String (Uri)

+ *

This is the obsolete version of {@link #BACKGROUND_IMAGE_URI}

+ * TODO: remove obsolete version when all clients have upgraded. + */ + public static final String BG_IMAGE_URI = "bg_image_uri"; + + /** + * The default width of the expanded image + * + *

Type: INTEGER

+ */ + public static final String DEFAULT_ITEM_WIDTH = "default_item_width"; + + /** + * The default height of the expanded image + * + *

Type: INTEGER

+ */ + public static final String DEFAULT_ITEM_HEIGHT = "default_item_height"; + + /** + * 1 to show a lane below images for description, 0 to hide. + * Default value is 1. + * + *

Type: INTEGER (0 or 1)

+ */ + public static final String SHOW_DESCRIPTIONS = "show_descriptions"; + + /** + * A group id. If this is not 0, contiguous headers with the same + * expand group will be expanded together. Non-contiguous headers with + * the same expand group is an error. + * + *

Type: INTEGER

+ */ + public static final String EXPAND_GROUP = "expand_group"; + + /** + * Controls whether the items in this row will wrap around back to the + * beginning when the user scrolls to the last item. 0 to not wrap items, + * 1 to wrap. + * + *

Type: INTEGER (0 or 1)

+ */ + public static final String WRAP_ITEMS = "wrap_items"; + + } + + public static final class BrowseHeaders implements BaseColumns, BrowseHeadersColumns { + /** + * Returns a uri for retrieving a list of browse header meta-data items that + * describe the categories for this browse path (name, badge, color hint, + * background image, etc.) + * + * @param root The base content Uri to browse. + * @return + */ + public static final Uri getBrowseHeadersUri(Uri root) { + return Uri.withAppendedPath(root, PATH_BROWSE_HEADERS); + } + + /** + * This utility class cannot be instantiated + */ + private BrowseHeaders(){} + } + + protected interface BrowseItemsColumns { + /** + * The _id of the header this item belongs to. + * + *

Type: INTEGER (long)

+ */ + public static final String PARENT_ID = "parent_id"; + + /** + * Text that may be shown to the user along with the image or instead + * of an image if no image was specified. + * + *

Type: String

+ */ + public static final String DISPLAY_NAME = "display_name"; + + /** + * Long description text of this item. + * + *

Type: String

+ */ + public static final String DISPLAY_DESCRIPTION = "display_description"; + + /** + * The uri for retrieving the image to show for this item. This string + * should be created using {@link Uri#toString()}. + * + *

Type: String (Uri)

+ */ + public static final String IMAGE_URI = "image_uri"; + + /** + * The width of the image for this item in pixels. + * + *

Type: INTEGER

+ */ + public static final String WIDTH = "width"; + + /** + * The height of the image for this item in pixels. + * + *

Type: INTEGER

+ */ + public static final String HEIGHT = "height"; + + /** + * An intent to launch when this item is selected. It may be another + * browse intent or a deep link into the app. This String should be + * generated using {@link Intent#toUri(int)} with + * {@link Intent#URI_INTENT_SCHEME}. + * + *

Type: String (Uri)

+ */ + public static final String INTENT_URI = "intent_uri"; + } + + public static final class BrowseItems implements BaseColumns, BrowseItemsColumns { + /** + * Returns a Uri that can be used to query the items within a browse + * category. + * + * @param root The base content Uri that is being browsed. + * @param headerId The _id of the header that will be queried. + * @return + */ + public static final Uri getBrowseItemsUri(Uri root, long headerId) { + return ContentUris.withAppendedId(root, headerId); + } + } + + protected interface UserRatingColumns { + /** + * A custom rating String for this item, such as "78 points" or + * "20/100". (Optional) + *

+ * A null or the absence of this column indicates there is no custom + * rating available. + *

Type: String

+ */ + public static final String USER_RATING_CUSTOM = "user_rating_custom"; + + /** + * A scaled rating for this item as a float in the range [0-10] + * inclusive. Pano will be responsible for visualizing this + * value.(Optional) + *

+ * A -1 or the absence of this column indicates there is no rating + * available. + *

Type: FLOAT

+ */ + public static final String USER_RATING = "user_rating"; + + /** + * The number of reviews included in the average rating. (Optional) + *

+ * A value of 0 indicates the count is not available. + * + *

Type: INTEGER

+ */ + public static final String USER_RATING_COUNT = "user_rating_count"; + } + + protected interface DetailItemColumns { + + /** + * Title of the item. + * + *

Type: String

+ */ + public static final String DISPLAY_NAME = "display_name"; + + /** + * Long description text of this item. + * + *

Type: String

+ */ + public static final String DISPLAY_DESCRIPTION = "display_description"; + + /** + * The uri for retrieving the foreground image to show for this item. This string + * should be created using {@link Uri#toString()}. + * + *

Type: String (Uri)

+ */ + public static final String FOREGROUND_IMAGE_URI = "foreground_image_uri"; + + /** + * The uri for retrieving the background image to show for this item. This string + * should be created using {@link Uri#toString()}. + * + *

Type: String (Uri)

+ */ + public static final String BACKGROUND_IMAGE_URI = "background_image_uri"; + + /** + * A 0xAARRGGBB color that should be applied to the background. + * + *

Type: INTEGER

+ */ + public static final String COLOR_HINT = "color_hint"; + + /** + * The uri for the badge + */ + public static final String BADGE_URI = "badge_uri"; + + /** + * A 0xAARRGGBB color that should be applied to rendered text so as no + * not conflict with the {@link #COLOR_HINT} or + * {@link #BACKGROUND_IMAGE_URI}. + * + *

Type: INTEGER

+ */ + public static final String TEXT_COLOR_HINT = "text_color_hint"; + } + + public static final class DetailItem implements BaseColumns, DetailItemColumns { + + /** + * Non instantiable. + */ + private DetailItem() {} + } + + protected interface DetailSectionsColumns { + + /** + * Text ID for a section. Can be used to target the section + * + *

Type: String

+ */ + public static final String NAME = "name"; + + /** + * Text that will be shown to the user for navigating between sections. + * + *

Type: String

+ */ + public static final String DISPLAY_HEADER = "display_header"; + + /** + * Primary text for display when a section is visible, such as + * an artist name or movie title. (Optional) + *

+ * This is only valid if {@link #SECTION_TYPE} is + * {@link #SECTION_TYPE_LIST} or {@link #SECTION_TYPE_SECTIONS}. + * + *

Type: String

+ */ + public static final String DISPLAY_NAME = "display_name"; + + /** + * Secondary text for display when a section is visible, such as + * a release date or album title. (Optional) + *

+ * This is only valid if {@link #SECTION_TYPE} is + * {@link #SECTION_TYPE_LIST} or {@link #SECTION_TYPE_SECTIONS}. + * + *

Type: String

+ */ + public static final String DISPLAY_SUBNAME = "display_subname"; + + /** + * Type of item. + *

+ * One of {@link #SECTION_TYPE_BLOB}, {@link #SECTION_TYPE_LIST}, + * {@link #SECTION_TYPE_BLURB}, {@link #SECTION_TYPE_REVIEWS}, or + * {@link #SECTION_TYPE_SECTIONS}. + * + *

Type: Integer

+ */ + public static final String SECTION_TYPE = "section_type"; + + /** + * Value for {@link #SECTION_TYPE} if this section has HTML content. + * This should only be used as a last resort if the other formats can't + * be made to work. + */ + public static final int SECTION_TYPE_BLOB = 0; + + /** + * Value for {@link #SECTION_TYPE} if this section uses the default list + * formatting for its content. + */ + public static final int SECTION_TYPE_LIST = 1; + + /** + * Value for {@link #SECTION_TYPE} if this section uses the default + * formatting for its content. + */ + public static final int SECTION_TYPE_BLURB = 2; + + /** + * Value for {@link #SECTION_TYPE} if this section has review style + * formatting for its content. + */ + public static final int SECTION_TYPE_REVIEWS = 3; + + /** + * Value for {@link #SECTION_TYPE} if this section is multiple related + * sections that can be grouped. For example, seasons of a TV show + * should use this type. + */ + public static final int SECTION_TYPE_SECTIONS = 4; + + /** + * Blob content, either a string or HTML. + *

+ * If HTML, this will be sanitized before displaying in a web view. + *

+ * JavaScript is not allowed. + * + *

Type: String

+ */ + public static final String BLOB_CONTENT = "blob_content"; + + /** + * Action or list of actions available for this section. + *

+ * Only valid if {@link #SECTION_TYPE} = {@link #SECTION_TYPE_BLOB}. + *

+ * This is either a single intent URI or a content URI pointing to a list of + * {@link DetailActions}. + */ + public static final String ACTION_URI = "action_uri"; + + /** + * Content URI. This must be nested under the detail item ID. + *

+ * Only valid if {@link #SECTION_TYPE} is one of + * {@link #SECTION_TYPE_LIST}, {@link #SECTION_TYPE_REVIEWS}, + * {@link #SECTION_TYPE_SECTIONS}. + */ + public static final String CONTENT_URI = "content_uri"; + } + + /** + * A top level listing of the sections for this item, such as "Ratings" or + * "Related." The BLOB_CONTENT column is only valid if + * {@link DetailSectionsColumns#SECTION_TYPE} = + * {@link DetailSectionsColumns#SECTION_TYPE_BLOB}. USER_RATING columns are + * only valid if {@link DetailSectionsColumns#SECTION_TYPE} = + * {@link DetailSectionsColumns#SECTION_TYPE_REVIEWS}. + */ + public static final class DetailSections + implements BaseColumns, DetailSectionsColumns, UserRatingColumns { + /** + * Non instantiable. + */ + private DetailSections() {} + + /** + * Gets a content URI suitable for loading the sections for an item. + */ + public static Uri getSectionsUri(Uri itemUri) { + return itemUri.buildUpon().appendPath(PATH_DETAIL_SECTIONS).build(); + } + } + + protected interface DetailBlurbColumns { + /** + * Primary text that will be shown to the user, generally the title. + * (Optional) + * + *

Type: String

+ */ + public static final String DISPLAY_NAME = "display_name"; + + /** + * A secondary title with more importance than the description, such as + * the artist or director. (Optional) + * + *

Type: String

+ */ + public static final String DISPLAY_SUBNAME = "display_subname"; + + /** + * Long description text of this item. (Optional) + * + *

Type: String

+ */ + public static final String DISPLAY_DESCRIPTION = "display_description"; + + /** + * The category of the item to show to the user, such as "Apps" or + * "Folk". (Optional) + * + *

Type: String

+ */ + public static final String DISPLAY_CATEGORY = "display_category"; + + /** + * The URI for retrieving an image to show. This should be a rating + * badge or other similar icon. This string should be created using + * {@link Uri#toString()}. (Optional) + * + *

Type: String (Uri)

+ */ + public static final String BADGE_URI = "badge_uri"; + } + + public static final class DetailBlurb + implements BaseColumns, DetailBlurbColumns, UserRatingColumns { + /** + * Non instantiable. + */ + private DetailBlurb() {} + } + + protected interface ItemChildrenColumns { + /** + * Primary text that will be shown to the user, generally the title. + * (Optional) + * + *

Type: String

+ */ + public static final String DISPLAY_NAME = "display_name"; + + /** + * A secondary title with more importance than the description, such as + * the artist or director. (Optional) + * + *

Type: String

+ */ + public static final String DISPLAY_SUBNAME = "display_subname"; + + /** + * Long description text of this item. (Optional) + * + *

Type: String

+ */ + public static final String DISPLAY_DESCRIPTION = "display_description"; + + /** + * A number to display next to the item, such as the track or + * episode number. 0 is not allowed. (Optional) + * + *

Type: INTEGER

+ */ + public static final String DISPLAY_NUMBER = "display_number"; + + /** + * Hint for how to display the item. This is either {@link #ITEM_DISPLAY_TYPE_NORMAL} or + * {@link #ITEM_DISPLAY_TYPE_SINGLE_LINE}. + */ + public static final String ITEM_DISPLAY_TYPE = "item_display_type"; + + /** + * Value for {@link #ITEM_DISPLAY_TYPE} which allows for multiple lines. + */ + public static final int ITEM_DISPLAY_TYPE_NORMAL = 0; + + /** + * Value for {@link #ITEM_DISPLAY_TYPE} which hints that the content should be displayed + * on a single line. + */ + public static final int ITEM_DISPLAY_TYPE_SINGLE_LINE = 1; + + /** + * The uri for retrieving the image to show for this item. This string + * should be created using {@link Uri#toString()}. (Optional) + * + *

Type: String (Uri)

+ */ + public static final String IMAGE_URI = "image_uri"; + + /** + * Either an intent URI for an intent that should be triggered or else a content URI + * pointing to a list of actions for this item. + *

+ * If the list has only 1 action per item, it is more efficient to supply an intent URI + * here. (Optional) + * + *

Type: String (Uri)

+ */ + public static final String ACTION_URI = "action_uri"; + } + + protected interface SearchBrowseResult { + public static final String RESULTS_URI = "results_uri"; + /** + * The default width of the expanded image + * + *

Type: INTEGER

+ */ + public static final String DEFAULT_ITEM_WIDTH = "default_item_width"; + + /** + * The default height of the expanded image + * + *

Type: INTEGER

+ */ + public static final String DEFAULT_ITEM_HEIGHT = "default_item_height"; + } + + public static final class DetailChildren + implements BaseColumns, ItemChildrenColumns, UserRatingColumns { + + /** + * Non instantiable. + */ + private DetailChildren() {} + } + + public static final class SearchResults + implements BaseColumns, ItemChildrenColumns, UserRatingColumns, SearchBrowseResult { + + /** + * Non instantiable. + */ + private SearchResults() {} + } + + protected interface MetaColumns { + + /** + * The uri for retrieving the background image to show for this item. This string + * should be created using {@link Uri#toString()}. + * + *

Type: String (Uri)

+ */ + public static final String BACKGROUND_IMAGE_URI = "background_image_uri"; + /** + * Uri pointing to an icon to be used for app branding on this tab. + * This String should be generated using {@link Uri#toString()} + * + *

Type: String (Uri)

+ */ + public static final String BADGE_URI = "badge_uri"; + + /** + * A 0xAARRGGBB color that should be applied to the background when on + * this tab. + * + *

Type: INTEGER

+ */ + public static final String COLOR_HINT = "color_hint"; + } + + public static final class MetaSchema implements BaseColumns, MetaColumns { + + /** + * Non instantiable. + */ + private MetaSchema() {} + } + + protected interface DetailActionsColumns { + + /** + * Text that will be shown to the user. + * + *

Type: String

+ */ + public static final String DISPLAY_NAME = "display_name"; + + /** + * Secondary text that will be shown to the user, such as "from $2.99". + * (Optional) + * + *

Type: String

+ */ + public static final String DISPLAY_SUBNAME = "display_subname"; + + /** + * Intent URI of the form intent:// which will be triggered. + * + *

Type: String (Uri)

+ */ + public static final String INTENT_URI = "intent_uri"; + } + + public static final class DetailActions implements BaseColumns, DetailActionsColumns { + + /** + * Non instantiable. + */ + private DetailActions() {} + } + + /** + * Returns a browse intent with the root included. The root should be a + * base Uri that the browse queries can build off of. + * + * Example: "content://com.google.movies/browse/action" + * + * @param root The authority + path that will be browsed on. + * @param start The index of the header to display expanded first. + * @return + */ + public static Intent getBrowseIntent(Uri root, int start) { + Intent intent = new Intent(ACTION_BROWSE); + intent.setData(root); + intent.putExtra(EXTRA_START_INDEX, start); + return intent; + } + + /** + * Returns a browse intent with the root included. The root should be a + * base Uri that the browse queries can build off of. + * + * Example: "content://com.google.movies/browse/action" + * + * @param root The authority + path that will be browsed on. + * @param startId The _id of the header to display expanded first. + * @return + */ + public static Intent getBrowseIntentById(Uri root, long startId) { + Intent intent = new Intent(ACTION_BROWSE); + intent.setData(root); + intent.putExtra(EXTRA_START_ID, startId); + return intent; + } + + /** + * Returns a details intent for the given root URI. The root should be a URI + * specific to the item being viewed that can be appended to for details + * queries. + * + * Example: "content://com.google.movies/details/75289" + */ + public static Intent getDetailsIntent(Uri root) { + Intent intent = new Intent(ACTION_DETAIL); + intent.setData(root); + return intent; + } +} -- cgit v1.2.3