1f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch/* 2f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * Copyright (C) 2011 The Android Open Source Project 3f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * 4f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * Licensed under the Apache License, Version 2.0 (the "License"); 5f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * you may not use this file except in compliance with the License. 6f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * You may obtain a copy of the License at 7f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * 8f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * http://www.apache.org/licenses/LICENSE-2.0 9f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * 10f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * Unless required by applicable law or agreed to in writing, software 11f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * distributed under the License is distributed on an "AS IS" BASIS, 12f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * See the License for the specific language governing permissions and 14f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch * limitations under the License. 15f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch */ 16f2ef799d0826b6d4f9bb3727f7878545b3ad29b9Ben Murdoch 1745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectpackage com.android.soundrecorder; 1845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 1945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport java.io.File; 2045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport java.text.SimpleDateFormat; 2145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport java.util.Date; 2245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 2345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.app.Activity; 2445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.app.AlertDialog; 2545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.content.ContentResolver; 2645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.content.ContentValues; 2745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.content.Intent; 2845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.content.Context; 2945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.content.IntentFilter; 3045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.content.BroadcastReceiver; 3145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.content.res.Configuration; 3245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.content.res.Resources; 3345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.database.Cursor; 3445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.media.MediaRecorder; 3545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.net.Uri; 3645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.os.Bundle; 3745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.os.Environment; 3845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.os.Handler; 3945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.os.PowerManager; 4045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.os.StatFs; 4145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.os.PowerManager.WakeLock; 4245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.provider.MediaStore; 4345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.util.Log; 4445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.view.KeyEvent; 4545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.view.View; 4645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.widget.Button; 4745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.widget.ImageButton; 4845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.widget.ImageView; 4945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.widget.LinearLayout; 5045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.widget.ProgressBar; 5145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectimport android.widget.TextView; 5245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 5345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project/** 5445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Calculates remaining recording time based on available disk space and 5545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * optionally a maximum recording file size. 5645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * 5745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * The reason why this is not trivial is that the file grows in blocks 5845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * every few seconds or so, while we want a smooth countdown. 5945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 6045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 6145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectclass RemainingTimeCalculator { 6245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public static final int UNKNOWN_LIMIT = 0; 6345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public static final int FILE_SIZE_LIMIT = 1; 6445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public static final int DISK_SPACE_LIMIT = 2; 6545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 6645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // which of the two limits we will hit (or have fit) first 6745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private int mCurrentLowerLimit = UNKNOWN_LIMIT; 6845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 6945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private File mSDCardDirectory; 7045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 7145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // State for tracking file size of recording. 7245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private File mRecordingFile; 7345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private long mMaxBytes; 7445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 7545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // Rate at which the file grows 7645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private int mBytesPerSecond; 7745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 7845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // time at which number of free blocks last changed 7945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private long mBlocksChangedTime; 8045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // number of available blocks at that time 8145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private long mLastBlocks; 8245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 8345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // time at which the size of the file has last changed 8445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private long mFileSizeChangedTime; 8545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // size of the file at that time 8645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private long mLastFileSize; 8745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 8845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public RemainingTimeCalculator() { 8945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mSDCardDirectory = Environment.getExternalStorageDirectory(); 9045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 9145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 9245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /** 9345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * If called, the calculator will return the minimum of two estimates: 9445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * how long until we run out of disk space and how long until the file 9545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * reaches the specified size. 9645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * 9745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * @param file the file to watch 9845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * @param maxBytes the limit 9945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 10045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 10145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public void setFileSizeLimit(File file, long maxBytes) { 10245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordingFile = file; 10345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mMaxBytes = maxBytes; 10445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 10545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 10645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /** 10745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Resets the interpolation. 10845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 10945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public void reset() { 11045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mCurrentLowerLimit = UNKNOWN_LIMIT; 11145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mBlocksChangedTime = -1; 11245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mFileSizeChangedTime = -1; 11345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 11445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 11545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /** 11645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Returns how long (in seconds) we can continue recording. 11745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 11845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public long timeRemaining() { 11945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // Calculate how long we can record based on free disk space 12045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 12145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project StatFs fs = new StatFs(mSDCardDirectory.getAbsolutePath()); 12245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project long blocks = fs.getAvailableBlocks(); 12345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project long blockSize = fs.getBlockSize(); 12445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project long now = System.currentTimeMillis(); 12545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 12645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mBlocksChangedTime == -1 || blocks != mLastBlocks) { 12745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mBlocksChangedTime = now; 12845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mLastBlocks = blocks; 12945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 13045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 13145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* The calculation below always leaves one free block, since free space 13245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project in the block we're currently writing to is not added. This 13345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project last block might get nibbled when we close and flush the file, but 13445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project we won't run out of disk. */ 13545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 13645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // at mBlocksChangedTime we had this much time 13745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project long result = mLastBlocks*blockSize/mBytesPerSecond; 13845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // so now we have this much time 13945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project result -= (now - mBlocksChangedTime)/1000; 14045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 14145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mRecordingFile == null) { 14245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mCurrentLowerLimit = DISK_SPACE_LIMIT; 14345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return result; 14445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 14545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 14645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // If we have a recording file set, we calculate a second estimate 14745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // based on how long it will take us to reach mMaxBytes. 14845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 14945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordingFile = new File(mRecordingFile.getAbsolutePath()); 15045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project long fileSize = mRecordingFile.length(); 15145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mFileSizeChangedTime == -1 || fileSize != mLastFileSize) { 15245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mFileSizeChangedTime = now; 15345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mLastFileSize = fileSize; 15445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 15545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 15645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project long result2 = (mMaxBytes - fileSize)/mBytesPerSecond; 15745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project result2 -= (now - mFileSizeChangedTime)/1000; 15845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project result2 -= 1; // just for safety 15945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 16045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mCurrentLowerLimit = result < result2 16145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project ? DISK_SPACE_LIMIT : FILE_SIZE_LIMIT; 16245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 16345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return Math.min(result, result2); 16445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 16545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 16645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /** 16745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Indicates which limit we will hit (or have hit) first, by returning one 16845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * of FILE_SIZE_LIMIT or DISK_SPACE_LIMIT or UNKNOWN_LIMIT. We need this to 16945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * display the correct message to the user when we hit one of the limits. 17045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 17145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public int currentLowerLimit() { 17245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return mCurrentLowerLimit; 17345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 17445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 17545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /** 17645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Is there any point of trying to start recording? 17745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 17845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public boolean diskSpaceAvailable() { 17945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project StatFs fs = new StatFs(mSDCardDirectory.getAbsolutePath()); 18045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // keep one free block 18145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return fs.getAvailableBlocks() > 1; 18245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 18345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 18445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /** 18545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Sets the bit rate used in the interpolation. 18645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * 18745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * @param bitRate the bit rate to set in bits/sec. 18845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 18945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public void setBitRate(int bitRate) { 19045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mBytesPerSecond = bitRate/8; 19145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 19245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project} 19345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 19445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Projectpublic class SoundRecorder extends Activity 19545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project implements Button.OnClickListener, Recorder.OnStateChangedListener { 19645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project static final String TAG = "SoundRecorder"; 19745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project static final String STATE_FILE_NAME = "soundrecorder.state"; 19845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project static final String RECORDER_STATE_KEY = "recorder_state"; 19945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project static final String SAMPLE_INTERRUPTED_KEY = "sample_interrupted"; 20045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project static final String MAX_FILE_SIZE_KEY = "max_file_size"; 20145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 20245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project static final String AUDIO_3GPP = "audio/3gpp"; 20345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project static final String AUDIO_AMR = "audio/amr"; 20445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project static final String AUDIO_ANY = "audio/*"; 2059a879fc7b23550a6b1d84535df02528ed0f49f27Gloria Wang static final String ANY_ANY = "*/*"; 20645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 20745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project static final int BITRATE_AMR = 5900; // bits/sec 20845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project static final int BITRATE_3GPP = 5900; 20945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 21045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project WakeLock mWakeLock; 21145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project String mRequestedType = AUDIO_ANY; 21245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Recorder mRecorder; 21345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project boolean mSampleInterrupted = false; 21445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project String mErrorUiMessage = null; // Some error messages are displayed in the UI, 21545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // not a dialog. This happens when a recording 21645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // is interrupted for some reason. 21745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 21845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project long mMaxFileSize = -1; // can be specified in the intent 21945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project RemainingTimeCalculator mRemainingTimeCalculator; 22045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 22145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project String mTimerFormat; 22245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project final Handler mHandler = new Handler(); 22345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Runnable mUpdateTimer = new Runnable() { 22445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public void run() { updateTimerView(); } 22545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project }; 22645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 22745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project ImageButton mRecordButton; 22845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project ImageButton mPlayButton; 22945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project ImageButton mStopButton; 23045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 23145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project ImageView mStateLED; 23245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project TextView mStateMessage1; 23345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project TextView mStateMessage2; 23445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project ProgressBar mStateProgressBar; 23545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project TextView mTimerView; 23645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 23745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project LinearLayout mExitButtons; 23845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Button mAcceptButton; 23945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Button mDiscardButton; 24045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project VUMeter mVUMeter; 24145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private BroadcastReceiver mSDCardMountEventReceiver = null; 24245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 24345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project @Override 24445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public void onCreate(Bundle icycle) { 24545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project super.onCreate(icycle); 24645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 24745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Intent i = getIntent(); 24845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (i != null) { 24945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project String s = i.getType(); 2509a879fc7b23550a6b1d84535df02528ed0f49f27Gloria Wang if (AUDIO_AMR.equals(s) || AUDIO_3GPP.equals(s) || AUDIO_ANY.equals(s) 2519a879fc7b23550a6b1d84535df02528ed0f49f27Gloria Wang || ANY_ANY.equals(s)) { 25245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRequestedType = s; 25345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } else if (s != null) { 25445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // we only support amr and 3gpp formats right now 25545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project setResult(RESULT_CANCELED); 25645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project finish(); 25745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return; 25845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 25945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 26045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project final String EXTRA_MAX_BYTES 26145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project = android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES; 26245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mMaxFileSize = i.getLongExtra(EXTRA_MAX_BYTES, -1); 26345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 26445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 2659a879fc7b23550a6b1d84535df02528ed0f49f27Gloria Wang if (AUDIO_ANY.equals(mRequestedType) || ANY_ANY.equals(mRequestedType)) { 26645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRequestedType = AUDIO_3GPP; 26745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 26845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 26945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project setContentView(R.layout.main); 27045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 27145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder = new Recorder(); 27245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.setOnStateChangedListener(this); 27345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRemainingTimeCalculator = new RemainingTimeCalculator(); 27445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 27545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project PowerManager pm 27645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project = (PowerManager) getSystemService(Context.POWER_SERVICE); 27745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, 27845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project "SoundRecorder"); 27945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 28045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project initResourceRefs(); 28145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 28245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project setResult(RESULT_CANCELED); 28345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project registerExternalStorageListener(); 28445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (icycle != null) { 28545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Bundle recorderState = icycle.getBundle(RECORDER_STATE_KEY); 28645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (recorderState != null) { 28745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.restoreState(recorderState); 28845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mSampleInterrupted = recorderState.getBoolean(SAMPLE_INTERRUPTED_KEY, false); 28945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mMaxFileSize = recorderState.getLong(MAX_FILE_SIZE_KEY, -1); 29045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 29145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 29245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 29345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project updateUi(); 29445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 29545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 29645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project @Override 29745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public void onConfigurationChanged(Configuration newConfig) { 29845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project super.onConfigurationChanged(newConfig); 29945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 30045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project setContentView(R.layout.main); 30145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project initResourceRefs(); 30245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project updateUi(); 30345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 30445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 30545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project @Override 30645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project protected void onSaveInstanceState(Bundle outState) { 30745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project super.onSaveInstanceState(outState); 30845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 30945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mRecorder.sampleLength() == 0) 31045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return; 31145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 31245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Bundle recorderState = new Bundle(); 31345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 31445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.saveState(recorderState); 31545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project recorderState.putBoolean(SAMPLE_INTERRUPTED_KEY, mSampleInterrupted); 31645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project recorderState.putLong(MAX_FILE_SIZE_KEY, mMaxFileSize); 31745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 31845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project outState.putBundle(RECORDER_STATE_KEY, recorderState); 31945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 32045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 32145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 32245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Whenever the UI is re-created (due f.ex. to orientation change) we have 32345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * to reinitialize references to the views. 32445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 32545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private void initResourceRefs() { 32645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordButton = (ImageButton) findViewById(R.id.recordButton); 32745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mPlayButton = (ImageButton) findViewById(R.id.playButton); 32845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStopButton = (ImageButton) findViewById(R.id.stopButton); 32945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 33045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateLED = (ImageView) findViewById(R.id.stateLED); 33145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage1 = (TextView) findViewById(R.id.stateMessage1); 33245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage2 = (TextView) findViewById(R.id.stateMessage2); 33345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateProgressBar = (ProgressBar) findViewById(R.id.stateProgressBar); 33445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mTimerView = (TextView) findViewById(R.id.timerView); 33545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 33645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mExitButtons = (LinearLayout) findViewById(R.id.exitButtons); 33745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mAcceptButton = (Button) findViewById(R.id.acceptButton); 33845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mDiscardButton = (Button) findViewById(R.id.discardButton); 33945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mVUMeter = (VUMeter) findViewById(R.id.uvMeter); 34045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 34145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordButton.setOnClickListener(this); 34245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mPlayButton.setOnClickListener(this); 34345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStopButton.setOnClickListener(this); 34445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mAcceptButton.setOnClickListener(this); 34545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mDiscardButton.setOnClickListener(this); 34645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 34745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mTimerFormat = getResources().getString(R.string.timer_format); 34845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 34945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mVUMeter.setRecorder(mRecorder); 35045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 35145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 35245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 35345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Make sure we're not recording music playing in the background, ask 35445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * the MediaPlaybackService to pause playback. 35545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 35645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private void stopAudioPlayback() { 35745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // Shamelessly copied from MediaPlaybackService.java, which 35845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // should be public, but isn't. 35945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Intent i = new Intent("com.android.music.musicservicecommand"); 36045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project i.putExtra("command", "pause"); 36145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 36245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project sendBroadcast(i); 36345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 36445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 36545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 36645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Handle the buttons. 36745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 36845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public void onClick(View button) { 36945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (!button.isEnabled()) 37045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return; 37145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 37245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project switch (button.getId()) { 37345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case R.id.recordButton: 37445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRemainingTimeCalculator.reset(); 37545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 37645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mSampleInterrupted = true; 37745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mErrorUiMessage = getResources().getString(R.string.insert_sd_card); 37845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project updateUi(); 37945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } else if (!mRemainingTimeCalculator.diskSpaceAvailable()) { 38045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mSampleInterrupted = true; 38145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mErrorUiMessage = getResources().getString(R.string.storage_is_full); 38245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project updateUi(); 38345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } else { 38445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project stopAudioPlayback(); 38545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 38645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (AUDIO_AMR.equals(mRequestedType)) { 38745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRemainingTimeCalculator.setBitRate(BITRATE_AMR); 388615384c62e2906613590e6f33a37f7dfe4276a59Jean-Michel Trivi mRecorder.startRecording(MediaRecorder.OutputFormat.AMR_NB, ".amr", this); 38945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } else if (AUDIO_3GPP.equals(mRequestedType)) { 39045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRemainingTimeCalculator.setBitRate(BITRATE_3GPP); 391615384c62e2906613590e6f33a37f7dfe4276a59Jean-Michel Trivi mRecorder.startRecording(MediaRecorder.OutputFormat.THREE_GPP, ".3gpp", 392615384c62e2906613590e6f33a37f7dfe4276a59Jean-Michel Trivi this); 39345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } else { 39445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project throw new IllegalArgumentException("Invalid output file type requested"); 39545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 39645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 39745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mMaxFileSize != -1) { 39845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRemainingTimeCalculator.setFileSizeLimit( 39945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.sampleFile(), mMaxFileSize); 40045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 40145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 40245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 40345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case R.id.playButton: 40445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.startPlayback(); 40545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 40645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case R.id.stopButton: 40745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.stop(); 40845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 40945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case R.id.acceptButton: 41045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.stop(); 41145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project saveSample(); 41245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project finish(); 41345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 41445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case R.id.discardButton: 41545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.delete(); 41645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project finish(); 41745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 41845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 41945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 42045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 42145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 42245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Handle the "back" hardware key. 42345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 42445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project @Override 42545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 42645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (keyCode == KeyEvent.KEYCODE_BACK) { 42745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project switch (mRecorder.state()) { 42845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case Recorder.IDLE_STATE: 42945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mRecorder.sampleLength() > 0) 43045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project saveSample(); 43145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project finish(); 43245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 43345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case Recorder.PLAYING_STATE: 43445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.stop(); 43545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project saveSample(); 43645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 43745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case Recorder.RECORDING_STATE: 43845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.clear(); 43945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 44045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 44145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return true; 44245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } else { 44345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return super.onKeyDown(keyCode, event); 44445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 44545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 44645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 44745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project @Override 44845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public void onStop() { 44945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.stop(); 45045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project super.onStop(); 45145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 45245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 45345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project @Override 45445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project protected void onPause() { 45545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mSampleInterrupted = mRecorder.state() == Recorder.RECORDING_STATE; 45645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.stop(); 45745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 45845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project super.onPause(); 45945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 46045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 46145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 46245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * If we have just recorded a smaple, this adds it to the media data base 46345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * and sets the result to the sample's URI. 46445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 46545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private void saveSample() { 46645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mRecorder.sampleLength() == 0) 46745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return; 46845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Uri uri = null; 46945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project try { 47045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project uri = this.addToMediaDB(mRecorder.sampleFile()); 47145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } catch(UnsupportedOperationException ex) { // Database manipulation failure 47245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return; 47345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 47445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (uri == null) { 47545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return; 47645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 47745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project setResult(RESULT_OK, new Intent().setData(uri)); 47845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 47945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 48045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 48145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Called on destroy to unregister the SD card mount event receiver. 48245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 48345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project @Override 48445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public void onDestroy() { 48545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mSDCardMountEventReceiver != null) { 48645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project unregisterReceiver(mSDCardMountEventReceiver); 48745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mSDCardMountEventReceiver = null; 48845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 48945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project super.onDestroy(); 49045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 49145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 49245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 49345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Registers an intent to listen for ACTION_MEDIA_EJECT/ACTION_MEDIA_MOUNTED 49445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * notifications. 49545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 49645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private void registerExternalStorageListener() { 49745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mSDCardMountEventReceiver == null) { 49845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mSDCardMountEventReceiver = new BroadcastReceiver() { 49945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project @Override 50045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public void onReceive(Context context, Intent intent) { 50145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project String action = intent.getAction(); 50245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (action.equals(Intent.ACTION_MEDIA_EJECT)) { 50345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.delete(); 50445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) { 50545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mSampleInterrupted = false; 50645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project updateUi(); 50745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 50845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 50945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project }; 51045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project IntentFilter iFilter = new IntentFilter(); 51145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project iFilter.addAction(Intent.ACTION_MEDIA_EJECT); 51245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project iFilter.addAction(Intent.ACTION_MEDIA_MOUNTED); 51345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project iFilter.addDataScheme("file"); 51445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project registerReceiver(mSDCardMountEventReceiver, iFilter); 51545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 51645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 51745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 51845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 51945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * A simple utility to do a query into the databases. 52045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 52145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 52245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project try { 52345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project ContentResolver resolver = getContentResolver(); 52445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (resolver == null) { 52545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return null; 52645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 52745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return resolver.query(uri, projection, selection, selectionArgs, sortOrder); 52845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } catch (UnsupportedOperationException ex) { 52945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return null; 53045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 53145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 53245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 53345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 53445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Add the given audioId to the playlist with the given playlistId; and maintain the 53545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * play_order in the playlist. 53645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 53745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private void addToPlaylist(ContentResolver resolver, int audioId, long playlistId) { 53845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project String[] cols = new String[] { 53945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project "count(*)" 54045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project }; 54145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId); 54245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Cursor cur = resolver.query(uri, cols, null, null, null); 54345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cur.moveToFirst(); 54445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project final int base = cur.getInt(0); 54545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cur.close(); 54645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project ContentValues values = new ContentValues(); 54745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(base + audioId)); 54845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, audioId); 54945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project resolver.insert(uri, values); 55045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 55145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 55245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 55345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Obtain the id for the default play list from the audio_playlists table. 55445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 55545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private int getPlaylistId(Resources res) { 55645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Uri uri = MediaStore.Audio.Playlists.getContentUri("external"); 55745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project final String[] ids = new String[] { MediaStore.Audio.Playlists._ID }; 55845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project final String where = MediaStore.Audio.Playlists.NAME + "=?"; 55945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project final String[] args = new String[] { res.getString(R.string.audio_db_playlist_name) }; 56045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Cursor cursor = query(uri, ids, where, args, null); 56145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (cursor == null) { 56245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Log.v(TAG, "query returns null"); 56345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 56445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project int id = -1; 56545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (cursor != null) { 56645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cursor.moveToFirst(); 56745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (!cursor.isAfterLast()) { 56845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project id = cursor.getInt(0); 56945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 57045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 57145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cursor.close(); 57245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return id; 57345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 57445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 57545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 57645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Create a playlist with the given default playlist name, if no such playlist exists. 57745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 57845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private Uri createPlaylist(Resources res, ContentResolver resolver) { 57945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project ContentValues cv = new ContentValues(); 58045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cv.put(MediaStore.Audio.Playlists.NAME, res.getString(R.string.audio_db_playlist_name)); 58145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Uri uri = resolver.insert(MediaStore.Audio.Playlists.getContentUri("external"), cv); 58245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (uri == null) { 58345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project new AlertDialog.Builder(this) 58445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .setTitle(R.string.app_name) 58545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .setMessage(R.string.error_mediadb_new_record) 58645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .setPositiveButton(R.string.button_ok, null) 58745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .setCancelable(false) 58845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .show(); 58945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 59045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return uri; 59145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 59245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 59345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 59445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Adds file and returns content uri. 59545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 59645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private Uri addToMediaDB(File file) { 59745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Resources res = getResources(); 59845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project ContentValues cv = new ContentValues(); 59945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project long current = System.currentTimeMillis(); 60045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project long modDate = file.lastModified(); 60145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Date date = new Date(current); 60245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project SimpleDateFormat formatter = new SimpleDateFormat( 60345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project res.getString(R.string.audio_db_title_format)); 60445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project String title = formatter.format(date); 6050508261c0f215eaa82a161158404cb317727b3f8Sahil Verma long sampleLengthMillis = mRecorder.sampleLength() * 1000L; 60645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 60745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // Lets label the recorded audio file as NON-MUSIC so that the file 60845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // won't be displayed automatically, except for in the playlist. 60945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cv.put(MediaStore.Audio.Media.IS_MUSIC, "0"); 61045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 61145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cv.put(MediaStore.Audio.Media.TITLE, title); 61245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cv.put(MediaStore.Audio.Media.DATA, file.getAbsolutePath()); 61345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cv.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000)); 61445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cv.put(MediaStore.Audio.Media.DATE_MODIFIED, (int) (modDate / 1000)); 6150508261c0f215eaa82a161158404cb317727b3f8Sahil Verma cv.put(MediaStore.Audio.Media.DURATION, sampleLengthMillis); 61645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cv.put(MediaStore.Audio.Media.MIME_TYPE, mRequestedType); 61745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cv.put(MediaStore.Audio.Media.ARTIST, 61845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project res.getString(R.string.audio_db_artist_name)); 61945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project cv.put(MediaStore.Audio.Media.ALBUM, 62045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project res.getString(R.string.audio_db_album_name)); 62145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Log.d(TAG, "Inserting audio record: " + cv.toString()); 62245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project ContentResolver resolver = getContentResolver(); 62345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 62445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Log.d(TAG, "ContentURI: " + base); 62545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Uri result = resolver.insert(base, cv); 62645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (result == null) { 62745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project new AlertDialog.Builder(this) 62845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .setTitle(R.string.app_name) 62945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .setMessage(R.string.error_mediadb_new_record) 63045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .setPositiveButton(R.string.button_ok, null) 63145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .setCancelable(false) 63245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .show(); 63345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return null; 63445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 63545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (getPlaylistId(res) == -1) { 63645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project createPlaylist(res, resolver); 63745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 63845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project int audioId = Integer.valueOf(result.getLastPathSegment()); 63945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project addToPlaylist(resolver, audioId, getPlaylistId(res)); 64045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 64145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // Notify those applications such as Music listening to the 64245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project // scanner events that a recorded audio file just created. 64345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result)); 64445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return result; 64545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 64645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 64745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /** 64845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Update the big MM:SS timer. If we are in playback, also update the 64945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * progress bar. 65045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 65145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private void updateTimerView() { 65245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Resources res = getResources(); 65345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project int state = mRecorder.state(); 65445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 65545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project boolean ongoing = state == Recorder.RECORDING_STATE || state == Recorder.PLAYING_STATE; 65645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 65745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project long time = ongoing ? mRecorder.progress() : mRecorder.sampleLength(); 65845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project String timeStr = String.format(mTimerFormat, time/60, time%60); 65945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mTimerView.setText(timeStr); 66045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 66145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (state == Recorder.PLAYING_STATE) { 66245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateProgressBar.setProgress((int)(100*time/mRecorder.sampleLength())); 66345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } else if (state == Recorder.RECORDING_STATE) { 66445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project updateTimeRemaining(); 66545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 66645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 66745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (ongoing) 66845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mHandler.postDelayed(mUpdateTimer, 1000); 66945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 67045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 67145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 67245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Called when we're in recording state. Find out how much longer we can 67345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * go on recording. If it's under 5 minutes, we display a count-down in 67445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * the UI. If we've run out of time, stop the recording. 67545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 67645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private void updateTimeRemaining() { 67745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project long t = mRemainingTimeCalculator.timeRemaining(); 67845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 67945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (t <= 0) { 68045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mSampleInterrupted = true; 68145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 68245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project int limit = mRemainingTimeCalculator.currentLowerLimit(); 68345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project switch (limit) { 68445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case RemainingTimeCalculator.DISK_SPACE_LIMIT: 68545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mErrorUiMessage 68645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project = getResources().getString(R.string.storage_is_full); 68745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 68845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case RemainingTimeCalculator.FILE_SIZE_LIMIT: 68945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mErrorUiMessage 69045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project = getResources().getString(R.string.max_length_reached); 69145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 69245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project default: 69345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mErrorUiMessage = null; 69445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 69545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 69645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 69745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecorder.stop(); 69845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project return; 69945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 70045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 70145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Resources res = getResources(); 70245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project String timeStr = ""; 70345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 70445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (t < 60) 70545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project timeStr = String.format(res.getString(R.string.sec_available), t); 70645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project else if (t < 540) 70745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project timeStr = String.format(res.getString(R.string.min_available), t/60 + 1); 70845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 70945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage1.setText(timeStr); 71045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 71145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 71245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /** 71345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Shows/hides the appropriate child views for the new state. 71445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 71545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project private void updateUi() { 71645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Resources res = getResources(); 71745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 71845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project switch (mRecorder.state()) { 71945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case Recorder.IDLE_STATE: 72045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mRecorder.sampleLength() == 0) { 72145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordButton.setEnabled(true); 72245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordButton.setFocusable(true); 72345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mPlayButton.setEnabled(false); 72445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mPlayButton.setFocusable(false); 72545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStopButton.setEnabled(false); 72645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStopButton.setFocusable(false); 72745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordButton.requestFocus(); 72845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 72945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage1.setVisibility(View.INVISIBLE); 7309913636a48ba71e91d45e6805bfe3e41ac877263Ben Murdoch mStateLED.setVisibility(View.INVISIBLE); 7319913636a48ba71e91d45e6805bfe3e41ac877263Ben Murdoch mStateMessage2.setVisibility(View.INVISIBLE); 73245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 73345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mExitButtons.setVisibility(View.INVISIBLE); 73445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mVUMeter.setVisibility(View.VISIBLE); 73545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 73645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateProgressBar.setVisibility(View.INVISIBLE); 73745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 73845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project setTitle(res.getString(R.string.record_your_message)); 73945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } else { 74045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordButton.setEnabled(true); 74145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordButton.setFocusable(true); 74245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mPlayButton.setEnabled(true); 74345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mPlayButton.setFocusable(true); 74445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStopButton.setEnabled(false); 74545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStopButton.setFocusable(false); 74645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 74745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage1.setVisibility(View.INVISIBLE); 74845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateLED.setVisibility(View.INVISIBLE); 74945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage2.setVisibility(View.INVISIBLE); 75045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 75145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mExitButtons.setVisibility(View.VISIBLE); 75245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mVUMeter.setVisibility(View.INVISIBLE); 75345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 75445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateProgressBar.setVisibility(View.INVISIBLE); 75545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 75645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project setTitle(res.getString(R.string.message_recorded)); 75745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 75845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 75945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mSampleInterrupted) { 76045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage2.setVisibility(View.VISIBLE); 76145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage2.setText(res.getString(R.string.recording_stopped)); 7629913636a48ba71e91d45e6805bfe3e41ac877263Ben Murdoch mStateLED.setVisibility(View.INVISIBLE); 76345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 76445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 76545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mErrorUiMessage != null) { 76645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage1.setText(mErrorUiMessage); 76745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage1.setVisibility(View.VISIBLE); 76845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 76945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 77045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 77145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case Recorder.RECORDING_STATE: 77245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordButton.setEnabled(false); 77345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordButton.setFocusable(false); 77445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mPlayButton.setEnabled(false); 77545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mPlayButton.setFocusable(false); 77645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStopButton.setEnabled(true); 77745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStopButton.setFocusable(true); 77845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 77945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage1.setVisibility(View.VISIBLE); 78045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateLED.setVisibility(View.VISIBLE); 78145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateLED.setImageResource(R.drawable.recording_led); 78245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage2.setVisibility(View.VISIBLE); 78345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage2.setText(res.getString(R.string.recording)); 78445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 78545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mExitButtons.setVisibility(View.INVISIBLE); 78645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mVUMeter.setVisibility(View.VISIBLE); 78745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 78845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateProgressBar.setVisibility(View.INVISIBLE); 78945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 79045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project setTitle(res.getString(R.string.record_your_message)); 79145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 79245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 79345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 79445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case Recorder.PLAYING_STATE: 79545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordButton.setEnabled(true); 79645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mRecordButton.setFocusable(true); 79745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mPlayButton.setEnabled(false); 79845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mPlayButton.setFocusable(false); 79945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStopButton.setEnabled(true); 80045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStopButton.setFocusable(true); 80145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 80245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage1.setVisibility(View.INVISIBLE); 80345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateLED.setVisibility(View.INVISIBLE); 80445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateMessage2.setVisibility(View.INVISIBLE); 80545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 80645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mExitButtons.setVisibility(View.VISIBLE); 80745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mVUMeter.setVisibility(View.INVISIBLE); 80845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 80945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mStateProgressBar.setVisibility(View.VISIBLE); 81045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 81145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project setTitle(res.getString(R.string.review_message)); 81245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 81345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 81445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 81545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 81645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project updateTimerView(); 81745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mVUMeter.invalidate(); 81845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 81945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 82045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 82145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Called when Recorder changed it's state. 82245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 82345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public void onStateChanged(int state) { 82445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (state == Recorder.PLAYING_STATE || state == Recorder.RECORDING_STATE) { 82545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mSampleInterrupted = false; 82645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mErrorUiMessage = null; 8278eced4bcd84e4006672dc9512f06e7f553c410c1Eva mWakeLock.acquire(); // we don't want to go to sleep while recording or playing 82845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } else { 82945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (mWakeLock.isHeld()) 83045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project mWakeLock.release(); 83145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 83245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 83345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project updateUi(); 83445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 83545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 83645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project /* 83745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project * Called when MediaPlayer encounters an error. 83845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project */ 83945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project public void onError(int error) { 84045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project Resources res = getResources(); 84145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project 84245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project String message = null; 84345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project switch (error) { 84445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case Recorder.SDCARD_ACCESS_ERROR: 84545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project message = res.getString(R.string.error_sdcard_access); 84645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 847615384c62e2906613590e6f33a37f7dfe4276a59Jean-Michel Trivi case Recorder.IN_CALL_RECORD_ERROR: 848615384c62e2906613590e6f33a37f7dfe4276a59Jean-Michel Trivi // TODO: update error message to reflect that the recording could not be 849615384c62e2906613590e6f33a37f7dfe4276a59Jean-Michel Trivi // performed during a call. 85045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project case Recorder.INTERNAL_ERROR: 85145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project message = res.getString(R.string.error_app_internal); 85245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project break; 85345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 85445fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project if (message != null) { 85545fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project new AlertDialog.Builder(this) 85645fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .setTitle(R.string.app_name) 85745fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .setMessage(message) 85845fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .setPositiveButton(R.string.button_ok, null) 85945fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .setCancelable(false) 86045fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project .show(); 86145fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 86245fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project } 86345fd319136b87911aae50269618b51c4a5902ad9The Android Open Source Project} 864