/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.provider; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.content.ContentResolver; import android.content.ContentValues; import android.content.ContentUris; import android.database.Cursor; import android.database.DatabaseUtils; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.net.Uri; import android.os.Environment; import android.util.Log; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.text.Collator; /** * The Media provider contains meta data for all available media on both internal * and external storage devices. */ public final class MediaStore { private final static String TAG = "MediaStore"; public static final String AUTHORITY = "media"; private static final String CONTENT_AUTHORITY_SLASH = "content://" + AUTHORITY + "/"; /** * Activity Action: Perform a search for media. * Contains at least the {@link android.app.SearchManager#QUERY} extra. * May also contain any combination of the following extras: * EXTRA_MEDIA_ARTIST, EXTRA_MEDIA_ALBUM, EXTRA_MEDIA_TITLE, EXTRA_MEDIA_FOCUS * * @see android.provider.MediaStore#EXTRA_MEDIA_ARTIST * @see android.provider.MediaStore#EXTRA_MEDIA_ALBUM * @see android.provider.MediaStore#EXTRA_MEDIA_TITLE * @see android.provider.MediaStore#EXTRA_MEDIA_FOCUS */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String INTENT_ACTION_MEDIA_SEARCH = "android.intent.action.MEDIA_SEARCH"; /** * The name of the Intent-extra used to define the artist */ public static final String EXTRA_MEDIA_ARTIST = "android.intent.extra.artist"; /** * The name of the Intent-extra used to define the album */ public static final String EXTRA_MEDIA_ALBUM = "android.intent.extra.album"; /** * The name of the Intent-extra used to define the song title */ public static final String EXTRA_MEDIA_TITLE = "android.intent.extra.title"; /** * The name of the Intent-extra used to define the search focus. The search focus * indicates whether the search should be for things related to the artist, album * or song that is identified by the other extras. */ public static final String EXTRA_MEDIA_FOCUS = "android.intent.extra.focus"; /** * The name of the Intent-extra used to control the orientation of a ViewImage or a MovieView. * This is an int property that overrides the activity's requestedOrientation. * @see android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED */ public static final String EXTRA_SCREEN_ORIENTATION = "android.intent.extra.screenOrientation"; /** * The name of an Intent-extra used to control the UI of a ViewImage. * This is a boolean property that overrides the activity's default fullscreen state. * @hide */ public static final String EXTRA_FULL_SCREEN = "android.intent.extra.fullScreen"; /** * The name of an Intent-extra used to control the UI of a ViewImage. * This is a boolean property that specifies whether or not to show action icons. * @hide */ public static final String EXTRA_SHOW_ACTION_ICONS = "android.intent.extra.showActionIcons"; /** * The name of the Intent-extra used to control the onCompletion behavior of a MovieView. * This is a boolean property that specifies whether or not to finish the MovieView activity * when the movie completes playing. The default value is true, which means to automatically * exit the movie player activity when the movie completes playing. */ public static final String EXTRA_FINISH_ON_COMPLETION = "android.intent.extra.finishOnCompletion"; /** * The name of the Intent action used to launch a camera in still image mode. */ public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA"; /** * The name of the Intent action used to launch a camera in video mode. */ public static final String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA"; /** * Standard Intent action that can be sent to have the camera application * capture an image and return it. * <p> * The caller may pass an extra EXTRA_OUTPUT to control where this image will be written. * If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap * object in the extra field. This is useful for applications that only need a small image. * If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri * value of EXTRA_OUTPUT. * @see #EXTRA_OUTPUT * @see #EXTRA_VIDEO_QUALITY */ public final static String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE"; /** * Standard Intent action that can be sent to have the camera application * capture an video and return it. * <p> * The caller may pass in an extra EXTRA_VIDEO_QUALITY to control the video quality. * <p> * The caller may pass in an extra EXTRA_OUTPUT to control * where the video is written. If EXTRA_OUTPUT is not present the video will be * written to the standard location for videos, and the Uri of that location will be * returned in the data field of the Uri. * @see #EXTRA_OUTPUT */ public final static String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE"; /** * The name of the Intent-extra used to control the quality of a recorded video. This is an * integer property. Currently value 0 means low quality, suitable for MMS messages, and * value 1 means high quality. In the future other quality levels may be added. */ public final static String EXTRA_VIDEO_QUALITY = "android.intent.extra.videoQuality"; /** * Specify the maximum allowed size. * @hide */ public final static String EXTRA_SIZE_LIMIT = "android.intent.extra.sizeLimit"; /** * The name of the Intent-extra used to indicate a content resolver Uri to be used to * store the requested image or video. */ public final static String EXTRA_OUTPUT = "output"; /** * Common fields for most MediaProvider tables */ public interface MediaColumns extends BaseColumns { /** * The data stream for the file * <P>Type: DATA STREAM</P> */ public static final String DATA = "_data"; /** * The size of the file in bytes * <P>Type: INTEGER (long)</P> */ public static final String SIZE = "_size"; /** * The display name of the file * <P>Type: TEXT</P> */ public static final String DISPLAY_NAME = "_display_name"; /** * The title of the content * <P>Type: TEXT</P> */ public static final String TITLE = "title"; /** * The time the file was added to the media provider * Units are seconds since 1970. * <P>Type: INTEGER (long)</P> */ public static final String DATE_ADDED = "date_added"; /** * The time the file was last modified * Units are seconds since 1970. * NOTE: This is for internal use by the media scanner. Do not modify this field. * <P>Type: INTEGER (long)</P> */ public static final String DATE_MODIFIED = "date_modified"; /** * The MIME type of the file * <P>Type: TEXT</P> */ public static final String MIME_TYPE = "mime_type"; } /** * Contains meta data for all available images. */ public static final class Images { public interface ImageColumns extends MediaColumns { /** * The description of the image * <P>Type: TEXT</P> */ public static final String DESCRIPTION = "description"; /** * The picasa id of the image * <P>Type: TEXT</P> */ public static final String PICASA_ID = "picasa_id"; /** * Whether the video should be published as public or private * <P>Type: INTEGER</P> */ public static final String IS_PRIVATE = "isprivate"; /** * The latitude where the image was captured. * <P>Type: DOUBLE</P> */ public static final String LATITUDE = "latitude"; /** * The longitude where the image was captured. * <P>Type: DOUBLE</P> */ public static final String LONGITUDE = "longitude"; /** * The date & time that the image was taken in units * of milliseconds since jan 1, 1970. * <P>Type: INTEGER</P> */ public static final String DATE_TAKEN = "datetaken"; /** * The orientation for the image expressed as degrees. * Only degrees 0, 90, 180, 270 will work. * <P>Type: INTEGER</P> */ public static final String ORIENTATION = "orientation"; /** * The mini thumb id. * <P>Type: INTEGER</P> */ public static final String MINI_THUMB_MAGIC = "mini_thumb_magic"; /** * The bucket id of the image. This is a read-only property that * is automatically computed from the DATA column. * <P>Type: TEXT</P> */ public static final String BUCKET_ID = "bucket_id"; /** * The bucket display name of the image. This is a read-only property that * is automatically computed from the DATA column. * <P>Type: TEXT</P> */ public static final String BUCKET_DISPLAY_NAME = "bucket_display_name"; } public static final class Media implements ImageColumns { public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) { return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER); } public static final Cursor query(ContentResolver cr, Uri uri, String[] projection, String where, String orderBy) { return cr.query(uri, projection, where, null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy); } public static final Cursor query(ContentResolver cr, Uri uri, String[] projection, String selection, String [] selectionArgs, String orderBy) { return cr.query(uri, projection, selection, selectionArgs, orderBy == null ? DEFAULT_SORT_ORDER : orderBy); } /** * Retrieves an image for the given url as a {@link Bitmap}. * * @param cr The content resolver to use * @param url The url of the image * @throws FileNotFoundException * @throws IOException */ public static final Bitmap getBitmap(ContentResolver cr, Uri url) throws FileNotFoundException, IOException { InputStream input = cr.openInputStream(url); Bitmap bitmap = BitmapFactory.decodeStream(input); input.close(); return bitmap; } /** * Insert an image and create a thumbnail for it. * * @param cr The content resolver to use * @param imagePath The path to the image to insert * @param name The name of the image * @param description The description of the image * @return The URL to the newly created image * @throws FileNotFoundException */ public static final String insertImage(ContentResolver cr, String imagePath, String name, String description) throws FileNotFoundException { // Check if file exists with a FileInputStream FileInputStream stream = new FileInputStream(imagePath); try { return insertImage(cr, BitmapFactory.decodeFile(imagePath), name, description); } finally { try { stream.close(); } catch (IOException e) { } } } private static final Bitmap StoreThumbnail( ContentResolver cr, Bitmap source, long id, float width, float height, int kind) { // create the matrix to scale it Matrix matrix = new Matrix(); float scaleX = width / source.getWidth(); float scaleY = height / source.getHeight(); matrix.setScale(scaleX, scaleY); Bitmap thumb = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true); ContentValues values = new ContentValues(4); values.put(Images.Thumbnails.KIND, kind); values.put(Images.Thumbnails.IMAGE_ID, (int)id); values.put(Images.Thumbnails.HEIGHT, thumb.getHeight()); values.put(Images.Thumbnails.WIDTH, thumb.getWidth()); Uri url = cr.insert(Images.Thumbnails.EXTERNAL_CONTENT_URI, values); try { OutputStream thumbOut = cr.openOutputStream(url); thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut); thumbOut.close(); return thumb; } catch (FileNotFoundException ex) { return null; } catch (IOException ex) { return null; } } /** * Insert an image and create a thumbnail for it. * * @param cr The content resolver to use * @param source The stream to use for the image * @param title The name of the image * @param description The description of the image * @return The URL to the newly created image, or <code>null</code> if the image failed to be stored * for any reason. */ public static final String insertImage(ContentResolver cr, Bitmap source, String title, String description) { ContentValues values = new ContentValues(); values.put(Images.Media.TITLE, title); values.put(Images.Media.DESCRIPTION, description); values.put(Images.Media.MIME_TYPE, "image/jpeg"); Uri url = null; String stringUrl = null; /* value to be returned */ try { url = cr.insert(EXTERNAL_CONTENT_URI, values); if (source != null) { OutputStream imageOut = cr.openOutputStream(url); try { source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut); } finally { imageOut.close(); } long id = ContentUris.parseId(url); Bitmap miniThumb = StoreThumbnail(cr, source, id, 320F, 240F, Images.Thumbnails.MINI_KIND); Bitmap microThumb = StoreThumbnail(cr, miniThumb, id, 50F, 50F, Images.Thumbnails.MICRO_KIND); } else { Log.e(TAG, "Failed to create thumbnail, removing original"); cr.delete(url, null, null); url = null; } } catch (Exception e) { Log.e(TAG, "Failed to insert image", e); if (url != null) { cr.delete(url, null, null); url = null; } } if (url != null) { stringUrl = url.toString(); } return stringUrl; } /** * Get the content:// style URI for the image media table on the * given volume. * * @param volumeName the name of the volume to get the URI for * @return the URI to the image media table on the given volume */ public static Uri getContentUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/images/media"); } /** * The content:// style URI for the internal storage. */ public static final Uri INTERNAL_CONTENT_URI = getContentUri("internal"); /** * The content:// style URI for the "primary" external storage * volume. */ public static final Uri EXTERNAL_CONTENT_URI = getContentUri("external"); /** * The MIME type of of this directory of * images. Note that each entry in this directory will have a standard * image MIME type as appropriate -- for example, image/jpeg. */ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/image"; /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = ImageColumns.BUCKET_DISPLAY_NAME; } public static class Thumbnails implements BaseColumns { public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) { return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER); } public static final Cursor queryMiniThumbnails(ContentResolver cr, Uri uri, int kind, String[] projection) { return cr.query(uri, projection, "kind = " + kind, null, DEFAULT_SORT_ORDER); } public static final Cursor queryMiniThumbnail(ContentResolver cr, long origId, int kind, String[] projection) { return cr.query(EXTERNAL_CONTENT_URI, projection, IMAGE_ID + " = " + origId + " AND " + KIND + " = " + kind, null, null); } /** * Get the content:// style URI for the image media table on the * given volume. * * @param volumeName the name of the volume to get the URI for * @return the URI to the image media table on the given volume */ public static Uri getContentUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/images/thumbnails"); } /** * The content:// style URI for the internal storage. */ public static final Uri INTERNAL_CONTENT_URI = getContentUri("internal"); /** * The content:// style URI for the "primary" external storage * volume. */ public static final Uri EXTERNAL_CONTENT_URI = getContentUri("external"); /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = "image_id ASC"; /** * The data stream for the thumbnail * <P>Type: DATA STREAM</P> */ public static final String DATA = "_data"; /** * The original image for the thumbnal * <P>Type: INTEGER (ID from Images table)</P> */ public static final String IMAGE_ID = "image_id"; /** * The kind of the thumbnail * <P>Type: INTEGER (One of the values below)</P> */ public static final String KIND = "kind"; public static final int MINI_KIND = 1; public static final int FULL_SCREEN_KIND = 2; public static final int MICRO_KIND = 3; /** * The width of the thumbnal * <P>Type: INTEGER (long)</P> */ public static final String WIDTH = "width"; /** * The height of the thumbnail * <P>Type: INTEGER (long)</P> */ public static final String HEIGHT = "height"; } } /** * Container for all audio content. */ public static final class Audio { /** * Columns for audio file that show up in multiple tables. */ public interface AudioColumns extends MediaColumns { /** * A non human readable key calculated from the TITLE, used for * searching, sorting and grouping * <P>Type: TEXT</P> */ public static final String TITLE_KEY = "title_key"; /** * The duration of the audio file, in ms * <P>Type: INTEGER (long)</P> */ public static final String DURATION = "duration"; /** * The position, in ms, playback was at when playback for this file * was last stopped. * <P>Type: INTEGER (long)</P> * @hide */ public static final String BOOKMARK = "bookmark"; /** * The id of the artist who created the audio file, if any * <P>Type: INTEGER (long)</P> */ public static final String ARTIST_ID = "artist_id"; /** * The artist who created the audio file, if any * <P>Type: TEXT</P> */ public static final String ARTIST = "artist"; /** * A non human readable key calculated from the ARTIST, used for * searching, sorting and grouping * <P>Type: TEXT</P> */ public static final String ARTIST_KEY = "artist_key"; /** * The composer of the audio file, if any * <P>Type: TEXT</P> */ public static final String COMPOSER = "composer"; /** * The id of the album the audio file is from, if any * <P>Type: INTEGER (long)</P> */ public static final String ALBUM_ID = "album_id"; /** * The album the audio file is from, if any * <P>Type: TEXT</P> */ public static final String ALBUM = "album"; /** * A non human readable key calculated from the ALBUM, used for * searching, sorting and grouping * <P>Type: TEXT</P> */ public static final String ALBUM_KEY = "album_key"; /** * A URI to the album art, if any * <P>Type: TEXT</P> */ public static final String ALBUM_ART = "album_art"; /** * The track number of this song on the album, if any. * This number encodes both the track number and the * disc number. For multi-disc sets, this number will * be 1xxx for tracks on the first disc, 2xxx for tracks * on the second disc, etc. * <P>Type: INTEGER</P> */ public static final String TRACK = "track"; /** * The year the audio file was recorded, if any * <P>Type: INTEGER</P> */ public static final String YEAR = "year"; /** * Non-zero if the audio file is music * <P>Type: INTEGER (boolean)</P> */ public static final String IS_MUSIC = "is_music"; /** * Non-zero if the audio file is a podcast * <P>Type: INTEGER (boolean)</P> * @hide */ public static final String IS_PODCAST = "is_podcast"; /** * Non-zero id the audio file may be a ringtone * <P>Type: INTEGER (boolean)</P> */ public static final String IS_RINGTONE = "is_ringtone"; /** * Non-zero id the audio file may be an alarm * <P>Type: INTEGER (boolean)</P> */ public static final String IS_ALARM = "is_alarm"; /** * Non-zero id the audio file may be a notification sound * <P>Type: INTEGER (boolean)</P> */ public static final String IS_NOTIFICATION = "is_notification"; } /** * Converts a name to a "key" that can be used for grouping, sorting * and searching. * The rules that govern this conversion are: * - remove 'special' characters like ()[]'!?., * - remove leading/trailing spaces * - convert everything to lowercase * - remove leading "the ", "an " and "a " * - remove trailing ", the|an|a" * - remove accents. This step leaves us with CollationKey data, * which is not human readable * * @param name The artist or album name to convert * @return The "key" for the given name. */ public static String keyFor(String name) { if (name != null) { if (name.equals(android.media.MediaFile.UNKNOWN_STRING)) { return "\001"; } name = name.trim().toLowerCase(); if (name.startsWith("the ")) { name = name.substring(4); } if (name.startsWith("an ")) { name = name.substring(3); } if (name.startsWith("a ")) { name = name.substring(2); } if (name.endsWith(", the") || name.endsWith(",the") || name.endsWith(", an") || name.endsWith(",an") || name.endsWith(", a") || name.endsWith(",a")) { name = name.substring(0, name.lastIndexOf(',')); } name = name.replaceAll("[\\[\\]\\(\\)'.,?!]", "").trim(); if (name.length() > 0) { // Insert a separator between the characters to avoid // matches on a partial character. If we ever change // to start-of-word-only matches, this can be removed. StringBuilder b = new StringBuilder(); b.append('.'); int nl = name.length(); for (int i = 0; i < nl; i++) { b.append(name.charAt(i)); b.append('.'); } name = b.toString(); return DatabaseUtils.getCollationKey(name); } else { return ""; } } return null; } public static final class Media implements AudioColumns { /** * Get the content:// style URI for the audio media table on the * given volume. * * @param volumeName the name of the volume to get the URI for * @return the URI to the audio media table on the given volume */ public static Uri getContentUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/audio/media"); } public static Uri getContentUriForPath(String path) { return (path.startsWith(Environment.getExternalStorageDirectory().getPath()) ? EXTERNAL_CONTENT_URI : INTERNAL_CONTENT_URI); } /** * The content:// style URI for the internal storage. */ public static final Uri INTERNAL_CONTENT_URI = getContentUri("internal"); /** * The content:// style URI for the "primary" external storage * volume. */ public static final Uri EXTERNAL_CONTENT_URI = getContentUri("external"); /** * The MIME type for this table. */ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/audio"; /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = TITLE; /** * Activity Action: Start SoundRecorder application. * <p>Input: nothing. * <p>Output: An uri to the recorded sound stored in the Media Library * if the recording was successful. * May also contain the extra EXTRA_MAX_BYTES. * @see #EXTRA_MAX_BYTES */ public static final String RECORD_SOUND_ACTION = "android.provider.MediaStore.RECORD_SOUND"; /** * The name of the Intent-extra used to define a maximum file size for * a recording made by the SoundRecorder application. * * @see #RECORD_SOUND_ACTION */ public static final String EXTRA_MAX_BYTES = "android.provider.MediaStore.extra.MAX_BYTES"; } /** * Columns representing an audio genre */ public interface GenresColumns { /** * The name of the genre * <P>Type: TEXT</P> */ public static final String NAME = "name"; } /** * Contains all genres for audio files */ public static final class Genres implements BaseColumns, GenresColumns { /** * Get the content:// style URI for the audio genres table on the * given volume. * * @param volumeName the name of the volume to get the URI for * @return the URI to the audio genres table on the given volume */ public static Uri getContentUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/audio/genres"); } /** * The content:// style URI for the internal storage. */ public static final Uri INTERNAL_CONTENT_URI = getContentUri("internal"); /** * The content:// style URI for the "primary" external storage * volume. */ public static final Uri EXTERNAL_CONTENT_URI = getContentUri("external"); /** * The MIME type for this table. */ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/genre"; /** * The MIME type for entries in this table. */ public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/genre"; /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = NAME; /** * Sub-directory of each genre containing all members. */ public static final class Members implements AudioColumns { public static final Uri getContentUri(String volumeName, long genreId) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/audio/genres/" + genreId + "/members"); } /** * A subdirectory of each genre containing all member audio files. */ public static final String CONTENT_DIRECTORY = "members"; /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = TITLE; /** * The ID of the audio file * <P>Type: INTEGER (long)</P> */ public static final String AUDIO_ID = "audio_id"; /** * The ID of the genre * <P>Type: INTEGER (long)</P> */ public static final String GENRE_ID = "genre_id"; } } /** * Columns representing a playlist */ public interface PlaylistsColumns { /** * The name of the playlist * <P>Type: TEXT</P> */ public static final String NAME = "name"; /** * The data stream for the playlist file * <P>Type: DATA STREAM</P> */ public static final String DATA = "_data"; /** * The time the file was added to the media provider * Units are seconds since 1970. * <P>Type: INTEGER (long)</P> */ public static final String DATE_ADDED = "date_added"; /** * The time the file was last modified * Units are seconds since 1970. * NOTE: This is for internal use by the media scanner. Do not modify this field. * <P>Type: INTEGER (long)</P> */ public static final String DATE_MODIFIED = "date_modified"; } /** * Contains playlists for audio files */ public static final class Playlists implements BaseColumns, PlaylistsColumns { /** * Get the content:// style URI for the audio playlists table on the * given volume. * * @param volumeName the name of the volume to get the URI for * @return the URI to the audio playlists table on the given volume */ public static Uri getContentUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/audio/playlists"); } /** * The content:// style URI for the internal storage. */ public static final Uri INTERNAL_CONTENT_URI = getContentUri("internal"); /** * The content:// style URI for the "primary" external storage * volume. */ public static final Uri EXTERNAL_CONTENT_URI = getContentUri("external"); /** * The MIME type for this table. */ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/playlist"; /** * The MIME type for entries in this table. */ public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/playlist"; /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = NAME; /** * Sub-directory of each playlist containing all members. */ public static final class Members implements AudioColumns { public static final Uri getContentUri(String volumeName, long playlistId) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/audio/playlists/" + playlistId + "/members"); } /** * The ID within the playlist. */ public static final String _ID = "_id"; /** * A subdirectory of each playlist containing all member audio * files. */ public static final String CONTENT_DIRECTORY = "members"; /** * The ID of the audio file * <P>Type: INTEGER (long)</P> */ public static final String AUDIO_ID = "audio_id"; /** * The ID of the playlist * <P>Type: INTEGER (long)</P> */ public static final String PLAYLIST_ID = "playlist_id"; /** * The order of the songs in the playlist * <P>Type: INTEGER (long)></P> */ public static final String PLAY_ORDER = "play_order"; /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = PLAY_ORDER; } } /** * Columns representing an artist */ public interface ArtistColumns { /** * The artist who created the audio file, if any * <P>Type: TEXT</P> */ public static final String ARTIST = "artist"; /** * A non human readable key calculated from the ARTIST, used for * searching, sorting and grouping * <P>Type: TEXT</P> */ public static final String ARTIST_KEY = "artist_key"; /** * The number of albums in the database for this artist */ public static final String NUMBER_OF_ALBUMS = "number_of_albums"; /** * The number of albums in the database for this artist */ public static final String NUMBER_OF_TRACKS = "number_of_tracks"; } /** * Contains artists for audio files */ public static final class Artists implements BaseColumns, ArtistColumns { /** * Get the content:// style URI for the artists table on the * given volume. * * @param volumeName the name of the volume to get the URI for * @return the URI to the audio artists table on the given volume */ public static Uri getContentUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/audio/artists"); } /** * The content:// style URI for the internal storage. */ public static final Uri INTERNAL_CONTENT_URI = getContentUri("internal"); /** * The content:// style URI for the "primary" external storage * volume. */ public static final Uri EXTERNAL_CONTENT_URI = getContentUri("external"); /** * The MIME type for this table. */ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/artists"; /** * The MIME type for entries in this table. */ public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/artist"; /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = ARTIST_KEY; /** * Sub-directory of each artist containing all albums on which * a song by the artist appears. */ public static final class Albums implements AlbumColumns { public static final Uri getContentUri(String volumeName, long artistId) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/audio/artists/" + artistId + "/albums"); } } } /** * Columns representing an album */ public interface AlbumColumns { /** * The id for the album * <P>Type: INTEGER</P> */ public static final String ALBUM_ID = "album_id"; /** * The album on which the audio file appears, if any * <P>Type: TEXT</P> */ public static final String ALBUM = "album"; /** * The artist whose songs appear on this album * <P>Type: TEXT</P> */ public static final String ARTIST = "artist"; /** * The number of songs on this album * <P>Type: INTEGER</P> */ public static final String NUMBER_OF_SONGS = "numsongs"; /** * This column is available when getting album info via artist, * and indicates the number of songs on the album by the given * artist. * <P>Type: INTEGER</P> */ public static final String NUMBER_OF_SONGS_FOR_ARTIST = "numsongs_by_artist"; /** * The year in which the earliest songs * on this album were released. This will often * be the same as {@link #LAST_YEAR}, but for compilation albums * they might differ. * <P>Type: INTEGER</P> */ public static final String FIRST_YEAR = "minyear"; /** * The year in which the latest songs * on this album were released. This will often * be the same as {@link #FIRST_YEAR}, but for compilation albums * they might differ. * <P>Type: INTEGER</P> */ public static final String LAST_YEAR = "maxyear"; /** * A non human readable key calculated from the ALBUM, used for * searching, sorting and grouping * <P>Type: TEXT</P> */ public static final String ALBUM_KEY = "album_key"; /** * Cached album art. * <P>Type: TEXT</P> */ public static final String ALBUM_ART = "album_art"; } /** * Contains artists for audio files */ public static final class Albums implements BaseColumns, AlbumColumns { /** * Get the content:// style URI for the albums table on the * given volume. * * @param volumeName the name of the volume to get the URI for * @return the URI to the audio albums table on the given volume */ public static Uri getContentUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/audio/albums"); } /** * The content:// style URI for the internal storage. */ public static final Uri INTERNAL_CONTENT_URI = getContentUri("internal"); /** * The content:// style URI for the "primary" external storage * volume. */ public static final Uri EXTERNAL_CONTENT_URI = getContentUri("external"); /** * The MIME type for this table. */ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/albums"; /** * The MIME type for entries in this table. */ public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/album"; /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = ALBUM_KEY; } } public static final class Video { /** * The default sort order for this table. */ public static final String DEFAULT_SORT_ORDER = MediaColumns.DISPLAY_NAME; public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) { return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER); } public interface VideoColumns extends MediaColumns { /** * The duration of the video file, in ms * <P>Type: INTEGER (long)</P> */ public static final String DURATION = "duration"; /** * The artist who created the video file, if any * <P>Type: TEXT</P> */ public static final String ARTIST = "artist"; /** * The album the video file is from, if any * <P>Type: TEXT</P> */ public static final String ALBUM = "album"; /** * The resolution of the video file, formatted as "XxY" * <P>Type: TEXT</P> */ public static final String RESOLUTION = "resolution"; /** * The description of the video recording * <P>Type: TEXT</P> */ public static final String DESCRIPTION = "description"; /** * Whether the video should be published as public or private * <P>Type: INTEGER</P> */ public static final String IS_PRIVATE = "isprivate"; /** * The user-added tags associated with a video * <P>Type: TEXT</P> */ public static final String TAGS = "tags"; /** * The YouTube category of the video * <P>Type: TEXT</P> */ public static final String CATEGORY = "category"; /** * The language of the video * <P>Type: TEXT</P> */ public static final String LANGUAGE = "language"; /** * The latitude where the image was captured. * <P>Type: DOUBLE</P> */ public static final String LATITUDE = "latitude"; /** * The longitude where the image was captured. * <P>Type: DOUBLE</P> */ public static final String LONGITUDE = "longitude"; /** * The date & time that the image was taken in units * of milliseconds since jan 1, 1970. * <P>Type: INTEGER</P> */ public static final String DATE_TAKEN = "datetaken"; /** * The mini thumb id. * <P>Type: INTEGER</P> */ public static final String MINI_THUMB_MAGIC = "mini_thumb_magic"; /** * The bucket id of the video. This is a read-only property that * is automatically computed from the DATA column. * <P>Type: TEXT</P> */ public static final String BUCKET_ID = "bucket_id"; /** * The bucket display name of the video. This is a read-only property that * is automatically computed from the DATA column. * <P>Type: TEXT</P> */ public static final String BUCKET_DISPLAY_NAME = "bucket_display_name"; /** * The bookmark for the video. Time in ms. Represents the location in the video that the * video should start playing at the next time it is opened. If the value is null or * out of the range 0..DURATION-1 then the video should start playing from the * beginning. * <P>Type: INTEGER</P> */ public static final String BOOKMARK = "bookmark"; } public static final class Media implements VideoColumns { /** * Get the content:// style URI for the video media table on the * given volume. * * @param volumeName the name of the volume to get the URI for * @return the URI to the video media table on the given volume */ public static Uri getContentUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/video/media"); } /** * The content:// style URI for the internal storage. */ public static final Uri INTERNAL_CONTENT_URI = getContentUri("internal"); /** * The content:// style URI for the "primary" external storage * volume. */ public static final Uri EXTERNAL_CONTENT_URI = getContentUri("external"); /** * The MIME type for this table. */ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/video"; /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = TITLE; } } /** * Uri for querying the state of the media scanner. */ public static Uri getMediaScannerUri() { return Uri.parse(CONTENT_AUTHORITY_SLASH + "none/media_scanner"); } /** * Name of current volume being scanned by the media scanner. */ public static final String MEDIA_SCANNER_VOLUME = "volume"; }