文中的代码主要是移植SoundRecorder的。主要是其中的VUMeter类,VUMeter是通过Recorder.getMaxAmplitude()的值计算,画出指针的偏移摆动。下面直接上代码
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.soundrecorder;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
public class VUMeter extends View {
static final float PIVOT_RADIUS = 3.5f;
static final float PIVOT_Y_OFFSET = 10f;
static final float SHADOW_OFFSET = 2.0f;
static final float DROPOFF_STEP = 0.18f;
static final float SURGE_STEP = 0.35f;
static final long ANIMATION_INTERVAL = 70;
Paint mPaint, mShadow;
float mCurrentAngle;
Recorder mRecorder;
public VUMeter(Context context) {
super(context);
init(context);
}
public VUMeter(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
void init(Context context) {
Drawable background = context.getResources().getDrawable(R.drawable.vumeter);
setBackgroundDrawable(background);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.WHITE);
mShadow = new Paint(Paint.ANTI_ALIAS_FLAG);
mShadow.setColor(Color.argb(60, 0, 0, 0));
mRecorder = null;
mCurrentAngle = 0;
}
public void setRecorder(Recorder recorder) {
mRecorder = recorder;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
final float minAngle = (float)Math.PI/8;
final float maxAngle = (float)Math.PI*7/8;
float angle = minAngle;
if (mRecorder != null)
angle += (float)(maxAngle - minAngle)*mRecorder.getMaxAmplitude()/32768;
if (angle > mCurrentAngle)
mCurrentAngle = angle;
else
mCurrentAngle = Math.max(angle, mCurrentAngle - DROPOFF_STEP);
mCurrentAngle = Math.min(maxAngle, mCurrentAngle);
float w = getWidth();
float h = getHeight();
float pivotX = w/2;
float pivotY = h - PIVOT_RADIUS - PIVOT_Y_OFFSET;
float l = h*4/5;
float sin = (float) Math.sin(mCurrentAngle);
float cos = (float) Math.cos(mCurrentAngle);
float x0 = pivotX - l*cos;
float y0 = pivotY - l*sin;
canvas.drawLine(x0 + SHADOW_OFFSET, y0 + SHADOW_OFFSET, pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, mShadow);
canvas.drawCircle(pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, PIVOT_RADIUS, mShadow);
canvas.drawLine(x0, y0, pivotX, pivotY, mPaint);
canvas.drawCircle(pivotX, pivotY, PIVOT_RADIUS, mPaint);
if (mRecorder != null && mRecorder.state() == Recorder.RECORDING_STATE)
postInvalidateDelayed(ANIMATION_INTERVAL);
}
}
package org.winplus.sh;
import java.io.File;
import java.io.IOException;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Bundle;
import android.os.Environment;
public class RecordHelper implements OnCompletionListener, OnErrorListener {
static final String SAMPLE_PREFIX = "recording";
static final String SAMPLE_PATH_KEY = "sample_path";
static final String SAMPLE_LENGTH_KEY = "sample_length";
public static final int IDLE_STATE = 0;
public static final int RECORDING_STATE = 1;
public static final int PLAYING_STATE = 2;
int mState = IDLE_STATE;
public static final int NO_ERROR = 0;
public static final int SDCARD_ACCESS_ERROR = 1;
public static final int INTERNAL_ERROR = 2;
public static final int IN_CALL_RECORD_ERROR = 3;
public interface OnStateChangedListener {
public void onStateChanged(int state);
public void onError(int error);
}
OnStateChangedListener mOnStateChangedListener = null;
long mSampleStart = 0; // time at which latest record or play operation started
int mSampleLength = 0; // length of current sample
File mSampleFile = null;
MediaRecorder mRecorder = null;
MediaPlayer mPlayer = null;
public RecordHelper() {
}
public void saveState(Bundle recorderState) {
recorderState.putString(SAMPLE_PATH_KEY, mSampleFile.getAbsolutePath());
recorderState.putInt(SAMPLE_LENGTH_KEY, mSampleLength);
}
public int getMaxAmplitude() {
if (mState != RECORDING_STATE)
return 0;
return mRecorder.getMaxAmplitude();
}
public void restoreState(Bundle recorderState) {
String samplePath = recorderState.getString(SAMPLE_PATH_KEY);
if (samplePath == null)
return;
int sampleLength = recorderState.getInt(SAMPLE_LENGTH_KEY, -1);
if (sampleLength == -1)
return;
File file = new File(samplePath);
if (!file.exists())
return;
if (mSampleFile != null
&& mSampleFile.getAbsolutePath().compareTo(file.getAbsolutePath()) == 0)
return;
delete();
mSampleFile = file;
mSampleLength = sampleLength;
signalStateChanged(IDLE_STATE);
}
public void setOnStateChangedListener(OnStateChangedListener listener) {
mOnStateChangedListener = listener;
}
public int state() {
return mState;
}
public int progress() {
if (mState == RECORDING_STATE || mState == PLAYING_STATE)
return (int) ((System.currentTimeMillis() - mSampleStart)/1000);
return 0;
}
public int sampleLength() {
return mSampleLength;
}
public File sampleFile() {
return mSampleFile;
}
/**
* Resets the recorder state. If a sample was recorded, the file is deleted.
*/
public void delete() {
stop();
if (mSampleFile != null)
mSampleFile.delete();
mSampleFile = null;
mSampleLength = 0;
signalStateChanged(IDLE_STATE);
}
/**
* Resets the recorder state. If a sample was recorded, the file is left on disk and will
* be reused for a new recording.
*/
public void clear() {
stop();
mSampleLength = 0;
signalStateChanged(IDLE_STATE);
}
public void startRecording(int outputfileformat, String extension, Context context) {
stop();
if (mSampleFile == null) {
File sampleDir = Environment.getExternalStorageDirectory();
if (!sampleDir.canWrite()) // Workaround for broken sdcard support on the device.
sampleDir = new File("/sdcard/sdcard");
try {
mSampleFile = File.createTempFile(SAMPLE_PREFIX, extension, sampleDir);
} catch (IOException e) {
setError(SDCARD_ACCESS_ERROR);
return;
}
}
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(outputfileformat);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.setOutputFile(mSampleFile.getAbsolutePath());
// Handle IOException
try {
mRecorder.prepare();
} catch(IOException exception) {
setError(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)context.getSystemService(Context.AUDIO_SERVICE);
boolean isInCall = ((audioMngr.getMode() == AudioManager.MODE_IN_CALL) ||
(audioMngr.getMode() == AudioManager.MODE_IN_COMMUNICATION));
if (isInCall) {
setError(IN_CALL_RECORD_ERROR);
} else {
setError(INTERNAL_ERROR);
}
mRecorder.reset();
mRecorder.release();
mRecorder = null;
return;
}
mSampleStart = System.currentTimeMillis();
setState(RECORDING_STATE);
}
public void stopRecording() {
if (mRecorder == null)
return;
mRecorder.stop();
mRecorder.release();
mRecorder = null;
mSampleLength = (int)( (System.currentTimeMillis() - mSampleStart)/1000 );
setState(IDLE_STATE);
}
public void startPlayback() {
stop();
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mSampleFile.getAbsolutePath());
mPlayer.setOnCompletionListener(this);
mPlayer.setOnErrorListener(this);
mPlayer.prepare();
mPlayer.start();
} catch (IllegalArgumentException e) {
setError(INTERNAL_ERROR);
mPlayer = null;
return;
} catch (IOException e) {
setError(SDCARD_ACCESS_ERROR);
mPlayer = null;
return;
}
mSampleStart = System.currentTimeMillis();
setState(PLAYING_STATE);
}
public void stopPlayback() {
if (mPlayer == null) // we were not in playback
return;
mPlayer.stop();
mPlayer.release();
mPlayer = null;
setState(IDLE_STATE);
}
public void stop() {
stopRecording();
stopPlayback();
}
public boolean onError(MediaPlayer mp, int what, int extra) {
stop();
setError(SDCARD_ACCESS_ERROR);
return true;
}
public void onCompletion(MediaPlayer mp) {
stop();
}
private void setState(int state) {
if (state == mState)
return;
mState = state;
signalStateChanged(mState);
}
private void signalStateChanged(int state) {
if (mOnStateChangedListener != null)
mOnStateChangedListener.onStateChanged(state);
}
private void setError(int error) {
if (mOnStateChangedListener != null)
mOnStateChangedListener.onError(error);
}
}
界面:
package org.winplus.sh;
import android.app.Activity;
import android.content.Context;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class SoundHandActivity extends Activity implements OnClickListener,
RecordHelper.OnStateChangedListener {
private static final String TAG = "SoundHandActivity";
private VUMeter mVUMeter;
private RecordHelper mRecorder;
private Button btnStart;
private Button btnStop;
WakeLock mWakeLock;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setupViews();
}
public void setupViews() {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,
"SoundRecorder");
mRecorder = new RecordHelper();
mRecorder.setOnStateChangedListener(this);
mVUMeter = (VUMeter) findViewById(R.id.uvMeter);
mVUMeter.setRecorder(mRecorder);
btnStart = (Button) findViewById(R.id.button1);
btnStop = (Button) findViewById(R.id.button2);
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
mRecorder.startRecording(MediaRecorder.OutputFormat.AMR_NB, ".amr",
this);
break;
case R.id.button2:
mRecorder.stop();
break;
}
}
private void updateUi() {
Log.e(TAG, "=======================updateUi");
mVUMeter.invalidate();
}
@Override
public void onStateChanged(int state) {
if (state == RecordHelper.PLAYING_STATE
|| state == RecordHelper.RECORDING_STATE) {
mWakeLock.acquire(); // we don't want to go to sleep while recording
// or playing
} else {
if (mWakeLock.isHeld())
mWakeLock.release();
}
updateUi();
}
@Override
public void onError(int error) {
// TODO Auto-generated method stub
}
}
OK,没有什么特别的。
源码下载==》
原创文章转载请注明出处:http://www.blog.csdn.net/tangcheng_ok