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