这个录音实现是我在Bus上看到并下载的,他那个源码不完整,再次把我整理完整的代码贴出,源码地址在这:http://download.csdn.net/detail/chaozhung/5618649
Bus上的那个网址找不到了,见谅!!!
下为核心代码:
核心代码1..
package com.lv.reco;
import java.io.File;
public class SoundRecorder extends Activity implements Button.OnClickListener,
Recorder.OnStateChangedListener {
private static final String TAG = "SoundRecorder";
private static final String RECORDER_STATE_KEY = "recorder_state";
private static final String SAMPLE_INTERRUPTED_KEY = "sample_interrupted";
private static final String MAX_FILE_SIZE_KEY = "max_file_size";
private static final String AUDIO_3GPP = "audio/3gpp";
private static final String AUDIO_AMR = "audio/amr";
private static final String AUDIO_ANY = "audio/*";
private static final String ANY_ANY = "*/*";
private static final String FILE_EXTENSION_AMR = ".amr";
private static final String FILE_EXTENSION_3GPP = ".3gpp";
public static final int BITRATE_AMR = 2 * 1024 * 8; // bits/sec
public static final int BITRATE_3GPP = 20 * 1024 * 8; // bits/sec
private static final int SEEK_BAR_MAX = 10000;
private static final long WHEEL_SPEED_NORMAL = 1800;
private static final long WHEEL_SPEED_FAST = 300;
private static final long WHEEL_SPEED_SUPER_FAST = 100;
private static final long SMALL_WHEEL_SPEED_NORMAL = 900;
private static final long SMALL_WHEEL_SPEED_FAST = 200;
private static final long SMALL_WHEEL_SPEED_SUPER_FAST = 200;
private String mRequestedType = AUDIO_ANY;
private boolean mCanRequestChanged = false;
private Recorder mRecorder;
private RecorderReceiver mReceiver;
private boolean mSampleInterrupted = false;
private boolean mShowFinishButton = false;
private String mErrorUiMessage = null; // Some error messages are displayed
// in the UI, not a dialog. This
// happens when a recording
// is interrupted for some reason.
private long mMaxFileSize = -1; // can be specified in the intent
private RemainingTimeCalculator mRemainingTimeCalculator;
private String mTimerFormat;
private SoundPool mSoundPool;
private int mPlaySound;
private int mPauseSound;
private HashSet<String> mSavedRecord;
private long mLastClickTime;
private int mLastButtonId;
private final Handler mHandler = new Handler();
private Runnable mUpdateTimer = new Runnable() {
public void run() {
if (!mStopUiUpdate) {
updateTimerView();
}
}
};
private Runnable mUpdateSeekBar = new Runnable() {
@Override
public void run() {
if (!mStopUiUpdate) {
updateSeekBar();
}
}
};
private Runnable mUpdateVUMetur = new Runnable() {
@Override
public void run() {
if (!mStopUiUpdate) {
updateVUMeterView();
}
}
};
private ImageButton mNewButton;
private ImageButton mFinishButton;
private ImageButton mRecordButton;
private ImageButton mStopButton;
private ImageButton mPlayButton;
private ImageButton mPauseButton;
private ImageButton mDeleteButton;
private WheelImageView mWheelLeft;
private WheelImageView mWheelRight;
private WheelImageView mSmallWheelLeft;
private WheelImageView mSmallWheelRight;
private RecordNameEditText mFileNameEditText;
private LinearLayout mTimerLayout;
private LinearLayout mVUMeterLayout;
private LinearLayout mSeekBarLayout;
private TextView mStartTime;
private TextView mTotalTime;
private SeekBar mPlaySeekBar;
private BroadcastReceiver mSDCardMountEventReceiver = null;
private int mPreviousVUMax;
private boolean mStopUiUpdate;
@Override
public void onCreate(Bundle icycle) {
super.onCreate(icycle);
initInternalState(getIntent());
setContentView(R.layout.main);
mRecorder = new Recorder(this);
mRecorder.setOnStateChangedListener(this);
mReceiver = new RecorderReceiver();
mRemainingTimeCalculator = new RemainingTimeCalculator();
mSavedRecord = new HashSet<String>();
initResourceRefs();
setResult(RESULT_CANCELED);
registerExternalStorageListener();
if (icycle != null) {
Bundle recorderState = icycle.getBundle(RECORDER_STATE_KEY);
if (recorderState != null) {
mRecorder.restoreState(recorderState);
mSampleInterrupted = recorderState.getBoolean(SAMPLE_INTERRUPTED_KEY, false);
mMaxFileSize = recorderState.getLong(MAX_FILE_SIZE_KEY, -1);
}
}
setVolumeControlStream(AudioManager.STREAM_MUSIC);
if (mShowFinishButton) {
// reset state if it is a recording request
mRecorder.reset();
resetFileNameEditText();
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
boolean preShowFinishButton = mShowFinishButton;
initInternalState(intent);
if (mShowFinishButton || preShowFinishButton != mShowFinishButton) {
// reset state if it is a recording request or state is changed
mRecorder.reset();
resetFileNameEditText();
}
}
private void initInternalState(Intent i) {
mRequestedType = AUDIO_ANY;
mShowFinishButton = false;
if (i != null) {
String s = i.getType();
if (AUDIO_AMR.equals(s) || AUDIO_3GPP.equals(s) || AUDIO_ANY.equals(s)
|| ANY_ANY.equals(s)) {
mRequestedType = s;
mShowFinishButton = true;
} else if (s != null) {
// we only support amr and 3gpp formats right now
setResult(RESULT_CANCELED);
finish();
return;
}
final String EXTRA_MAX_BYTES = android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES;
mMaxFileSize = i.getLongExtra(EXTRA_MAX_BYTES, -1);
}
if (AUDIO_ANY.equals(mRequestedType)) {
mRequestedType = SoundRecorderPreferenceActivity.getRecordType(this);
} else if (ANY_ANY.equals(mRequestedType)) {
mRequestedType = AUDIO_3GPP;
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.main);
initResourceRefs();
updateUi(false);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mRecorder.sampleLength() == 0)
return;
Bundle recorderState = new Bundle();
if (mRecorder.state() != Recorder.RECORDING_STATE) {
mRecorder.saveState(recorderState);
}
recorderState.putBoolean(SAMPLE_INTERRUPTED_KEY, mSampleInterrupted);
recorderState.putLong(MAX_FILE_SIZE_KEY, mMaxFileSize);
outState.putBundle(RECORDER_STATE_KEY, recorderState);
}
/*
* Whenever the UI is re-created (due f.ex. to orientation change) we have
* to reinitialize references to the views.
*/
private void initResourceRefs() {
mNewButton = (ImageButton) findViewById(R.id.newButton);
mFinishButton = (ImageButton) findViewById(R.id.finishButton);
mRecordButton = (ImageButton) findViewById(R.id.recordButton);
mStopButton = (ImageButton) findViewById(R.id.stopButton);
mPlayButton = (ImageButton) findViewById(R.id.playButton);
mPauseButton = (ImageButton) findViewById(R.id.pauseButton);
mDeleteButton = (ImageButton) findViewById(R.id.deleteButton);
mNewButton.setOnClickListener(this);
mFinishButton.setOnClickListener(this);
mRecordButton.setOnClickListener(this);
mStopButton.setOnClickListener(this);
mPlayButton.setOnClickListener(this);
mPauseButton.setOnClickListener(this);
mDeleteButton.setOnClickListener(this);
mWheelLeft = (WheelImageView) findViewById(R.id.wheel_left);
mWheelRight = (WheelImageView) findViewById(R.id.wheel_right);
mSmallWheelLeft = (WheelImageView) findViewById(R.id.wheel_small_left);
mSmallWheelRight = (WheelImageView) findViewById(R.id.wheel_small_right);
mFileNameEditText = (RecordNameEditText) findViewById(R.id.file_name);
resetFileNameEditText();
mFileNameEditText.setNameChangeListener(new RecordNameEditText.OnNameChangeListener() {
@Override
public void onNameChanged(String name) {
if (!TextUtils.isEmpty(name)) {
mRecorder.renameSampleFile(name);
}
}
});
mTimerLayout = (LinearLayout) findViewById(R.id.time_calculator);
mVUMeterLayout = (LinearLayout) findViewById(R.id.vumeter_layout);
mSeekBarLayout = (LinearLayout) findViewById(R.id.play_seek_bar_layout);
mStartTime = (TextView) findViewById(R.id.starttime);
mTotalTime = (TextView) findViewById(R.id.totaltime);
mPlaySeekBar = (SeekBar) findViewById(R.id.play_seek_bar);
mPlaySeekBar.setMax(SEEK_BAR_MAX);
mPlaySeekBar.setOnSeekBarChangeListener(mSeekBarChangeListener);
mTimerFormat = getResources().getString(R.string.timer_format);
if (mShowFinishButton) {
mNewButton.setVisibility(View.GONE);
mFinishButton.setVisibility(View.VISIBLE);
mNewButton = mFinishButton; // use mNewButon variable for left
// button in the control panel
}
mSoundPool = new SoundPool(5, AudioManager.STREAM_SYSTEM, 5);
mPlaySound = mSoundPool.load("/system/media/audio/ui/SoundRecorderPlay.ogg", 1);
mPauseSound = mSoundPool.load("/system/media/audio/ui/SoundRecorderPause.ogg", 1);
mLastClickTime = 0;
mLastButtonId = 0;
}
private void resetFileNameEditText() {
String extension = "";
if (AUDIO_AMR.equals(mRequestedType)) {
extension = FILE_EXTENSION_AMR;
} else if (AUDIO_3GPP.equals(mRequestedType)) {
extension = FILE_EXTENSION_3GPP;
}
// for audio which is used for mms, we can only use english file name
// mShowFinishButon indicates whether this is an audio for mms
mFileNameEditText.initFileName(mRecorder.getRecordDir(), extension, mShowFinishButton);
}
private void startRecordPlayingAnimation() {
mWheelLeft.startAnimation(WHEEL_SPEED_NORMAL, true);
mWheelRight.startAnimation(WHEEL_SPEED_NORMAL, true);
mSmallWheelLeft.startAnimation(SMALL_WHEEL_SPEED_NORMAL, true);
mSmallWheelRight.startAnimation(SMALL_WHEEL_SPEED_NORMAL, true);
}
private void stopRecordPlayingAnimation() {
stopAnimation();
startRecordPlayingDoneAnimation();
}
private void startRecordPlayingDoneAnimation() {
mWheelLeft.startAnimation(WHEEL_SPEED_SUPER_FAST, false, 4);
mWheelRight.startAnimation(WHEEL_SPEED_SUPER_FAST, false, 4);
mSmallWheelLeft.startAnimation(SMALL_WHEEL_SPEED_SUPER_FAST, false, 2);
mSmallWheelRight.startAnimation(SMALL_WHEEL_SPEED_SUPER_FAST, false, 2);
}
private void startForwardAnimation() {
mWheelLeft.startAnimation(WHEEL_SPEED_FAST, true);
mWheelRight.startAnimation(WHEEL_SPEED_FAST, true);
mSmallWheelLeft.startAnimation(SMALL_WHEEL_SPEED_FAST, true);
mSmallWheelRight.startAnimation(SMALL_WHEEL_SPEED_FAST, true);
}
private void startBackwardAnimation() {
mWheelLeft.startAnimation(WHEEL_SPEED_FAST, false);
mWheelRight.startAnimation(WHEEL_SPEED_FAST, false);
mSmallWheelLeft.startAnimation(SMALL_WHEEL_SPEED_FAST, false);
mSmallWheelRight.startAnimation(SMALL_WHEEL_SPEED_FAST, false);
}
private void stopAnimation() {
mWheelLeft.stopAnimation();
mWheelRight.stopAnimation();
mSmallWheelLeft.stopAnimation();
mSmallWheelRight.stopAnimation();
}
/*
* Make sure we're not recording music playing in the background, ask the
* MediaPlaybackService to pause playback.
*/
private void stopAudioPlayback() {
// Shamelessly copied from MediaPlaybackService.java, which
// should be public, but isn't.
Intent i = new Intent("com.android.music.musicservicecommand");
i.putExtra("command", "pause");
sendBroadcast(i);
}
/*
* Handle the buttons.
*/
public void onClick(View button) {
if (System.currentTimeMillis() - mLastClickTime < 300) {
// in order to avoid user click bottom too quickly
return;
}
if (!button.isEnabled())
return;
if (button.getId() == mLastButtonId && button.getId() != R.id.newButton) {
// as the recorder state is async with the UI
// we need to avoid launching the duplicated action
return;
}
if (button.getId() == R.id.stopButton && System.currentTimeMillis() - mLastClickTime < 1500) {
// it seems that the media recorder is not robust enough
// sometime it crashes when stop recording right after starting
return;
}
mLastClickTime = System.currentTimeMillis();
mLastButtonId = button.getId();
switch (button.getId()) {
case R.id.newButton:
mFileNameEditText.clearFocus();
saveSample();
mRecorder.reset();
resetFileNameEditText();
break;
case R.id.recordButton:
showOverwriteConfirmDialogIfConflicts();
break;
case R.id.stopButton:
mRecorder.stop();
break;
case R.id.playButton:
mRecorder.startPlayback(mRecorder.playProgress());
break;
case R.id.pauseButton:
mRecorder.pausePlayback();
break;
case R.id.finishButton:
mRecorder.stop();
saveSample();
finish();
break;
case R.id.deleteButton:
showDeleteConfirmDialog();
break;
}
}
private void startRecording() {
mRemainingTimeCalculator.reset();
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
mSampleInterrupted = true;
mErrorUiMessage = getResources().getString(R.string.insert_sd_card);
updateUi(false);
} else if (!mRemainingTimeCalculator.diskSpaceAvailable()) {
mSampleInterrupted = true;
mErrorUiMessage = getResources().getString(R.string.storage_is_full);
updateUi(false);
} else {
stopAudioPlayback();
boolean isHighQuality = SoundRecorderPreferenceActivity.isHighQuality(this);
if (AUDIO_AMR.equals(mRequestedType)) {
mRemainingTimeCalculator.setBitRate(BITRATE_AMR);
int outputfileformat = isHighQuality ? MediaRecorder.OutputFormat.RAW_AMR
: MediaRecorder.OutputFormat.RAW_AMR;
mRecorder.startRecording(outputfileformat, mFileNameEditText.getText().toString(),
FILE_EXTENSION_AMR, isHighQuality, mMaxFileSize);
} else if (AUDIO_3GPP.equals(mRequestedType)) {
// HACKME: for HD2, there is an issue with high quality 3gpp
// use low quality instead
if (Build.MODEL.equals("HTC HD2")) {
isHighQuality = false;
}
mRemainingTimeCalculator.setBitRate(BITRATE_3GPP);
mRecorder.startRecording(MediaRecorder.OutputFormat.THREE_GPP, mFileNameEditText
.getText().toString(), FILE_EXTENSION_3GPP, isHighQuality, mMaxFileSize);
} else {
throw new IllegalArgumentException("Invalid output file type requested");
}
if (mMaxFileSize != -1) {
mRemainingTimeCalculator.setFileSizeLimit(mRecorder.sampleFile(), mMaxFileSize);
}
}
}
/*
* Handle the "back" hardware key.
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
switch (mRecorder.state()) {
case Recorder.IDLE_STATE:
case Recorder.PLAYING_PAUSED_STATE:
if (mRecorder.sampleLength() > 0)
saveSample();
finish();
break;
case Recorder.PLAYING_STATE:
mRecorder.stop();
saveSample();
break;
case Recorder.RECORDING_STATE:
if (mShowFinishButton) {
mRecorder.clear();
} else {
finish();
}
break;
}
return true;
} else {
return super.onKeyDown(keyCode, event);
}
}
@Override
protected void onResume() {
super.onResume();
String type = SoundRecorderPreferenceActivity.getRecordType(this);
if (mCanRequestChanged && !TextUtils.equals(type, mRequestedType)) {
saveSample();
mRecorder.reset();
mRequestedType = type;
resetFileNameEditText();
}
mCanRequestChanged = false;
if (!mRecorder.syncStateWithService()) {
mRecorder.reset();
resetFileNameEditText();
}
if (mRecorder.state() == Recorder.RECORDING_STATE) {
String preExtension = AUDIO_AMR.equals(mRequestedType) ? FILE_EXTENSION_AMR
: FILE_EXTENSION_3GPP;
if (!mRecorder.sampleFile().getName().endsWith(preExtension)) {
// the extension is changed need to stop current recording
mRecorder.reset();
resetFileNameEditText();
} else {
// restore state
if (!mShowFinishButton) {
String fileName = mRecorder.sampleFile().getName().replace(preExtension, "");
mFileNameEditText.setText(fileName);
}
if (AUDIO_AMR.equals(mRequestedType)) {
mRemainingTimeCalculator.setBitRate(BITRATE_AMR);
} else if (AUDIO_3GPP.equals(mRequestedType)) {
mRemainingTimeCalculator.setBitRate(BITRATE_3GPP);
}
}
} else {
File file = mRecorder.sampleFile();
if (file != null && !file.exists()) {
mRecorder.reset();
resetFileNameEditText();
}
}
IntentFilter filter = new IntentFilter();
filter.addAction(RecorderService.RECORDER_SERVICE_BROADCAST_NAME);
registerReceiver(mReceiver, filter);
mStopUiUpdate = false;
updateUi(true);
if (RecorderService.isRecording()) {
Intent intent = new Intent(this, RecorderService.class);
intent.putExtra(RecorderService.ACTION_NAME,
RecorderService.ACTION_DISABLE_MONITOR_REMAIN_TIME);
startService(intent);
}
}
@Override
protected void onPause() {
if (mRecorder.state() != Recorder.RECORDING_STATE || mShowFinishButton
|| mMaxFileSize != -1) {
mRecorder.stop();
saveSample();
mFileNameEditText.clearFocus();
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE))
.cancel(RecorderService.NOTIFICATION_ID);
}
if (mReceiver != null) {
unregisterReceiver(mReceiver);
}
mCanRequestChanged = true;
mStopUiUpdate = true;
stopAnimation();
if (RecorderService.isRecording()) {
Intent intent = new Intent(this, RecorderService.class);
intent.putExtra(RecorderService.ACTION_NAME,
RecorderService.ACTION_ENABLE_MONITOR_REMAIN_TIME);
startService(intent);
}
super.onPause();
}
@Override
protected void onStop() {
if (mShowFinishButton) {
finish();
}
super.onStop();
}
/*
* If we have just recorded a sample, this adds it to the media data base
* and sets the result to the sample's URI.
*/
private void saveSample() {
if (mRecorder.sampleLength() == 0)
return;
if (!mSavedRecord.contains(mRecorder.sampleFile().getAbsolutePath())) {
Uri uri = null;
try {
uri = this.addToMediaDB(mRecorder.sampleFile());
} catch (UnsupportedOperationException ex) { // Database
// manipulation
// failure
return;
}
if (uri == null) {
return;
}
mSavedRecord.add(mRecorder.sampleFile().getAbsolutePath());
setResult(RESULT_OK, new Intent().setData(uri));
}
}
private void showDeleteConfirmDialog() {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
dialogBuilder.setIcon(android.R.drawable.ic_dialog_alert);
dialogBuilder.setTitle(R.string.delete_dialog_title);
dialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mRecorder.delete();
}
});
dialogBuilder.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mLastButtonId = 0;
}
});
dialogBuilder.show();
}
private void showOverwriteConfirmDialogIfConflicts() {
String fileName = mFileNameEditText.getText().toString()
+ (AUDIO_AMR.equals(mRequestedType) ? FILE_EXTENSION_AMR : FILE_EXTENSION_3GPP);
if (mRecorder.isRecordExisted(fileName) && !mShowFinishButton) {
// file already existed and it's not a recording request from other
// app
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
dialogBuilder.setIcon(android.R.drawable.ic_dialog_alert);
dialogBuilder.setTitle(getString(R.string.overwrite_dialog_title, fileName));
dialogBuilder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startRecording();
}
});
dialogBuilder.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mLastButtonId = 0;
}
});
dialogBuilder.show();
} else {
startRecording();
}
}
/*
* Called on destroy to unregister the SD card mount event receiver.
*/
@Override
public void onDestroy() {
if (mSDCardMountEventReceiver != null) {
unregisterReceiver(mSDCardMountEventReceiver);
mSDCardMountEventReceiver = null;
}
mSoundPool.release();
super.onDestroy();
}
/*
* Registers an intent to listen for
* ACTION_MEDIA_EJECT/ACTION_MEDIA_UNMOUNTED/ACTION_MEDIA_MOUNTED
* notifications.
*/
private void registerExternalStorageListener() {
if (mSDCardMountEventReceiver == null) {
mSDCardMountEventReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mSampleInterrupted = false;
mRecorder.reset();
resetFileNameEditText();
updateUi(false);
}
};
IntentFilter iFilter = new IntentFilter();
iFilter.addAction(Intent.ACTION_MEDIA_EJECT);
iFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
iFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
iFilter.addDataScheme("file");
registerReceiver(mSDCardMountEventReceiver, iFilter);
}
}
/*
* A simple utility to do a query into the databases.
*/
private Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
try {
ContentResolver resolver = getContentResolver();
if (resolver == null) {
return null;
}
return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
} catch (UnsupportedOperationException ex) {
return null;
}
}
/*
* Add the given audioId to the playlist with the given playlistId; and
* maintain the play_order in the playlist.
*/
private void addToPlaylist(ContentResolver resolver, int audioId, long playlistId) {
String[] cols = new String[] {
"count(*)"
};
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
Cursor cur = resolver.query(uri, cols, null, null, null);
cur.moveToFirst();
final int base = cur.getInt(0);
cur.close();
ContentValues values = new ContentValues();
values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(base + audioId));
values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, audioId);
resolver.insert(uri, values);
}
/*
* Obtain the id for the default play list from the audio_playlists table.
*/
private int getPlaylistId(Resources res) {
Uri uri = MediaStore.Audio.Playlists.getContentUri("external");
final String[] ids = new String[] {
MediaStore.Audio.Playlists._ID
};
final String where = MediaStore.Audio.Playlists.NAME + "=?";
final String[] args = new String[] {
res.getString(R.string.audio_db_playlist_name)
};
Cursor cursor = query(uri, ids, where, args, null);
if (cursor == null) {
Log.v(TAG, "query returns null");
}
int id = -1;
if (cursor != null) {
cursor.moveToFirst();
if (!cursor.isAfterLast()) {
id = cursor.getInt(0);
}
cursor.close();
}
return id;
}
/*
* Create a playlist with the given default playlist name, if no such
* playlist exists.
*/
private Uri createPlaylist(Resources res, ContentResolver resolver) {
ContentValues cv = new ContentValues();
cv.put(MediaStore.Audio.Playlists.NAME, res.getString(R.string.audio_db_playlist_name));
Uri uri = resolver.insert(MediaStore.Audio.Playlists.getContentUri("external"), cv);
if (uri == null) {
new AlertDialog.Builder(this).setTitle(R.string.app_name)
.setMessage(R.string.error_mediadb_new_record)
.setPositiveButton(R.string.button_ok, null).setCancelable(false).show();
}
return uri;
}
/*
* Adds file and returns content uri.
*/
private Uri addToMediaDB(File file) {
Resources res = getResources();
ContentValues cv = new ContentValues();
long current = System.currentTimeMillis();
long modDate = file.lastModified();
Date date = new Date(current);
SimpleDateFormat formatter = new SimpleDateFormat(
res.getString(R.string.audio_db_title_format));
String title = formatter.format(date);
long sampleLengthMillis = mRecorder.sampleLength() * 1000L;
// Lets label the recorded audio file as NON-MUSIC so that the file
// won't be displayed automatically, except for in the playlist.
cv.put(MediaStore.Audio.Media.IS_MUSIC, "0");
cv.put(MediaStore.Audio.Media.TITLE, title);
cv.put(MediaStore.Audio.Media.DATA, file.getAbsolutePath());
cv.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000));
cv.put(MediaStore.Audio.Media.DATE_MODIFIED, (int) (modDate / 1000));
cv.put(MediaStore.Audio.Media.DURATION, sampleLengthMillis);
cv.put(MediaStore.Audio.Media.MIME_TYPE, mRequestedType);
cv.put(MediaStore.Audio.Media.ARTIST, res.getString(R.string.audio_db_artist_name));
cv.put(MediaStore.Audio.Media.ALBUM, res.getString(R.string.audio_db_album_name));
Log.d(TAG, "Inserting audio record: " + cv.toString());
ContentResolver resolver = getContentResolver();
Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Log.d(TAG, "ContentURI: " + base);
Uri result = resolver.insert(base, cv);
if (result == null) {
Log.w(TAG, getString(R.string.error_mediadb_new_record));
return null;
}
if (getPlaylistId(res) == -1) {
createPlaylist(res, resolver);
}
int audioId = Integer.valueOf(result.getLastPathSegment());
addToPlaylist(resolver, audioId, getPlaylistId(res));
// Notify those applications such as Music listening to the
// scanner events that a recorded audio file just created.
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
return result;
}
private ImageView getTimerImage(char number) {
ImageView image = new ImageView(this);
LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
if (number != ':') {
image.setBackgroundResource(R.drawable.background_number);
}
switch (number) {
case '0':
image.setImageResource(R.drawable.number_0);
break;
case '1':
image.setImageResource(R.drawable.number_1);
break;
case '2':
image.setImageResource(R.drawable.number_2);
break;
case '3':
image.setImageResource(R.drawable.number_3);
break;
case '4':
image.setImageResource(R.drawable.number_4);
break;
case '5':
image.setImageResource(R.drawable.number_5);
break;
case '6':
image.setImageResource(R.drawable.number_6);
break;
case '7':
image.setImageResource(R.drawable.number_7);
break;
case '8':
image.setImageResource(R.drawable.number_8);
break;
case '9':
image.setImageResource(R.drawable.number_9);
break;
case ':':
image.setImageResource(R.drawable.colon);
break;
}
image.setLayoutParams(lp);
return image;
}
/**
* Update the big MM:SS timer. If we are in playback, also update the
* progress bar.
*/
private void updateTimerView() {
int state = mRecorder.state();
boolean ongoing = state == Recorder.RECORDING_STATE || state == Recorder.PLAYING_STATE;
long time = mRecorder.progress();
String timeStr = String.format(mTimerFormat, time / 60, time % 60);
mTimerLayout.removeAllViews();
for (int i = 0; i < timeStr.length(); i++) {
mTimerLayout.addView(getTimerImage(timeStr.charAt(i)));
}
if (state == Recorder.RECORDING_STATE) {
updateTimeRemaining();
}
if (ongoing) {
mHandler.postDelayed(mUpdateTimer, 500);
}
}
private void setTimerView(float progress) {
long time = (long) (progress * mRecorder.sampleLength());
String timeStr = String.format(mTimerFormat, time / 60, time % 60);
mTimerLayout.removeAllViews();
for (int i = 0; i < timeStr.length(); i++) {
mTimerLayout.addView(getTimerImage(timeStr.charAt(i)));
}
}
private void updateSeekBar() {
if (mRecorder.state() == Recorder.PLAYING_STATE) {
mPlaySeekBar.setProgress((int) (SEEK_BAR_MAX * mRecorder.playProgress()));
mHandler.postDelayed(mUpdateSeekBar, 10);
}
}
/*
* Called when we're in recording state. Find out how much longer we can go
* on recording. If it's under 5 minutes, we display a count-down in the UI.
* If we've run out of time, stop the recording.
*/
private void updateTimeRemaining() {
long t = mRemainingTimeCalculator.timeRemaining();
if (t <= 0) {
mSampleInterrupted = true;
int limit = mRemainingTimeCalculator.currentLowerLimit();
switch (limit) {
case RemainingTimeCalculator.DISK_SPACE_LIMIT:
mErrorUiMessage = getResources().getString(R.string.storage_is_full);
break;
case RemainingTimeCalculator.FILE_SIZE_LIMIT:
mErrorUiMessage = getResources().getString(R.string.max_length_reached);
break;
default:
mErrorUiMessage = null;
break;
}
mRecorder.stop();
return;
}
}
private void updateVUMeterView() {
final int MAX_VU_SIZE = 11;
boolean showVUArray[] = new boolean[MAX_VU_SIZE];
if (mVUMeterLayout.getVisibility() == View.VISIBLE
&& mRecorder.state() == Recorder.RECORDING_STATE) {
int vuSize = MAX_VU_SIZE * mRecorder.getMaxAmplitude() / 32768;
if (vuSize >= MAX_VU_SIZE) {
vuSize = MAX_VU_SIZE - 1;
}
if (vuSize >= mPreviousVUMax) {
mPreviousVUMax = vuSize;
} else if (mPreviousVUMax > 0) {
mPreviousVUMax--;
}
for (int i = 0; i < MAX_VU_SIZE; i++) {
if (i <= vuSize) {
showVUArray[i] = true;
} else if (i == mPreviousVUMax) {
showVUArray[i] = true;
} else {
showVUArray[i] = false;
}
}
mHandler.postDelayed(mUpdateVUMetur, 100);
} else if (mVUMeterLayout.getVisibility() == View.VISIBLE) {
mPreviousVUMax = 0;
for (int i = 0; i < MAX_VU_SIZE; i++) {
showVUArray[i] = false;
}
}
if (mVUMeterLayout.getVisibility() == View.VISIBLE) {
mVUMeterLayout.removeAllViews();
for (boolean show : showVUArray) {
ImageView imageView = new ImageView(this);
imageView.setBackgroundResource(R.drawable.background_vumeter);
if (show) {
imageView.setImageResource(R.drawable.icon_vumeter);
}
imageView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
mVUMeterLayout.addView(imageView);
}
}
}
/**
* Shows/hides the appropriate child views for the new state.
*/
private void updateUi(boolean skipRewindAnimation) {
switch (mRecorder.state()) {
case Recorder.IDLE_STATE:
mLastButtonId = 0;
case Recorder.PLAYING_PAUSED_STATE:
if (mRecorder.sampleLength() == 0) {
mNewButton.setEnabled(true);
mNewButton.setVisibility(View.VISIBLE);
mRecordButton.setVisibility(View.VISIBLE);
mStopButton.setVisibility(View.GONE);
mPlayButton.setVisibility(View.GONE);
mPauseButton.setVisibility(View.GONE);
mDeleteButton.setEnabled(false);
mRecordButton.requestFocus();
mVUMeterLayout.setVisibility(View.VISIBLE);
mSeekBarLayout.setVisibility(View.GONE);
} else {
mNewButton.setEnabled(true);
mNewButton.setVisibility(View.VISIBLE);
mRecordButton.setVisibility(View.GONE);
mStopButton.setVisibility(View.GONE);
mPlayButton.setVisibility(View.VISIBLE);
mPauseButton.setVisibility(View.GONE);
mDeleteButton.setEnabled(true);
mPauseButton.requestFocus();
mVUMeterLayout.setVisibility(View.GONE);
mSeekBarLayout.setVisibility(View.VISIBLE);
mStartTime.setText(String.format(mTimerFormat, 0, 0));
mTotalTime.setText(String.format(mTimerFormat, mRecorder.sampleLength() / 60,
mRecorder.sampleLength() % 60));
}
mFileNameEditText.setEnabled(true);
mFileNameEditText.clearFocus();
if (mRecorder.sampleLength() > 0) {
if (mRecorder.state() == Recorder.PLAYING_PAUSED_STATE) {
stopAnimation();
if (SoundRecorderPreferenceActivity.isEnabledSoundEffect(this)) {
mSoundPool.play(mPauseSound, 1.0f, 1.0f, 0, 0, 1);
}
} else {
mPlaySeekBar.setProgress(0);
if (!skipRewindAnimation) {
stopRecordPlayingAnimation();
} else {
stopAnimation();
}
}
} else {
stopAnimation();
}
// we allow only one toast at one time
if (mSampleInterrupted && mErrorUiMessage == null) {
Toast.makeText(this, R.string.recording_stopped, Toast.LENGTH_SHORT).show();
}
if (mErrorUiMessage != null) {
Toast.makeText(this, mErrorUiMessage, Toast.LENGTH_SHORT).show();
}
break;
case Recorder.RECORDING_STATE:
mNewButton.setEnabled(false);
mNewButton.setVisibility(View.VISIBLE);
mRecordButton.setVisibility(View.GONE);
mStopButton.setVisibility(View.VISIBLE);
mPlayButton.setVisibility(View.GONE);
mPauseButton.setVisibility(View.GONE);
mDeleteButton.setEnabled(false);
mStopButton.requestFocus();
mVUMeterLayout.setVisibility(View.VISIBLE);
mSeekBarLayout.setVisibility(View.GONE);
mFileNameEditText.setEnabled(false);
startRecordPlayingAnimation();
mPreviousVUMax = 0;
break;
case Recorder.PLAYING_STATE:
mNewButton.setEnabled(false);
mNewButton.setVisibility(View.VISIBLE);
mRecordButton.setVisibility(View.GONE);
mStopButton.setVisibility(View.GONE);
mPlayButton.setVisibility(View.GONE);
mPauseButton.setVisibility(View.VISIBLE);
mDeleteButton.setEnabled(false);
mPauseButton.requestFocus();
mVUMeterLayout.setVisibility(View.GONE);
mSeekBarLayout.setVisibility(View.VISIBLE);
mFileNameEditText.setEnabled(false);
if (SoundRecorderPreferenceActivity.isEnabledSoundEffect(this)) {
mSoundPool.play(mPlaySound, 1.0f, 1.0f, 0, 0, 1);
}
startRecordPlayingAnimation();
break;
}
updateTimerView();
updateSeekBar();
updateVUMeterView();
}
/*
* Called when Recorder changed it's state.
*/
public void onStateChanged(int state) {
if (state == Recorder.PLAYING_STATE || state == Recorder.RECORDING_STATE) {
mSampleInterrupted = false;
mErrorUiMessage = null;
}
updateUi(false);
}
/*
* Called when MediaPlayer encounters an error.
*/
public void onError(int error) {
Resources res = getResources();
String message = null;
switch (error) {
case Recorder.STORAGE_ACCESS_ERROR:
message = res.getString(R.string.error_sdcard_access);
break;
case Recorder.IN_CALL_RECORD_ERROR:
// TODO: update error message to reflect that the recording
// could not be
// performed during a call.
case Recorder.INTERNAL_ERROR:
message = res.getString(R.string.error_app_internal);
break;
}
if (message != null) {
new AlertDialog.Builder(this).setTitle(R.string.app_name).setMessage(message)
.setPositiveButton(R.string.button_ok, null).setCancelable(false).show();
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
if (mRecorder.state() == Recorder.RECORDING_STATE
|| mRecorder.state() == Recorder.PLAYING_STATE) {
return false;
} else {
getMenuInflater().inflate(R.layout.view_list_menu, menu);
return true;
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent;
switch (item.getItemId()) {
case R.id.menu_fm:
saveSample();
intent = new Intent();
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("file://" + mRecorder.getRecordDir()));
startActivity(intent);
break;
case R.id.menu_setting:
intent = new Intent(this, SoundRecorderPreferenceActivity.class);
startActivity(intent);
break;
default:
break;
}
return true;
}
private SeekBar.OnSeekBarChangeListener mSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
private final int DELTA = SEEK_BAR_MAX / 20;
private int mProgress = 0;
private boolean mPlayingAnimation = false;
private boolean mForwardAnimation = true;
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
stopAnimation();
mRecorder.startPlayback((float) seekBar.getProgress() / SEEK_BAR_MAX);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
mRecorder.pausePlayback();
mPlayingAnimation = false;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
if (!mPlayingAnimation) {
mForwardAnimation = true;
startForwardAnimation();
mPlayingAnimation = true;
mProgress = progress;
}
if (progress >= mProgress + DELTA) {
if (!mForwardAnimation) {
mForwardAnimation = true;
stopAnimation();
startForwardAnimation();
}
mProgress = progress;
} else if (progress < mProgress - DELTA) {
if (mForwardAnimation) {
mForwardAnimation = false;
stopAnimation();
startBackwardAnimation();
}
mProgress = progress;
}
setTimerView(((float) progress) / SEEK_BAR_MAX);
mLastButtonId = 0;
}
}
};
private class RecorderReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.hasExtra(RecorderService.RECORDER_SERVICE_BROADCAST_STATE)) {
boolean isRecording = intent.getBooleanExtra(
RecorderService.RECORDER_SERVICE_BROADCAST_STATE, false);
mRecorder.setState(isRecording ? Recorder.RECORDING_STATE : Recorder.IDLE_STATE);
} else if (intent.hasExtra(RecorderService.RECORDER_SERVICE_BROADCAST_ERROR)) {
int error = intent.getIntExtra(RecorderService.RECORDER_SERVICE_BROADCAST_ERROR, 0);
mRecorder.setError(error);
}
}
}
}
核心代码2...
package com.lv.reco;
import java.io.File;
import java.io.IOException;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class RecorderService extends Service implements MediaRecorder.OnErrorListener {
public final static String ACTION_NAME = "action_type";
public final static int ACTION_INVALID = 0;
public final static int ACTION_START_RECORDING = 1;
public final static int ACTION_STOP_RECORDING = 2;
public final static int ACTION_ENABLE_MONITOR_REMAIN_TIME = 3;
public final static int ACTION_DISABLE_MONITOR_REMAIN_TIME = 4;
public final static String ACTION_PARAM_FORMAT = "format";
public final static String ACTION_PARAM_PATH = "path";
public final static String ACTION_PARAM_HIGH_QUALITY = "high_quality";
public final static String ACTION_PARAM_MAX_FILE_SIZE = "max_file_size";
public final static String RECORDER_SERVICE_BROADCAST_NAME = "com.android.soundrecorder.broadcast";
public final static String RECORDER_SERVICE_BROADCAST_STATE = "is_recording";
public final static String RECORDER_SERVICE_BROADCAST_ERROR = "error_code";
public final static int NOTIFICATION_ID = 62343234;
private static MediaRecorder mRecorder = null;
private static String mFilePath = null;
private static long mStartTime = 0;
private RemainingTimeCalculator mRemainingTimeCalculator;
private NotificationManager mNotifiManager;
private Notification mLowStorageNotification;
private TelephonyManager mTeleManager;
private WakeLock mWakeLock;
private KeyguardManager mKeyguardManager;
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
if (state != TelephonyManager.CALL_STATE_IDLE) {
localStopRecording();
}
}
};
private final Handler mHandler = new Handler();
private Runnable mUpdateRemainingTime = new Runnable() {
public void run() {
if (mRecorder != null && mNeedUpdateRemainingTime) {
updateRemainingTime();
}
}
};
private boolean mNeedUpdateRemainingTime;
@Override
public void onCreate() {
super.onCreate();
mRecorder = null;
mLowStorageNotification = null;
mRemainingTimeCalculator = new RemainingTimeCalculator();
mNeedUpdateRemainingTime = false;
mNotifiManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mTeleManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
mTeleManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SoundRecorder");
mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Bundle bundle = intent.getExtras();
if (bundle != null && bundle.containsKey(ACTION_NAME)) {
switch (bundle.getInt(ACTION_NAME, ACTION_INVALID)) {
case ACTION_START_RECORDING:
localStartRecording(bundle.getInt(ACTION_PARAM_FORMAT),
bundle.getString(ACTION_PARAM_PATH),
bundle.getBoolean(ACTION_PARAM_HIGH_QUALITY),
bundle.getLong(ACTION_PARAM_MAX_FILE_SIZE));
break;
case ACTION_STOP_RECORDING:
localStopRecording();
break;
case ACTION_ENABLE_MONITOR_REMAIN_TIME:
if (mRecorder != null) {
mNeedUpdateRemainingTime = true;
mHandler.post(mUpdateRemainingTime);
}
break;
case ACTION_DISABLE_MONITOR_REMAIN_TIME:
mNeedUpdateRemainingTime = false;
if (mRecorder != null) {
showRecordingNotification();
}
break;
default:
break;
}
return START_STICKY;
}
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
mTeleManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
if (mWakeLock.isHeld()) {
mWakeLock.release();
}
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onLowMemory() {
localStopRecording();
super.onLowMemory();
}
private void localStartRecording(int outputfileformat, String path, boolean highQuality,
long maxFileSize) {
if (mRecorder == null) {
mRemainingTimeCalculator.reset();
if (maxFileSize != -1) {
mRemainingTimeCalculator.setFileSizeLimit(new File(path), maxFileSize);
}
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
if (outputfileformat == MediaRecorder.OutputFormat.THREE_GPP) {
mRemainingTimeCalculator.setBitRate(SoundRecorder.BITRATE_3GPP);
mRecorder.setAudioSamplingRate(highQuality ? 44100 : 22050);
mRecorder.setOutputFormat(outputfileformat);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
} else {
mRemainingTimeCalculator.setBitRate(SoundRecorder.BITRATE_AMR);
mRecorder.setAudioSamplingRate(highQuality ? 16000 : 8000);
mRecorder.setOutputFormat(outputfileformat);
mRecorder.setAudioEncoder(highQuality ? MediaRecorder.AudioEncoder.AMR_NB
: MediaRecorder.AudioEncoder.AMR_NB);
}
mRecorder.setOutputFile(path);
mRecorder.setOnErrorListener(this);
// Handle IOException
try {
mRecorder.prepare();
} catch (IOException exception) {
sendErrorBroadcast(Recorder.INTERNAL_ERROR);
mRecorder.reset();
mRecorder.release();
mRecorder = null;
return;
}
// Handle RuntimeException if the recording couldn't start
try {
mRecorder.start();
} catch (RuntimeException exception) {
AudioManager audioMngr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
boolean isInCall = (audioMngr.getMode() == AudioManager.MODE_IN_CALL);
if (isInCall) {
sendErrorBroadcast(Recorder.IN_CALL_RECORD_ERROR);
} else {
sendErrorBroadcast(Recorder.INTERNAL_ERROR);
}
mRecorder.reset();
mRecorder.release();
mRecorder = null;
return;
}
mFilePath = path;
mStartTime = System.currentTimeMillis();
mWakeLock.acquire();
mNeedUpdateRemainingTime = false;
sendStateBroadcast();
showRecordingNotification();
}
}
private void localStopRecording() {
if (mRecorder != null) {
mNeedUpdateRemainingTime = false;
try {
mRecorder.stop();
} catch (RuntimeException e) {
}
mRecorder.release();
mRecorder = null;
sendStateBroadcast();
showStoppedNotification();
}
stopSelf();
}
private void showRecordingNotification() {
Notification notification = new Notification(R.drawable.stat_sys_call_record,
getString(R.string.notification_recording), System.currentTimeMillis());
notification.flags = Notification.FLAG_ONGOING_EVENT;
PendingIntent pendingIntent;
pendingIntent = PendingIntent
.getActivity(this, 0, new Intent(this, SoundRecorder.class), 0);
notification.setLatestEventInfo(this, getString(R.string.app_name),
getString(R.string.notification_recording), pendingIntent);
startForeground(NOTIFICATION_ID, notification);
}
private void showLowStorageNotification(int minutes) {
if (mKeyguardManager.inKeyguardRestrictedInputMode()) {
// it's not necessary to show this notification in lock-screen
return;
}
if (mLowStorageNotification == null) {
mLowStorageNotification = new Notification(R.drawable.stat_sys_call_record_full,
getString(R.string.notification_recording), System.currentTimeMillis());
mLowStorageNotification.flags = Notification.FLAG_ONGOING_EVENT;
}
PendingIntent pendingIntent;
pendingIntent = PendingIntent
.getActivity(this, 0, new Intent(this, SoundRecorder.class), 0);
mLowStorageNotification.setLatestEventInfo(this, getString(R.string.app_name),
getString(R.string.notification_warning, minutes), pendingIntent);
startForeground(NOTIFICATION_ID, mLowStorageNotification);
}
private void showStoppedNotification() {
stopForeground(true);
mLowStorageNotification = null;
Notification notification = new Notification(R.drawable.stat_sys_call_record,
getString(R.string.notification_stopped), System.currentTimeMillis());
notification.flags = Notification.FLAG_AUTO_CANCEL;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setType("audio/*");
intent.setDataAndType(Uri.fromFile(new File(mFilePath)), "audio/*");
PendingIntent pendingIntent;
pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(this, getString(R.string.app_name),
getString(R.string.notification_stopped), pendingIntent);
mNotifiManager.notify(NOTIFICATION_ID, notification);
}
private void sendStateBroadcast() {
Intent intent = new Intent(RECORDER_SERVICE_BROADCAST_NAME);
intent.putExtra(RECORDER_SERVICE_BROADCAST_STATE, mRecorder != null);
sendBroadcast(intent);
}
private void sendErrorBroadcast(int error) {
Intent intent = new Intent(RECORDER_SERVICE_BROADCAST_NAME);
intent.putExtra(RECORDER_SERVICE_BROADCAST_ERROR, error);
sendBroadcast(intent);
}
private void updateRemainingTime() {
long t = mRemainingTimeCalculator.timeRemaining();
if (t <= 0) {
localStopRecording();
return;
} else if (t <= 1800
&& mRemainingTimeCalculator.currentLowerLimit() != RemainingTimeCalculator.FILE_SIZE_LIMIT) {
// less than half one hour
showLowStorageNotification((int) Math.ceil(t / 60.0));
}
if (mRecorder != null && mNeedUpdateRemainingTime) {
mHandler.postDelayed(mUpdateRemainingTime, 500);
}
}
public static boolean isRecording() {
return mRecorder != null;
}
public static String getFilePath() {
return mFilePath;
}
public static long getStartTime() {
return mStartTime;
}
public static void startRecording(Context context, int outputfileformat, String path,
boolean highQuality, long maxFileSize) {
Intent intent = new Intent(context, RecorderService.class);
intent.putExtra(ACTION_NAME, ACTION_START_RECORDING);
intent.putExtra(ACTION_PARAM_FORMAT, outputfileformat);
intent.putExtra(ACTION_PARAM_PATH, path);
intent.putExtra(ACTION_PARAM_HIGH_QUALITY, highQuality);
intent.putExtra(ACTION_PARAM_MAX_FILE_SIZE, maxFileSize);
context.startService(intent);
}
public static void stopRecording(Context context) {
Intent intent = new Intent(context, RecorderService.class);
intent.putExtra(ACTION_NAME, ACTION_STOP_RECORDING);
context.startService(intent);
}
public static int getMaxAmplitude() {
return mRecorder == null ? 0 : mRecorder.getMaxAmplitude();
}
@Override
public void onError(MediaRecorder mr, int what, int extra) {
sendErrorBroadcast(Recorder.INTERNAL_ERROR);
localStopRecording();
}
}
效果图: