/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.media; import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; import android.provider.DrmStore; import android.provider.MediaStore; import android.provider.Settings; import android.util.Log; import java.io.FileDescriptor; import java.io.IOException; /** * Ringtone provides a quick method for playing a ringtone, notification, or * other similar types of sounds. * <p> * For ways of retrieving {@link Ringtone} objects or to show a ringtone * picker, see {@link RingtoneManager}. * * @see RingtoneManager */ public class Ringtone { private static String TAG = "Ringtone"; private static final String[] MEDIA_COLUMNS = new String[] { MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.TITLE }; private static final String[] DRM_COLUMNS = new String[] { DrmStore.Audio._ID, DrmStore.Audio.DATA, DrmStore.Audio.TITLE }; private MediaPlayer mAudio; private Uri mUri; private String mTitle; private FileDescriptor mFileDescriptor; private AssetFileDescriptor mAssetFileDescriptor; private int mStreamType = AudioManager.STREAM_RING; private Context mContext; Ringtone(Context context) { mContext = context; } /** * Sets the stream type where this ringtone will be played. * * @param streamType The stream, see {@link AudioManager}. */ public void setStreamType(int streamType) { mStreamType = streamType; if (mAudio != null) { /* * The stream type has to be set before the media player is * prepared. Re-initialize it. */ try { openMediaPlayer(); } catch (IOException e) { Log.w(TAG, "Couldn't set the stream type", e); } } } /** * Gets the stream type where this ringtone will be played. * * @return The stream type, see {@link AudioManager}. */ public int getStreamType() { return mStreamType; } /** * Returns a human-presentable title for ringtone. Looks in media and DRM * content providers. If not in either, uses the filename * * @param context A context used for querying. */ public String getTitle(Context context) { if (mTitle != null) return mTitle; return mTitle = getTitle(context, mUri, true); } private static String getTitle(Context context, Uri uri, boolean followSettingsUri) { Cursor cursor = null; ContentResolver res = context.getContentResolver(); String title = null; if (uri != null) { String authority = uri.getAuthority(); if (Settings.AUTHORITY.equals(authority)) { if (followSettingsUri) { Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(context, RingtoneManager.getDefaultType(uri)); String actualTitle = getTitle(context, actualUri, false); title = context .getString(com.android.internal.R.string.ringtone_default_with_actual, actualTitle); } } else { if (DrmStore.AUTHORITY.equals(authority)) { cursor = res.query(uri, DRM_COLUMNS, null, null, null); } else if (MediaStore.AUTHORITY.equals(authority)) { cursor = res.query(uri, MEDIA_COLUMNS, null, null, null); } if (cursor != null && cursor.getCount() == 1) { cursor.moveToFirst(); return cursor.getString(2); } else { title = uri.getLastPathSegment(); } } } if (title == null) { title = context.getString(com.android.internal.R.string.ringtone_unknown); if (title == null) { title = ""; } } return title; } private void openMediaPlayer() throws IOException { mAudio = new MediaPlayer(); if (mUri != null) { mAudio.setDataSource(mContext, mUri); } else if (mFileDescriptor != null) { mAudio.setDataSource(mFileDescriptor); } else if (mAssetFileDescriptor != null) { // Note: using getDeclaredLength so that our behavior is the same // as previous versions when the content provider is returning // a full file. if (mAssetFileDescriptor.getDeclaredLength() < 0) { mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor()); } else { mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor(), mAssetFileDescriptor.getStartOffset(), mAssetFileDescriptor.getDeclaredLength()); } } else { throw new IOException("No data source set."); } mAudio.setAudioStreamType(mStreamType); mAudio.prepare(); } void open(FileDescriptor fd) throws IOException { mFileDescriptor = fd; openMediaPlayer(); } void open(AssetFileDescriptor fd) throws IOException { mAssetFileDescriptor = fd; openMediaPlayer(); } void open(Uri uri) throws IOException { mUri = uri; openMediaPlayer(); } /** * Plays the ringtone. */ public void play() { if (mAudio == null) { try { openMediaPlayer(); } catch (Exception ex) { Log.e(TAG, "play() caught ", ex); mAudio = null; } } if (mAudio != null) { mAudio.start(); } } /** * Stops a playing ringtone. */ public void stop() { if (mAudio != null) { mAudio.reset(); mAudio.release(); mAudio = null; } } /** * Whether this ringtone is currently playing. * * @return True if playing, false otherwise. */ public boolean isPlaying() { return mAudio != null && mAudio.isPlaying(); } void setTitle(String title) { mTitle = title; } }