版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
【移動(dòng)應(yīng)用開發(fā)技術(shù)】如何在Android中實(shí)現(xiàn)一個(gè)微信錄音功能
本文章向大家介紹如何在Android中實(shí)現(xiàn)一個(gè)微信錄音功能的基本知識(shí)點(diǎn)總結(jié)和需要注意事項(xiàng),具有一定的參考價(jià)值,需要的朋友可以參考一下。Android是一種基于Linux內(nèi)核的自由及開放源代碼的操作系統(tǒng),主要使用于移動(dòng)設(shè)備,如智能手機(jī)和平板電腦,由美國Google公司和開放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開發(fā)。使用方法:1.在xml文件中添加<.audiodemo.view.SoundTextView
android:id="@+id/record_audio"
android:text="按住開始錄音"
android:gravity="center"
android:background="@drawable/bg_round_black"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="40px"
android:padding="20px"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</.audiodemo.view.SoundTextView>2.別忘了申請錄音權(quán)限AndPermission.with(MainActivity.this)
.permission(Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE)
.onGranted(permissions
->
{
showSelect();
})
.onDenied(permissions
->
{
Toast.makeText(MainActivity.this,"請同意錄音權(quán)限",Toast.LENGTH_SHORT).show();
})
.start();
private
void
showSelect()
{
SoundTextView
recordAudio
=
findViewById(R.id.record_audio);
recordAudio.setOnRecordFinishedListener(new
SoundTextView.OnRecordFinishedListener()
{
@Override
public
void
newMessage(String
path,
int
duration)
{
int
index
=
path.lastIndexOf("/");
String
fileName
=
path.substring(index
+
1);
Log.e("錄音文件",
"path=:
"+path
);
}
});
}使用方法如上非常簡單:主要的類package
.audiodemo.view;
import
android.app.Activity;
import
android.app.Dialog;
import
android.content.Context;
import
android.os.Environment;
import
android.os.Handler;
import
android.os.Message;
import
android.util.AttributeSet;
import
android.util.Log;
import
android.view.MotionEvent;
import
android.widget.TextView;
import
android.widget.Toast;
import
androidx.appcompat.widget.AppCompatTextView;
import
java.io.File;
import
.audiodemo.R;
import
.audiodemo.audio.ProgressTextUtils;
import
.audiodemo.audio.RecordManager;
public
class
SoundTextView
extends
AppCompatTextView
{
private
Context
mContext;
private
Dialog
recordIndicator;
private
TextView
mVoiceTime;
private
File
file;
private
String
type
=
"1";//默認(rèn)開始錄音
type=2,錄音完畢
RecordManager
recordManager;
File
fileto;
int
level;
private
long
downT;
String
sountime;
public
SoundTextView(Context
context)
{
super(context);
init();
}
public
SoundTextView(Context
context,
AttributeSet
attrs,
int
defStyle)
{
super(context,
attrs,
defStyle);
this.mContext
=
context;
init();
}
public
SoundTextView(Context
context,
AttributeSet
attrs)
{
super(context,
attrs);
this.mContext
=
context;
init();
}
private
void
init()
{
recordIndicator
=
new
Dialog(getContext(),
R.style.jmui_record_voice_dialog);
recordIndicator.setContentView(R.layout.jmui_dialog_record_voice);
mVoiceTime
=
(TextView)
recordIndicator.findViewById(R.id.voice_time);
file
=
new
File(Environment.getExternalStorageDirectory()
+
"/recoder.amr");
fileto
=
new
File(Environment.getExternalStorageDirectory()
+
"/recoder.mp3");
recordManager
=
new
RecordManager(
(Activity)
mContext,
String.valueOf(file),
String.valueOf(fileto));
recordManager.setOnAudioStatusUpdateListener(new
RecordManager.OnAudioStatusUpdateListener()
{
@Override
public
void
onUpdate(double
db)
{
//得到分貝
if
(null
!=
recordIndicator)
{
level
=
(int)
db;
handler.sendEmptyMessage(0x111);
}
}
});
}
Handler
handler
=
new
Handler()
{
@Override
public
void
handleMessage(Message
msg)
{
super.handleMessage(msg);
switch
(msg.what)
{
case
0x111:
sountime
=
ProgressTextUtils.getSecsProgress(System.currentTimeMillis()
-
downT);
long
time
=
System.currentTimeMillis()
-
downT;
mVoiceTime.setText(ProgressTextUtils.getProgressText(time));
//判斷時(shí)間
judetime(Integer.parseInt(sountime));
break;
}
}
};
public
void
judetime(int
time)
{
if
(time
>
14)
{
//結(jié)束錄制
Toast.makeText(mContext,
"錄音不能超過十五秒",
Toast.LENGTH_SHORT).show();
recordManager.stop_mp3();
new
Thread()
{
@Override
public
void
run()
{
super.run();
recordManager.saveData();
finishRecord(fileto.getPath(),
sountime);
}
}.start();
recordIndicator.dismiss();
type
=
"2";
}
}
@Override
public
boolean
onTouchEvent(MotionEvent
event)
{
int
action
=
event.getAction();
switch
(action)
{
case
MotionEvent.ACTION_DOWN:
if
(type.equals("1"))
{
//開始發(fā)送時(shí)間
downT
=
System.currentTimeMillis();
recordManager.start_mp3();
recordIndicator.show();
}
else
{
Log.e("-log-",
"您已經(jīng)錄制完畢:
");
}
return
true;
case
MotionEvent.ACTION_UP:
if
(type.equals("1"))
{
try
{
if
(Integer.parseInt(sountime)
>
2)
{
recordManager.stop_mp3();
new
Thread()
{
@Override
public
void
run()
{
super.run();
recordManager.saveData();
finishRecord(fileto.getPath(),
sountime);
}
}.start();
if
(recordIndicator.isShowing())
{
recordIndicator.dismiss();
}
type
=
"2";
}
else
{
recordManager.stop_mp3();
if
(recordIndicator.isShowing())
{
recordIndicator.dismiss();
}
sountime
=
null;
Toast.makeText(mContext,
"錄音時(shí)間少于3秒,請重新錄制",
Toast.LENGTH_SHORT).show();
}
}
catch
(Exception
e)
{
recordManager.stop_mp3();
if
(recordIndicator.isShowing())
{
recordIndicator.dismiss();
}
sountime
=
null;
Toast.makeText(mContext,
"錄音時(shí)間少于3秒,請重新錄制",
Toast.LENGTH_SHORT).show();
}
}
break;
case
MotionEvent.ACTION_CANCEL:
if
(recordIndicator.isShowing())
{
recordIndicator.dismiss();
}
break;
}
return
super.onTouchEvent(event);
}
//錄音完畢加載
ListView
item
private
void
finishRecord(String
path,
String
time)
{
if
(onRecordFinishedListener
!=
null)
{
onRecordFinishedListener.newMessage(path,
Integer.parseInt(time));
type
=
"1";
}
//發(fā)送語音
//
Toasts.toast(getContext(),"您已經(jīng)錄完了一條語音"+myRecAudioFile);
}
private
OnRecordFinishedListener
onRecordFinishedListener;
public
void
setOnRecordFinishedListener(OnRecordFinishedListener
onRecordFinishedListener)
{
this.onRecordFinishedListener
=
onRecordFinishedListener;
}
public
interface
OnRecordFinishedListener
{
void
newMessage(String
path,
int
duration);
}
}主要的錄音管理類public
class
RecordManager
{
//錄制成MP3格式
/**構(gòu)造時(shí)候需要的Activity,主要用于獲取文件夾的路徑*/
private
Activity
activity;
/**文件代號(hào)*/
public
static
final
int
RAW
=
0X00000001;
public
static
final
int
MP3
=
0X00000002;
/**文件路徑*/
private
String
rawPath
=
null;
private
String
mp3Path
=
null;
/**采樣頻率*/
private
static
final
int
SAMPLE_RATE
=
11025;
/**錄音需要的一些變量*/
private
short[]
mBuffer;
private
AudioRecord
mRecorder;
/**錄音狀態(tài)*/
private
boolean
isRecording
=
false;
/**是否轉(zhuǎn)換ok*/
private
boolean
convertOk
=
false;
public
RecordManager(Activity
activity,
String
rawPath,
String
mp3Path)
{
this.activity
=
activity;
this.rawPath
=
rawPath;
this.mp3Path
=
mp3Path;
}
/**開始錄音*/
public
boolean
start_mp3()
{
//
如果正在錄音,則返回
if
(isRecording)
{
return
isRecording;
}
//
初始化
if
(mRecorder
==
null)
{
initRecorder();
}
getFilePath();
mRecorder.startRecording();
startBufferedWrite(new
File(rawPath));
isRecording
=
true;
return
isRecording;
}
/**停止錄音,并且轉(zhuǎn)換文件,這很可能是個(gè)耗時(shí)操作,建議在后臺(tái)中做*/
public
boolean
stop_mp3()
{
if
(!isRecording)
{
return
isRecording;
}
//
停止
mRecorder.stop();
isRecording
=
false;
//TODO
//
開始轉(zhuǎn)換(轉(zhuǎn)換代碼就這兩句)
//
FLameUtils
lameUtils
=
new
FLameUtils(1,
SAMPLE_RATE,
96);
//
convertOk
=
lameUtils.raw2mp3(rawPath,
mp3Path);
//
return
isRecording
^
convertOk;//
convertOk==true,return
true
return
isRecording;
}
public
void
saveData(){
FLameUtils
lameUtils
=
new
FLameUtils(1,
SAMPLE_RATE,
96);
convertOk
=
lameUtils.raw2mp3(rawPath,
mp3Path);
}
/**獲取文件的路徑*/
public
String
getFilePath(int
fileAlias)
{
if
(fileAlias
==
RAW)
{
return
rawPath;
}
else
if
(fileAlias
==
MP3)
{
return
mp3Path;
}
else
return
null;
}
/**清理文件*/
public
void
cleanFile(int
cleanFlag)
{
File
f
=
null;
try
{
switch
(cleanFlag)
{
case
MP3:
f
=
new
File(mp3Path);
if
(f.exists())
f.delete();
break;
case
RAW:
f
=
new
File(rawPath);
if
(f.exists())
f.delete();
break;
case
RAW
|
MP3:
f
=
new
File(rawPath);
if
(f.exists())
f.delete();
f
=
new
File(mp3Path);
if
(f.exists())
f.delete();
break;
}
f
=
null;
}
catch
(Exception
e)
{
e.printStackTrace();
}
}
/**關(guān)閉,可以先調(diào)用cleanFile來清理文件*/
public
void
close()
{
if
(mRecorder
!=
null)
mRecorder.release();
activity
=
null;
}
/**初始化*/
private
void
initRecorder()
{
int
bufferSize
=
AudioRecord.getMinBufferSize(SAMPLE_RATE,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
mBuffer
=
new
short[bufferSize];
mRecorder
=
new
AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize);
}
/**設(shè)置路徑,第一個(gè)為raw文件,第二個(gè)為mp3文件*/
private
void
getFilePath()
{
try
{
String
folder
=
"audio_recorder_2_mp3";
String
fileName
=
String.valueOf(System.currentTimeMillis());
if
(rawPath
==
null)
{
File
raw
=
new
File(activity.getDir(folder,
activity.MODE_PRIVATE),
fileName
+
".raw");
raw.createNewFile();
rawPath
=
raw.getAbsolutePath();
raw
=
null;
}
if
(mp3Path
==
null)
{
File
mp3
=
new
File(activity.getDir(folder,
activity.MODE_PRIVATE),
fileName
+
".mp3");
mp3.createNewFile();
mp3Path
=
mp3.getAbsolutePath();
mp3
=
null;
}
Log.d("rawPath",
rawPath);
Log.d("mp3Path",
mp3Path);
}
catch
(Exception
e)
{
e.printStackTrace();
}
}
/**執(zhí)行cmd命令,并等待結(jié)果*/
private
boolean
runCommand(String
command)
{
boolean
ret
=
false;
Process
process
=
null;
try
{
process
=
Runtime.getRuntime().exec(command);
process.waitFor();
ret
=
true;
}
catch
(Exception
e)
{
e.printStackTrace();
}
finally
{
try
{
process.destroy();
}
catch
(Exception
e)
{
e.printStackTrace();
}
}
return
ret;
}
/**寫入到raw文件*/
private
void
startBufferedWrite(final
File
file)
{
Object
mLock
=
new
Object();
new
Thread(new
Runnable()
{
@Override
public
void
run()
{
DataOutputStream
output
=
null;
try
{
output
=
new
DataOutputStream(new
BufferedOutputStream(
new
FileOutputStream(file)));
while
(isRecording)
{//開始錄制
int
readSize
=
mRecorder.read(mBuffer,
0,
mBuffer.length);//是實(shí)際讀取的數(shù)據(jù)長度
for
(int
i
=
0;
i
<
readSize;
i++)
{
output.writeShort(mBuffer[i]);
}
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年陜西國防工業(yè)職業(yè)技術(shù)學(xué)院單招綜合素質(zhì)筆試模擬試題含詳細(xì)答案解析
- 2026年青海交通職業(yè)技術(shù)學(xué)院單招職業(yè)技能考試備考題庫含詳細(xì)答案解析
- 2026年安徽揚(yáng)子職業(yè)技術(shù)學(xué)院單招職業(yè)技能考試備考試題含詳細(xì)答案解析
- 2026廣東湛江市旅游投資集團(tuán)有限公司招聘1人考試重點(diǎn)題庫及答案解析
- 2026年湘潭醫(yī)衛(wèi)職業(yè)技術(shù)學(xué)院單招綜合素質(zhì)考試備考題庫含詳細(xì)答案解析
- 2026年吐魯番職業(yè)技術(shù)學(xué)院單招綜合素質(zhì)考試參考題庫含詳細(xì)答案解析
- 2026年滁州城市職業(yè)學(xué)院單招綜合素質(zhì)筆試備考試題含詳細(xì)答案解析
- 2026年西南財(cái)經(jīng)大學(xué)天府學(xué)院單招綜合素質(zhì)筆試備考題庫含詳細(xì)答案解析
- 2026年贛州職業(yè)技術(shù)學(xué)院高職單招職業(yè)適應(yīng)性測試備考題庫及答案詳細(xì)解析
- 2026年河北石油職業(yè)技術(shù)大學(xué)單招綜合素質(zhì)筆試備考試題含詳細(xì)答案解析
- 2025年中國抑郁障礙防治指南
- 2024年輕工行業(yè)經(jīng)濟(jì)運(yùn)行報(bào)告
- 電解銅銷售合同范本
- 住院患者節(jié)前安全宣教
- FGR的基因檢測策略與臨床解讀
- 建筑施工工地安全隱患排查清單
- 2026春人教版英語八下單詞表(先鳥版)
- 電力工程安全培訓(xùn)課件
- 中糧貿(mào)易錄用通知書
- 高二半期考試物理考題及答案
- 2025年食品安全檢測服務(wù)協(xié)議書標(biāo)準(zhǔn)版(含檢測項(xiàng)目+報(bào)告時(shí)效+填寫指導(dǎo))
評論
0/150
提交評論