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