/*
 * 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.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.UriPermission;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.MiniThumbFile;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.service.media.CameraPrewarmService;
import android.util.Log;

import libcore.io.IoUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;

The Media provider contains meta data for all available media on both internal and external storage devices.
/** * 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 + "/";
The method name used by the media scanner and mtp to tell the media provider to rescan and reclassify that have become unhidden because of renaming folders or removing nomedia files
@hide
/** * The method name used by the media scanner and mtp to tell the media provider to * rescan and reclassify that have become unhidden because of renaming folders or * removing nomedia files * @hide */
public static final String UNHIDE_CALL = "unhide";
The method name used by the media scanner service to reload all localized ringtone titles due to a locale change.
@hide
/** * The method name used by the media scanner service to reload all localized ringtone titles due * to a locale change. * @hide */
public static final String RETRANSLATE_CALL = "update_titles";
This is for internal use by the media scanner only. Name of the (optional) Uri parameter that determines whether to skip deleting the file pointed to by the _data column, when deleting the database entry. The only appropriate value for this parameter is "false", in which case the delete will be skipped. Note especially that setting this to true, or omitting the parameter altogether, will perform the default action, which is different for different types of media.
@hide
/** * This is for internal use by the media scanner only. * Name of the (optional) Uri parameter that determines whether to skip deleting * the file pointed to by the _data column, when deleting the database entry. * The only appropriate value for this parameter is "false", in which case the * delete will be skipped. Note especially that setting this to true, or omitting * the parameter altogether, will perform the default action, which is different * for different types of media. * @hide */
public static final String PARAM_DELETE_DATA = "deletedata";
Activity Action: Launch a music player. The activity should be able to play, browse, or manipulate music files stored on the device.
Deprecated:Use Intent.CATEGORY_APP_MUSIC instead.
/** * Activity Action: Launch a music player. * The activity should be able to play, browse, or manipulate music files stored on the device. * * @deprecated Use {@link android.content.Intent#CATEGORY_APP_MUSIC} instead. */
@Deprecated @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String INTENT_ACTION_MUSIC_PLAYER = "android.intent.action.MUSIC_PLAYER";
Activity Action: Perform a search for media. Contains at least the 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 Also:
/** * 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";
An intent to perform a search for music media and automatically play content from the result when possible. This can be fired, for example, by the result of a voice recognition command to listen to music.

This intent always includes the EXTRA_MEDIA_FOCUS and SearchManager.QUERY extras. The EXTRA_MEDIA_FOCUS extra determines the search mode, and the value of the SearchManager.QUERY extra depends on the search mode. For more information about the search modes for this intent, see Play music based on a search query in Common Intents.

This intent makes the most sense for apps that can support large-scale search of music, such as services connected to an online database of music which can be streamed and played on the device.

/** * An intent to perform a search for music media and automatically play content from the * result when possible. This can be fired, for example, by the result of a voice recognition * command to listen to music. * <p>This intent always includes the {@link android.provider.MediaStore#EXTRA_MEDIA_FOCUS} * and {@link android.app.SearchManager#QUERY} extras. The * {@link android.provider.MediaStore#EXTRA_MEDIA_FOCUS} extra determines the search mode, and * the value of the {@link android.app.SearchManager#QUERY} extra depends on the search mode. * For more information about the search modes for this intent, see * <a href="{@docRoot}guide/components/intents-common.html#PlaySearch">Play music based * on a search query</a> in <a href="{@docRoot}guide/components/intents-common.html">Common * Intents</a>.</p> * * <p>This intent makes the most sense for apps that can support large-scale search of music, * such as services connected to an online database of music which can be streamed and played * on the device.</p> */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH = "android.media.action.MEDIA_PLAY_FROM_SEARCH";
An intent to perform a search for readable media and automatically play content from the result when possible. This can be fired, for example, by the result of a voice recognition command to read a book or magazine.

Contains the SearchManager.QUERY extra, which is a string that can contain any type of unstructured text search, like the name of a book or magazine, an author a genre, a publisher, or any combination of these.

Because this intent includes an open-ended unstructured search string, it makes the most sense for apps that can support large-scale search of text media, such as services connected to an online database of books and/or magazines which can be read on the device.

/** * An intent to perform a search for readable media and automatically play content from the * result when possible. This can be fired, for example, by the result of a voice recognition * command to read a book or magazine. * <p> * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string that can * contain any type of unstructured text search, like the name of a book or magazine, an author * a genre, a publisher, or any combination of these. * <p> * Because this intent includes an open-ended unstructured search string, it makes the most * sense for apps that can support large-scale search of text media, such as services connected * to an online database of books and/or magazines which can be read on the device. */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String INTENT_ACTION_TEXT_OPEN_FROM_SEARCH = "android.media.action.TEXT_OPEN_FROM_SEARCH";
An intent to perform a search for video media and automatically play content from the result when possible. This can be fired, for example, by the result of a voice recognition command to play movies.

Contains the SearchManager.QUERY extra, which is a string that can contain any type of unstructured video search, like the name of a movie, one or more actors, a genre, or any combination of these.

Because this intent includes an open-ended unstructured search string, it makes the most sense for apps that can support large-scale search of video, such as services connected to an online database of videos which can be streamed and played on the device.

/** * An intent to perform a search for video media and automatically play content from the * result when possible. This can be fired, for example, by the result of a voice recognition * command to play movies. * <p> * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string that can * contain any type of unstructured video search, like the name of a movie, one or more actors, * a genre, or any combination of these. * <p> * Because this intent includes an open-ended unstructured search string, it makes the most * sense for apps that can support large-scale search of video, such as services connected to an * online database of videos which can be streamed and played on the device. */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH = "android.media.action.VIDEO_PLAY_FROM_SEARCH";
The name of the Intent-extra used to define the artist
/** * 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
/** * 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
/** * 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 genre.
/** * The name of the Intent-extra used to define the genre. */
public static final String EXTRA_MEDIA_GENRE = "android.intent.extra.genre";
The name of the Intent-extra used to define the playlist.
/** * The name of the Intent-extra used to define the playlist. */
public static final String EXTRA_MEDIA_PLAYLIST = "android.intent.extra.playlist";
The name of the Intent-extra used to define the radio channel.
/** * The name of the Intent-extra used to define the radio channel. */
public static final String EXTRA_MEDIA_RADIO_CHANNEL = "android.intent.extra.radio_channel";
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.
/** * 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 Also:
  • SCREEN_ORIENTATION_UNSPECIFIED
/** * 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.
/** * 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. */
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.
/** * 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. */
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.
/** * 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.
/** * The name of the Intent action used to launch a camera in still image mode. */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
Name under which an activity handling INTENT_ACTION_STILL_IMAGE_CAMERA or INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE publishes the service name for its prewarm service.

This meta-data should reference the fully qualified class name of the prewarm service extending CameraPrewarmService.

The prewarm service will get bound and receive a prewarm signal CameraPrewarmService.onPrewarm() when a camera launch intent fire might be imminent. An application implementing a prewarm service should do the absolute minimum amount of work to initialize the camera in order to reduce startup time in likely case that shortly after a camera launch intent would be sent.

/** * Name under which an activity handling {@link #INTENT_ACTION_STILL_IMAGE_CAMERA} or * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE} publishes the service name for its prewarm * service. * <p> * This meta-data should reference the fully qualified class name of the prewarm service * extending {@link CameraPrewarmService}. * <p> * The prewarm service will get bound and receive a prewarm signal * {@link CameraPrewarmService#onPrewarm()} when a camera launch intent fire might be imminent. * An application implementing a prewarm service should do the absolute minimum amount of work * to initialize the camera in order to reduce startup time in likely case that shortly after a * camera launch intent would be sent. */
public static final String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE = "android.media.still_image_camera_preview_service";
The name of the Intent action used to launch a camera in still image mode for use when the device is secured (e.g. with a pin, password, pattern, or face unlock). Applications responding to this intent must not expose any personal content like existing photos or videos on the device. The applications should be careful not to share any photo or video with other applications or internet. The activity should use LayoutParams.FLAG_SHOW_WHEN_LOCKED to display on top of the lock screen while secured. There is no activity stack when this flag is used, so launching more than one activity is strongly discouraged.
/** * The name of the Intent action used to launch a camera in still image mode * for use when the device is secured (e.g. with a pin, password, pattern, * or face unlock). Applications responding to this intent must not expose * any personal content like existing photos or videos on the device. The * applications should be careful not to share any photo or video with other * applications or internet. The activity should use {@link * android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} to display * on top of the lock screen while secured. There is no activity stack when * this flag is used, so launching more than one activity is strongly * discouraged. */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE = "android.media.action.STILL_IMAGE_CAMERA_SECURE";
The name of the Intent action used to launch a camera in video mode.
/** * The name of the Intent action used to launch a camera in video mode. */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 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.

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. As of VERSION_CODES.LOLLIPOP, this uri can also be supplied through Intent.setClipData(ClipData). If using this approach, you still must supply the uri through the EXTRA_OUTPUT field for compatibility with old applications. If you don't set a ClipData, it will be copied there for you when calling Context.startActivity(Intent).

Note: if you app targets M and above and declares as using the CAMERA.CAMERA permission which is not granted, then attempting to use this action will result in a SecurityException. @see #EXTRA_OUTPUT

/** * 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. * As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this uri can also be supplied through * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications. * If you don't set a ClipData, it will be copied there for you when calling * {@link Context#startActivity(Intent)}. * * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#M M} and above * and declares as using the {@link android.Manifest.permission#CAMERA} permission which * is not granted, then attempting to use this action will result in a {@link * java.lang.SecurityException}. * * @see #EXTRA_OUTPUT */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public final static String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
Intent action that can be sent to have the camera application capture an image and return it when the device is secured (e.g. with a pin, password, pattern, or face unlock). Applications responding to this intent must not expose any personal content like existing photos or videos on the device. The applications should be careful not to share any photo or video with other applications or internet. The activity should use LayoutParams.FLAG_SHOW_WHEN_LOCKED to display on top of the lock screen while secured. There is no activity stack when this flag is used, so launching more than one activity is strongly discouraged.

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. As of VERSION_CODES.LOLLIPOP, this uri can also be supplied through Intent.setClipData(ClipData). If using this approach, you still must supply the uri through the EXTRA_OUTPUT field for compatibility with old applications. If you don't set a ClipData, it will be copied there for you when calling Context.startActivity(Intent).

See Also:
/** * Intent action that can be sent to have the camera application capture an image and return * it when the device is secured (e.g. with a pin, password, pattern, or face unlock). * Applications responding to this intent must not expose any personal content like existing * photos or videos on the device. The applications should be careful not to share any photo * or video with other applications or internet. The activity should use {@link * android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} to display on top of the * lock screen while secured. There is no activity stack when this flag is used, so * launching more than one activity is strongly discouraged. * <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. * As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this uri can also be supplied through * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications. * If you don't set a ClipData, it will be copied there for you when calling * {@link Context#startActivity(Intent)}. * * @see #ACTION_IMAGE_CAPTURE * @see #EXTRA_OUTPUT */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
Standard Intent action that can be sent to have the camera application capture a video and return it.

The caller may pass in an extra EXTRA_VIDEO_QUALITY to control the video quality.

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. As of VERSION_CODES.LOLLIPOP, this uri can also be supplied through Intent.setClipData(ClipData). If using this approach, you still must supply the uri through the EXTRA_OUTPUT field for compatibility with old applications. If you don't set a ClipData, it will be copied there for you when calling Context.startActivity(Intent).

Note: if you app targets M and above and declares as using the CAMERA.CAMERA permission which is not granted, then atempting to use this action will result in a SecurityException.

See Also:
/** * Standard Intent action that can be sent to have the camera application * capture a 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. * As of {@link android.os.Build.VERSION_CODES#LOLLIPOP}, this uri can also be supplied through * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications. * If you don't set a ClipData, it will be copied there for you when calling * {@link Context#startActivity(Intent)}. * * <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#M M} and above * and declares as using the {@link android.Manifest.permission#CAMERA} permission which * is not granted, then atempting to use this action will result in a {@link * java.lang.SecurityException}. * * @see #EXTRA_OUTPUT * @see #EXTRA_VIDEO_QUALITY * @see #EXTRA_SIZE_LIMIT * @see #EXTRA_DURATION_LIMIT */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 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.
/** * 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.
/** * Specify the maximum allowed size. */
public final static String EXTRA_SIZE_LIMIT = "android.intent.extra.sizeLimit";
Specify the maximum allowed recording duration in seconds.
/** * Specify the maximum allowed recording duration in seconds. */
public final static String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
The name of the Intent-extra used to indicate a content resolver Uri to be used to store the requested image or video.
/** * 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";
The string that is used when a media attribute is not known. For example, if an audio file does not have any meta data, the artist and album columns will be set to this value.
/** * The string that is used when a media attribute is not known. For example, * if an audio file does not have any meta data, the artist and album columns * will be set to this value. */
public static final String UNKNOWN_STRING = "<unknown>";
Common fields for most MediaProvider tables
/** * Common fields for most MediaProvider tables */
public interface MediaColumns extends BaseColumns {
Path to the file on disk.

Note that apps may not have filesystem permissions to directly access this path. Instead of trying to open this path directly, apps should use ContentResolver.openFileDescriptor(Uri, String) to gain access.

Type: TEXT

/** * Path to the file on disk. * <p> * Note that apps may not have filesystem permissions to directly access * this path. Instead of trying to open this path directly, apps should * use {@link ContentResolver#openFileDescriptor(Uri, String)} to gain * access. * <p> * Type: TEXT */
public static final String DATA = "_data";
The size of the file in bytes

Type: INTEGER (long)

/** * The size of the file in bytes * <P>Type: INTEGER (long)</P> */
public static final String SIZE = "_size";
The display name of the file

Type: TEXT

/** * The display name of the file * <P>Type: TEXT</P> */
public static final String DISPLAY_NAME = "_display_name";
The title of the content

Type: TEXT

/** * 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.

Type: INTEGER (long)

/** * 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.

Type: INTEGER (long)

/** * 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

Type: TEXT

/** * The MIME type of the file * <P>Type: TEXT</P> */
public static final String MIME_TYPE = "mime_type";
The MTP object handle of a newly transfered file. Used to pass the new file's object handle through the media scanner from MTP to the media provider For internal use only by MTP, media scanner and media provider.

Type: INTEGER

@hide
/** * The MTP object handle of a newly transfered file. * Used to pass the new file's object handle through the media scanner * from MTP to the media provider * For internal use only by MTP, media scanner and media provider. * <P>Type: INTEGER</P> * @hide */
public static final String MEDIA_SCANNER_NEW_OBJECT_ID = "media_scanner_new_object_id";
Non-zero if the media file is drm-protected

Type: INTEGER (boolean)

@hide
/** * Non-zero if the media file is drm-protected * <P>Type: INTEGER (boolean)</P> * @hide */
public static final String IS_DRM = "is_drm";
The width of the image/video in pixels.
/** * The width of the image/video in pixels. */
public static final String WIDTH = "width";
The height of the image/video in pixels.
/** * The height of the image/video in pixels. */
public static final String HEIGHT = "height"; }
Media provider table containing an index of all files in the media storage, including non-media files. This should be used by applications that work with non-media file types (text, HTML, PDF, etc) as well as applications that need to work with multiple media file types in a single query.
/** * Media provider table containing an index of all files in the media storage, * including non-media files. This should be used by applications that work with * non-media file types (text, HTML, PDF, etc) as well as applications that need to * work with multiple media file types in a single query. */
public static final class Files {
Get the content:// style URI for the files table on the given volume.
Params:
  • volumeName – the name of the volume to get the URI for
Returns:the URI to the files table on the given volume
/** * Get the content:// style URI for the files table on the * given volume. * * @param volumeName the name of the volume to get the URI for * @return the URI to the files table on the given volume */
public static Uri getContentUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/file"); }
Get the content:// style URI for a single row in the files table on the given volume.
Params:
  • volumeName – the name of the volume to get the URI for
  • rowId – the file to get the URI for
Returns:the URI to the files table on the given volume
/** * Get the content:// style URI for a single row in the files table on the * given volume. * * @param volumeName the name of the volume to get the URI for * @param rowId the file to get the URI for * @return the URI to the files table on the given volume */
public static final Uri getContentUri(String volumeName, long rowId) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/file/" + rowId); }
For use only by the MTP implementation.
@hide
/** * For use only by the MTP implementation. * @hide */
public static Uri getMtpObjectsUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/object"); }
For use only by the MTP implementation.
@hide
/** * For use only by the MTP implementation. * @hide */
public static final Uri getMtpObjectsUri(String volumeName, long fileId) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/object/" + fileId); }
Used to implement the MTP GetObjectReferences and SetObjectReferences commands.
@hide
/** * Used to implement the MTP GetObjectReferences and SetObjectReferences commands. * @hide */
public static final Uri getMtpReferencesUri(String volumeName, long fileId) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/object/" + fileId + "/references"); }
Used to trigger special logic for directories.
@hide
/** * Used to trigger special logic for directories. * @hide */
public static final Uri getDirectoryUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/dir"); }
Fields for master table for all media files. Table also contains MediaColumns._ID, DATA, SIZE and DATE_MODIFIED.
/** * Fields for master table for all media files. * Table also contains MediaColumns._ID, DATA, SIZE and DATE_MODIFIED. */
public interface FileColumns extends MediaColumns {
The MTP storage ID of the file

Type: INTEGER

@hide
/** * The MTP storage ID of the file * <P>Type: INTEGER</P> * @hide */
public static final String STORAGE_ID = "storage_id";
The MTP format code of the file

Type: INTEGER

@hide
/** * The MTP format code of the file * <P>Type: INTEGER</P> * @hide */
public static final String FORMAT = "format";
The index of the parent directory of the file

Type: INTEGER

/** * The index of the parent directory of the file * <P>Type: INTEGER</P> */
public static final String PARENT = "parent";
The MIME type of the file

Type: TEXT

/** * The MIME type of the file * <P>Type: TEXT</P> */
public static final String MIME_TYPE = "mime_type";
The title of the content

Type: TEXT

/** * The title of the content * <P>Type: TEXT</P> */
public static final String TITLE = "title";
The media type (audio, video, image or playlist) of the file, or 0 for not a media file

Type: TEXT

/** * The media type (audio, video, image or playlist) * of the file, or 0 for not a media file * <P>Type: TEXT</P> */
public static final String MEDIA_TYPE = "media_type";
Constant for the MEDIA_TYPE column indicating that file is not an audio, image, video or playlist file.
/** * Constant for the {@link #MEDIA_TYPE} column indicating that file * is not an audio, image, video or playlist file. */
public static final int MEDIA_TYPE_NONE = 0;
Constant for the MEDIA_TYPE column indicating that file is an image file.
/** * Constant for the {@link #MEDIA_TYPE} column indicating that file is an image file. */
public static final int MEDIA_TYPE_IMAGE = 1;
Constant for the MEDIA_TYPE column indicating that file is an audio file.
/** * Constant for the {@link #MEDIA_TYPE} column indicating that file is an audio file. */
public static final int MEDIA_TYPE_AUDIO = 2;
Constant for the MEDIA_TYPE column indicating that file is a video file.
/** * Constant for the {@link #MEDIA_TYPE} column indicating that file is a video file. */
public static final int MEDIA_TYPE_VIDEO = 3;
Constant for the MEDIA_TYPE column indicating that file is a playlist file.
/** * Constant for the {@link #MEDIA_TYPE} column indicating that file is a playlist file. */
public static final int MEDIA_TYPE_PLAYLIST = 4; } }
This class is used internally by Images.Thumbnails and Video.Thumbnails, it's not intended to be accessed elsewhere.
/** * This class is used internally by Images.Thumbnails and Video.Thumbnails, it's not intended * to be accessed elsewhere. */
private static class InternalThumbnails implements BaseColumns { private static final int MINI_KIND = 1; private static final int FULL_SCREEN_KIND = 2; private static final int MICRO_KIND = 3; private static final String[] PROJECTION = new String[] {_ID, MediaColumns.DATA}; static final int DEFAULT_GROUP_ID = 0; private static final Object sThumbBufLock = new Object(); private static byte[] sThumbBuf; private static Bitmap getMiniThumbFromFile( Cursor c, Uri baseUri, ContentResolver cr, BitmapFactory.Options options) { Bitmap bitmap = null; Uri thumbUri = null; try { long thumbId = c.getLong(0); String filePath = c.getString(1); thumbUri = ContentUris.withAppendedId(baseUri, thumbId); ParcelFileDescriptor pfdInput = cr.openFileDescriptor(thumbUri, "r"); bitmap = BitmapFactory.decodeFileDescriptor( pfdInput.getFileDescriptor(), null, options); pfdInput.close(); } catch (FileNotFoundException ex) { Log.e(TAG, "couldn't open thumbnail " + thumbUri + "; " + ex); } catch (IOException ex) { Log.e(TAG, "couldn't open thumbnail " + thumbUri + "; " + ex); } catch (OutOfMemoryError ex) { Log.e(TAG, "failed to allocate memory for thumbnail " + thumbUri + "; " + ex); } return bitmap; }
This method cancels the thumbnail request so clients waiting for getThumbnail will be interrupted and return immediately. Only the original process which made the getThumbnail requests can cancel their own requests.
Params:
  • cr – ContentResolver
  • origId – original image or video id. use -1 to cancel all requests.
  • groupId – the same groupId used in getThumbnail
  • baseUri – the base URI of requested thumbnails
/** * This method cancels the thumbnail request so clients waiting for getThumbnail will be * interrupted and return immediately. Only the original process which made the getThumbnail * requests can cancel their own requests. * * @param cr ContentResolver * @param origId original image or video id. use -1 to cancel all requests. * @param groupId the same groupId used in getThumbnail * @param baseUri the base URI of requested thumbnails */
static void cancelThumbnailRequest(ContentResolver cr, long origId, Uri baseUri, long groupId) { Uri cancelUri = baseUri.buildUpon().appendQueryParameter("cancel", "1") .appendQueryParameter("orig_id", String.valueOf(origId)) .appendQueryParameter("group_id", String.valueOf(groupId)).build(); Cursor c = null; try { c = cr.query(cancelUri, PROJECTION, null, null, null); } finally { if (c != null) c.close(); } }
This method ensure thumbnails associated with origId are generated and decode the byte stream from database (MICRO_KIND) or file (MINI_KIND). Special optimization has been done to avoid further IPC communication for MICRO_KIND thumbnails.
Params:
  • cr – ContentResolver
  • origId – original image or video id
  • kind – could be MINI_KIND or MICRO_KIND
  • options – this is only used for MINI_KIND when decoding the Bitmap
  • baseUri – the base URI of requested thumbnails
  • groupId – the id of group to which this request belongs
Returns:Bitmap bitmap of specified thumbnail kind
/** * This method ensure thumbnails associated with origId are generated and decode the byte * stream from database (MICRO_KIND) or file (MINI_KIND). * * Special optimization has been done to avoid further IPC communication for MICRO_KIND * thumbnails. * * @param cr ContentResolver * @param origId original image or video id * @param kind could be MINI_KIND or MICRO_KIND * @param options this is only used for MINI_KIND when decoding the Bitmap * @param baseUri the base URI of requested thumbnails * @param groupId the id of group to which this request belongs * @return Bitmap bitmap of specified thumbnail kind */
static Bitmap getThumbnail(ContentResolver cr, long origId, long groupId, int kind, BitmapFactory.Options options, Uri baseUri, boolean isVideo) { Bitmap bitmap = null; // Log.v(TAG, "getThumbnail: origId="+origId+", kind="+kind+", isVideo="+isVideo); // If the magic is non-zero, we simply return thumbnail if it does exist. // querying MediaProvider and simply return thumbnail. MiniThumbFile thumbFile = MiniThumbFile.instance( isVideo ? Video.Media.EXTERNAL_CONTENT_URI : Images.Media.EXTERNAL_CONTENT_URI); Cursor c = null; try { long magic = thumbFile.getMagic(origId); if (magic != 0) { if (kind == MICRO_KIND) { synchronized (sThumbBufLock) { if (sThumbBuf == null) { sThumbBuf = new byte[MiniThumbFile.BYTES_PER_MINTHUMB]; } if (thumbFile.getMiniThumbFromFile(origId, sThumbBuf) != null) { bitmap = BitmapFactory.decodeByteArray(sThumbBuf, 0, sThumbBuf.length); if (bitmap == null) { Log.w(TAG, "couldn't decode byte array."); } } } return bitmap; } else if (kind == MINI_KIND) { String column = isVideo ? "video_id=" : "image_id="; c = cr.query(baseUri, PROJECTION, column + origId, null, null); if (c != null && c.moveToFirst()) { bitmap = getMiniThumbFromFile(c, baseUri, cr, options); if (bitmap != null) { return bitmap; } } } } Uri blockingUri = baseUri.buildUpon().appendQueryParameter("blocking", "1") .appendQueryParameter("orig_id", String.valueOf(origId)) .appendQueryParameter("group_id", String.valueOf(groupId)).build(); if (c != null) c.close(); c = cr.query(blockingUri, PROJECTION, null, null, null); // This happens when original image/video doesn't exist. if (c == null) return null; // Assuming thumbnail has been generated, at least original image exists. if (kind == MICRO_KIND) { synchronized (sThumbBufLock) { if (sThumbBuf == null) { sThumbBuf = new byte[MiniThumbFile.BYTES_PER_MINTHUMB]; } Arrays.fill(sThumbBuf, (byte)0); if (thumbFile.getMiniThumbFromFile(origId, sThumbBuf) != null) { bitmap = BitmapFactory.decodeByteArray(sThumbBuf, 0, sThumbBuf.length); if (bitmap == null) { Log.w(TAG, "couldn't decode byte array."); } } } } else if (kind == MINI_KIND) { if (c.moveToFirst()) { bitmap = getMiniThumbFromFile(c, baseUri, cr, options); } } else { throw new IllegalArgumentException("Unsupported kind: " + kind); } // We probably run out of space, so create the thumbnail in memory. if (bitmap == null) { Log.v(TAG, "Create the thumbnail in memory: origId=" + origId + ", kind=" + kind + ", isVideo="+isVideo); Uri uri = Uri.parse( baseUri.buildUpon().appendPath(String.valueOf(origId)) .toString().replaceFirst("thumbnails", "media")); if (c != null) c.close(); c = cr.query(uri, PROJECTION, null, null, null); if (c == null || !c.moveToFirst()) { return null; } String filePath = c.getString(1); if (filePath != null) { if (isVideo) { bitmap = ThumbnailUtils.createVideoThumbnail(filePath, kind); } else { bitmap = ThumbnailUtils.createImageThumbnail(filePath, kind); } } } } catch (SQLiteException ex) { Log.w(TAG, ex); } finally { if (c != null) c.close(); // To avoid file descriptor leak in application process. thumbFile.deactivate(); thumbFile = null; } return bitmap; } }
Contains meta data for all available images.
/** * Contains meta data for all available images. */
public static final class Images { public interface ImageColumns extends MediaColumns {
The description of the image

Type: TEXT

/** * The description of the image * <P>Type: TEXT</P> */
public static final String DESCRIPTION = "description";
The picasa id of the image

Type: TEXT

/** * 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

Type: INTEGER

/** * 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.

Type: DOUBLE

/** * The latitude where the image was captured. * <P>Type: DOUBLE</P> */
public static final String LATITUDE = "latitude";
The longitude where the image was captured.

Type: DOUBLE

/** * 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.

Type: INTEGER

/** * 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.

Type: INTEGER

/** * 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.

Type: INTEGER

/** * 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.

Type: TEXT

/** * 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.

Type: TEXT

/** * 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 Bitmap.
Params:
  • cr – The content resolver to use
  • url – The url of the image
Throws:
/** * 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.
Params:
  • cr – The content resolver to use
  • imagePath – The path to the image to insert
  • name – The name of the image
  • description – The description of the image
Throws:
Returns:The URL to the newly created image
/** * 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 { Bitmap bm = BitmapFactory.decodeFile(imagePath); String ret = insertImage(cr, bm, name, description); bm.recycle(); return ret; } 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.
Params:
  • cr – The content resolver to use
  • source – The stream to use for the image
  • title – The name of the image
  • description – The description of the image
Returns:The URL to the newly created image, or null if the image failed to be stored for any reason.
/** * 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); // Wait until MINI_KIND thumbnail is generated. Bitmap miniThumb = Images.Thumbnails.getThumbnail(cr, id, Images.Thumbnails.MINI_KIND, null); // This is for backward compatibility. 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.
Params:
  • volumeName – the name of the volume to get the URI for
Returns:the URI to the image media table on the given volume
/** * 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.
/** * 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.
/** * 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.
/** * 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
/** * The default sort order for this table */
public static final String DEFAULT_SORT_ORDER = ImageColumns.BUCKET_DISPLAY_NAME; }
This class allows developers to query and get two kinds of thumbnails: MINI_KIND: 512 x 384 thumbnail MICRO_KIND: 96 x 96 thumbnail
/** * This class allows developers to query and get two kinds of thumbnails: * MINI_KIND: 512 x 384 thumbnail * MICRO_KIND: 96 x 96 thumbnail */
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); }
This method cancels the thumbnail request so clients waiting for getThumbnail will be interrupted and return immediately. Only the original process which made the getThumbnail requests can cancel their own requests.
Params:
  • cr – ContentResolver
  • origId – original image id
/** * This method cancels the thumbnail request so clients waiting for getThumbnail will be * interrupted and return immediately. Only the original process which made the getThumbnail * requests can cancel their own requests. * * @param cr ContentResolver * @param origId original image id */
public static void cancelThumbnailRequest(ContentResolver cr, long origId) { InternalThumbnails.cancelThumbnailRequest(cr, origId, EXTERNAL_CONTENT_URI, InternalThumbnails.DEFAULT_GROUP_ID); }
This method checks if the thumbnails of the specified image (origId) has been created. It will be blocked until the thumbnails are generated.
Params:
  • cr – ContentResolver used to dispatch queries to MediaProvider.
  • origId – Original image id associated with thumbnail of interest.
  • kind – The type of thumbnail to fetch. Should be either MINI_KIND or MICRO_KIND.
  • options – this is only used for MINI_KIND when decoding the Bitmap
Returns:A Bitmap instance. It could be null if the original image associated with origId doesn't exist or memory is not enough.
/** * This method checks if the thumbnails of the specified image (origId) has been created. * It will be blocked until the thumbnails are generated. * * @param cr ContentResolver used to dispatch queries to MediaProvider. * @param origId Original image id associated with thumbnail of interest. * @param kind The type of thumbnail to fetch. Should be either MINI_KIND or MICRO_KIND. * @param options this is only used for MINI_KIND when decoding the Bitmap * @return A Bitmap instance. It could be null if the original image * associated with origId doesn't exist or memory is not enough. */
public static Bitmap getThumbnail(ContentResolver cr, long origId, int kind, BitmapFactory.Options options) { return InternalThumbnails.getThumbnail(cr, origId, InternalThumbnails.DEFAULT_GROUP_ID, kind, options, EXTERNAL_CONTENT_URI, false); }
This method cancels the thumbnail request so clients waiting for getThumbnail will be interrupted and return immediately. Only the original process which made the getThumbnail requests can cancel their own requests.
Params:
  • cr – ContentResolver
  • origId – original image id
  • groupId – the same groupId used in getThumbnail.
/** * This method cancels the thumbnail request so clients waiting for getThumbnail will be * interrupted and return immediately. Only the original process which made the getThumbnail * requests can cancel their own requests. * * @param cr ContentResolver * @param origId original image id * @param groupId the same groupId used in getThumbnail. */
public static void cancelThumbnailRequest(ContentResolver cr, long origId, long groupId) { InternalThumbnails.cancelThumbnailRequest(cr, origId, EXTERNAL_CONTENT_URI, groupId); }
This method checks if the thumbnails of the specified image (origId) has been created. It will be blocked until the thumbnails are generated.
Params:
  • cr – ContentResolver used to dispatch queries to MediaProvider.
  • origId – Original image id associated with thumbnail of interest.
  • groupId – the id of group to which this request belongs
  • kind – The type of thumbnail to fetch. Should be either MINI_KIND or MICRO_KIND.
  • options – this is only used for MINI_KIND when decoding the Bitmap
Returns:A Bitmap instance. It could be null if the original image associated with origId doesn't exist or memory is not enough.
/** * This method checks if the thumbnails of the specified image (origId) has been created. * It will be blocked until the thumbnails are generated. * * @param cr ContentResolver used to dispatch queries to MediaProvider. * @param origId Original image id associated with thumbnail of interest. * @param groupId the id of group to which this request belongs * @param kind The type of thumbnail to fetch. Should be either MINI_KIND or MICRO_KIND. * @param options this is only used for MINI_KIND when decoding the Bitmap * @return A Bitmap instance. It could be null if the original image * associated with origId doesn't exist or memory is not enough. */
public static Bitmap getThumbnail(ContentResolver cr, long origId, long groupId, int kind, BitmapFactory.Options options) { return InternalThumbnails.getThumbnail(cr, origId, groupId, kind, options, EXTERNAL_CONTENT_URI, false); }
Get the content:// style URI for the image media table on the given volume.
Params:
  • volumeName – the name of the volume to get the URI for
Returns:the URI to the image media table on the given volume
/** * 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.
/** * 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.
/** * 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
/** * The default sort order for this table */
public static final String DEFAULT_SORT_ORDER = "image_id ASC";
Path to the thumbnail file on disk.

Note that apps may not have filesystem permissions to directly access this path. Instead of trying to open this path directly, apps should use ContentResolver.openFileDescriptor(Uri, String) to gain access.

Type: TEXT

/** * Path to the thumbnail file on disk. * <p> * Note that apps may not have filesystem permissions to directly * access this path. Instead of trying to open this path directly, * apps should use * {@link ContentResolver#openFileDescriptor(Uri, String)} to gain * access. * <p> * Type: TEXT */
public static final String DATA = "_data";
The original image for the thumbnal

Type: INTEGER (ID from Images table)

/** * 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

Type: INTEGER (One of the values below)

/** * 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 blob raw data of thumbnail

Type: DATA STREAM

/** * The blob raw data of thumbnail * <P>Type: DATA STREAM</P> */
public static final String THUMB_DATA = "thumb_data";
The width of the thumbnal

Type: INTEGER (long)

/** * The width of the thumbnal * <P>Type: INTEGER (long)</P> */
public static final String WIDTH = "width";
The height of the thumbnail

Type: INTEGER (long)

/** * The height of the thumbnail * <P>Type: INTEGER (long)</P> */
public static final String HEIGHT = "height"; } }
Container for all audio content.
/** * Container for all audio content. */
public static final class Audio {
Columns for audio file that show up in multiple tables.
/** * 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

Type: TEXT

/** * 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

Type: INTEGER (long)

/** * 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.

Type: INTEGER (long)

/** * The position, in ms, playback was at when playback for this file * was last stopped. * <P>Type: INTEGER (long)</P> */
public static final String BOOKMARK = "bookmark";
The id of the artist who created the audio file, if any

Type: INTEGER (long)

/** * 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

Type: TEXT

/** * The artist who created the audio file, if any * <P>Type: TEXT</P> */
public static final String ARTIST = "artist";
The artist credited for the album that contains the audio file

Type: TEXT

@hide
/** * The artist credited for the album that contains the audio file * <P>Type: TEXT</P> * @hide */
public static final String ALBUM_ARTIST = "album_artist";
Whether the song is part of a compilation

Type: TEXT

@hide
/** * Whether the song is part of a compilation * <P>Type: TEXT</P> * @hide */
public static final String COMPILATION = "compilation";
A non human readable key calculated from the ARTIST, used for searching, sorting and grouping

Type: TEXT

/** * 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

Type: TEXT

/** * 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

Type: INTEGER (long)

/** * 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

Type: TEXT

/** * 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

Type: TEXT

/** * 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";
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.

Type: INTEGER

/** * 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

Type: INTEGER

/** * 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

Type: INTEGER (boolean)

/** * 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

Type: INTEGER (boolean)

/** * Non-zero if the audio file is a podcast * <P>Type: INTEGER (boolean)</P> */
public static final String IS_PODCAST = "is_podcast";
Non-zero if the audio file may be a ringtone

Type: INTEGER (boolean)

/** * Non-zero if the audio file may be a ringtone * <P>Type: INTEGER (boolean)</P> */
public static final String IS_RINGTONE = "is_ringtone";
Non-zero if the audio file may be an alarm

Type: INTEGER (boolean)

/** * Non-zero if the audio file may be an alarm * <P>Type: INTEGER (boolean)</P> */
public static final String IS_ALARM = "is_alarm";
Non-zero if the audio file may be a notification sound

Type: INTEGER (boolean)

/** * Non-zero if the audio file may be a notification sound * <P>Type: INTEGER (boolean)</P> */
public static final String IS_NOTIFICATION = "is_notification";
The genre of the audio file, if any

Type: TEXT

Does not exist in the database - only used by the media scanner for inserts.
@hide
/** * The genre of the audio file, if any * <P>Type: TEXT</P> * Does not exist in the database - only used by the media scanner for inserts. * @hide */
public static final String GENRE = "genre";
The resource URI of a localized title, if any

Type: TEXT

Conforms to this pattern: Scheme: SCHEME_ANDROID_RESOURCE Authority: Package Name of ringtone title provider First Path Segment: Type of resource (must be "string") Second Path Segment: Resource ID of title
@hide
/** * The resource URI of a localized title, if any * <P>Type: TEXT</P> * Conforms to this pattern: * Scheme: {@link ContentResolver.SCHEME_ANDROID_RESOURCE} * Authority: Package Name of ringtone title provider * First Path Segment: Type of resource (must be "string") * Second Path Segment: Resource ID of title * @hide */
public static final String TITLE_RESOURCE_URI = "title_resource_uri"; }
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
Params:
  • name – The artist or album name to convert
Returns:The "key" for the given name.
/** * 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) { boolean sortfirst = false; if (name.equals(UNKNOWN_STRING)) { return "\001"; } // Check if the first character is \001. We use this to // force sorting of certain special files, like the silent ringtone. if (name.startsWith("\001")) { sortfirst = true; } 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(); String key = DatabaseUtils.getCollationKey(name); if (sortfirst) { key = "\001" + key; } return key; } else { return ""; } } return null; } public static final class Media implements AudioColumns { private static final String[] EXTERNAL_PATHS; static { String secondary_storage = System.getenv("SECONDARY_STORAGE"); if (secondary_storage != null) { EXTERNAL_PATHS = secondary_storage.split(":"); } else { EXTERNAL_PATHS = new String[0]; } }
Get the content:// style URI for the audio media table on the given volume.
Params:
  • volumeName – the name of the volume to get the URI for
Returns:the URI to the audio media table on the given volume
/** * 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) { for (String ep : EXTERNAL_PATHS) { if (path.startsWith(ep)) { return EXTERNAL_CONTENT_URI; } } return (path.startsWith(Environment.getExternalStorageDirectory().getPath()) ? EXTERNAL_CONTENT_URI : INTERNAL_CONTENT_URI); }
The content:// style URI for the internal storage.
/** * 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.
/** * 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.
/** * The MIME type for this table. */
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/audio";
The MIME type for an audio track.
/** * The MIME type for an audio track. */
public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/audio";
The default sort order for this table
/** * The default sort order for this table */
public static final String DEFAULT_SORT_ORDER = TITLE_KEY;
Activity Action: Start SoundRecorder application.

Input: nothing.

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 Also:
  • EXTRA_MAX_BYTES
/** * 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 */
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 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 Also:
  • RECORD_SOUND_ACTION
/** * 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
/** * Columns representing an audio genre */
public interface GenresColumns {
The name of the genre

Type: TEXT

/** * The name of the genre * <P>Type: TEXT</P> */
public static final String NAME = "name"; }
Contains all genres for audio files
/** * 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.
Params:
  • volumeName – the name of the volume to get the URI for
Returns:the URI to the audio genres table on the given volume
/** * 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"); }
Get the content:// style URI for querying the genres of an audio file.
Params:
  • volumeName – the name of the volume to get the URI for
  • audioId – the ID of the audio file for which to retrieve the genres
Returns:the URI to for querying the genres for the audio file with the given the volume and audioID
/** * Get the content:// style URI for querying the genres of an audio file. * * @param volumeName the name of the volume to get the URI for * @param audioId the ID of the audio file for which to retrieve the genres * @return the URI to for querying the genres for the audio file * with the given the volume and audioID */
public static Uri getContentUriForAudioId(String volumeName, int audioId) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/audio/media/" + audioId + "/genres"); }
The content:// style URI for the internal storage.
/** * 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.
/** * 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.
/** * 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.
/** * 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
/** * The default sort order for this table */
public static final String DEFAULT_SORT_ORDER = NAME;
Sub-directory of each genre containing all members.
/** * 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.
/** * A subdirectory of each genre containing all member audio files. */
public static final String CONTENT_DIRECTORY = "members";
The default sort order for this table
/** * The default sort order for this table */
public static final String DEFAULT_SORT_ORDER = TITLE_KEY;
The ID of the audio file

Type: INTEGER (long)

/** * The ID of the audio file * <P>Type: INTEGER (long)</P> */
public static final String AUDIO_ID = "audio_id";
The ID of the genre

Type: INTEGER (long)

/** * The ID of the genre * <P>Type: INTEGER (long)</P> */
public static final String GENRE_ID = "genre_id"; } }
Columns representing a playlist
/** * Columns representing a playlist */
public interface PlaylistsColumns {
The name of the playlist

Type: TEXT

/** * The name of the playlist * <P>Type: TEXT</P> */
public static final String NAME = "name";
Path to the playlist file on disk.

Note that apps may not have filesystem permissions to directly access this path. Instead of trying to open this path directly, apps should use ContentResolver.openFileDescriptor(Uri, String) to gain access.

Type: TEXT

/** * Path to the playlist file on disk. * <p> * Note that apps may not have filesystem permissions to directly * access this path. Instead of trying to open this path directly, * apps should use * {@link ContentResolver#openFileDescriptor(Uri, String)} to gain * access. * <p> * Type: TEXT */
public static final String DATA = "_data";
The time the file was added to the media provider Units are seconds since 1970.

Type: INTEGER (long)

/** * 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.

Type: INTEGER (long)

/** * 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
/** * 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.
Params:
  • volumeName – the name of the volume to get the URI for
Returns:the URI to the audio playlists table on the given volume
/** * 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.
/** * 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.
/** * 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.
/** * 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.
/** * 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
/** * The default sort order for this table */
public static final String DEFAULT_SORT_ORDER = NAME;
Sub-directory of each playlist containing all members.
/** * 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"); }
Convenience method to move a playlist item to a new location
Params:
  • res – The content resolver to use
  • playlistId – The numeric id of the playlist
  • from – The position of the item to move
  • to – The position to move the item to
Returns:true on success
/** * Convenience method to move a playlist item to a new location * @param res The content resolver to use * @param playlistId The numeric id of the playlist * @param from The position of the item to move * @param to The position to move the item to * @return true on success */
public static final boolean moveItem(ContentResolver res, long playlistId, int from, int to) { Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId) .buildUpon() .appendEncodedPath(String.valueOf(from)) .appendQueryParameter("move", "true") .build(); ContentValues values = new ContentValues(); values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, to); return res.update(uri, values, null, null) != 0; }
The ID within the playlist.
/** * The ID within the playlist. */
public static final String _ID = "_id";
A subdirectory of each playlist containing all member audio files.
/** * A subdirectory of each playlist containing all member audio * files. */
public static final String CONTENT_DIRECTORY = "members";
The ID of the audio file

Type: INTEGER (long)

/** * The ID of the audio file * <P>Type: INTEGER (long)</P> */
public static final String AUDIO_ID = "audio_id";
The ID of the playlist

Type: INTEGER (long)

/** * 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

Type: INTEGER (long)>

/** * 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
/** * The default sort order for this table */
public static final String DEFAULT_SORT_ORDER = PLAY_ORDER; } }
Columns representing an artist
/** * Columns representing an artist */
public interface ArtistColumns {
The artist who created the audio file, if any

Type: TEXT

/** * 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

Type: TEXT

/** * 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
/** * 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
/** * 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
/** * 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.
Params:
  • volumeName – the name of the volume to get the URI for
Returns:the URI to the audio artists table on the given volume
/** * 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.
/** * 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.
/** * 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.
/** * 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.
/** * 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
/** * 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.
/** * 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
/** * Columns representing an album */
public interface AlbumColumns {
The id for the album

Type: INTEGER

/** * 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

Type: TEXT

/** * 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

Type: TEXT

/** * 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

Type: INTEGER

/** * 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.

Type: INTEGER

/** * 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 LAST_YEAR, but for compilation albums they might differ.

Type: INTEGER

/** * 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 FIRST_YEAR, but for compilation albums they might differ.

Type: INTEGER

/** * 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

Type: TEXT

/** * 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.

Type: TEXT

/** * Cached album art. * <P>Type: TEXT</P> */
public static final String ALBUM_ART = "album_art"; }
Contains artists for audio files
/** * 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.
Params:
  • volumeName – the name of the volume to get the URI for
Returns:the URI to the audio albums table on the given volume
/** * 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.
/** * 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.
/** * 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.
/** * 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.
/** * 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
/** * The default sort order for this table */
public static final String DEFAULT_SORT_ORDER = ALBUM_KEY; } public static final class Radio {
The MIME type for entries in this table.
/** * The MIME type for entries in this table. */
public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/radio"; // Not instantiable. private Radio() { } } } public static final class Video {
The default sort order for this table.
/** * 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

Type: INTEGER (long)

/** * 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

Type: TEXT

/** * 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

Type: TEXT

/** * 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"

Type: TEXT

/** * 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

Type: TEXT

/** * 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

Type: INTEGER

/** * 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

Type: TEXT

/** * The user-added tags associated with a video * <P>Type: TEXT</P> */
public static final String TAGS = "tags";
The YouTube category of the video

Type: TEXT

/** * The YouTube category of the video * <P>Type: TEXT</P> */
public static final String CATEGORY = "category";
The language of the video

Type: TEXT

/** * The language of the video * <P>Type: TEXT</P> */
public static final String LANGUAGE = "language";
The latitude where the video was captured.

Type: DOUBLE

/** * The latitude where the video was captured. * <P>Type: DOUBLE</P> */
public static final String LATITUDE = "latitude";
The longitude where the video was captured.

Type: DOUBLE

/** * The longitude where the video was captured. * <P>Type: DOUBLE</P> */
public static final String LONGITUDE = "longitude";
The date & time that the video was taken in units of milliseconds since jan 1, 1970.

Type: INTEGER

/** * The date & time that the video 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.

Type: INTEGER

/** * 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.

Type: TEXT

/** * 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.

Type: TEXT

/** * 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.

Type: INTEGER

/** * 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.
Params:
  • volumeName – the name of the volume to get the URI for
Returns:the URI to the video media table on the given volume
/** * 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.
/** * 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.
/** * 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.
/** * The MIME type for this table. */
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/video";
The default sort order for this table
/** * The default sort order for this table */
public static final String DEFAULT_SORT_ORDER = TITLE; }
This class allows developers to query and get two kinds of thumbnails: MINI_KIND: 512 x 384 thumbnail MICRO_KIND: 96 x 96 thumbnail
/** * This class allows developers to query and get two kinds of thumbnails: * MINI_KIND: 512 x 384 thumbnail * MICRO_KIND: 96 x 96 thumbnail * */
public static class Thumbnails implements BaseColumns {
This method cancels the thumbnail request so clients waiting for getThumbnail will be interrupted and return immediately. Only the original process which made the getThumbnail requests can cancel their own requests.
Params:
  • cr – ContentResolver
  • origId – original video id
/** * This method cancels the thumbnail request so clients waiting for getThumbnail will be * interrupted and return immediately. Only the original process which made the getThumbnail * requests can cancel their own requests. * * @param cr ContentResolver * @param origId original video id */
public static void cancelThumbnailRequest(ContentResolver cr, long origId) { InternalThumbnails.cancelThumbnailRequest(cr, origId, EXTERNAL_CONTENT_URI, InternalThumbnails.DEFAULT_GROUP_ID); }
This method checks if the thumbnails of the specified image (origId) has been created. It will be blocked until the thumbnails are generated.
Params:
  • cr – ContentResolver used to dispatch queries to MediaProvider.
  • origId – Original image id associated with thumbnail of interest.
  • kind – The type of thumbnail to fetch. Should be either MINI_KIND or MICRO_KIND.
  • options – this is only used for MINI_KIND when decoding the Bitmap
Returns:A Bitmap instance. It could be null if the original image associated with origId doesn't exist or memory is not enough.
/** * This method checks if the thumbnails of the specified image (origId) has been created. * It will be blocked until the thumbnails are generated. * * @param cr ContentResolver used to dispatch queries to MediaProvider. * @param origId Original image id associated with thumbnail of interest. * @param kind The type of thumbnail to fetch. Should be either MINI_KIND or MICRO_KIND. * @param options this is only used for MINI_KIND when decoding the Bitmap * @return A Bitmap instance. It could be null if the original image * associated with origId doesn't exist or memory is not enough. */
public static Bitmap getThumbnail(ContentResolver cr, long origId, int kind, BitmapFactory.Options options) { return InternalThumbnails.getThumbnail(cr, origId, InternalThumbnails.DEFAULT_GROUP_ID, kind, options, EXTERNAL_CONTENT_URI, true); }
This method checks if the thumbnails of the specified image (origId) has been created. It will be blocked until the thumbnails are generated.
Params:
  • cr – ContentResolver used to dispatch queries to MediaProvider.
  • origId – Original image id associated with thumbnail of interest.
  • groupId – the id of group to which this request belongs
  • kind – The type of thumbnail to fetch. Should be either MINI_KIND or MICRO_KIND
  • options – this is only used for MINI_KIND when decoding the Bitmap
Returns:A Bitmap instance. It could be null if the original image associated with origId doesn't exist or memory is not enough.
/** * This method checks if the thumbnails of the specified image (origId) has been created. * It will be blocked until the thumbnails are generated. * * @param cr ContentResolver used to dispatch queries to MediaProvider. * @param origId Original image id associated with thumbnail of interest. * @param groupId the id of group to which this request belongs * @param kind The type of thumbnail to fetch. Should be either MINI_KIND or MICRO_KIND * @param options this is only used for MINI_KIND when decoding the Bitmap * @return A Bitmap instance. It could be null if the original image associated with * origId doesn't exist or memory is not enough. */
public static Bitmap getThumbnail(ContentResolver cr, long origId, long groupId, int kind, BitmapFactory.Options options) { return InternalThumbnails.getThumbnail(cr, origId, groupId, kind, options, EXTERNAL_CONTENT_URI, true); }
This method cancels the thumbnail request so clients waiting for getThumbnail will be interrupted and return immediately. Only the original process which made the getThumbnail requests can cancel their own requests.
Params:
  • cr – ContentResolver
  • origId – original video id
  • groupId – the same groupId used in getThumbnail.
/** * This method cancels the thumbnail request so clients waiting for getThumbnail will be * interrupted and return immediately. Only the original process which made the getThumbnail * requests can cancel their own requests. * * @param cr ContentResolver * @param origId original video id * @param groupId the same groupId used in getThumbnail. */
public static void cancelThumbnailRequest(ContentResolver cr, long origId, long groupId) { InternalThumbnails.cancelThumbnailRequest(cr, origId, EXTERNAL_CONTENT_URI, groupId); }
Get the content:// style URI for the image media table on the given volume.
Params:
  • volumeName – the name of the volume to get the URI for
Returns:the URI to the image media table on the given volume
/** * 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 + "/video/thumbnails"); }
The content:// style URI for the internal storage.
/** * 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.
/** * 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
/** * The default sort order for this table */
public static final String DEFAULT_SORT_ORDER = "video_id ASC";
Path to the thumbnail file on disk.

Note that apps may not have filesystem permissions to directly access this path. Instead of trying to open this path directly, apps should use ContentResolver.openFileDescriptor(Uri, String) to gain access.

Type: TEXT

/** * Path to the thumbnail file on disk. * <p> * Note that apps may not have filesystem permissions to directly * access this path. Instead of trying to open this path directly, * apps should use * {@link ContentResolver#openFileDescriptor(Uri, String)} to gain * access. * <p> * Type: TEXT */
public static final String DATA = "_data";
The original image for the thumbnal

Type: INTEGER (ID from Video table)

/** * The original image for the thumbnal * <P>Type: INTEGER (ID from Video table)</P> */
public static final String VIDEO_ID = "video_id";
The kind of the thumbnail

Type: INTEGER (One of the values below)

/** * 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

Type: INTEGER (long)

/** * The width of the thumbnal * <P>Type: INTEGER (long)</P> */
public static final String WIDTH = "width";
The height of the thumbnail

Type: INTEGER (long)

/** * The height of the thumbnail * <P>Type: INTEGER (long)</P> */
public static final String HEIGHT = "height"; } }
Uri for querying the state of the media scanner.
/** * 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.
/** * Name of current volume being scanned by the media scanner. */
public static final String MEDIA_SCANNER_VOLUME = "volume";
Name of the file signaling the media scanner to ignore media in the containing directory and its subdirectories. Developers should use this to avoid application graphics showing up in the Gallery and likewise prevent application sounds and music from showing up in the Music app.
/** * Name of the file signaling the media scanner to ignore media in the containing directory * and its subdirectories. Developers should use this to avoid application graphics showing * up in the Gallery and likewise prevent application sounds and music from showing up in * the Music app. */
public static final String MEDIA_IGNORE_FILENAME = ".nomedia";
Get the media provider's version. Applications that import data from the media provider into their own caches can use this to detect that the media provider changed, and reimport data as needed. No other assumptions should be made about the meaning of the version.
Params:
  • context – Context to use for performing the query.
Returns:A version string, or null if the version could not be determined.
/** * Get the media provider's version. * Applications that import data from the media provider into their own caches * can use this to detect that the media provider changed, and reimport data * as needed. No other assumptions should be made about the meaning of the version. * @param context Context to use for performing the query. * @return A version string, or null if the version could not be determined. */
public static String getVersion(Context context) { Cursor c = context.getContentResolver().query( Uri.parse(CONTENT_AUTHORITY_SLASH + "none/version"), null, null, null, null); if (c != null) { try { if (c.moveToFirst()) { return c.getString(0); } } finally { c.close(); } } return null; }
Gets a URI backed by a DocumentsProvider that points to the same media file as the specified mediaUri. This allows apps who have permissions to access media files in Storage Access Framework to perform file operations through that on media files.

Note: this method doesn't grant any URI permission. Callers need to obtain permission before calling this method. One way to obtain permission is through a 3-step process:

  1. Call StorageManager.getStorageVolume(File) to obtain the StorageVolume of a media file;
  2. Invoke the intent returned by StorageVolume.createAccessIntent(String) to obtain the access of the volume or one of its specific subdirectories;
  3. Check whether permission is granted and take persistent permission.
Params:
  • mediaUri – the media URI which document URI is requested
Returns:the document URI
/** * Gets a URI backed by a {@link DocumentsProvider} that points to the same media * file as the specified mediaUri. This allows apps who have permissions to access * media files in Storage Access Framework to perform file operations through that * on media files. * <p> * Note: this method doesn't grant any URI permission. Callers need to obtain * permission before calling this method. One way to obtain permission is through * a 3-step process: * <ol> * <li>Call {@link android.os.storage.StorageManager#getStorageVolume(File)} to * obtain the {@link android.os.storage.StorageVolume} of a media file;</li> * * <li>Invoke the intent returned by * {@link android.os.storage.StorageVolume#createAccessIntent(String)} to * obtain the access of the volume or one of its specific subdirectories;</li> * * <li>Check whether permission is granted and take persistent permission.</li> * </ol> * @param mediaUri the media URI which document URI is requested * @return the document URI */
public static Uri getDocumentUri(Context context, Uri mediaUri) { try { final ContentResolver resolver = context.getContentResolver(); final String path = getFilePath(resolver, mediaUri); final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions(); return getDocumentUri(resolver, path, uriPermissions); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } private static String getFilePath(ContentResolver resolver, Uri mediaUri) throws RemoteException { try (ContentProviderClient client = resolver.acquireUnstableContentProviderClient(AUTHORITY)) { final Cursor c = client.query( mediaUri, new String[]{ MediaColumns.DATA }, null, /* selection */ null, /* selectionArg */ null /* sortOrder */); final String path; try { if (c.getCount() == 0) { throw new IllegalStateException("Not found media file under URI: " + mediaUri); } if (!c.moveToFirst()) { throw new IllegalStateException("Failed to move cursor to the first item."); } path = c.getString(0); } finally { IoUtils.closeQuietly(c); } return path; } } private static Uri getDocumentUri( ContentResolver resolver, String path, List<UriPermission> uriPermissions) throws RemoteException { try (ContentProviderClient client = resolver.acquireUnstableContentProviderClient( DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY)) { final Bundle in = new Bundle(); in.putParcelableList( DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY + ".extra.uriPermissions", uriPermissions); final Bundle out = client.call("getDocumentId", path, in); return out.getParcelable(DocumentsContract.EXTRA_URI); } } }