RingtoneManager.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.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 * @hide Pending API Council approval 276 */ 277 public int inferStreamType() { 278 switch (mType) { 279 280 case TYPE_ALARM: 281 return AudioManager.STREAM_ALARM; 282 283 case TYPE_NOTIFICATION: 284 return AudioManager.STREAM_NOTIFICATION; 285 286 default: 287 return AudioManager.STREAM_RING; 288 } 289 } 290 291 /** 292 * Whether retrieving another {@link Ringtone} will stop playing the 293 * previously retrieved {@link Ringtone}. 294 * <p> 295 * If this is false, make sure to {@link Ringtone#stop()} any previous 296 * ringtones to free resources. 297 * 298 * @param stopPreviousRingtone If true, the previously retrieved 299 * {@link Ringtone} will be stopped. 300 */ 301 public void setStopPreviousRingtone(boolean stopPreviousRingtone) { 302 mStopPreviousRingtone = stopPreviousRingtone; 303 } 304 305 /** 306 * @see #setStopPreviousRingtone(boolean) 307 */ 308 public boolean getStopPreviousRingtone() { 309 return mStopPreviousRingtone; 310 } 311 312 /** 313 * Stops playing the last {@link Ringtone} retrieved from this. 314 */ 315 public void stopPreviousRingtone() { 316 if (mPreviousRingtone != null) { 317 mPreviousRingtone.stop(); 318 } 319 } 320 321 /** 322 * Returns whether DRM ringtones will be included. 323 * 324 * @return Whether DRM ringtones will be included. 325 * @see #setIncludeDrm(boolean) 326 */ 327 public boolean getIncludeDrm() { 328 return mIncludeDrm; 329 } 330 331 /** 332 * Sets whether to include DRM ringtones. 333 * 334 * @param includeDrm Whether to include DRM ringtones. 335 */ 336 public void setIncludeDrm(boolean includeDrm) { 337 mIncludeDrm = includeDrm; 338 } 339 340 /** 341 * Returns a {@link Cursor} of all the ringtones available. The returned 342 * cursor will be the same cursor returned each time this method is called, 343 * so do not {@link Cursor#close()} the cursor. The cursor can be 344 * {@link Cursor#deactivate()} safely. 345 * <p> 346 * If {@link RingtoneManager#RingtoneManager(Activity)} was not used, the 347 * caller should manage the returned cursor through its activity's life 348 * cycle to prevent leaking the cursor. 349 * 350 * @return A {@link Cursor} of all the ringtones available. 351 * @see #ID_COLUMN_INDEX 352 * @see #TITLE_COLUMN_INDEX 353 * @see #URI_COLUMN_INDEX 354 */ 355 public Cursor getCursor() { 356 if (mCursor != null && mCursor.requery()) { 357 return mCursor; 358 } 359 360 final Cursor internalCursor = getInternalRingtones(); 361 final Cursor drmCursor = mIncludeDrm ? getDrmRingtones() : null; 362 final Cursor mediaCursor = getMediaRingtones(); 363 364 return mCursor = new SortCursor(new Cursor[] { internalCursor, drmCursor, mediaCursor }, 365 MediaStore.MediaColumns.TITLE); 366 } 367 368 /** 369 * Gets a {@link Ringtone} for the ringtone at the given position in the 370 * {@link Cursor}. 371 * 372 * @param position The position (in the {@link Cursor}) of the ringtone. 373 * @return A {@link Ringtone} pointing to the ringtone. 374 */ 375 public Ringtone getRingtone(int position) { 376 if (mStopPreviousRingtone && mPreviousRingtone != null) { 377 mPreviousRingtone.stop(); 378 } 379 380 mPreviousRingtone = getRingtone(mContext, getRingtoneUri(position), inferStreamType()); 381 return mPreviousRingtone; 382 } 383 384 /** 385 * Gets a {@link Uri} for the ringtone at the given position in the {@link Cursor}. 386 * 387 * @param position The position (in the {@link Cursor}) of the ringtone. 388 * @return A {@link Uri} pointing to the ringtone. 389 */ 390 public Uri getRingtoneUri(int position) { 391 final Cursor cursor = getCursor(); 392 393 if (!cursor.moveToPosition(position)) { 394 return null; 395 } 396 397 return getUriFromCursor(cursor); 398 } 399 400 private static Uri getUriFromCursor(Cursor cursor) { 401 return ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)), cursor 402 .getLong(ID_COLUMN_INDEX)); 403 } 404 405 /** 406 * Gets the position of a {@link Uri} within this {@link RingtoneManager}. 407 * 408 * @param ringtoneUri The {@link Uri} to retreive the position of. 409 * @return The position of the {@link Uri}, or -1 if it cannot be found. 410 */ 411 public int getRingtonePosition(Uri ringtoneUri) { 412 413 if (ringtoneUri == null) return -1; 414 415 final Cursor cursor = getCursor(); 416 final int cursorCount = cursor.getCount(); 417 418 if (!cursor.moveToFirst()) { 419 return -1; 420 } 421 422 // Only create Uri objects when the actual URI changes 423 Uri currentUri = null; 424 String previousUriString = null; 425 for (int i = 0; i < cursorCount; i++) { 426 String uriString = cursor.getString(URI_COLUMN_INDEX); 427 if (currentUri == null || !uriString.equals(previousUriString)) { 428 currentUri = Uri.parse(uriString); 429 } 430 431 if (ringtoneUri.equals(ContentUris.withAppendedId(currentUri, cursor 432 .getLong(ID_COLUMN_INDEX)))) { 433 return i; 434 } 435 436 cursor.move(1); 437 438 previousUriString = uriString; 439 } 440 441 return -1; 442 } 443 444 /** 445 * Returns a valid ringtone URI. No guarantees on which it returns. If it 446 * cannot find one, returns null. 447 * 448 * @param context The context to use for querying. 449 * @return A ringtone URI, or null if one cannot be found. 450 */ 451 public static Uri getValidRingtoneUri(Context context) { 452 final RingtoneManager rm = new RingtoneManager(context); 453 454 Uri uri = getValidRingtoneUriFromCursorAndClose(context, rm.getInternalRingtones()); 455 456 if (uri == null) { 457 uri = getValidRingtoneUriFromCursorAndClose(context, rm.getMediaRingtones()); 458 } 459 460 if (uri == null) { 461 uri = getValidRingtoneUriFromCursorAndClose(context, rm.getDrmRingtones()); 462 } 463 464 return uri; 465 } 466 467 private static Uri getValidRingtoneUriFromCursorAndClose(Context context, Cursor cursor) { 468 if (cursor != null) { 469 Uri uri = null; 470 471 if (cursor.moveToFirst()) { 472 uri = getUriFromCursor(cursor); 473 } 474 cursor.close(); 475 476 return uri; 477 } else { 478 return null; 479 } 480 } 481 482 private Cursor getInternalRingtones() { 483 return query( 484 MediaStore.Audio.Media.INTERNAL_CONTENT_URI, INTERNAL_COLUMNS, 485 constructBooleanTrueWhereClause(mFilterColumns), 486 null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER); 487 } 488 489 private Cursor getDrmRingtones() { 490 // DRM store does not have any columns to use for filtering 491 return query( 492 DrmStore.Audio.CONTENT_URI, DRM_COLUMNS, 493 null, null, DrmStore.Audio.TITLE); 494 } 495 496 private Cursor getMediaRingtones() { 497 // Get the external media cursor. First check to see if it is mounted. 498 final String status = Environment.getExternalStorageState(); 499 500 return (status.equals(Environment.MEDIA_MOUNTED) || 501 status.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) 502 ? query( 503 MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MEDIA_COLUMNS, 504 constructBooleanTrueWhereClause(mFilterColumns), null, 505 MediaStore.Audio.Media.DEFAULT_SORT_ORDER) 506 : null; 507 } 508 509 private void setFilterColumnsList(int type) { 510 List<String> columns = mFilterColumns; 511 columns.clear(); 512 513 if ((type & TYPE_RINGTONE) != 0) { 514 columns.add(MediaStore.Audio.AudioColumns.IS_RINGTONE); 515 } 516 517 if ((type & TYPE_NOTIFICATION) != 0) { 518 columns.add(MediaStore.Audio.AudioColumns.IS_NOTIFICATION); 519 } 520 521 if ((type & TYPE_ALARM) != 0) { 522 columns.add(MediaStore.Audio.AudioColumns.IS_ALARM); 523 } 524 } 525 526 /** 527 * Constructs a where clause that consists of at least one column being 1 528 * (true). This is used to find all matching sounds for the given sound 529 * types (ringtone, notifications, etc.) 530 * 531 * @param columns The columns that must be true. 532 * @return The where clause. 533 */ 534 private static String constructBooleanTrueWhereClause(List<String> columns) { 535 536 if (columns == null) return null; 537 538 StringBuilder sb = new StringBuilder(); 539 for (int i = columns.size() - 1; i >= 0; i--) { 540 sb.append(columns.get(i)).append("=1 or "); 541 } 542 543 if (columns.size() > 0) { 544 // Remove last ' or ' 545 sb.setLength(sb.length() - 4); 546 } 547 548 return sb.toString(); 549 } 550 551 private Cursor query(Uri uri, 552 String[] projection, 553 String selection, 554 String[] selectionArgs, 555 String sortOrder) { 556 if (mActivity != null) { 557 return mActivity.managedQuery(uri, projection, selection, selectionArgs, sortOrder); 558 } else { 559 return mContext.getContentResolver().query(uri, projection, selection, selectionArgs, 560 sortOrder); 561 } 562 } 563 564 /** 565 * Returns a {@link Ringtone} for a given sound URI. 566 * <p> 567 * If the given URI cannot be opened for any reason, this method will 568 * attempt to fallback on another sound. If it cannot find any, it will 569 * return null. 570 * 571 * @param context A context used to query. 572 * @param ringtoneUri The {@link Uri} of a sound or ringtone. 573 * @return A {@link Ringtone} for the given URI, or null. 574 */ 575 public static Ringtone getRingtone(final Context context, Uri ringtoneUri) { 576 // Don't set the stream type 577 return getRingtone(context, ringtoneUri, -1); 578 } 579 580 /** 581 * Returns a {@link Ringtone} for a given sound URI on the given stream 582 * type. Normally, if you change the stream type on the returned 583 * {@link Ringtone}, it will re-create the {@link MediaPlayer}. This is just 584 * an optimized route to avoid that. 585 * 586 * @param streamType The stream type for the ringtone, or -1 if it should 587 * not be set (and the default used instead). 588 * @see #getRingtone(Context, Uri) 589 */ 590 private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType) { 591 592 try { 593 Ringtone r = new Ringtone(context); 594 if (streamType >= 0) { 595 r.setStreamType(streamType); 596 } 597 r.open(ringtoneUri); 598 return r; 599 } catch (Exception ex) { 600 Log.e(TAG, "Failed to open ringtone " + ringtoneUri); 601 } 602 603 // Ringtone doesn't exist, use the fallback ringtone. 604 try { 605 AssetFileDescriptor afd = context.getResources().openRawResourceFd( 606 com.android.internal.R.raw.fallbackring); 607 if (afd != null) { 608 Ringtone r = new Ringtone(context); 609 r.open(afd); 610 afd.close(); 611 return r; 612 } 613 } catch (Exception ex) { 614 } 615 616 // we should never get here 617 Log.e(TAG, "unable to find a usable ringtone"); 618 return null; 619 } 620 621 /** 622 * Gets the current default sound's {@link Uri}. This will give the actual 623 * sound {@link Uri}, instead of using this, most clients can use 624 * {@link System#DEFAULT_RINGTONE_URI}. 625 * 626 * @param context A context used for querying. 627 * @param type The type whose default sound should be returned. One of 628 * {@link #TYPE_RINGTONE} or {@link #TYPE_NOTIFICATION}. 629 * @return A {@link Uri} pointing to the default sound for the sound type. 630 * @see #setActualDefaultRingtoneUri(Context, int, Uri) 631 */ 632 public static Uri getActualDefaultRingtoneUri(Context context, int type) { 633 String setting = getSettingForType(type); 634 if (setting == null) return null; 635 final String uriString = Settings.System.getString(context.getContentResolver(), setting); 636 return uriString != null ? Uri.parse(uriString) : getValidRingtoneUri(context); 637 } 638 639 /** 640 * Sets the {@link Uri} of the default sound for a given sound type. 641 * 642 * @param context A context used for querying. 643 * @param type The type whose default sound should be set. One of 644 * {@link #TYPE_RINGTONE} or {@link #TYPE_NOTIFICATION}. 645 * @param ringtoneUri A {@link Uri} pointing to the default sound to set. 646 * @see #getActualDefaultRingtoneUri(Context, int) 647 */ 648 public static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri) { 649 String setting = getSettingForType(type); 650 if (setting == null) return; 651 Settings.System.putString(context.getContentResolver(), setting, ringtoneUri.toString()); 652 } 653 654 private static String getSettingForType(int type) { 655 if ((type & TYPE_RINGTONE) != 0) { 656 return Settings.System.RINGTONE; 657 } else if ((type & TYPE_NOTIFICATION) != 0) { 658 return Settings.System.NOTIFICATION_SOUND; 659 } else { 660 return null; 661 } 662 } 663 664 /** 665 * Returns whether the given {@link Uri} is one of the default ringtones. 666 * 667 * @param ringtoneUri The ringtone {@link Uri} to be checked. 668 * @return Whether the {@link Uri} is a default. 669 */ 670 public static boolean isDefault(Uri ringtoneUri) { 671 return getDefaultType(ringtoneUri) != -1; 672 } 673 674 /** 675 * Returns the type of a default {@link Uri}. 676 * 677 * @param defaultRingtoneUri The default {@link Uri}. For example, 678 * {@link System#DEFAULT_RINGTONE_URI} or 679 * {@link System#DEFAULT_NOTIFICATION_URI}. 680 * @return The type of the defaultRingtoneUri, or -1. 681 */ 682 public static int getDefaultType(Uri defaultRingtoneUri) { 683 if (defaultRingtoneUri == null) { 684 return -1; 685 } else if (defaultRingtoneUri.equals(Settings.System.DEFAULT_RINGTONE_URI)) { 686 return TYPE_RINGTONE; 687 } else if (defaultRingtoneUri.equals(Settings.System.DEFAULT_NOTIFICATION_URI)) { 688 return TYPE_NOTIFICATION; 689 } else { 690 return -1; 691 } 692 } 693 694 /** 695 * Returns the {@link Uri} for the default ringtone of a particular type. 696 * Rather than returning the actual ringtone's sound {@link Uri}, this will 697 * return the symbolic {@link Uri} which will resolved to the actual sound 698 * when played. 699 * 700 * @param type The ringtone type whose default should be returned. 701 * @return The {@link Uri} of the default ringtone for the given type. 702 */ 703 public static Uri getDefaultUri(int type) { 704 if ((type & TYPE_RINGTONE) != 0) { 705 return Settings.System.DEFAULT_RINGTONE_URI; 706 } else if ((type & TYPE_NOTIFICATION) != 0) { 707 return Settings.System.DEFAULT_NOTIFICATION_URI; 708 } else { 709 return null; 710 } 711 } 712 713} 714