MediaActionSound.java revision e69095869c1b324aa20991ed1805c492c3f731e8
1e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala/* 2e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * Copyright (C) 2012 The Android Open Source Project 3e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * 4e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * Licensed under the Apache License, Version 2.0 (the "License"); 5e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * you may not use this file except in compliance with the License. 6e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * You may obtain a copy of the License at 7e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * 8e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * http://www.apache.org/licenses/LICENSE-2.0 9e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * 10e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * Unless required by applicable law or agreed to in writing, software 11e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * distributed under the License is distributed on an "AS IS" BASIS, 12e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * See the License for the specific language governing permissions and 14e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * limitations under the License. 15e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala */ 16e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 17e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvalapackage android.media; 18e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 19e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvalaimport android.media.AudioManager; 20e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvalaimport android.media.SoundPool; 21e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvalaimport android.util.Log; 22e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 23e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala/** 24e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * <p>A class for producing sounds that match those produced by various actions 25e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * taken by the media and camera APIs. </p> 26e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * 27e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * <p>Use this class to play an appropriate camera operation sound when 28e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * implementing a custom still or video recording mechanism (through the Camera 29e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * preview callbacks with {@link android.hardware.Camera#setPreviewCallback 30e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * Camera.setPreviewCallback}, or through GPU processing with {@link 31e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * android.hardware.Camera#setPreviewTexture Camera.setPreviewTexture}, for 32e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * example), or when implementing some other camera-like function in your 33e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * application.</p> 34e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * 35e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * <p>There is no need to play sounds when using 36e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * {@link android.hardware.Camera#takePicture Camera.takePicture} or 37e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * {@link android.media.MediaRecorder} for still images or video, respectively, 38e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * as the Android framework will play the appropriate sounds when needed for 39e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * these calls.</p> 40e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * 41e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala */ 42e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvalapublic class MediaActionSound { 43e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala private static final int NUM_MEDIA_SOUND_STREAMS = 1; 44e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 45e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala private SoundPool mSoundPool; 46e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala private int[] mSoundIds; 47e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala private int mSoundIdToPlay; 48e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 49e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala private static final String[] SOUND_FILES = { 50e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala "/system/media/audio/ui/camera_click.ogg", 51e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala "/system/media/audio/ui/camera_focus.ogg", 52e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala "/system/media/audio/ui/VideoRecord.ogg", 53e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala "/system/media/audio/ui/VideoRecord.ogg" 54e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala }; 55e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 56e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala private static final String TAG = "MediaActionSound"; 57e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala /** 58e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * The sound used by 59e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * {@link android.hardware.Camera#takePicture Camera.takePicture} to 60e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * indicate still image capture. 61e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #play 62e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala */ 63e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala public static final int SHUTTER_CLICK = 0; 64e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 65e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala /** 66e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * A sound to indicate that focusing has completed. Because deciding 67e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * when this occurs is application-dependent, this sound is not used by 68e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * any methods in the media or camera APIs. 69e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #play 70e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala */ 71e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala public static final int FOCUS_COMPLETE = 1; 72e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 73e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala /** 74e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * The sound used by 75e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * {@link android.media.MediaRecorder#start MediaRecorder.start()} to 76e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * indicate the start of video recording. 77e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #play 78e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala */ 79e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala public static final int START_VIDEO_RECORDING = 2; 80e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 81e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala /** 82e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * The sound used by 83e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * {@link android.media.MediaRecorder#stop MediaRecorder.stop()} to 84e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * indicate the end of video recording. 85e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #play 86e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala */ 87e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala public static final int STOP_VIDEO_RECORDING = 3; 88e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 89e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala private static final int SOUND_NOT_LOADED = -1; 90e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 91e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala /** 92e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * Construct a new MediaActionSound instance. Only a single instance is 93e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * needed for playing any platform media action sound; you do not need a 94e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * separate instance for each sound type. 95e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala */ 96e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala public MediaActionSound() { 97e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundPool = new SoundPool(NUM_MEDIA_SOUND_STREAMS, 98e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala AudioManager.STREAM_SYSTEM_ENFORCED, 0); 99e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundPool.setOnLoadCompleteListener(mLoadCompleteListener); 100e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundIds = new int[SOUND_FILES.length]; 101e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala for (int i = 0; i < mSoundIds.length; i++) { 102e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundIds[i] = SOUND_NOT_LOADED; 103e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } 104e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundIdToPlay = SOUND_NOT_LOADED; 105e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } 106e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 107e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala /** 108e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * Preload a predefined platform sound to minimize latency when the sound is 109e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * played later by {@link #play}. 110e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @param soundName The type of sound to preload, selected from 111e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * SHUTTER_CLICK, FOCUS_COMPLETE, START_VIDEO_RECORDING, or 112e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * STOP_VIDEO_RECORDING. 113e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #play 114e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #SHUTTER_CLICK 115e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #FOCUS_COMPLETE 116e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #START_VIDEO_RECORDING 117e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #STOP_VIDEO_RECORDING 118e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala */ 119e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala public synchronized void load(int soundName) { 120e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala if (soundName < 0 || soundName >= SOUND_FILES.length) { 121e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala throw new RuntimeException("Unknown sound requested: " + soundName); 122e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } 123e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala if (mSoundIds[soundName] == SOUND_NOT_LOADED) { 124e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundIds[soundName] = 125e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundPool.load(SOUND_FILES[soundName], 1); 126e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } 127e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } 128e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 129e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala /** 130e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * <p>Play one of the predefined platform sounds for media actions.</p> 131e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * 132e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * <p>Use this method to play a platform-specific sound for various media 133e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * actions. The sound playback is done asynchronously, with the same 134e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * behavior and content as the sounds played by 135e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * {@link android.hardware.Camera#takePicture Camera.takePicture}, 136e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * {@link android.media.MediaRecorder#start MediaRecorder.start}, and 137e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p> 138e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * 139e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * <p>Using this method makes it easy to match the default device sounds 140e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * when recording or capturing data through the preview callbacks, or when 141e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * implementing custom camera-like features in your 142e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * application.</p> 143e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * 144e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * <p>If the sound has not been loaded by {@link #load} before calling play, 145e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * play will load the sound at the cost of some additional latency before 146e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * sound playback begins. </p> 147e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * 148e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @param soundName The type of sound to play, selected from 149e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * SHUTTER_CLICK, FOCUS_COMPLETE, START_VIDEO_RECORDING, or 150e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * STOP_VIDEO_RECORDING. 151e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see android.hardware.Camera#takePicture 152e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see android.media.MediaRecorder 153e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #SHUTTER_CLICK 154e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #FOCUS_COMPLETE 155e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #START_VIDEO_RECORDING 156e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * @see #STOP_VIDEO_RECORDING 157e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala */ 158e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala public synchronized void play(int soundName) { 159e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala if (soundName < 0 || soundName >= SOUND_FILES.length) { 160e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala throw new RuntimeException("Unknown sound requested: " + soundName); 161e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } 162e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala if (mSoundIds[soundName] == SOUND_NOT_LOADED) { 163e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundIdToPlay = 164e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundPool.load(SOUND_FILES[soundName], 1); 165e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundIds[soundName] = mSoundIdToPlay; 166e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } else { 167e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundPool.play(mSoundIds[soundName], 1.0f, 1.0f, 0, 0, 1.0f); 168e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } 169e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } 170e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 171e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala private SoundPool.OnLoadCompleteListener mLoadCompleteListener = 172e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala new SoundPool.OnLoadCompleteListener() { 173e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala public void onLoadComplete(SoundPool soundPool, 174e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala int sampleId, int status) { 175e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala if (status == 0) { 176e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala if (mSoundIdToPlay == sampleId) { 177e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala soundPool.play(sampleId, 1.0f, 1.0f, 0, 0, 1.0f); 178e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundIdToPlay = SOUND_NOT_LOADED; 179e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } 180e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } else { 181e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala Log.e(TAG, "Unable to load sound for playback (status: " + 182e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala status + ")"); 183e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } 184e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } 185e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala }; 186e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala 187e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala /** 188e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala * Free up all audio resources used by this MediaActionSound instance 189e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala */ 190e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala public void release() { 191e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundPool.release(); 192e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala mSoundPool = null; 193e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala } 194e69095869c1b324aa20991ed1805c492c3f731e8Eino-Ville Talvala} 195