'android audio'에 해당되는 글 1건

  1. 2013.01.28 Android - ProgressBar를 이용한 Recorder 만들기 (녹음기) (2)

Android - ProgressBar를 이용한 Recorder 만들기 (녹음기)

Android 2013.01.28 17:47

 

안녕하세요 오랜만에 글을 쓰게되었습니다. 만 1년이 지나갔나요?

개발자로 일을 하다가 잠시 다른일에 허덕이다가 지금은 백수.......... 현재 다시 공부중입니다 하하 ㅡㅡ;;

 

개발쪽일은 취미로 할까 생각해요 ㅎ 저녁에 조금씩 java쪽을 공부하고 있네요 ㅎ

이제는 Android 뿐만 아니라 Web도 다루게 될 것 같습니다 !

 

다들 화이팅 하십시요 !

 

 

오늘은 프로그래스바를 이용한 녹음기를 만들어보겠습니다.

기초적인 것이구요 . 이것을 토대로 채팅에 필요한 음성메세지 구현을 했었습니다.

 

이 프로젝트를 응용하여 적용시키는 것은 여러분의 몫입니다 . 기초적인 프로그래스 이용 녹음기 설명 시작하겠습니다.

 

대부분 필요한 내용은 주석 처리로 설명을 대신하였구요 살펴볼 내용만 몇가지 집고 소스 첨부하겠습니다.

 

 

녹음기 말 그대로 말을 녹음한뒤에 다시 듣는 것이지요.

이것을 프로그래스바를 이용하여서 진행하는 정도와 듣기 시 내가 얼마나 들었는지를 표시하여 사용의 편함을 추가한 것이지요.

 

UI 변경을 위해서 Handler를 이용했습니다.

Handler가 아니면 동시에 UI를 변경할 수 없기에 백그라운드에서 돌리기 위함입니다. 하지만 다른 방법도 있겠지요?

 


 

mRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);

 

이부분 setOutputFormat은 파일이 생성될 때 포맷을 정해주는 역활을 합니다. 이것을 바꿔줌으로써 아이폰과 동시에 쓸 수 있게 포맷을 바꿔주던가 자신이 원하는 포맷으로 파일을 생성할 수 있습니다.

 

mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);

 

파일의 인코더를 어떤식으로 해줄 것인가를 정해주는 것입니다. DEFAULT 무난하게 !


mRecorder.setOutputFile(mFilePath + mFileName);

 

마지막으로 녹음이 되어지는 파일을 어떠한경로에 생성을 하느냐에 대한 문장이지요.

변수로 설정하였기에 mFilePath 파일 경로 / mFileName 파일 명 이 되겠습니다. 직접 적어주셔도되고 저처럼 한번 선언한 수 가져다가 쓰셔도 좋습니다. 후자가 편합니다.

 

 

그리구 중요한 한가지 uses-permission 부분입니다.

이 프로젝트에서 안드로이드폰에서 저장소와 오디오 부분을 사용하기 때문에 그 부분을 사용하기 위한 허락?을 받아야죠?

Permission에서 두가지를 설정해 주세요.

먼저 오디오를 사용하기 위해 android.permission.RECORD_AUDIO

저장소를 사용하기 위해 android.permission.WRITE_EXTERNAL_STORAGE 두가지를 설정하셔야 합니다.

 

 

제가 생각했던 부분은 이정도 이구요. 빠뜨린 부분이 있다면 주석으로 처리해두셔서 보기 어렵지 않으실거라 생각합니다.

 

 

앗! 그리고 프로젝트 생성이 바뀌었더군요 ㅎ

알아서 잘들 하실거라 생각합니다. 제가 설정한 몇가지만 적겠습니다.

 

 

 

프로젝트 생성

 

패키지 : com.jsh.examrecorder

클래스명 : ProgressRecorder

XML파일명 : main

타겟은 : 2.2 ~ 4.2

 

 

ProgressRecorder.java 

ProgressRecorder.txt

 

package com.example.com.jsh.examrecorder;


import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

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, mBtnStopPlay;
  private String mFilePath, mFileName = null;
  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 < 20000)
      {
        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);
        }
      }
      catch (IllegalStateException e)
      {}
      catch (Exception e)
      {}
    }
  };
 
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
   
    // 미디어 레코더 저장할 파일 생성
    mFilePath = "/sdcard/Download/";
   
    // 파일명을 년도월일시간분초 로 생성 겹치는 상황 없애기
    SimpleDateFormat timeStampFormat = new SimpleDateFormat(
"yyyyMMddHHmmss");
   
    // 파일명 위에서 정한 파일명을 WJ 폴더에 저장
    mFileName = "/WJ"
+ timeStampFormat.format(new Date()).toString()
+ "Rec.mp4";
   
    mBtnStartRec = (Button) findViewById(R.id.btnStartRec);
    mBtnStartPlay = (Button) findViewById(R.id.btnStartPlay);
    mBtnStopPlay = (Button) findViewById(R.id.btnStopPlay);
    mRecProgressBar = (SeekBar) findViewById(R.id.recProgressBar);
    mPlayProgressBar = (SeekBar) findViewById(R.id.playProgressBar);
    mTvPlayMaxPoint = (TextView) findViewById(R.id.tvPlayMaxPoint);
   
    mBtnStartRec.setOnClickListener(this);
    mBtnStartPlay.setOnClickListener(this);
    mBtnStopPlay.setOnClickListener(this);
  }
 
  // 버튼의 OnClick 이벤트 리스너
  public void onClick(View v)
  {
    switch(v.getId())
    {
      case R.id.btnStartRec:
        mBtnStartRecOnClick();
        break;
      case R.id.btnStartPlay:
        mBtnStartPlayOnClick();
        break;
      case R.id.btnStopPlay:
        mBtnStopPlayOnClick();
        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;
      initMediaPlayer();
      startPlay();
      updateUI();
    }
    else if (mPlayerState == PLAYING)
    {
      mPlayerState = PLAY_PAUSE;
      pausePlay();
      updateUI();
    }
    else if (mPlayerState == PLAY_PAUSE)
    {
      mPlayerState = PLAYING;
      startPlay();
      updateUI();
    }
  }
  private void mBtnStopPlayOnClick()
  {
    if (mPlayerState == PLAYING || mPlayerState == PLAY_PAUSE)
    {
      mPlayerState = PLAY_STOP;
      stopPlay();
      releaseMediaPlayer();
      updateUI();     
    }
  }
 
  private void initMediaPlayer()
  {
    // 미디어 플레이어 생성
    if (mPlayer == null)
      mPlayer = new MediaPlayer();
    else
      mPlayer.reset();
   
    mPlayer.setOnCompletionListener(this);
    String fullFilePath = mFilePath + mFileName;
   
    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);
     
      mPlayProgressBar.setProgress(0);
    }
    catch(Exception e)
    {
      Log.v("ProgressRecorder", "미디어 플레이어 Prepare Error ==========> " + e);
    }
  }
 
  // 재생 시작
  private void startPlay()
  {
    Log.v("ProgressRecorder", "startPlay().....");
   
    try
    {
      mPlayer.start();
     
      // SeekBar의 상태를 0.1초마다 체크     
      mProgressHandler2.sendEmptyMessageDelayed(0, 100);
    }
    catch (Exception e)
    {
      e.printStackTrace();
      Toast.makeText(this, "error : " + e.getMessage(), 0).show();
    }
  }
 
  private void pausePlay()
  {
    Log.v("ProgressRecorder", "pausePlay().....");
   
    // 재생을 일시 정지하고
    mPlayer.pause();
   
    // 재생이 일시정지되면 즉시 SeekBar 메세지 핸들러를 호출한다.
    mProgressHandler2.sendEmptyMessageDelayed(0, 0);
  }
 
  private void stopPlay()
  {
    Log.v("ProgressRecorder", "stopPlay().....");
   
    // 재생을 중지하고
    mPlayer.stop();
   
    // 즉시 SeekBar 메세지 핸들러를 호출한다.
    mProgressHandler2.sendEmptyMessageDelayed(0, 0);
  }
 
  private void releaseMediaPlayer()
  {
    Log.v("ProgressRecorder", "releaseMediaPlayer().....");
    mPlayer.release();
    mPlayer = null;
    mPlayProgressBar.setProgress(0);
  }
 
  public void onCompletion(MediaPlayer mp)
  {
    mPlayerState = PLAY_STOP; // 재생이 종료됨

    // 재생이 종료되면 즉시 SeekBar 메세지 핸들러를 호출한다.
    mProgressHandler2.sendEmptyMessageDelayed(0, 0);
   
    updateUI();
  }
 
  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("Pause");
    else if (mPlayerState == PLAY_PAUSE)
      mBtnStartPlay.setText("Start");
  }
}

 

main.xml

 

 

 

 

 

main.txt

 

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#06000b" >
<!-- progress bar -->
<LinearLayout
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:gravity="center_vertical|center_horizontal"
  android:background="@null">
  <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:gravity="center_vertical"
      android:orientation="vertical"
      android:background="@null">

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

<LinearLayout
  android:orientation="horizontal"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:gravity="center_vertical|center_horizontal"
  android:background="@null">
  <Button
      android:id="@+id/btnStartRec"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:textSize="14sp"
      android:text="Rec" />
</LinearLayout>


<!-- progress bar -->
<LinearLayout
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:gravity="center_vertical|center_horizontal"
  android:background="@null">
  <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:gravity="center_vertical"
      android:orientation="vertical"
      android:background="@null">

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

<LinearLayout
  android:orientation="horizontal"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:gravity="center_vertical|center_horizontal"
  android:background="@null">
  <Button
      android:id="@+id/btnStartPlay"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:textSize="14sp"
      android:text="Play" />
  <Button
      android:id="@+id/btnStopPlay"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:textSize="14sp"
      android:text="Stop" />
</LinearLayout>
</LinearLayout>

 

 

실행결과

 

 

 

 

 

 

 

 

 

 

 

실행결과 화면이구요.

제가 개발 했을때 보다 환경이 바뀌었네요 ㅎㅎ

소리는 직접 하셔서 들어보셔요 !

문의는 댓글로 부탁드립니다.

저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback 0 : Comments 2
  1. HJ_Reden 2015.02.24 13:45 신고 Modify/Delete Reply

    안녕하세요~~ 코드 감사합니다!!
    궁금한게 있는데요ㅠㅠ
    녹음을 시작했는데 00:00은 왜 안올라가는걸까요?

  2. HJ_Reden 2015.02.24 13:45 신고 Modify/Delete Reply

    안녕하세요~~ 코드 감사합니다!!
    궁금한게 있는데요ㅠㅠ
    녹음을 시작했는데 00:00은 왜 안올라가는걸까요?

Write a comment