RingtoneManager.java revision f8a7ceaef2e7d5cd530c9426bde91b6fa9a40b75
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.media; 18 19import com.android.internal.database.SortCursor; 20 21import android.annotation.SdkConstant; 22import android.annotation.SdkConstant.SdkConstantType; 23import android.app.Activity; 24import android.content.ContentUris; 25import android.content.Context; 26import android.content.res.AssetFileDescriptor; 27import android.database.Cursor; 28import android.net.Uri; 29import android.os.Environment; 30import android.provider.DrmStore; 31import android.provider.MediaStore; 32import android.provider.Settings; 33import android.provider.Settings.System; 34import android.util.Log; 35 36import java.util.ArrayList; 37import java.util.List; 38 39/** 40 * RingtoneManager provides access to ringtones, notification, and other types 41 * of sounds. It manages querying the different media providers and combines the 42 * results into a single cursor. It also provides a {@link Ringtone} for each 43 * ringtone. We generically call these sounds ringtones, however the 44 * {@link #TYPE_RINGTONE} refers to the type of sounds that are suitable for the 45 * phone ringer. 46 * <p> 47 * To show a ringtone picker to the user, use the 48 * {@link #ACTION_RINGTONE_PICKER} intent to launch the picker as a subactivity. 49 * 50 * @see Ringtone 51 */ 52public class RingtoneManager { 53 54 private static final String TAG = "RingtoneManager"; 55 56 // Make sure these are in sync with attrs.xml: 57 // <attr name="ringtoneType"> 58 59 /** 60 * Type that refers to sounds that are used for the phone ringer. 61 */ 62 public static final int TYPE_RINGTONE = 1; 63 64 /** 65 * Type that refers to sounds that are used for notifications. 66 */ 67 public static final int TYPE_NOTIFICATION = 2; 68 69 /** 70 * Type that refers to sounds that are used for the alarm. 71 */ 72 public static final int TYPE_ALARM = 4; 73 74 /** 75 * All types of sounds. 76 */ 77 public static final int TYPE_ALL = TYPE_RINGTONE | TYPE_NOTIFICATION | TYPE_ALARM; 78 79 // </attr> 80 81 /** 82 * Activity Action: Shows a ringtone picker. 83 * <p> 84 * Input: {@link #EXTRA_RINGTONE_EXISTING_URI}, 85 * {@link #EXTRA_RINGTONE_SHOW_DEFAULT}, 86 * {@link #EXTRA_RINGTONE_SHOW_SILENT}, {@link #EXTRA_RINGTONE_TYPE}, 87 * {@link #EXTRA_RINGTONE_DEFAULT_URI}, {@link #EXTRA_RINGTONE_TITLE}, 88 * {@link #EXTRA_RINGTONE_INCLUDE_DRM}. 89 * <p> 90 * Output: {@link #EXTRA_RINGTONE_PICKED_URI}. 91 */ 92 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 93 public static final String ACTION_RINGTONE_PICKER = "android.intent.action.RINGTONE_PICKER"; 94 95 /** 96 * Given to the ringtone picker as a boolean. Whether to show an item for 97 * "Default". 98 * 99 * @see #ACTION_RINGTONE_PICKER 100 */ 101 public static final String EXTRA_RINGTONE_SHOW_DEFAULT = 102 "android.intent.extra.ringtone.SHOW_DEFAULT"; 103 104 /** 105 * Given to the ringtone picker as a boolean. Whether to show an item for 106 * "Silent". If the "Silent" item is picked, 107 * {@link #EXTRA_RINGTONE_PICKED_URI} will be null. 108 * 109 * @see #ACTION_RINGTONE_PICKER 110 */ 111 public static final String EXTRA_RINGTONE_SHOW_SILENT = 112 "android.intent.extra.ringtone.SHOW_SILENT"; 113 114 /** 115 * Given to the ringtone picker as a boolean. Whether to include DRM ringtones. 116 */ 117 public static final String EXTRA_RINGTONE_INCLUDE_DRM = 118 "android.intent.extra.ringtone.INCLUDE_DRM"; 119 120 /** 121 * Given to the ringtone picker as a {@link Uri}. The {@link Uri} of the 122 * current ringtone, which will be used to show a checkmark next to the item 123 * for this {@link Uri}. If showing an item for "Default" (@see 124 * {@link #EXTRA_RINGTONE_SHOW_DEFAULT}), this can also be one of 125 * {@link System#DEFAULT_RINGTONE_URI} or 126 * {@link System#DEFAULT_NOTIFICATION_URI} to have the "Default" item 127 * checked. 128 * 129 * @see #ACTION_RINGTONE_PICKER 130 */ 131 public static final String EXTRA_RINGTONE_EXISTING_URI = 132 "android.intent.extra.ringtone.EXISTING_URI"; 133 134 /** 135 * Given to the ringtone picker as a {@link Uri}. The {@link Uri} of the 136 * ringtone to play when the user attempts to preview the "Default" 137 * ringtone. This can be one of {@link System#DEFAULT_RINGTONE_URI} or 138 * {@link System#DEFAULT_NOTIFICATION_URI} to have the "Default" point to 139 * the current sound for the given default sound type. If you are showing a 140 * ringtone picker for some other type of sound, you are free to provide any 141 * {@link Uri} here. 142 */ 143 public static final String EXTRA_RINGTONE_DEFAULT_URI = 144 "android.intent.extra.ringtone.DEFAULT_URI"; 145 146 /** 147 * Given to the ringtone picker as an int. Specifies which ringtone type(s) should be 148 * shown in the picker. One or more of {@link #TYPE_RINGTONE}, 149 * {@link #TYPE_NOTIFICATION}, {@link #TYPE_ALARM}, or {@link #TYPE_ALL} 150 * (bitwise-ored together). 151 */ 152 public static final String EXTRA_RINGTONE_TYPE = "android.intent.extra.ringtone.TYPE"; 153 154 /** 155 * Given to the ringtone picker as a {@link CharSequence}. The title to 156 * show for the ringtone picker. This has a default value that is suitable 157 * in most cases. 158 */ 159 public static final String EXTRA_RINGTONE_TITLE = "android.intent.extra.ringtone.TITLE"; 160 161 /** 162 * Returned from the ringtone picker as a {@link Uri}. 163 * <p> 164 * It will be one of: 165 * <li> the picked ringtone, 166 * <li> a {@link Uri} that equals {@link System#DEFAULT_RINGTONE_URI} or 167 * {@link System#DEFAULT_NOTIFICATION_URI} if the default was chosen, 168 * <li> null if the "Silent" item was picked. 169 * 170 * @see #ACTION_RINGTONE_PICKER 171 */ 172 public static final String EXTRA_RINGTONE_PICKED_URI = 173 "android.intent.extra.ringtone.PICKED_URI"; 174 175 // Make sure the column ordering and then ..._COLUMN_INDEX are in sync 176 177 private static final String[] INTERNAL_COLUMNS = new String[] { 178 MediaStore.Audio.Media._ID, MediaStore.Audio.Media.TITLE, 179 "\"" + MediaStore.Audio.Media.INTERNAL_CONTENT_URI + "\"" 180 }; 181 182 private static final String[] DRM_COLUMNS = new String[] { 183 DrmStore.Audio._ID, DrmStore.Audio.TITLE, 184 "\"" + DrmStore.Audio.CONTENT_URI + "\"" 185 }; 186 187 private static final String[] MEDIA_COLUMNS = new String[] { 188 MediaStore.Audio.Media._ID, MediaStore.Audio.Media.TITLE, 189 "\"" + MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + "\"" 190 }; 191 192 /** 193 * The column index (in the cursor returned by {@link #getCursor()} for the 194 * row ID. 195 */ 196 public static final int ID_COLUMN_INDEX = 0; 197 198 /** 199 * The column index (in the cursor returned by {@link #getCursor()} for the 200 * title. 201 */ 202 public static final int TITLE_COLUMN_INDEX = 1; 203 204 /** 205 * The column index (in the cursor returned by {@link #getCursor()} for the 206 * media provider's URI. 207 */ 208 public static final int URI_COLUMN_INDEX = 2; 209 210 private Activity mActivity; 211 private Context mContext; 212 213 private Cursor mCursor; 214 215 private int mType = TYPE_RINGTONE; 216 217 /** 218 * If a column (item from this list) exists in the Cursor, its value must 219 * be true (value of 1) for the row to be returned. 220 */ 221 private List<String> mFilterColumns = new ArrayList<String>(); 222 223 private boolean mStopPreviousRingtone = true; 224 private Ringtone mPreviousRingtone; 225 226 private boolean mIncludeDrm; 227 228 /** 229 * Constructs a RingtoneManager. This constructor is recommended as its 230 * constructed instance manages cursor(s). 231 * 232 * @param activity The activity used to get a managed cursor. 233 */ 234 public RingtoneManager(Activity activity) { 235 mContext = mActivity = activity; 236 setType(mType); 237 } 238 239 /** 240 * Constructs a RingtoneManager. The instance constructed by this 241 * constructor will not manage the cursor(s), so the client should handle 242 * this itself. 243 * 244 * @param context The context to used to get a cursor. 245 */ 246 public RingtoneManager(Context context) { 247 mContext = context; 248 setType(mType); 249 } 250 251 /** 252 * Sets which type(s) of ringtones will be listed by this. 253 * 254 * @param type The type(s), one or more of {@link #TYPE_RINGTONE}, 255 * {@link #TYPE_NOTIFICATION}, {@link #TYPE_ALARM}, 256 * {@link #TYPE_ALL}. 257 * @see #EXTRA_RINGTONE_TYPE 258 */ 259 public void setType(int type) { 260 261 if (mCursor != null) { 262 throw new IllegalStateException( 263 "Setting filter columns should be done before querying for ringtones."); 264 } 265 266 mType = type; 267 setFilterColumnsList(type); 268 } 269 270 /** 271 * Infers the playback stream type based on what type of ringtones this 272 * manager is returning. 273 * 274 * @return The stream type. 275 */ 276 public int inferStreamType() { 277 switch (mType) { 278 279 case TYPE_ALARM: 280 return AudioManager.STREAM_ALARM; 281 282 case TYPE_NOTIFICATION: 283 return AudioManager.STREAM_NOTIFICATION; 284 285 default: 286 return AudioManager.STREAM_RING; 287 } 288 } 289 290 /** 291 * Whether retrieving another {@link Ringtone} will stop playing the 292 * previously retrieved {@link Ringtone}. 293 * <p> 294 * If this is false, make sure to {@link Ringtone#stop()} any previous 295 * ringtones to free resources. 296 * 297 * @param stopPreviousRingtone If true, the previously retrieved 298 * {@link Ringtone} will be stopped. 299 */ 300 public void setStopPreviousRingtone(boolean stopPreviousRingtone) { 301 mStopPreviousRingtone = stopPreviousRingtone; 302 } 303 304 /** 305 * @see #setStopPreviousRingtone(boolean) 306 */ 307 public boolean getStopPreviousRingtone() { 308 return mStopPreviousRingtone; 309 } 310 311 /** 312 * Stops playing the last {@link Ringtone} retrieved from this. 313 */ 314 public void stopPreviousRingtone() { 315 if (mPreviousRingtone != null) { 316 mPreviousRingtone.stop(); 317 } 318 } 319 320 /** 321 * Returns whether DRM ringtones will be included. 322 * 323 * @return Whether DRM ringtones will be included. 324 * @see #setIncludeDrm(boolean) 325 */ 326 public boolean getIncludeDrm() { 327 return mIncludeDrm; 328 } 329 330 /** 331 * Sets whether to include DRM ringtones. 332 * 333 * @param includeDrm Whether to include DRM ringtones. 334 */ 335 public void setIncludeDrm(boolean includeDrm) { 336 mIncludeDrm = includeDrm; 337 } 338 339 /** 340 * Returns a {@link Cursor} of all the ringtones available. The returned 341 * cursor will be the same cursor returned each time this method is called, 342 * so do not {@link Cursor#close()} the cursor. The cursor can be 343 * {@link Cursor#deactivate()} safely. 344 * <p> 345 * If {@link RingtoneManager#RingtoneManager(Activity)} was not used, the 346 * caller should manage the returned cursor through its activity's life 347 * cycle to prevent leaking the cursor. 348 * 349 * @return A {@link Cursor} of all the ringtones available. 350 * @see #ID_COLUMN_INDEX 351 * @see #TITLE_COLUMN_INDEX 352 * @see #URI_COLUMN_INDEX 353 */ 354 public Cursor getCursor() { 355 if (mCursor != null && mCursor.requery()) { 356 return mCursor; 357 } 358 359 final Cursor internalCursor = getInternalRingtones(); 360 final Cursor drmCursor = mIncludeDrm ? getDrmRingtones() : null; 361 final Cursor mediaCursor = getMediaRingtones(); 362 363 return mCursor = new SortCursor(new Cursor[] { internalCursor, drmCursor, mediaCursor }, 364 MediaStore.MediaColumns.TITLE); 365 } 366 367 /** 368 * Gets a {@link Ringtone} for the ringtone at the given position in the 369 * {@link Cursor}. 370 * 371 * @param position The position (in the {@link Cursor}) of the ringtone. 372 * @return A {@link Ringtone} pointing to the ringtone. 373 */ 374 public Ringtone getRingtone(int position) { 375 if (mStopPreviousRingtone && mPreviousRingtone != null) { 376 mPreviousRingtone.stop(); 377 } 378 379 mPreviousRingtone = getRingtone(mContext, getRingtoneUri(position), inferStreamType()); 380 return mPreviousRingtone; 381 } 382 383 /** 384 * Gets a {@link Uri} for the ringtone at the given position in the {@link Cursor}. 385 * 386 * @param position The position (in the {@link Cursor}) of the ringtone. 387 * @return A {@link Uri} pointing to the ringtone. 388 */ 389 public Uri getRingtoneUri(int position) { 390 final Cursor cursor = getCursor(); 391 392 if (!cursor.moveToPosition(position)) { 393 return null; 394 } 395 396 return getUriFromCursor(cursor); 397 } 398 399 private static Uri getUriFromCursor(Cursor cursor) { 400 return ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)), cursor 401 .getLong(ID_COLUMN_INDEX)); 402 } 403 404 /** 405 * Gets the position of a {@link Uri} within this {@link RingtoneManager}. 406 * 407 * @param ringtoneUri The {@link Uri} to retreive the position of. 408 * @return The position of the {@link Uri}, or -1 if it cannot be found. 409 */ 410 public int getRingtonePosition(Uri ringtoneUri) { 411 412 if (ringtoneUri == null) return -1; 413 414 final Cursor cursor = getCursor(); 415 final int cursorCount = cursor.getCount(); 416 417 if (!cursor.moveToFirst()) { 418 return -1; 419 } 420 421 // Only create Uri objects when the actual URI changes 422 Uri currentUri = null; 423 String previousUriString = null; 424 for (int i = 0; i < cursorCount; i++) { 425 String uriString = cursor.getString(URI_COLUMN_INDEX); 426 if (currentUri == null || !uriString.equals(previousUriString)) { 427 currentUri = Uri.parse(uriString); 428 } 429 430 if (ringtoneUri.equals(ContentUris.withAppendedId(currentUri, cursor 431 .getLong(ID_COLUMN_INDEX)))) { 432 return i; 433 } 434 435 cursor.move(1); 436 437 previousUriString = uriString; 438 } 439 440 return -1; 441 } 442 443 /** 444 * Returns a valid ringtone URI. No guarantees on which it returns. If it 445 * cannot find one, returns null. 446 * 447 * @param context The context to use for querying. 448 * @return A ringtone URI, or null if one cannot be found. 449 */ 450 public static Uri getValidRingtoneUri(Context context) { 451 final RingtoneManager rm = new RingtoneManager(context); 452 453 Uri uri = getValidRingtoneUriFromCursorAndClose(context, rm.getInternalRingtones()); 454 455 if (uri == null) { 456 uri = getValidRingtoneUriFromCursorAndClose(context, rm.getMediaRingtones()); 457 } 458 459 if (uri == null) { 460 uri = getValidRingtoneUriFromCursorAndClose(context, rm.getDrmRingtones()); 461 } 462 463 return uri; 464 } 465 466 private static Uri getValidRingtoneUriFromCursorAndClose(Context context, Cursor cursor) { 467 if (cursor != null) { 468 Uri uri = null; 469 470 if (cursor.moveToFirst()) { 471 uri = getUriFromCursor(cursor); 472 } 473 cursor.close(); 474 475 return uri; 476 } else { 477 return null; 478 } 479 } 480 481 private Cursor getInternalRingtones() { 482 return query( 483 MediaStore.Audio.Media.INTERNAL_CONTENT_URI, INTERNAL_COLUMNS, 484 constructBooleanTrueWhereClause(mFilterColumns), 485 null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER); 486 } 487 488 private Cursor getDrmRingtones() { 489 // DRM store does not have any columns to use for filtering 490 return query( 491 DrmStore.Audio.CONTENT_URI, DRM_COLUMNS, 492 null, null, DrmStore.Audio.TITLE); 493 } 494 495 private Cursor getMediaRingtones() { 496 // Get the external media cursor. First check to see if it is mounted. 497 final String status = Environment.getExternalStorageState(); 498 499 return (status.equals(Environment.MEDIA_MOUNTED) || 500 status.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) 501 ? query( 502 MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MEDIA_COLUMNS, 503 constructBooleanTrueWhereClause(mFilterColumns), null, 504 MediaStore.Audio.Media.DEFAULT_SORT_ORDER) 505 : null; 506 } 507 508 private void setFilterColumnsList(int type) { 509 List<String> columns = mFilterColumns; 510 columns.clear(); 511 512 if ((type & TYPE_RINGTONE) != 0) { 513 columns.add(MediaStore.Audio.AudioColumns.IS_RINGTONE); 514 } 515 516 if ((type & TYPE_NOTIFICATION) != 0) { 517 columns.add(MediaStore.Audio.AudioColumns.IS_NOTIFICATION); 518 } 519 520 if ((type & TYPE_ALARM) != 0) { 521 columns.add(MediaStore.Audio.AudioColumns.IS_ALARM); 522 } 523 } 524 525 /** 526 * Constructs a where clause that consists of at least one column being 1 527 * (true). This is used to find all matching sounds for the given sound 528 * types (ringtone, notifications, etc.) 529 * 530 * @param columns The columns that must be true. 531 * @return The where clause. 532 */ 533 private static String constructBooleanTrueWhereClause(List<String> columns) { 534 535 if (columns == null) return null; 536 537 StringBuilder sb = new StringBuilder(); 538 for (int i = columns.size() - 1; i >= 0; i--) { 539 sb.append(columns.get(i)).append("=1 or "); 540 } 541 542 if (columns.size() > 0) { 543 // Remove last ' or ' 544 sb.setLength(sb.length() - 4); 545 } 546 547 return sb.toString(); 548 } 549 550 private Cursor query(Uri uri, 551 String[] projection, 552 String selection, 553 String[] selectionArgs, 554 String sortOrder) { 555 if (mActivity != null) { 556 return mActivity.managedQuery(uri, projection, selection, selectionArgs, sortOrder); 557 } else { 558 return mContext.getContentResolver().query(uri, projection, selection, selectionArgs, 559 sortOrder); 560 } 561 } 562 563 /** 564 * Returns a {@link Ringtone} for a given sound URI. 565 * <p> 566 * If the given URI cannot be opened for any reason, this method will 567 * attempt to fallback on another sound. If it cannot find any, it will 568 * return null. 569 * 570 * @param context A context used to query. 571 * @param ringtoneUri The {@link Uri} of a sound or ringtone. 572 * @return A {@link Ringtone} for the given URI, or null. 573 */ 574 public static Ringtone getRingtone(final Context context, Uri ringtoneUri) { 575 // Don't set the stream type 576 return getRingtone(context, ringtoneUri, -1); 577 } 578 579 /** 580 * Returns a {@link Ringtone} for a given sound URI on the given stream 581 * type. Normally, if you change the stream type on the returned 582 * {@link Ringtone}, it will re-create the {@link MediaPlayer}. This is just 583 * an optimized route to avoid that. 584 * 585 * @param streamType The stream type for the ringtone, or -1 if it should 586 * not be set (and the default used instead). 587 * @see #getRingtone(Context, Uri) 588 */ 589 private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType) { 590 591 try { 592 Ringtone r = new Ringtone(context); 593 if (streamType >= 0) { 594 r.setStreamType(streamType); 595 } 596 r.open(ringtoneUri); 597 return r; 598 } catch (Exception ex) { 599 Log.e(TAG, "Failed to open ringtone " + ringtoneUri); 600 } 601 602 // Ringtone doesn't exist, use the fallback ringtone. 603 try { 604 AssetFileDescriptor afd = context.getResources().openRawResourceFd( 605 com.android.internal.R.raw.fallbackring); 606 if (afd != null) { 607 Ringtone r = new Ringtone(context); 608 r.open(afd); 609 afd.close(); 610 return r; 611 } 612 } catch (Exception ex) { 613 } 614 615 // we should never get here 616 Log.e(TAG, "unable to find a usable ringtone"); 617 return null; 618 } 619 620 /** 621 * Gets the current default sound's {@link Uri}. This will give the actual 622 * sound {@link Uri}, instead of using this, most clients can use 623 * {@link System#DEFAULT_RINGTONE_URI}. 624 * 625 * @param context A context used for querying. 626 * @param type The type whose default sound should be returned. One of 627 * {@link #TYPE_RINGTONE} or {@link #TYPE_NOTIFICATION}. 628 * @return A {@link Uri} pointing to the default sound for the sound type. 629 * @see #setActualDefaultRingtoneUri(Context, int, Uri) 630 */ 631 public static Uri getActualDefaultRingtoneUri(Context context, int type) { 632 String setting = getSettingForType(type); 633 if (setting == null) return null; 634 final String uriString = Settings.System.getString(context.getContentResolver(), setting); 635 return uriString != null ? Uri.parse(uriString) : getValidRingtoneUri(context); 636 } 637 638 /** 639 * Sets the {@link Uri} of the default sound for a given sound type. 640 * 641 * @param context A context used for querying. 642 * @param type The type whose default sound should be set. One of 643 * {@link #TYPE_RINGTONE} or {@link #TYPE_NOTIFICATION}. 644 * @param ringtoneUri A {@link Uri} pointing to the default sound to set. 645 * @see #getActualDefaultRingtoneUri(Context, int) 646 */ 647 public static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri) { 648 String setting = getSettingForType(type); 649 if (setting == null) return; 650 Settings.System.putString(context.getContentResolver(), setting, ringtoneUri.toString()); 651 } 652 653 private static String getSettingForType(int type) { 654 if ((type & TYPE_RINGTONE) != 0) { 655 return Settings.System.RINGTONE; 656 } else if ((type & TYPE_NOTIFICATION) != 0) { 657 return Settings.System.NOTIFICATION_SOUND; 658 } else { 659 return null; 660 } 661 } 662 663 /** 664 * Returns whether the given {@link Uri} is one of the default ringtones. 665 * 666 * @param ringtoneUri The ringtone {@link Uri} to be checked. 667 * @return Whether the {@link Uri} is a default. 668 */ 669 public static boolean isDefault(Uri ringtoneUri) { 670 return getDefaultType(ringtoneUri) != -1; 671 } 672 673 /** 674 * Returns the type of a default {@link Uri}. 675 * 676 * @param defaultRingtoneUri The default {@link Uri}. For example, 677 * {@link System#DEFAULT_RINGTONE_URI} or 678 * {@link System#DEFAULT_NOTIFICATION_URI}. 679 * @return The type of the defaultRingtoneUri, or -1. 680 */ 681 public static int getDefaultType(Uri defaultRingtoneUri) { 682 if (defaultRingtoneUri == null) { 683 return -1; 684 } else if (defaultRingtoneUri.equals(Settings.System.DEFAULT_RINGTONE_URI)) { 685 return TYPE_RINGTONE; 686 } else if (defaultRingtoneUri.equals(Settings.System.DEFAULT_NOTIFICATION_URI)) { 687 return TYPE_NOTIFICATION; 688 } else { 689 return -1; 690 } 691 } 692 693 /** 694 * Returns the {@link Uri} for the default ringtone of a particular type. 695 * Rather than returning the actual ringtone's sound {@link Uri}, this will 696 * return the symbolic {@link Uri} which will resolved to the actual sound 697 * when played. 698 * 699 * @param type The ringtone type whose default should be returned. 700 * @return The {@link Uri} of the default ringtone for the given type. 701 */ 702 public static Uri getDefaultUri(int type) { 703 if ((type & TYPE_RINGTONE) != 0) { 704 return Settings.System.DEFAULT_RINGTONE_URI; 705 } else if ((type & TYPE_NOTIFICATION) != 0) { 706 return Settings.System.DEFAULT_NOTIFICATION_URI; 707 } else { 708 return null; 709 } 710 } 711 712} 713