Android 錄音與播放功能的簡單實例
Android 錄音與播放功能的簡單實例
最近在研究Android中一些常用的功能,像地圖、拍照、錄音和播放的實現(xiàn)等等,還有一些側(cè)滑、動畫等是如何實現(xiàn)的。
今天就把錄音和播放的實現(xiàn)分享一下,錄音和播放比較簡單,利用android內(nèi)部的類即可實現(xiàn)。
1、先看下運行后的界面:
以下三張圖分別是進(jìn)入、錄音、播放時的。
2、Layout布局文件
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:background="@drawable/switcherbar_bg" android:gravity="center" android:text="@string/audio_record_title" android:textColor="#ffffff" android:textSize="16sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:orientation="vertical" android:paddingLeft="10dip" android:paddingRight="10dip" > <TextView android:id="@+id/audio_record_time" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="00:00" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dip" android:orientation="horizontal" > <Button android:id="@+id/audio_record_start" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/searchbtn_normal" android:text="開始錄音" android:textSize="14sp" /> <Button android:id="@+id/audio_record_stop" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_marginLeft="5dip" android:layout_weight="1" android:background="@drawable/searchbtn_bg" android:text="結(jié)束錄音" android:textSize="14sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dip" android:orientation="horizontal" > <Button android:id="@+id/audio_record_play" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/searchbtn_normal" android:text="播放錄音" android:textSize="14sp" /> <Button android:id="@+id/audio_record_select" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_marginLeft="5dip" android:layout_weight="1" android:background="@drawable/searchbtn_bg" android:text="確定選擇" android:textSize="14sp" /> </LinearLayout> </LinearLayout> </RelativeLayout>
3 Activity類
錄音涉及到二個Activity,第一個Activity比較簡單,我這里大概說下,其實就是有個按鈕,點擊后轉(zhuǎn)移第二個Activity,錄音返回后,在第一個Activity中獲取錄音的文件名、時長等。
第一個Activity部分代碼:
// 錄音事件 ksly_btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MaintainVisitEditActivity.this, AudioRecordActivity.class); intent.setAction(Intent.ACTION_VIEW); intent.putExtra("duration", entity.getVoiceDuration()); intent.putExtra("fileName", entity.getVoiceRecord()); startActivityForResult(intent, VOICE_RECODE); } }); @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == VOICE_RECODE && resultCode == AudioRecordActivity.SUCCESS) { entity.setVoiceDuration(data.getLongExtra("duration", 0));// 時長 entity.setVoiceRecord(data.getStringExtra("fileName"));// 文件名(絕對路徑) ksly_time.setText(DateTimeUtils.formatToMillisecond(entity.getVoiceDuration())); } }
第二個Activity代碼:
這里要注意一下,就是需要捕獲返回鍵,處理一下,就是點擊返回鍵時,也返回個狀態(tài)碼,以表示沒有錄音成功。
package com.whowii.ct.cm.activity; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.content.Intent; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.whowii.ct.cm.R; import com.whowii.ct.cm.command.QueryParams; import com.whowii.ct.cm.utils.DateTimeUtils; import com.whowii.ct.cm.utils.SDCardUtils; /** * 錄制音頻 * * @author Administrator * */ public class AudioRecordActivity extends Activity { private TextView audio_record_time; private Button audio_record_start, audio_record_stop, audio_record_play, audio_record_select; private MediaRecorder mediaRecorder; private final String TAG = AudioRecordActivity.class.getSimpleName(); private boolean isIdle = true;// 當(dāng)前是否空閑,false:表示正在錄音 private long startTime = 0, stopTime = 0, duration = 0;// 開始時間、結(jié)束時間、錄音時長 private String fileName = null;// 存儲錄音文件的路徑 private Timer timer = null;// Timer計時器 public static final int SUCCESS = 1;// 錄制成功; public static final int FAILURE = 0;// 錄制失敗 private MediaPlayer mediaPlayer; private TimerTask task = new TimerTask() { final Handler handler = new Handler() { public void handleMessage(Message message) { Bundle data = message.getData(); audio_record_time.setText(DateTimeUtils.formatToMillisecond(data.getLong("time"))); } }; public void run() { Message message = new Message(); long t = System.currentTimeMillis(); Bundle data = new Bundle(); data.putLong("time", t - startTime); message.setData(data); handler.sendMessage(message); } }; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); // 設(shè)置無標(biāo)題欄 setContentView(R.layout.audio_record); mediaPlayer = new MediaPlayer(); initControl(); setListener(); timer = new Timer(true); fileName = getIntent().getStringExtra("fileName"); duration = getIntent().getLongExtra("duration", 0); } private void initControl() { audio_record_time = (TextView) findViewById(R.id.audio_record_time); audio_record_start = (Button) findViewById(R.id.audio_record_start); audio_record_stop = (Button) findViewById(R.id.audio_record_stop); audio_record_play = (Button) findViewById(R.id.audio_record_play); audio_record_select = (Button) findViewById(R.id.audio_record_select); } private void setListener() { // 播放完成事件 mediaPlayer.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { isIdle = true; audio_record_play.setText("播放錄音"); audio_record_play.setBackgroundResource(R.drawable.searchinput_bg); } }); // 開始錄音 audio_record_start.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (!isIdle) { return; } if (!SDCardUtils.sdCardExists()) { Toast.makeText(AudioRecordActivity.this, "缺少SD卡,請先插入后再操作!", Toast.LENGTH_LONG).show(); return; } audio_record_start.setText("開始錄音"); audio_record_start.setEnabled(true); duration = 0; startTime = System.currentTimeMillis(); fileName = QueryParams.CACHE_AUDIO_PATH; fileName += new SimpleDateFormat("yyyyMMdd_hhmmss").format(new Date(startTime)) + ".amr"; File file = new File(fileName); mediaRecorder = new MediaRecorder(); mediaRecorder.setOutputFile(file.getAbsolutePath()); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); try { mediaRecorder.prepare(); mediaRecorder.start(); isIdle = false; audio_record_start.setBackgroundResource(R.drawable.searchbtn_pressed); timer.schedule(task, 0, 100); } catch (IOException e) { startTime = 0; Log.e(TAG, e.toString()); Toast.makeText(AudioRecordActivity.this, "錄制時發(fā)生異常!", Toast.LENGTH_LONG).show(); } } }); // 結(jié)束錄音 audio_record_stop.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mediaRecorder != null) { stopTime = System.currentTimeMillis(); duration = stopTime - startTime; timer.cancel(); mediaRecorder.stop(); mediaRecorder.release(); mediaRecorder = null; audio_record_start.setBackgroundResource(R.drawable.searchbtn_normal); isIdle = true; } } }); // 播放錄音 audio_record_play.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (!isIdle) { return; } if (audio_record_play.getText().equals("播放錄音")) { if (fileName == null || fileName.equals("") || duration == 0) { Toast.makeText(AudioRecordActivity.this, "沒有錄音文件!", Toast.LENGTH_LONG).show(); return; } try { mediaPlayer.reset(); mediaPlayer.setDataSource(fileName); mediaPlayer.prepare(); mediaPlayer.start(); isIdle = false; audio_record_play.setText("終止播放"); audio_record_play.setBackgroundResource(R.drawable.searchbtn_pressed); } catch (Exception e) { e.printStackTrace(); Toast.makeText(AudioRecordActivity.this, "播放錄音時遇到錯誤!", Toast.LENGTH_LONG).show(); } } else { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.stop(); isIdle = true; } audio_record_play.setText("播放錄音"); audio_record_play.setBackgroundResource(R.drawable.searchinput_bg); } } }); // 確認(rèn)選擇 audio_record_select.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (fileName == null || fileName.equals("") || duration == 0) { Toast.makeText(AudioRecordActivity.this, "沒有錄音文件!", Toast.LENGTH_LONG).show(); return; } Intent intent = new Intent(); intent.putExtra("fileName", fileName); intent.putExtra("duration", duration); setResult(SUCCESS, intent);// 返回成功標(biāo)識 isIdle = true; if (mediaPlayer != null) { if (mediaPlayer.isPlaying()) { mediaPlayer.stop(); } mediaPlayer = null; } finish();// 結(jié)束當(dāng)前的activity,等于點擊返回按鈕 } }); } // 捕獲返回鍵,關(guān)閉當(dāng)前頁面時返回失敗標(biāo)識 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { setResult(FAILURE); isIdle = true; if (mediaPlayer != null) { if (mediaPlayer.isPlaying()) { mediaPlayer.stop(); } mediaPlayer = null; } finish(); return true; } return super.onKeyDown(keyCode, event); } }
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
Kotlin協(xié)程flowOn與線程切換超詳細(xì)示例介紹
這篇文章主要介紹了Kotlin協(xié)程flowOn與線程切換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09Android進(jìn)階CoordinatorLayout協(xié)調(diào)者布局實現(xiàn)吸頂效果
這篇文章主要為大家介紹了Android進(jìn)階CoordinatorLayout協(xié)調(diào)者布局實現(xiàn)吸頂效果,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01Android UI實現(xiàn)SlidingMenu側(cè)滑菜單效果
這篇文章主要為大家詳細(xì)介紹了Android UI實現(xiàn)SlidingMenu側(cè)滑菜單效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12android notification 的總結(jié)分析
notification是一種出現(xiàn)在任務(wù)欄的提示,特別是在4.0以后notification改進(jìn)了不少,本文內(nèi)容都是基于4.0及4.1以后總結(jié)來的2013-05-05android實現(xiàn)主動連接和被動連接的藍(lán)牙聊天功能
這篇文章主要為大家詳細(xì)介紹了android實現(xiàn)主動連接和被動連接的藍(lán)牙聊天功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-06-06