19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.media; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 211c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhéimport android.content.res.AssetFileDescriptor; 221c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhéimport android.content.res.Resources.NotFoundException; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri; 25098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport android.os.Binder; 26098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkeyimport android.os.RemoteException; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.MediaStore; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Ringtone provides a quick method for playing a ringtone, notification, or 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * other similar types of sounds. 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For ways of retrieving {@link Ringtone} objects or to show a ringtone 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * picker, see {@link RingtoneManager}. 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see RingtoneManager 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Ringtone { 43098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private static final String TAG = "Ringtone"; 44098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private static final boolean LOGD = true; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String[] MEDIA_COLUMNS = new String[] { 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaStore.Audio.Media._ID, 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaStore.Audio.Media.DATA, 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaStore.Audio.Media.TITLE 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 52098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private final Context mContext; 53098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private final AudioManager mAudioManager; 54098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private final boolean mAllowRemote; 55098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private final IRingtonePlayer mRemotePlayer; 56098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private final Binder mRemoteToken; 57098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 58098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private MediaPlayer mLocalPlayer; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Uri mUri; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mTitle; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mStreamType = AudioManager.STREAM_RING; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 65098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey /** {@hide} */ 66098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public Ringtone(Context context, boolean allowRemote) { 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 68524dc046b1225087f481878a5c3ae7f733c9f0e2Eric Laurent mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 69098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mAllowRemote = allowRemote; 70098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mRemotePlayer = allowRemote ? mAudioManager.getRingtonePlayer() : null; 71098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mRemoteToken = allowRemote ? new Binder() : null; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the stream type where this ringtone will be played. 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param streamType The stream, see {@link AudioManager}. 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setStreamType(int streamType) { 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamType = streamType; 81098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 82098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey // The stream type has to be set before the media player is prepared. 83098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey // Re-initialize it. 84098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey setUri(mUri); 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the stream type where this ringtone will be played. 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The stream type, see {@link AudioManager}. 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStreamType() { 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mStreamType; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 97853ad6fbe34fa26e81e4b7325309a034d7a1b038Mike Lockwood * Returns a human-presentable title for ringtone. Looks in media 98853ad6fbe34fa26e81e4b7325309a034d7a1b038Mike Lockwood * content provider. If not in either, uses the filename 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context A context used for querying. 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getTitle(Context context) { 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mTitle != null) return mTitle; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mTitle = getTitle(context, mUri, true); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String getTitle(Context context, Uri uri, boolean followSettingsUri) { 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cursor cursor = null; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver res = context.getContentResolver(); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String title = null; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uri != null) { 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String authority = uri.getAuthority(); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Settings.AUTHORITY.equals(authority)) { 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (followSettingsUri) { 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(context, 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RingtoneManager.getDefaultType(uri)); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String actualTitle = getTitle(context, actualUri, false); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project title = context 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getString(com.android.internal.R.string.ringtone_default_with_actual, 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project actualTitle); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1261d8e5c588035550293ecd2558a2e285ee2789d38Jeff Sharkey try { 127853ad6fbe34fa26e81e4b7325309a034d7a1b038Mike Lockwood if (MediaStore.AUTHORITY.equals(authority)) { 1281d8e5c588035550293ecd2558a2e285ee2789d38Jeff Sharkey cursor = res.query(uri, MEDIA_COLUMNS, null, null, null); 1291d8e5c588035550293ecd2558a2e285ee2789d38Jeff Sharkey } 1301d8e5c588035550293ecd2558a2e285ee2789d38Jeff Sharkey } catch (SecurityException e) { 1311d8e5c588035550293ecd2558a2e285ee2789d38Jeff Sharkey // missing cursor is handled below 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1331d8e5c588035550293ecd2558a2e285ee2789d38Jeff Sharkey 1346b51a98acbc710a4e1a1656d85bb5d3c92f82fe9Josh Guilfoyle try { 1356b51a98acbc710a4e1a1656d85bb5d3c92f82fe9Josh Guilfoyle if (cursor != null && cursor.getCount() == 1) { 1366b51a98acbc710a4e1a1656d85bb5d3c92f82fe9Josh Guilfoyle cursor.moveToFirst(); 1376b51a98acbc710a4e1a1656d85bb5d3c92f82fe9Josh Guilfoyle return cursor.getString(2); 1386b51a98acbc710a4e1a1656d85bb5d3c92f82fe9Josh Guilfoyle } else { 1396b51a98acbc710a4e1a1656d85bb5d3c92f82fe9Josh Guilfoyle title = uri.getLastPathSegment(); 1406b51a98acbc710a4e1a1656d85bb5d3c92f82fe9Josh Guilfoyle } 1416b51a98acbc710a4e1a1656d85bb5d3c92f82fe9Josh Guilfoyle } finally { 1426b51a98acbc710a4e1a1656d85bb5d3c92f82fe9Josh Guilfoyle if (cursor != null) { 1436b51a98acbc710a4e1a1656d85bb5d3c92f82fe9Josh Guilfoyle cursor.close(); 1446b51a98acbc710a4e1a1656d85bb5d3c92f82fe9Josh Guilfoyle } 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (title == null) { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project title = context.getString(com.android.internal.R.string.ringtone_unknown); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (title == null) { 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project title = ""; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return title; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 159098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 160098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey /** 161098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * Set {@link Uri} to be used for ringtone playback. Attempts to open 162098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * locally, otherwise will delegate playback to remote 163098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * {@link IRingtonePlayer}. 164098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * 165098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey * @hide 166098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey */ 167098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public void setUri(Uri uri) { 168098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey destroyLocalPlayer(); 169098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 170098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mUri = uri; 171098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey if (mUri == null) { 172098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey return; 173e1bd048cf2af24cbd93e549875c875239e5f4829Marco Nelissen } 174098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 175098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey // TODO: detect READ_EXTERNAL and specific content provider case, instead of relying on throwing 176098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 177098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey // try opening uri locally before delegating to remote player 178098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mLocalPlayer = new MediaPlayer(); 179098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey try { 180098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mLocalPlayer.setDataSource(mContext, mUri); 181098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mLocalPlayer.setAudioStreamType(mStreamType); 182098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mLocalPlayer.prepare(); 183098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 184098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } catch (SecurityException e) { 185098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey destroyLocalPlayer(); 186098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey if (!mAllowRemote) { 1871d8e5c588035550293ecd2558a2e285ee2789d38Jeff Sharkey Log.w(TAG, "Remote playback not allowed: " + e); 188098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 189098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } catch (IOException e) { 190098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey destroyLocalPlayer(); 191098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey if (!mAllowRemote) { 1921d8e5c588035550293ecd2558a2e285ee2789d38Jeff Sharkey Log.w(TAG, "Remote playback not allowed: " + e); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 196098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey if (LOGD) { 197098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey if (mLocalPlayer != null) { 198098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey Log.d(TAG, "Successfully created local player"); 199098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } else { 200098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey Log.d(TAG, "Problem opening; delegating to remote player"); 201098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 202098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 205098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey /** {@hide} */ 206098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public Uri getUri() { 207098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey return mUri; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 209e47e8520fa48bd014287eda94ea39927de73d6bcDianne Hackborn 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Plays the ringtone. 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void play() { 214098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey if (mLocalPlayer != null) { 215098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey // do not play ringtones if stream volume is 0 216524dc046b1225087f481878a5c3ae7f733c9f0e2Eric Laurent // (typically because ringer mode is silent). 217524dc046b1225087f481878a5c3ae7f733c9f0e2Eric Laurent if (mAudioManager.getStreamVolume(mStreamType) != 0) { 218098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mLocalPlayer.start(); 219098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 220098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } else if (mAllowRemote) { 22165c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey final Uri canonicalUri = mUri.getCanonicalUri(); 222098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey try { 22365c4a2b26cd8776b0927e9b0e07ecf53bd31b627Jeff Sharkey mRemotePlayer.play(mRemoteToken, canonicalUri, mStreamType); 224098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } catch (RemoteException e) { 2251c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé if (!playFallbackRingtone()) { 2261c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé Log.w(TAG, "Problem playing ringtone: " + e); 2271c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé } 228524dc046b1225087f481878a5c3ae7f733c9f0e2Eric Laurent } 229098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } else { 2301c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé if (!playFallbackRingtone()) { 2311c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé Log.w(TAG, "Neither local nor remote playback available"); 2321c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé } 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Stops a playing ringtone. 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void stop() { 240098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey if (mLocalPlayer != null) { 241098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey destroyLocalPlayer(); 242098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } else if (mAllowRemote) { 243098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey try { 244098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mRemotePlayer.stop(mRemoteToken); 245098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } catch (RemoteException e) { 246098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey Log.w(TAG, "Problem stopping ringtone: " + e); 247098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 248098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 249098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 250098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 251098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private void destroyLocalPlayer() { 252098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey if (mLocalPlayer != null) { 253098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mLocalPlayer.reset(); 254098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mLocalPlayer.release(); 255098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mLocalPlayer = null; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Whether this ringtone is currently playing. 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return True if playing, false otherwise. 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isPlaying() { 265098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey if (mLocalPlayer != null) { 266098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey return mLocalPlayer.isPlaying(); 267098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } else if (mAllowRemote) { 268098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey try { 269098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey return mRemotePlayer.isPlaying(mRemoteToken); 270098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } catch (RemoteException e) { 271098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey Log.w(TAG, "Problem checking ringtone: " + e); 272098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey return false; 273098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 274098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } else { 2751d8e5c588035550293ecd2558a2e285ee2789d38Jeff Sharkey Log.w(TAG, "Neither local nor remote playback available"); 2761d8e5c588035550293ecd2558a2e285ee2789d38Jeff Sharkey return false; 277098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2801c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé private boolean playFallbackRingtone() { 2811c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé if (mAudioManager.getStreamVolume(mStreamType) != 0) { 2821c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé int ringtoneType = RingtoneManager.getDefaultType(mUri); 28319a4671b10e7d07309f1d427e1d81b87d5bbca18Marco Nelissen if (ringtoneType == -1 || 2841c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé RingtoneManager.getActualDefaultRingtoneUri(mContext, ringtoneType) != null) { 2851c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé // Default ringtone, try fallback ringtone. 2861c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé try { 2871c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé AssetFileDescriptor afd = mContext.getResources().openRawResourceFd( 2881c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé com.android.internal.R.raw.fallbackring); 2891c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé if (afd != null) { 2901c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé mLocalPlayer = new MediaPlayer(); 2911c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé if (afd.getDeclaredLength() < 0) { 2921c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé mLocalPlayer.setDataSource(afd.getFileDescriptor()); 2931c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé } else { 2941c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé mLocalPlayer.setDataSource(afd.getFileDescriptor(), 2951c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé afd.getStartOffset(), 2961c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé afd.getDeclaredLength()); 2971c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé } 2981c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé mLocalPlayer.setAudioStreamType(mStreamType); 2991c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé mLocalPlayer.prepare(); 3001c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé mLocalPlayer.start(); 3011c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé afd.close(); 3021c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé return true; 3031c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé } else { 3041c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé Log.e(TAG, "Could not load fallback ringtone"); 3051c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé } 3061c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé } catch (IOException ioe) { 3071c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé destroyLocalPlayer(); 3081c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé Log.e(TAG, "Failed to open fallback ringtone"); 3091c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé } catch (NotFoundException nfe) { 3101c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé Log.e(TAG, "Fallback ringtone does not exist"); 3111c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé } 31219a4671b10e7d07309f1d427e1d81b87d5bbca18Marco Nelissen } else { 31319a4671b10e7d07309f1d427e1d81b87d5bbca18Marco Nelissen Log.w(TAG, "not playing fallback for " + mUri); 3141c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé } 3151c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé } 3161c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé return false; 3171c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé } 3181c25a21ffcfbc78a0edced4076d533f34902428aOscar Rydhé 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void setTitle(String title) { 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTitle = title; 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 323