Android实现多媒体录音笔
作者:lijiao 发布时间:2022-03-26 17:25:00
标签:Android,多媒体,录音笔
记事本涉及到的仅仅是对string 的存储,而且在读取上并不存在什么难点,直接用textview显示便可以了。需要做的主要是使用SQLite对数据进行一个整理。
而录音笔需要考虑的就相对较多了:比如录音时中断,录音时用户点击播放按钮;未录音,用户点击停止按钮;在录音或者播放时关闭activity;listview的item中需要为button设置不同的点击效果等等。
为了便于新手学习,在此还是罗列一下涉及的主要知识点:
1、Baseadapter
2、JAVA的file
3、MediaRecorder
4、较多的AlertDialog
5、MediaPlayer
遇到的问题:
在listview item中的button控件可以获得焦点时,直接为listview设置item长按事件的监听。出现了listview的item长按事件无效的情况。
解决方法:
直接在Baseadapter中对该item的布局进行长按事件的监听(在笔者demo中是linearlayout),也就是说对item中button的父布局进行长按事件的监听。
效果:
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();
//如果手机有sd卡
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
try {
path = Environment.getExternalStorageDirectory()
.getCanonicalPath().toString()
+ "/MyRecorders";
File files = new File(path);
if (!files.exists()) {
//如果有没有文件夹就创建文件夹
files.mkdir();
}
listFile = files.list();
} catch (IOException e) {
e.printStackTrace();
}
}
start.setOnClickListener(this);
stop.setOnClickListener(this);
listView.setAdapter(showRecord);
}
//由于在item中涉及到了控件的点击效果,所以采用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中显示的时候把“.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();
// 当文件被删除刷新ListView
showRecord.notifyDataSetChanged();
}
})
.setNegativeButton("取消", null)
.create();
//设置不允许点击提示框之外的区域
aler.setCanceledOnTouchOutside(false);
aler.show();
return false;
}
});
// 播放录音
plays.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
//确认不是在录音的过程中播放
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();
// 当文件增加刷新ListView
showRecord.notifyDataSetChanged();
}
}
})
.setNegativeButton("取消",null)
.create();
//设置不允许点击提示框之外的区域
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();
// 当文件被删除刷新ListView
showRecord.notifyDataSetChanged();
}
}).create();
//设置不允许点击提示框之外的区域
aler.setCanceledOnTouchOutside(false);
aler.show();
start.setText("录音");
start.setEnabled(true);
stop.setEnabled(false);
default:
break;
}
}
private void RecorderStart(String text) {
try {
myRecorder = new MediaRecorder();
// 从麦克风源进行录音
myRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
// 设置输出格式
myRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
// 设置编码格式
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有内容(代表正在录音),那么就直接释放资源
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>


猜你喜欢
- JVM与DalvikAndroid应用程序运行在Dalvik/ART虚拟机,并且每一个应用程序对应有一个单独的Dalvik虚拟机实例。Dal
- 本文实例讲述了java实现简单的英文文本单词翻译器功能。分享给大家供大家参考,具体如下:直接上代码:package fanyi;import
- 本文实例为大家分享了java实现马踏棋盘的具体代码,供大家参考,具体内容如下马踏棋盘算法介绍8X8棋盘,马走日字,要求每个方格只进入一次,走
- 1. 使用蓝牙的响应权限<uses-permission android:name="android.permission.
- 看书的时候被一段代码能凌乱啦,代码是这样的:package 继承;abstract class People {
- 前言相信很多人选择Spring Boot主要是考虑到它既能兼顾Spring的强大功能,还能实现快速开发的便捷。我们在Spring Boot使
- 本文实例讲述了java数据结构与算法之中缀表达式转为后缀表达式的方法。分享给大家供大家参考,具体如下://stackpublic class
- Java调用cmd命令,并输出显示信息:package com.anxin.cmd.test; import java.io.Buffere
- 本文,将介绍如何通过Java后端程序代码在PDF中创建工具提示。添加工具提示后,当鼠标悬停在页面上的元素时,将显示工具提示内容。导入jar包
- 如果一个内存中的对象没有任何引用的话,就说明这个对象已经不再被使用了,从而可以成为被垃圾回收的候选。不过由于垃圾回收器的运行时间不确定,可被
- 面向对象三要素:封装、继承、多态。封装和继承,这两个比较好理解,但要理解多态的话,可就稍微有点难度了。今天,我们就来讲讲多态的理解。我们应该
- 1.元组(Tuple)元组(Tuple)在4.0 的时候就有了,但元组也有些缺点,如: 1)Tuple 会影响代码的
- 最新Spring Data JPA官方参考手册 Version 2.0.0.RC2,2017-07-25https://docs.sprin
- package com.cooly;import java.util.LinkedList;/*** @author coolyqq*模拟打
- java StringBuilder类的详解及简单实例实现代码:public class StringBuilder
- 1、对称二叉树【OJ链接】分为以下几种情况:二叉树为空,是对称二叉树二叉树不为空,其左子树或者右子树为空,不是对称二叉树二叉树不为空,左右子
- 前言:已经有一个月没写点什么了,感觉心里空落落的。今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧。之前分享过一
- 前言 Spring中最重要的概念IOC和AOP,实际围绕的就是Bean的生成与使用。什么叫做Bean呢?
- 本文实例为大家分享了C# Winform 自动更新程序,供大家参考,具体内容如下第一步:检查更新检查更新其实无非就是去比较更新包的版本和本地
- 原始数据:string input = "3,7,2,8,1,9,1,34,67,78,22";要处理为:string[