MediaStore.java revision f1e484acb594a726fb57ad0ae4cfe902c7f35858
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.provider;
18
19import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
21import android.content.ContentResolver;
22import android.content.ContentValues;
23import android.content.ContentUris;
24import android.database.Cursor;
25import android.database.DatabaseUtils;
26import android.graphics.Bitmap;
27import android.graphics.BitmapFactory;
28import android.graphics.Matrix;
29import android.net.Uri;
30import android.os.Environment;
31import android.util.Log;
32
33import java.io.FileInputStream;
34import java.io.FileNotFoundException;
35import java.io.IOException;
36import java.io.InputStream;
37import java.io.OutputStream;
38import java.io.UnsupportedEncodingException;
39import java.text.Collator;
40
41/**
42 * The Media provider contains meta data for all available media on both internal
43 * and external storage devices.
44 */
45public final class MediaStore
46{
47    private final static String TAG = "MediaStore";
48
49    public static final String AUTHORITY = "media";
50
51    private static final String CONTENT_AUTHORITY_SLASH = "content://" + AUTHORITY + "/";
52
53    /**
54     * Activity Action: Perform a search for media.
55     * Contains at least the {@link android.app.SearchManager#QUERY} extra.
56     * May also contain any combination of the following extras:
57     * EXTRA_MEDIA_ARTIST, EXTRA_MEDIA_ALBUM, EXTRA_MEDIA_TITLE, EXTRA_MEDIA_FOCUS
58     *
59     * @see android.provider.MediaStore#EXTRA_MEDIA_ARTIST
60     * @see android.provider.MediaStore#EXTRA_MEDIA_ALBUM
61     * @see android.provider.MediaStore#EXTRA_MEDIA_TITLE
62     * @see android.provider.MediaStore#EXTRA_MEDIA_FOCUS
63     */
64    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
65    public static final String INTENT_ACTION_MEDIA_SEARCH = "android.intent.action.MEDIA_SEARCH";
66
67    /**
68     * The name of the Intent-extra used to define the artist
69     */
70    public static final String EXTRA_MEDIA_ARTIST = "android.intent.extra.artist";
71    /**
72     * The name of the Intent-extra used to define the album
73     */
74    public static final String EXTRA_MEDIA_ALBUM = "android.intent.extra.album";
75    /**
76     * The name of the Intent-extra used to define the song title
77     */
78    public static final String EXTRA_MEDIA_TITLE = "android.intent.extra.title";
79    /**
80     * The name of the Intent-extra used to define the search focus. The search focus
81     * indicates whether the search should be for things related to the artist, album
82     * or song that is identified by the other extras.
83     */
84    public static final String EXTRA_MEDIA_FOCUS = "android.intent.extra.focus";
85
86    /**
87     * The name of the Intent-extra used to control the orientation of a ViewImage or a MovieView.
88     * This is an int property that overrides the activity's requestedOrientation.
89     * @see android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
90     */
91    public static final String EXTRA_SCREEN_ORIENTATION = "android.intent.extra.screenOrientation";
92
93    /**
94     * The name of the Intent-extra used to control the orientation of a ViewImage.
95     * This is a boolean property that overrides the activity's default fullscreen state.
96     * @hide
97     */
98    public static final String EXTRA_FULL_SCREEN = "android.intent.extra.fullScreen";
99
100    /**
101     * The name of the Intent-extra used to control the orientation of a ViewImage.
102     * This is a boolean property that specifies whether or not to show action icons.
103     * @hide
104     */
105    public static final String EXTRA_SHOW_ACTION_ICONS = "android.intent.extra.showActionIcons";
106
107    /**
108     * The name of the Intent-extra used to control the onCompletion behavior of a MovieView.
109     * This is a boolean property that specifies whether or not to finish the MovieView activity
110     * when the movie completes playing. The default value is true, which means to automatically
111     * exit the movie player activity when the movie completes playing.
112     */
113    public static final String EXTRA_FINISH_ON_COMPLETION = "android.intent.extra.finishOnCompletion";
114
115    /**
116     * The name of the Intent action used to launch a camera in still image mode.
117     */
118    public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
119
120
121    /**
122     * The name of the Intent action used to launch a camera in video mode.
123     */
124    public static final String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
125
126    /**
127     * Standard Intent action that can be sent to have the media application
128     * capture an image and return it.  The image is returned as a Bitmap
129     * object in the extra field.
130     * @hide
131     */
132    public final static String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
133
134    /**
135     * Standard Intent action that can be sent to have the media application
136     * capture an video and return it.  The caller may pass in an extra EXTRA_VIDEO_QUALITY
137     * control the video quality.
138     * @hide
139     */
140    public final static String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
141
142    /**
143     * The name of the Intent-extra used to control the quality of a recorded video. This is an
144     * integer property. Currently value 0 means low quality, suitable for MMS messages, and
145     * value 1 means high quality. In the future other quality levels may be added.
146     * @hide
147     */
148    public final static String EXTRA_VIDEO_QUALITY = "android.intent.extra.videoQuality";
149
150    /**
151     * The name of the Intent-extra used to indicate a Uri to be used to
152     * store the requested image or video.
153     * @hide
154     */
155    public final static String EXTRA_OUTPUT = "output";
156
157    /**
158     * Common fields for most MediaProvider tables
159     */
160
161     public interface MediaColumns extends BaseColumns {
162        /**
163         * The data stream for the file
164         * <P>Type: DATA STREAM</P>
165         */
166        public static final String DATA = "_data";
167
168        /**
169         * The size of the file in bytes
170         * <P>Type: INTEGER (long)</P>
171         */
172        public static final String SIZE = "_size";
173
174        /**
175         * The display name of the file
176         * <P>Type: TEXT</P>
177         */
178        public static final String DISPLAY_NAME = "_display_name";
179
180        /**
181         * The title of the content
182         * <P>Type: TEXT</P>
183         */
184        public static final String TITLE = "title";
185
186        /**
187         * The time the file was added to the media provider
188         * Units are seconds since 1970.
189         * <P>Type: INTEGER (long)</P>
190         */
191        public static final String DATE_ADDED = "date_added";
192
193        /**
194         * The time the file was last modified
195         * Units are seconds since 1970.
196         * NOTE: This is for internal use by the media scanner.  Do not modify this field.
197         * <P>Type: INTEGER (long)</P>
198         */
199        public static final String DATE_MODIFIED = "date_modified";
200
201        /**
202         * The MIME type of the file
203         * <P>Type: TEXT</P>
204         */
205        public static final String MIME_TYPE = "mime_type";
206     }
207
208    /**
209     * Contains meta data for all available images.
210     */
211    public static final class Images
212    {
213        public interface ImageColumns extends MediaColumns {
214            /**
215             * The description of the image
216             * <P>Type: TEXT</P>
217             */
218            public static final String DESCRIPTION = "description";
219
220            /**
221             * The picasa id of the image
222             * <P>Type: TEXT</P>
223             */
224            public static final String PICASA_ID = "picasa_id";
225
226            /**
227             * Whether the video should be published as public or private
228             * <P>Type: INTEGER</P>
229             */
230            public static final String IS_PRIVATE = "isprivate";
231
232            /**
233             * The latitude where the image was captured.
234             * <P>Type: DOUBLE</P>
235             */
236            public static final String LATITUDE = "latitude";
237
238            /**
239             * The longitude where the image was captured.
240             * <P>Type: DOUBLE</P>
241             */
242            public static final String LONGITUDE = "longitude";
243
244            /**
245             * The date & time that the image was taken in units
246             * of milliseconds since jan 1, 1970.
247             * <P>Type: INTEGER</P>
248             */
249            public static final String DATE_TAKEN = "datetaken";
250
251            /**
252             * The orientation for the image expressed as degrees.
253             * Only degrees 0, 90, 180, 270 will work.
254             * <P>Type: INTEGER</P>
255             */
256            public static final String ORIENTATION = "orientation";
257
258            /**
259             * The mini thumb id.
260             * <P>Type: INTEGER</P>
261             */
262            public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
263
264            /**
265             * The bucket id of the image. This is a read-only property that
266             * is automatically computed from the DATA column.
267             * <P>Type: TEXT</P>
268             */
269            public static final String BUCKET_ID = "bucket_id";
270
271            /**
272             * The bucket display name of the image. This is a read-only property that
273             * is automatically computed from the DATA column.
274             * <P>Type: TEXT</P>
275             */
276            public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
277        }
278
279        public static final class Media implements ImageColumns {
280            public static final Cursor query(ContentResolver cr, Uri uri, String[] projection)
281            {
282                return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
283            }
284
285            public static final Cursor query(ContentResolver cr, Uri uri, String[] projection,
286                                           String where, String orderBy)
287            {
288                return cr.query(uri, projection, where,
289                                             null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
290            }
291
292            public static final Cursor query(ContentResolver cr, Uri uri, String[] projection,
293                    String selection, String [] selectionArgs, String orderBy)
294            {
295                return cr.query(uri, projection, selection,
296                        selectionArgs, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
297            }
298
299            /**
300             * Retrieves an image for the given url as a {@link Bitmap}.
301             *
302             * @param cr The content resolver to use
303             * @param url The url of the image
304             * @throws FileNotFoundException
305             * @throws IOException
306             */
307            public static final Bitmap getBitmap(ContentResolver cr, Uri url)
308                    throws FileNotFoundException, IOException
309            {
310                InputStream input = cr.openInputStream(url);
311                Bitmap bitmap = BitmapFactory.decodeStream(input);
312                input.close();
313                return bitmap;
314            }
315
316            /**
317             * Insert an image and create a thumbnail for it.
318             *
319             * @param cr The content resolver to use
320             * @param imagePath The path to the image to insert
321             * @param name The name of the image
322             * @param description The description of the image
323             * @return The URL to the newly created image
324             * @throws FileNotFoundException
325             */
326            public static final String insertImage(ContentResolver cr, String imagePath, String name,
327                                                   String description) throws FileNotFoundException
328            {
329                // Check if file exists with a FileInputStream
330                FileInputStream stream = new FileInputStream(imagePath);
331                try {
332                    return insertImage(cr, BitmapFactory.decodeFile(imagePath), name, description);
333                } finally {
334                    try {
335                        stream.close();
336                    } catch (IOException e) {
337                    }
338                }
339            }
340
341            private static final Bitmap StoreThumbnail(
342                    ContentResolver cr,
343                    Bitmap source,
344                    long id,
345                    float width, float height,
346                    int kind) {
347                // create the matrix to scale it
348                Matrix matrix = new Matrix();
349
350                float scaleX = width / source.getWidth();
351                float scaleY = height / source.getHeight();
352
353                matrix.setScale(scaleX, scaleY);
354
355                Bitmap thumb = Bitmap.createBitmap(source, 0, 0,
356                                                   source.getWidth(),
357                                                   source.getHeight(), matrix,
358                                                   true);
359
360                ContentValues values = new ContentValues(4);
361                values.put(Images.Thumbnails.KIND,     kind);
362                values.put(Images.Thumbnails.IMAGE_ID, (int)id);
363                values.put(Images.Thumbnails.HEIGHT,   thumb.getHeight());
364                values.put(Images.Thumbnails.WIDTH,    thumb.getWidth());
365
366                Uri url = cr.insert(Images.Thumbnails.EXTERNAL_CONTENT_URI, values);
367
368                try {
369                    OutputStream thumbOut = cr.openOutputStream(url);
370
371                    thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut);
372                    thumbOut.close();
373                    return thumb;
374                }
375                catch (FileNotFoundException ex) {
376                    return null;
377                }
378                catch (IOException ex) {
379                    return null;
380                }
381            }
382
383            /**
384             * Insert an image and create a thumbnail for it.
385             *
386             * @param cr The content resolver to use
387             * @param source The stream to use for the image
388             * @param title The name of the image
389             * @param description The description of the image
390             * @return The URL to the newly created image, or <code>null</code> if the image failed to be stored
391             *              for any reason.
392             */
393            public static final String insertImage(ContentResolver cr, Bitmap source,
394                                                   String title, String description)
395            {
396                ContentValues values = new ContentValues();
397                values.put(Images.Media.TITLE, title);
398                values.put(Images.Media.DESCRIPTION, description);
399                values.put(Images.Media.MIME_TYPE, "image/jpeg");
400
401                Uri url = null;
402                String stringUrl = null;    /* value to be returned */
403
404                try
405                {
406                    url = cr.insert(EXTERNAL_CONTENT_URI, values);
407
408                    if (source != null) {
409                        OutputStream imageOut = cr.openOutputStream(url);
410                        try {
411                            source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut);
412                        } finally {
413                            imageOut.close();
414                        }
415
416                        long id = ContentUris.parseId(url);
417                        Bitmap miniThumb  = StoreThumbnail(cr, source, id, 320F, 240F, Images.Thumbnails.MINI_KIND);
418                        Bitmap microThumb = StoreThumbnail(cr, miniThumb, id, 50F, 50F, Images.Thumbnails.MICRO_KIND);
419                    } else {
420                        Log.e(TAG, "Failed to create thumbnail, removing original");
421                        cr.delete(url, null, null);
422                        url = null;
423                    }
424                } catch (Exception e) {
425                    Log.e(TAG, "Failed to insert image", e);
426                    if (url != null) {
427                        cr.delete(url, null, null);
428                        url = null;
429                    }
430                }
431
432                if (url != null) {
433                    stringUrl = url.toString();
434                }
435
436                return stringUrl;
437            }
438
439            /**
440             * Get the content:// style URI for the image media table on the
441             * given volume.
442             *
443             * @param volumeName the name of the volume to get the URI for
444             * @return the URI to the image media table on the given volume
445             */
446            public static Uri getContentUri(String volumeName) {
447                return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
448                        "/images/media");
449            }
450
451            /**
452             * The content:// style URI for the internal storage.
453             */
454            public static final Uri INTERNAL_CONTENT_URI =
455                    getContentUri("internal");
456
457            /**
458             * The content:// style URI for the "primary" external storage
459             * volume.
460             */
461            public static final Uri EXTERNAL_CONTENT_URI =
462                    getContentUri("external");
463
464            /**
465             * The MIME type of of this directory of
466             * images.  Note that each entry in this directory will have a standard
467             * image MIME type as appropriate -- for example, image/jpeg.
468             */
469            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/image";
470
471            /**
472             * The default sort order for this table
473             */
474            public static final String DEFAULT_SORT_ORDER = "name ASC";
475       }
476
477        public static class Thumbnails implements BaseColumns
478        {
479            public static final Cursor query(ContentResolver cr, Uri uri, String[] projection)
480            {
481                return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
482            }
483
484            public static final Cursor queryMiniThumbnails(ContentResolver cr, Uri uri, int kind, String[] projection)
485            {
486                return cr.query(uri, projection, "kind = " + kind, null, DEFAULT_SORT_ORDER);
487            }
488
489            public static final Cursor queryMiniThumbnail(ContentResolver cr, long origId, int kind, String[] projection)
490            {
491                return cr.query(EXTERNAL_CONTENT_URI, projection,
492                        IMAGE_ID + " = " + origId + " AND " + KIND + " = " +
493                        kind, null, null);
494            }
495
496            /**
497             * Get the content:// style URI for the image media table on the
498             * given volume.
499             *
500             * @param volumeName the name of the volume to get the URI for
501             * @return the URI to the image media table on the given volume
502             */
503            public static Uri getContentUri(String volumeName) {
504                return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
505                        "/images/thumbnails");
506            }
507
508            /**
509             * The content:// style URI for the internal storage.
510             */
511            public static final Uri INTERNAL_CONTENT_URI =
512                    getContentUri("internal");
513
514            /**
515             * The content:// style URI for the "primary" external storage
516             * volume.
517             */
518            public static final Uri EXTERNAL_CONTENT_URI =
519                    getContentUri("external");
520
521            /**
522             * The default sort order for this table
523             */
524            public static final String DEFAULT_SORT_ORDER = "image_id ASC";
525
526            /**
527             * The data stream for the thumbnail
528             * <P>Type: DATA STREAM</P>
529             */
530            public static final String DATA = "_data";
531
532            /**
533             * The original image for the thumbnal
534             * <P>Type: INTEGER (ID from Images table)</P>
535             */
536            public static final String IMAGE_ID = "image_id";
537
538            /**
539             * The kind of the thumbnail
540             * <P>Type: INTEGER (One of the values below)</P>
541             */
542            public static final String KIND = "kind";
543
544            public static final int MINI_KIND = 1;
545            public static final int FULL_SCREEN_KIND = 2;
546            public static final int MICRO_KIND = 3;
547
548            /**
549             * The width of the thumbnal
550             * <P>Type: INTEGER (long)</P>
551             */
552            public static final String WIDTH = "width";
553
554            /**
555             * The height of the thumbnail
556             * <P>Type: INTEGER (long)</P>
557             */
558            public static final String HEIGHT = "height";
559        }
560    }
561
562    /**
563     * Container for all audio content.
564     */
565    public static final class Audio {
566        /**
567         * Columns for audio file that show up in multiple tables.
568         */
569        public interface AudioColumns extends MediaColumns {
570
571            /**
572             * A non human readable key calculated from the TITLE, used for
573             * searching, sorting and grouping
574             * <P>Type: TEXT</P>
575             */
576            public static final String TITLE_KEY = "title_key";
577
578            /**
579             * The duration of the audio file, in ms
580             * <P>Type: INTEGER (long)</P>
581             */
582            public static final String DURATION = "duration";
583
584            /**
585             * The id of the artist who created the audio file, if any
586             * <P>Type: INTEGER (long)</P>
587             */
588            public static final String ARTIST_ID = "artist_id";
589
590            /**
591             * The artist who created the audio file, if any
592             * <P>Type: TEXT</P>
593             */
594            public static final String ARTIST = "artist";
595
596            /**
597             * A non human readable key calculated from the ARTIST, used for
598             * searching, sorting and grouping
599             * <P>Type: TEXT</P>
600             */
601            public static final String ARTIST_KEY = "artist_key";
602
603            /**
604             * The composer of the audio file, if any
605             * <P>Type: TEXT</P>
606             */
607            public static final String COMPOSER = "composer";
608
609            /**
610             * The id of the album the audio file is from, if any
611             * <P>Type: INTEGER (long)</P>
612             */
613            public static final String ALBUM_ID = "album_id";
614
615            /**
616             * The album the audio file is from, if any
617             * <P>Type: TEXT</P>
618             */
619            public static final String ALBUM = "album";
620
621            /**
622             * A non human readable key calculated from the ALBUM, used for
623             * searching, sorting and grouping
624             * <P>Type: TEXT</P>
625             */
626            public static final String ALBUM_KEY = "album_key";
627
628            /**
629             * A URI to the album art, if any
630             * <P>Type: TEXT</P>
631             */
632            public static final String ALBUM_ART = "album_art";
633
634            /**
635             * The track number of this song on the album, if any.
636             * This number encodes both the track number and the
637             * disc number. For multi-disc sets, this number will
638             * be 1xxx for tracks on the first disc, 2xxx for tracks
639             * on the second disc, etc.
640             * <P>Type: INTEGER</P>
641             */
642            public static final String TRACK = "track";
643
644            /**
645             * The year the audio file was recorded, if any
646             * <P>Type: INTEGER</P>
647             */
648            public static final String YEAR = "year";
649
650            /**
651             * Non-zero if the audio file is music
652             * <P>Type: INTEGER (boolean)</P>
653             */
654            public static final String IS_MUSIC = "is_music";
655
656            /**
657             * Non-zero id the audio file may be a ringtone
658             * <P>Type: INTEGER (boolean)</P>
659             */
660            public static final String IS_RINGTONE = "is_ringtone";
661
662            /**
663             * Non-zero id the audio file may be an alarm
664             * <P>Type: INTEGER (boolean)</P>
665             */
666            public static final String IS_ALARM = "is_alarm";
667
668            /**
669             * Non-zero id the audio file may be a notification sound
670             * <P>Type: INTEGER (boolean)</P>
671             */
672            public static final String IS_NOTIFICATION = "is_notification";
673        }
674
675        /**
676         * Converts a name to a "key" that can be used for grouping, sorting
677         * and searching.
678         * The rules that govern this conversion are:
679         * - remove 'special' characters like ()[]'!?.,
680         * - remove leading/trailing spaces
681         * - convert everything to lowercase
682         * - remove leading "the ", "an " and "a "
683         * - remove trailing ", the|an|a"
684         * - remove accents. This step leaves us with CollationKey data,
685         *   which is not human readable
686         *
687         * @param name The artist or album name to convert
688         * @return The "key" for the given name.
689         */
690        public static String keyFor(String name) {
691            if (name != null)  {
692                if (name.equals(android.media.MediaFile.UNKNOWN_STRING)) {
693                    return "\001";
694                }
695                name = name.trim().toLowerCase();
696                if (name.startsWith("the ")) {
697                    name = name.substring(4);
698                }
699                if (name.startsWith("an ")) {
700                    name = name.substring(3);
701                }
702                if (name.startsWith("a ")) {
703                    name = name.substring(2);
704                }
705                if (name.endsWith(", the") || name.endsWith(",the") ||
706                    name.endsWith(", an") || name.endsWith(",an") ||
707                    name.endsWith(", a") || name.endsWith(",a")) {
708                    name = name.substring(0, name.lastIndexOf(','));
709                }
710                name = name.replaceAll("[\\[\\]\\(\\)'.,?!]", "").trim();
711                if (name.length() > 0) {
712                    // Insert a separator between the characters to avoid
713                    // matches on a partial character. If we ever change
714                    // to start-of-word-only matches, this can be removed.
715                    StringBuilder b = new StringBuilder();
716                    b.append('.');
717                    int nl = name.length();
718                    for (int i = 0; i < nl; i++) {
719                        b.append(name.charAt(i));
720                        b.append('.');
721                    }
722                    name = b.toString();
723                    return DatabaseUtils.getCollationKey(name);
724               } else {
725                    return "";
726                }
727            }
728            return null;
729        }
730
731        public static final class Media implements AudioColumns {
732            /**
733             * Get the content:// style URI for the audio media table on the
734             * given volume.
735             *
736             * @param volumeName the name of the volume to get the URI for
737             * @return the URI to the audio media table on the given volume
738             */
739            public static Uri getContentUri(String volumeName) {
740                return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
741                        "/audio/media");
742            }
743
744            public static Uri getContentUriForPath(String path) {
745                return (path.startsWith(Environment.getExternalStorageDirectory().getPath()) ?
746                        EXTERNAL_CONTENT_URI : INTERNAL_CONTENT_URI);
747            }
748
749            /**
750             * The content:// style URI for the internal storage.
751             */
752            public static final Uri INTERNAL_CONTENT_URI =
753                    getContentUri("internal");
754
755            /**
756             * The content:// style URI for the "primary" external storage
757             * volume.
758             */
759            public static final Uri EXTERNAL_CONTENT_URI =
760                    getContentUri("external");
761
762            /**
763             * The MIME type for this table.
764             */
765            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/audio";
766
767            /**
768             * The default sort order for this table
769             */
770            public static final String DEFAULT_SORT_ORDER = TITLE;
771
772            /**
773             * Activity Action: Start SoundRecorder application.
774             * <p>Input: nothing.
775             * <p>Output: An uri to the recorded sound stored in the Media Library
776             * if the recording was successful.
777             * May also contain the extra EXTRA_MAX_BYTES.
778             * @see #EXTRA_MAX_BYTES
779             */
780            public static final String RECORD_SOUND_ACTION =
781                    "android.provider.MediaStore.RECORD_SOUND";
782
783            /**
784             * The name of the Intent-extra used to define a maximum file size for
785             * a recording made by the SoundRecorder application.
786             *
787             * @see #RECORD_SOUND_ACTION
788             */
789             public static final String EXTRA_MAX_BYTES =
790                    "android.provider.MediaStore.extra.MAX_BYTES";
791        }
792
793        /**
794         * Columns representing an audio genre
795         */
796        public interface GenresColumns {
797            /**
798             * The name of the genre
799             * <P>Type: TEXT</P>
800             */
801            public static final String NAME = "name";
802        }
803
804        /**
805         * Contains all genres for audio files
806         */
807        public static final class Genres implements BaseColumns, GenresColumns {
808            /**
809             * Get the content:// style URI for the audio genres table on the
810             * given volume.
811             *
812             * @param volumeName the name of the volume to get the URI for
813             * @return the URI to the audio genres table on the given volume
814             */
815            public static Uri getContentUri(String volumeName) {
816                return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
817                        "/audio/genres");
818            }
819
820            /**
821             * The content:// style URI for the internal storage.
822             */
823            public static final Uri INTERNAL_CONTENT_URI =
824                    getContentUri("internal");
825
826            /**
827             * The content:// style URI for the "primary" external storage
828             * volume.
829             */
830            public static final Uri EXTERNAL_CONTENT_URI =
831                    getContentUri("external");
832
833            /**
834             * The MIME type for this table.
835             */
836            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/genre";
837
838            /**
839             * The MIME type for entries in this table.
840             */
841            public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/genre";
842
843            /**
844             * The default sort order for this table
845             */
846            public static final String DEFAULT_SORT_ORDER = NAME;
847
848            /**
849             * Sub-directory of each genre containing all members.
850             */
851            public static final class Members implements AudioColumns {
852
853                public static final Uri getContentUri(String volumeName,
854                        long genreId) {
855                    return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName
856                            + "/audio/genres/" + genreId + "/members");
857                }
858
859                /**
860                 * A subdirectory of each genre containing all member audio files.
861                 */
862                public static final String CONTENT_DIRECTORY = "members";
863
864                /**
865                 * The default sort order for this table
866                 */
867                public static final String DEFAULT_SORT_ORDER = TITLE;
868
869                /**
870                 * The ID of the audio file
871                 * <P>Type: INTEGER (long)</P>
872                 */
873                public static final String AUDIO_ID = "audio_id";
874
875                /**
876                 * The ID of the genre
877                 * <P>Type: INTEGER (long)</P>
878                 */
879                public static final String GENRE_ID = "genre_id";
880            }
881        }
882
883        /**
884         * Columns representing a playlist
885         */
886        public interface PlaylistsColumns {
887            /**
888             * The name of the playlist
889             * <P>Type: TEXT</P>
890             */
891            public static final String NAME = "name";
892
893            /**
894             * The data stream for the playlist file
895             * <P>Type: DATA STREAM</P>
896             */
897            public static final String DATA = "_data";
898
899            /**
900             * The time the file was added to the media provider
901             * Units are seconds since 1970.
902             * <P>Type: INTEGER (long)</P>
903             */
904            public static final String DATE_ADDED = "date_added";
905
906            /**
907             * The time the file was last modified
908             * Units are seconds since 1970.
909             * NOTE: This is for internal use by the media scanner.  Do not modify this field.
910             * <P>Type: INTEGER (long)</P>
911             */
912            public static final String DATE_MODIFIED = "date_modified";
913        }
914
915        /**
916         * Contains playlists for audio files
917         */
918        public static final class Playlists implements BaseColumns,
919                PlaylistsColumns {
920            /**
921             * Get the content:// style URI for the audio playlists table on the
922             * given volume.
923             *
924             * @param volumeName the name of the volume to get the URI for
925             * @return the URI to the audio playlists table on the given volume
926             */
927            public static Uri getContentUri(String volumeName) {
928                return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
929                        "/audio/playlists");
930            }
931
932            /**
933             * The content:// style URI for the internal storage.
934             */
935            public static final Uri INTERNAL_CONTENT_URI =
936                    getContentUri("internal");
937
938            /**
939             * The content:// style URI for the "primary" external storage
940             * volume.
941             */
942            public static final Uri EXTERNAL_CONTENT_URI =
943                    getContentUri("external");
944
945            /**
946             * The MIME type for this table.
947             */
948            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/playlist";
949
950            /**
951             * The MIME type for entries in this table.
952             */
953            public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/playlist";
954
955            /**
956             * The default sort order for this table
957             */
958            public static final String DEFAULT_SORT_ORDER = NAME;
959
960            /**
961             * Sub-directory of each playlist containing all members.
962             */
963            public static final class Members implements AudioColumns {
964                public static final Uri getContentUri(String volumeName,
965                        long playlistId) {
966                    return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName
967                            + "/audio/playlists/" + playlistId + "/members");
968                }
969
970                /**
971                 * The ID within the playlist.
972                 */
973                public static final String _ID = "_id";
974
975                /**
976                 * A subdirectory of each playlist containing all member audio
977                 * files.
978                 */
979                public static final String CONTENT_DIRECTORY = "members";
980
981                /**
982                 * The ID of the audio file
983                 * <P>Type: INTEGER (long)</P>
984                 */
985                public static final String AUDIO_ID = "audio_id";
986
987                /**
988                 * The ID of the playlist
989                 * <P>Type: INTEGER (long)</P>
990                 */
991                public static final String PLAYLIST_ID = "playlist_id";
992
993                /**
994                 * The order of the songs in the playlist
995                 * <P>Type: INTEGER (long)></P>
996                 */
997                public static final String PLAY_ORDER = "play_order";
998
999                /**
1000                 * The default sort order for this table
1001                 */
1002                public static final String DEFAULT_SORT_ORDER = PLAY_ORDER;
1003            }
1004        }
1005
1006        /**
1007         * Columns representing an artist
1008         */
1009        public interface ArtistColumns {
1010            /**
1011             * The artist who created the audio file, if any
1012             * <P>Type: TEXT</P>
1013             */
1014            public static final String ARTIST = "artist";
1015
1016            /**
1017             * A non human readable key calculated from the ARTIST, used for
1018             * searching, sorting and grouping
1019             * <P>Type: TEXT</P>
1020             */
1021            public static final String ARTIST_KEY = "artist_key";
1022
1023            /**
1024             * The number of albums in the database for this artist
1025             */
1026            public static final String NUMBER_OF_ALBUMS = "number_of_albums";
1027
1028            /**
1029             * The number of albums in the database for this artist
1030             */
1031            public static final String NUMBER_OF_TRACKS = "number_of_tracks";
1032        }
1033
1034        /**
1035         * Contains artists for audio files
1036         */
1037        public static final class Artists implements BaseColumns, ArtistColumns {
1038            /**
1039             * Get the content:// style URI for the artists table on the
1040             * given volume.
1041             *
1042             * @param volumeName the name of the volume to get the URI for
1043             * @return the URI to the audio artists table on the given volume
1044             */
1045            public static Uri getContentUri(String volumeName) {
1046                return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
1047                        "/audio/artists");
1048            }
1049
1050            /**
1051             * The content:// style URI for the internal storage.
1052             */
1053            public static final Uri INTERNAL_CONTENT_URI =
1054                    getContentUri("internal");
1055
1056            /**
1057             * The content:// style URI for the "primary" external storage
1058             * volume.
1059             */
1060            public static final Uri EXTERNAL_CONTENT_URI =
1061                    getContentUri("external");
1062
1063            /**
1064             * The MIME type for this table.
1065             */
1066            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/artists";
1067
1068            /**
1069             * The MIME type for entries in this table.
1070             */
1071            public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/artist";
1072
1073            /**
1074             * The default sort order for this table
1075             */
1076            public static final String DEFAULT_SORT_ORDER = ARTIST_KEY;
1077
1078            /**
1079             * Sub-directory of each artist containing all albums on which
1080             * a song by the artist appears.
1081             */
1082            public static final class Albums implements AlbumColumns {
1083                public static final Uri getContentUri(String volumeName,
1084                        long artistId) {
1085                    return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName
1086                            + "/audio/artists/" + artistId + "/albums");
1087                }
1088            }
1089        }
1090
1091        /**
1092         * Columns representing an album
1093         */
1094        public interface AlbumColumns {
1095
1096            /**
1097             * The id for the album
1098             * <P>Type: INTEGER</P>
1099             */
1100            public static final String ALBUM_ID = "album_id";
1101
1102            /**
1103             * The album on which the audio file appears, if any
1104             * <P>Type: TEXT</P>
1105             */
1106            public static final String ALBUM = "album";
1107
1108            /**
1109             * The artist whose songs appear on this album
1110             * <P>Type: TEXT</P>
1111             */
1112            public static final String ARTIST = "artist";
1113
1114            /**
1115             * The number of songs on this album
1116             * <P>Type: INTEGER</P>
1117             */
1118            public static final String NUMBER_OF_SONGS = "numsongs";
1119
1120            /**
1121             * This column is available when getting album info via artist,
1122             * and indicates the number of songs on the album by the given
1123             * artist.
1124             * <P>Type: INTEGER</P>
1125             *
1126             * @hide pending API Council approval
1127             */
1128            public static final String NUMBER_OF_SONGS_FOR_ARTIST = "numsongs_by_artist";
1129
1130            /**
1131             * The year in which the earliest and latest songs
1132             * on this album were released. These will often
1133             * be the same, but for compilation albums they
1134             * might differ.
1135             * <P>Type: INTEGER</P>
1136             */
1137            public static final String FIRST_YEAR = "minyear";
1138            public static final String LAST_YEAR = "maxyear";
1139
1140            /**
1141             * A non human readable key calculated from the ALBUM, used for
1142             * searching, sorting and grouping
1143             * <P>Type: TEXT</P>
1144             */
1145            public static final String ALBUM_KEY = "album_key";
1146
1147            /**
1148             * Cached album art.
1149             * <P>Type: TEXT</P>
1150             */
1151            public static final String ALBUM_ART = "album_art";
1152        }
1153
1154        /**
1155         * Contains artists for audio files
1156         */
1157        public static final class Albums implements BaseColumns, AlbumColumns {
1158            /**
1159             * Get the content:// style URI for the albums table on the
1160             * given volume.
1161             *
1162             * @param volumeName the name of the volume to get the URI for
1163             * @return the URI to the audio albums table on the given volume
1164             */
1165            public static Uri getContentUri(String volumeName) {
1166                return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
1167                        "/audio/albums");
1168            }
1169
1170            /**
1171             * The content:// style URI for the internal storage.
1172             */
1173            public static final Uri INTERNAL_CONTENT_URI =
1174                    getContentUri("internal");
1175
1176            /**
1177             * The content:// style URI for the "primary" external storage
1178             * volume.
1179             */
1180            public static final Uri EXTERNAL_CONTENT_URI =
1181                    getContentUri("external");
1182
1183            /**
1184             * The MIME type for this table.
1185             */
1186            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/albums";
1187
1188            /**
1189             * The MIME type for entries in this table.
1190             */
1191            public static final String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/album";
1192
1193            /**
1194             * The default sort order for this table
1195             */
1196            public static final String DEFAULT_SORT_ORDER = ALBUM_KEY;
1197        }
1198    }
1199
1200    public static final class Video {
1201        /**
1202         *  deprecated  Replaced by DEFAULT_SORT_ORDER2
1203         *  This variable is a mistake that is retained for backwards compatibility.
1204         *  (There is no "name" column in the Video table.)
1205         */
1206        public static final String DEFAULT_SORT_ORDER = "name ASC";
1207
1208        /**
1209         * The default sort order for this table
1210         * @hide
1211         */
1212        public static final String DEFAULT_SORT_ORDER2 = MediaColumns.DISPLAY_NAME;
1213
1214        public static final Cursor query(ContentResolver cr, Uri uri, String[] projection)
1215        {
1216            return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER2);
1217        }
1218
1219        public interface VideoColumns extends MediaColumns {
1220
1221            /**
1222             * The duration of the video file, in ms
1223             * <P>Type: INTEGER (long)</P>
1224             */
1225            public static final String DURATION = "duration";
1226
1227            /**
1228             * The artist who created the video file, if any
1229             * <P>Type: TEXT</P>
1230             */
1231            public static final String ARTIST = "artist";
1232
1233            /**
1234             * The album the video file is from, if any
1235             * <P>Type: TEXT</P>
1236             */
1237            public static final String ALBUM = "album";
1238
1239            /**
1240             * The resolution of the video file, formatted as "XxY"
1241             * <P>Type: TEXT</P>
1242             */
1243            public static final String RESOLUTION = "resolution";
1244
1245            /**
1246             * The description of the video recording
1247             * <P>Type: TEXT</P>
1248             */
1249            public static final String DESCRIPTION = "description";
1250
1251            /**
1252             * Whether the video should be published as public or private
1253             * <P>Type: INTEGER</P>
1254             */
1255            public static final String IS_PRIVATE = "isprivate";
1256
1257            /**
1258             * The user-added tags associated with a video
1259             * <P>Type: TEXT</P>
1260             */
1261            public static final String TAGS = "tags";
1262
1263            /**
1264             * The YouTube category of the video
1265             * <P>Type: TEXT</P>
1266             */
1267            public static final String CATEGORY = "category";
1268
1269            /**
1270             * The language of the video
1271             * <P>Type: TEXT</P>
1272             */
1273            public static final String LANGUAGE = "language";
1274
1275            /**
1276             * The latitude where the image was captured.
1277             * <P>Type: DOUBLE</P>
1278             */
1279            public static final String LATITUDE = "latitude";
1280
1281            /**
1282             * The longitude where the image was captured.
1283             * <P>Type: DOUBLE</P>
1284             */
1285            public static final String LONGITUDE = "longitude";
1286
1287            /**
1288             * The date & time that the image was taken in units
1289             * of milliseconds since jan 1, 1970.
1290             * <P>Type: INTEGER</P>
1291             */
1292            public static final String DATE_TAKEN = "datetaken";
1293
1294            /**
1295             * The mini thumb id.
1296             * <P>Type: INTEGER</P>
1297             */
1298            public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
1299
1300            /**
1301             * The bucket id of the video. This is a read-only property that
1302             * is automatically computed from the DATA column.
1303             * <P>Type: TEXT</P>
1304             */
1305            public static final String BUCKET_ID = "bucket_id";
1306
1307            /**
1308             * The bucket display name of the video. This is a read-only property that
1309             * is automatically computed from the DATA column.
1310             * <P>Type: TEXT</P>
1311             */
1312            public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
1313
1314            /**
1315             * The bookmark for the video. Time in ms. Represents the location in the video that the
1316             * video should start playing at the next time it is opened. If the value is null or
1317             * out of the range 0..DURATION-1 then the video should start playing from the
1318             * beginning.
1319             * @hide
1320             * <P>Type: INTEGER</P>
1321             */
1322            public static final String BOOKMARK = "bookmark";
1323        }
1324
1325        public static final class Media implements VideoColumns {
1326            /**
1327             * Get the content:// style URI for the video media table on the
1328             * given volume.
1329             *
1330             * @param volumeName the name of the volume to get the URI for
1331             * @return the URI to the video media table on the given volume
1332             */
1333            public static Uri getContentUri(String volumeName) {
1334                return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName +
1335                        "/video/media");
1336            }
1337
1338            /**
1339             * The content:// style URI for the internal storage.
1340             */
1341            public static final Uri INTERNAL_CONTENT_URI =
1342                    getContentUri("internal");
1343
1344            /**
1345             * The content:// style URI for the "primary" external storage
1346             * volume.
1347             */
1348            public static final Uri EXTERNAL_CONTENT_URI =
1349                    getContentUri("external");
1350
1351            /**
1352             * The MIME type for this table.
1353             */
1354            public static final String CONTENT_TYPE = "vnd.android.cursor.dir/video";
1355
1356            /**
1357             * The default sort order for this table
1358             */
1359            public static final String DEFAULT_SORT_ORDER = TITLE;
1360        }
1361    }
1362
1363    /**
1364     * Uri for querying the state of the media scanner.
1365     */
1366    public static Uri getMediaScannerUri() {
1367        return Uri.parse(CONTENT_AUTHORITY_SLASH + "none/media_scanner");
1368    }
1369
1370    /**
1371     * Name of current volume being scanned by the media scanner.
1372     */
1373    public static final String MEDIA_SCANNER_VOLUME = "volume";
1374}
1375