본문 바로가기

JAVA/Android

안드로이드 녹음(MediaRecorder) 예제 따라하기

- MediaRecorder를 이용해서 녹음,재생이 되는 간단한 예제이다.
- 이 예제를 통해서 녹음 App을 개발하여 보자.

-Java 소스

public class ProgressRecorder extends Activity implements View.OnClickListener,
OnCompletionListener {
private static final int REC_STOP = 0;
private static final int RECORDING = 1;
private static final int PLAY_STOP = 0;
private static final int PLAYING = 1;
private static final int PLAY_PAUSE = 2;

private MediaRecorder mRecorder = null;
private MediaPlayer mPlayer = null;
private int mRecState = REC_STOP;
private int mPlayerState = PLAY_STOP;
private SeekBar mRecProgressBar, mPlayProgressBar;
private Button mBtnStartRec, mBtnStartPlay;
private String mFilePath, mFileName = "test.amr";
private TextView mTvPlayMaxPoint;

private int mCurRecTimeMs = 0;
private int mCurProgressTimeDisplay = 0;

// 녹음시 SeekBar처리
Handler mProgressHandler = new Handler() {
public void handleMessage(Message msg) {
mCurRecTimeMs = mCurRecTimeMs + 100;
mCurProgressTimeDisplay = mCurProgressTimeDisplay + 100;

// 녹음시간이 음수이면 정지버튼을 눌러 정지시켰음을 의미하므로
// SeekBar는 그대로 정지시키고 레코더를 정지시킨다.
if (mCurRecTimeMs < 0) {
}
// 녹음시간이 아직 최대녹음제한시간보다 작으면 녹음중이라는 의미이므로
// SeekBar의 위치를 옮겨주고 0.1초 후에 다시 체크하도록 한다.
else if (mCurRecTimeMs < 60000) {
mRecProgressBar.setProgress(mCurProgressTimeDisplay);
mProgressHandler.sendEmptyMessageDelayed(0, 100);
}
// 녹음시간이 최대 녹음제한 시간보다 크면 녹음을 정지 시킨다.
else {
mBtnStartRecOnClick();
}
}
};

// 재생시 SeekBar 처리
Handler mProgressHandler2 = new Handler() {
public void handleMessage(Message msg) {
if (mPlayer == null)
return;

try {
if (mPlayer.isPlaying()) {
mPlayProgressBar.setProgress(mPlayer.getCurrentPosition());
mProgressHandler2.sendEmptyMessageDelayed(0, 100);
} else {
mPlayer.release();
mPlayer = null;

updateUI();
}
} catch (IllegalStateException e) {
} catch (Exception e) {
}
}
};

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// SD카드에 디렉토리를 만든다.
mFilePath = SunUtil.makeDir("progress_recorder");

mBtnStartRec = (Button) findViewById(R.id.btnStartRec);
mBtnStartPlay = (Button) findViewById(R.id.btnStartPlay);
mRecProgressBar = (SeekBar) findViewById(R.id.recProgressBar);
mPlayProgressBar = (SeekBar) findViewById(R.id.playProgressBar);
mTvPlayMaxPoint = (TextView) findViewById(R.id.tvPlayMaxPoint);

mBtnStartRec.setOnClickListener(this);
mBtnStartPlay.setOnClickListener(this);
}

// 버튼의 OnClick 이벤트 리스너
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnStartRec:
mBtnStartRecOnClick();
break;
case R.id.btnStartPlay:
mBtnStartPlayOnClick();
break;
default:
break;
}
}

private void mBtnStartRecOnClick() {
if (mRecState == REC_STOP) {
mRecState = RECORDING;
startRec();
updateUI();
} else if (mRecState == RECORDING) {
mRecState = REC_STOP;
stopRec();
updateUI();
}
}

// 녹음시작
private void startRec() {
mCurRecTimeMs = 0;
mCurProgressTimeDisplay = 0;

// SeekBar의 상태를 0.1초후 체크 시작
mProgressHandler.sendEmptyMessageDelayed(0, 100);

if (mRecorder == null) {
mRecorder = new MediaRecorder();
mRecorder.reset();
} else {
mRecorder.reset();
}

try {
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mRecorder.setOutputFile(mFilePath + mFileName);
mRecorder.prepare();
mRecorder.start();
} catch (IllegalStateException e) {
Toast.makeText(this, "IllegalStateException", 1).show();
} catch (IOException e) {
Toast.makeText(this, "IOException", 1).show();
}
}

// 녹음정지
private void stopRec() {
try {
mRecorder.stop();
} catch (Exception e) {
} finally {
mRecorder.release();
mRecorder = null;
}

mCurRecTimeMs = -999;
// SeekBar의 상태를 즉시 체크
mProgressHandler.sendEmptyMessageDelayed(0, 0);
}

private void mBtnStartPlayOnClick() {
if (mPlayerState == PLAY_STOP) {
mPlayerState = PLAYING;
startPlay();
updateUI();
} else if (mPlayerState == PLAYING) {
mPlayerState = PLAY_STOP;
stopPlay();
updateUI();
}
}

// 재생 시작
private void startPlay() {
// 미디어 플레이어 생성
if (mPlayer == null)
mPlayer = new MediaPlayer();
else
mPlayer.reset();

mPlayer.setOnCompletionListener(this);

String fullFilePath = mFilePath + mFileName;
Log.v("ProgressRecorder", "녹음파일명 ==========> " + fullFilePath);

try {
mPlayer.setDataSource(fullFilePath);
mPlayer.prepare();
int point = mPlayer.getDuration();
mPlayProgressBar.setMax(point);

int maxMinPoint = point / 1000 / 60;
int maxSecPoint = (point / 1000) % 60;
String maxMinPointStr = "";
String maxSecPointStr = "";

if (maxMinPoint < 10)
maxMinPointStr = "0" + maxMinPoint + ":";
else
maxMinPointStr = maxMinPoint + ":";

if (maxSecPoint < 10)
maxSecPointStr = "0" + maxSecPoint;
else
maxSecPointStr = String.valueOf(maxSecPoint);

mTvPlayMaxPoint.setText(maxMinPointStr + maxSecPointStr);
} catch (Exception e) {
Log.v("ProgressRecorder", "미디어 플레이어 Prepare Error ==========> " + e);
}

if (mPlayerState == PLAYING) {
mPlayProgressBar.setProgress(0);

try {
// SeekBar의 상태를 0.1초마다 체크
mProgressHandler2.sendEmptyMessageDelayed(0, 100);
mPlayer.start();
} catch (Exception e) {
Toast.makeText(this, "error : " + e.getMessage(), 0).show();
}
}
}

private void stopPlay() {
// 재생을 중지하고
mPlayer.stop();
mPlayer.release();
mPlayer = null;
mPlayProgressBar.setProgress(0);

// 즉시 SeekBar 메세지 핸들러를 호출한다.
mProgressHandler2.sendEmptyMessageDelayed(0, 0);
}

public void onCompletion(MediaPlayer mp) {
mPlayerState = PLAY_STOP; // 재생이 종료됨

// 재생이 종료되면 즉시 SeekBar 메세지 핸들러를 호출한다.
mProgressHandler2.sendEmptyMessageDelayed(0, 0);
}

private void updateUI() {
if (mRecState == REC_STOP) {
mBtnStartRec.setText("Rec");
mRecProgressBar.setProgress(0);
} else if (mRecState == RECORDING)
mBtnStartRec.setText("Stop");

if (mPlayerState == PLAY_STOP) {
mBtnStartPlay.setText("Play");
mPlayProgressBar.setProgress(0);
} else if (mPlayerState == PLAYING)
mBtnStartPlay.setText("Stop");
}
}
-------------------------------------------------------------------------------------------------------
public class SunUtil {
// 디렉토리를 만든다.
public static String makeDir(String dirName) {
String mRootPath = Environment.getExternalStorageDirectory()
.getAbsolutePath() + File.separator + dirName;

try {
File fRoot = new File(mRootPath);
if (fRoot.exists() == false) {
if (fRoot.mkdirs() == false) {
throw new Exception("");
}
}
} catch (Exception e) {
mRootPath = "-1";
}

return mRootPath + "/";
}
}
--------------------------------------------------------------------------------------------------------
-xml 소스
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <!-- progress bar -->

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@null"
        android:gravity="center_vertical|center_horizontal"
        android:orientation="vertical" >

        <SeekBar
            android:id="@+id/recProgressBar"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical|center_horizontal"
            android:max="60000"
            android:padding="10dp"
            android:progress="0" />

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@null"
            android:gravity="center_vertical"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/tvRecStartPoint"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_gravity="center_vertical|left"
                android:text="00:00"
                android:textColor="#FFFFFF"
                android:textSize="12sp" />

            <TextView
                android:id="@+id/tvRecMaxPoint"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_gravity="center_vertical|right"
                android:text="01:00"
                android:textColor="#FFFFFF"
                android:textSize="12sp" />
        </RelativeLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:gravity="center_vertical|center_horizontal"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btnStartRec"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Rec"
            android:textSize="14sp" />
    </LinearLayout>

    <!-- progress bar -->

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@null"
        android:gravity="center_vertical|center_horizontal"
        android:orientation="vertical" >

        <SeekBar
            android:id="@+id/playProgressBar"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical|center_horizontal"
            android:max="60000"
            android:padding="10dp"
            android:progress="0" />

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@null"
            android:gravity="center_vertical"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/tvPlayStartPoint"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_gravity="center_vertical|left"
                android:text="00:00"
                android:textColor="#FFFFFF"
                android:textSize="12sp" />

            <TextView
                android:id="@+id/tvPlayMaxPoint"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_gravity="center_vertical|right"
                android:text="01:00"
                android:textColor="#FFFFFF"
                android:textSize="12sp" />
        </RelativeLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:gravity="center_vertical|center_horizontal"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btnStartPlay"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Play"
            android:textSize="14sp" />
    </LinearLayout>

</LinearLayout> 
--------------------------------------------------------------------------------------------------------
- AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="Smarthangles.org"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".ProgressRecorder"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

</manifest>

- 실행 화면



- 출처
 http://jeehun.egloos.com/