Android實(shí)現(xiàn)多媒體錄音筆
記事本涉及到的僅僅是對string 的存儲,而且在讀取上并不存在什么難點(diǎn),直接用textview顯示便可以了。需要做的主要是使用SQLite對數(shù)據(jù)進(jìn)行一個(gè)整理。
而錄音筆需要考慮的就相對較多了:比如錄音時(shí)中斷,錄音時(shí)用戶點(diǎn)擊播放按鈕;未錄音,用戶點(diǎn)擊停止按鈕;在錄音或者播放時(shí)關(guān)閉activity;listview的item中需要為button設(shè)置不同的點(diǎn)擊效果等等。
為了便于新手學(xué)習(xí),在此還是羅列一下涉及的主要知識點(diǎn):
- 1、Baseadapter
- 2、JAVA的file
- 3、MediaRecorder
- 4、較多的AlertDialog
- 5、MediaPlayer
遇到的問題:
在listview item中的button控件可以獲得焦點(diǎn)時(shí),直接為listview設(shè)置item長按事件的監(jiān)聽。出現(xiàn)了listview的item長按事件無效的情況。
解決方法:
直接在Baseadapter中對該item的布局進(jìn)行長按事件的監(jiān)聽(在筆者demo中是linearlayout),也就是說對item中button的父布局進(jìn)行長按事件的監(jiān)聽。
效果:
MainActivity:
package com.example.recorder; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.DialogInterface; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import java.io.File; import java.io.IOException; public class MainActivity extends Activity implements OnClickListener { private Button start; private Button stop; private ListView listView; ShowRecorderAdpter showRecord; // 錄音文件播放 // 錄音 // 音頻文件保存地址 private MediaPlayer myPlayer; private MediaRecorder myRecorder = null; private String path; private File saveFilePath; // 所錄音的文件名 String[] listFile = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化控件 InitView(); } private void InitView() { start = (Button) findViewById(R.id.start); stop = (Button) findViewById(R.id.stop); listView = (ListView) findViewById(R.id.list); myPlayer = new MediaPlayer(); showRecord = new ShowRecorderAdpter(); //如果手機(jī)有sd卡 if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { try { path = Environment.getExternalStorageDirectory() .getCanonicalPath().toString() + "/MyRecorders"; File files = new File(path); if (!files.exists()) { //如果有沒有文件夾就創(chuàng)建文件夾 files.mkdir(); } listFile = files.list(); } catch (IOException e) { e.printStackTrace(); } } start.setOnClickListener(this); stop.setOnClickListener(this); listView.setAdapter(showRecord); } //由于在item中涉及到了控件的點(diǎn)擊效果,所以采用BaseAdapter class ShowRecorderAdpter extends BaseAdapter { @Override public int getCount() { return listFile.length; } @Override public Object getItem(int arg0) { return arg0; } @Override public long getItemId(int arg0) { return arg0; } @Override public View getView(final int postion, View arg1, ViewGroup arg2) { View views = LayoutInflater.from(MainActivity.this).inflate( R.layout.list_item, null); LinearLayout parent = (LinearLayout) views.findViewById(R.id.list_parent); TextView filename = (TextView) views.findViewById(R.id.show_file_name); Button plays = (Button) views.findViewById(R.id.bt_list_play); Button stop = (Button) views.findViewById(R.id.bt_list_stop); //在textview中顯示的時(shí)候把“.amr”去掉 filename.setText(listFile[postion].substring(0, listFile[postion].length() - 4)); parent.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { AlertDialog aler = new AlertDialog.Builder(MainActivity.this) .setTitle("確定刪除該錄音?") .setPositiveButton("確定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog , int which) { File file = new File(path + "/" + listFile[postion]); file.delete(); // 在刪除文件后刷新文件名列表 File files = new File(path); listFile = files.list(); // 當(dāng)文件被刪除刷新ListView showRecord.notifyDataSetChanged(); } }) .setNegativeButton("取消", null) .create(); //設(shè)置不允許點(diǎn)擊提示框之外的區(qū)域 aler.setCanceledOnTouchOutside(false); aler.show(); return false; } }); // 播放錄音 plays.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { //確認(rèn)不是在錄音的過程中播放 if (myRecorder == null) { try { myPlayer.reset(); myPlayer.setDataSource(path + "/" + listFile[postion]); if (!myPlayer.isPlaying()) { myPlayer.prepare(); myPlayer.start(); } else { myPlayer.pause(); } } catch (IOException e) { e.printStackTrace(); } } else { Toast.makeText(MainActivity.this, "請不要再錄音的過程中播放!", Toast.LENGTH_SHORT).show(); } } }); // 停止播放 stop.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if (myRecorder == null && myPlayer.isPlaying()) { myPlayer.stop(); } } }); return views; } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.start: final EditText filename = new EditText(this); AlertDialog aler = new Builder(this) .setTitle("請輸入要保存的文件名") .setView(filename) .setPositiveButton("確定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String text = filename.getText().toString(); //如果文件名為空則跳出提示信息 if (text.equals("")) { Toast.makeText(MainActivity.this, "請不要輸入空的文件名!", Toast.LENGTH_SHORT).show(); } else { //開啟錄音 RecorderStart(text); start.setText("正在錄音中。。"); start.setEnabled(false); stop.setEnabled(true); // 在增添文件后刷新文件名列表 File files = new File(path); listFile = files.list(); // 當(dāng)文件增加刷新ListView showRecord.notifyDataSetChanged(); } } }) .setNegativeButton("取消",null) .create(); //設(shè)置不允許點(diǎn)擊提示框之外的區(qū)域 aler.setCanceledOnTouchOutside(false); aler.show(); break; case R.id.stop: myRecorder.stop(); myRecorder.release(); myRecorder = null; // 判斷是否保存 如果不保存則刪除 aler = new AlertDialog.Builder(this) .setTitle("是否保存該錄音") .setPositiveButton("確定", null) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { saveFilePath.delete(); // 在刪除文件后刷新文件名列表 File files = new File(path); listFile = files.list(); // 當(dāng)文件被刪除刷新ListView showRecord.notifyDataSetChanged(); } }).create(); //設(shè)置不允許點(diǎn)擊提示框之外的區(qū)域 aler.setCanceledOnTouchOutside(false); aler.show(); start.setText("錄音"); start.setEnabled(true); stop.setEnabled(false); default: break; } } private void RecorderStart(String text) { try { myRecorder = new MediaRecorder(); // 從麥克風(fēng)源進(jìn)行錄音 myRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); // 設(shè)置輸出格式 myRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); // 設(shè)置編碼格式 myRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); String paths = path + "/" + text + ".amr"; saveFilePath = new File(paths); myRecorder.setOutputFile(saveFilePath.getAbsolutePath()); myRecorder.prepare(); // 開始錄音 myRecorder.start(); } catch (Exception e) { e.printStackTrace(); } } @Override protected void onDestroy() { super.onDestroy(); // 如果myPlayer正在播放,那么就停止播放,并且釋放資源 if (myPlayer.isPlaying()) { myPlayer.stop(); myPlayer.release(); } //如果myRecorder有內(nèi)容(代表正在錄音),那么就直接釋放資源 if(myRecorder!=null) { myRecorder.release(); myPlayer.release(); } } }
activity_main:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#000" android:padding="13dp" android:text="語音筆" android:textColor="#fff" android:textSize="22sp" android:textStyle="bold" /> <ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:padding="10dp" ></ListView> <LinearLayout android:id="@+id/li1" android:padding="10dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/start" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="20sp" android:text="開始錄音" /> <Button android:id="@+id/stop" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:enabled="false" android:textSize="20sp" android:text="停止錄音" /> </LinearLayout> </LinearLayout>
list_item:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" android:id="@+id/list_parent" android:orientation="horizontal"> <TextView android:id="@+id/show_file_name" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="文件名" android:textColor="#000" android:textSize="20sp" /> <Button android:id="@+id/bt_list_play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:text="播放" /> <Button android:id="@+id/bt_list_stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:text="停止" /> </LinearLayout>
以上就是本文的全部內(nèi)容,希望對大家實(shí)現(xiàn)Android軟件編程有所幫助。
- Android音頻錄制MediaRecorder之簡易的錄音軟件實(shí)現(xiàn)代碼
- Android簡單的利用MediaRecorder進(jìn)行錄音的實(shí)例代碼
- Android錄音應(yīng)用實(shí)例教程
- android編程實(shí)現(xiàn)電話錄音的方法
- Android 實(shí)現(xiàn)電話來去自動(dòng)錄音的功能
- Android編程開發(fā)錄音和播放錄音簡單示例
- Android中簡單調(diào)用圖片、視頻、音頻、錄音和拍照的方法
- Android錄音播放管理工具
- android 通過MediaRecorder實(shí)現(xiàn)簡單的錄音示例
- 利用libmp3lame實(shí)現(xiàn)在Android上錄音MP3文件示例
相關(guān)文章
3種Android隱藏頂部狀態(tài)欄及標(biāo)題欄的方法
這篇文章主要為大家詳細(xì)介紹了3種Android隱藏頂部狀態(tài)欄及標(biāo)題欄的方法,還涉及一種隱藏Android 4.0平板底部狀態(tài)欄的方法,感興趣的小伙伴們可以參考一下2016-02-02Android原生態(tài)實(shí)現(xiàn)分享轉(zhuǎn)發(fā)功能實(shí)例
大家好,本篇文章主要講的是Android原生態(tài)實(shí)現(xiàn)分享轉(zhuǎn)發(fā)功能實(shí)例,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下2021-12-12Android SQLite數(shù)據(jù)庫中的表詳解
這篇文章主要介紹了Android SQLite數(shù)據(jù)庫中的表詳解的相關(guān)資料,這里附有實(shí)例代碼,需要的朋友可以參考下2017-01-01Android編程實(shí)現(xiàn)通話錄音功能的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)通話錄音功能的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android廣播接收機(jī)制實(shí)現(xiàn)錄音功能的操作技巧,需要的朋友可以參考下2017-06-06Android style的繼承方式 點(diǎn)(.)和parent詳解及實(shí)例
這篇文章主要介紹了Android style的繼承方式 點(diǎn)(.)和parent詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02Android 實(shí)現(xiàn)切圓圖作為頭像使用實(shí)例
這篇文章主要介紹了Android 實(shí)現(xiàn)切圓圖作為頭像使用實(shí)例的相關(guān)資料,需要的朋友可以參考下2016-12-12