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