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