Ringtone.java revision 524dc046b1225087f481878a5c3ae7f733c9f0e2
1/* 2 * Copyright (C) 2006 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 android.content.ContentResolver; 20import android.content.Context; 21import android.content.res.AssetFileDescriptor; 22import android.database.Cursor; 23import android.media.AudioManager; 24import android.media.MediaPlayer; 25import android.net.Uri; 26import android.provider.DrmStore; 27import android.provider.MediaStore; 28import android.provider.Settings; 29import android.util.Log; 30 31import java.io.FileDescriptor; 32import java.io.IOException; 33 34/** 35 * Ringtone provides a quick method for playing a ringtone, notification, or 36 * other similar types of sounds. 37 * <p> 38 * For ways of retrieving {@link Ringtone} objects or to show a ringtone 39 * picker, see {@link RingtoneManager}. 40 * 41 * @see RingtoneManager 42 */ 43public class Ringtone { 44 private static String TAG = "Ringtone"; 45 46 private static final String[] MEDIA_COLUMNS = new String[] { 47 MediaStore.Audio.Media._ID, 48 MediaStore.Audio.Media.DATA, 49 MediaStore.Audio.Media.TITLE 50 }; 51 52 private static final String[] DRM_COLUMNS = new String[] { 53 DrmStore.Audio._ID, 54 DrmStore.Audio.DATA, 55 DrmStore.Audio.TITLE 56 }; 57 58 private MediaPlayer mAudio; 59 60 private Uri mUri; 61 private String mTitle; 62 private FileDescriptor mFileDescriptor; 63 private AssetFileDescriptor mAssetFileDescriptor; 64 65 private int mStreamType = AudioManager.STREAM_RING; 66 private AudioManager mAudioManager; 67 68 private Context mContext; 69 70 Ringtone(Context context) { 71 mContext = context; 72 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 73 } 74 75 /** 76 * Sets the stream type where this ringtone will be played. 77 * 78 * @param streamType The stream, see {@link AudioManager}. 79 */ 80 public void setStreamType(int streamType) { 81 mStreamType = streamType; 82 83 if (mAudio != null) { 84 /* 85 * The stream type has to be set before the media player is 86 * prepared. Re-initialize it. 87 */ 88 try { 89 openMediaPlayer(); 90 } catch (IOException e) { 91 Log.w(TAG, "Couldn't set the stream type", e); 92 } 93 } 94 } 95 96 /** 97 * Gets the stream type where this ringtone will be played. 98 * 99 * @return The stream type, see {@link AudioManager}. 100 */ 101 public int getStreamType() { 102 return mStreamType; 103 } 104 105 /** 106 * Returns a human-presentable title for ringtone. Looks in media and DRM 107 * content providers. If not in either, uses the filename 108 * 109 * @param context A context used for querying. 110 */ 111 public String getTitle(Context context) { 112 if (mTitle != null) return mTitle; 113 return mTitle = getTitle(context, mUri, true); 114 } 115 116 private static String getTitle(Context context, Uri uri, boolean followSettingsUri) { 117 Cursor cursor = null; 118 ContentResolver res = context.getContentResolver(); 119 120 String title = null; 121 122 if (uri != null) { 123 String authority = uri.getAuthority(); 124 125 if (Settings.AUTHORITY.equals(authority)) { 126 if (followSettingsUri) { 127 Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(context, 128 RingtoneManager.getDefaultType(uri)); 129 String actualTitle = getTitle(context, actualUri, false); 130 title = context 131 .getString(com.android.internal.R.string.ringtone_default_with_actual, 132 actualTitle); 133 } 134 } else { 135 136 if (DrmStore.AUTHORITY.equals(authority)) { 137 cursor = res.query(uri, DRM_COLUMNS, null, null, null); 138 } else if (MediaStore.AUTHORITY.equals(authority)) { 139 cursor = res.query(uri, MEDIA_COLUMNS, null, null, null); 140 } 141 142 if (cursor != null && cursor.getCount() == 1) { 143 cursor.moveToFirst(); 144 return cursor.getString(2); 145 } else { 146 title = uri.getLastPathSegment(); 147 } 148 } 149 } 150 151 if (title == null) { 152 title = context.getString(com.android.internal.R.string.ringtone_unknown); 153 154 if (title == null) { 155 title = ""; 156 } 157 } 158 159 return title; 160 } 161 162 private void openMediaPlayer() throws IOException { 163 mAudio = new MediaPlayer(); 164 if (mUri != null) { 165 mAudio.setDataSource(mContext, mUri); 166 } else if (mFileDescriptor != null) { 167 mAudio.setDataSource(mFileDescriptor); 168 } else if (mAssetFileDescriptor != null) { 169 // Note: using getDeclaredLength so that our behavior is the same 170 // as previous versions when the content provider is returning 171 // a full file. 172 if (mAssetFileDescriptor.getDeclaredLength() < 0) { 173 mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor()); 174 } else { 175 mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor(), 176 mAssetFileDescriptor.getStartOffset(), 177 mAssetFileDescriptor.getDeclaredLength()); 178 } 179 } else { 180 throw new IOException("No data source set."); 181 } 182 mAudio.setAudioStreamType(mStreamType); 183 mAudio.prepare(); 184 } 185 186 void open(FileDescriptor fd) throws IOException { 187 mFileDescriptor = fd; 188 openMediaPlayer(); 189 } 190 191 void open(AssetFileDescriptor fd) throws IOException { 192 mAssetFileDescriptor = fd; 193 openMediaPlayer(); 194 } 195 196 void open(Uri uri) throws IOException { 197 mUri = uri; 198 openMediaPlayer(); 199 } 200 201 /** 202 * Plays the ringtone. 203 */ 204 public void play() { 205 if (mAudio == null) { 206 try { 207 openMediaPlayer(); 208 } catch (Exception ex) { 209 Log.e(TAG, "play() caught ", ex); 210 mAudio = null; 211 } 212 } 213 if (mAudio != null) { 214 // do not ringtones if stream volume is 0 215 // (typically because ringer mode is silent). 216 if (mAudioManager.getStreamVolume(mStreamType) != 0) { 217 mAudio.start(); 218 } 219 } 220 } 221 222 /** 223 * Stops a playing ringtone. 224 */ 225 public void stop() { 226 if (mAudio != null) { 227 mAudio.reset(); 228 mAudio.release(); 229 mAudio = null; 230 } 231 } 232 233 /** 234 * Whether this ringtone is currently playing. 235 * 236 * @return True if playing, false otherwise. 237 */ 238 public boolean isPlaying() { 239 return mAudio != null && mAudio.isPlaying(); 240 } 241 242 void setTitle(String title) { 243 mTitle = title; 244 } 245} 246