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