Android实现多媒体录音笔

作者:lijiao 时间:2022-03-26 17:25:00 

记事本涉及到的仅仅是对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的父布局进行长按事件的监听。

效果:

Android实现多媒体录音笔   

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>  
标签:Android,多媒体,录音笔
0
投稿

猜你喜欢

  • Android开发中软键盘的显示和隐藏

    2023-10-03 06:00:20
  • Android之listfragment的使用例子

    2021-05-31 02:10:19
  • android 设置全屏的两种方法

    2023-06-30 00:06:11
  • 记一次公司JVM堆溢出抽丝剥茧定位的过程解析

    2023-11-09 13:11:24
  • MFC程序设计常用技巧汇总

    2023-11-02 20:37:12
  • C#将布尔类型转换成字节数组的方法

    2023-06-21 15:30:16
  • C#套接字(Socket)通信之UDP组播详解

    2022-06-11 05:49:52
  • SSH框架网上商城项目第8战之查询和删除商品类别功能实现

    2023-02-12 05:54:39
  • 深入解析C#中的泛型类与泛型接口

    2023-04-30 02:35:39
  • C#使用winform简单导出Excel的方法

    2022-06-11 06:58:49
  • Java生成10个1000以内的随机数并用消息框显示数组内容然后求和输出

    2023-09-30 21:20:19
  • java中如何执行xshell命令

    2021-10-06 16:22:18
  • Java使用DateTimeFormatter格式化输入的日期时间

    2023-03-09 04:52:38
  • JDK10中的局部变量类型推断var

    2022-06-16 20:32:48
  • RecylerView实现流布局StaggeredGridLayoutManager使用详解

    2023-04-30 20:51:38
  • C++中的异常处理机制详解

    2023-04-16 16:01:10
  • Java安全 ysoserial CommonsCollections3示例分析

    2022-01-19 05:08:19
  • C#中通过Command模式实现Redo/Undo方案

    2021-07-12 14:58:59
  • C# List引用类型克隆的3种方法

    2023-04-19 14:20:44
  • gson对象序列化的示例

    2023-11-25 08:54:28
  • asp之家 软件编程 m.aspxhome.com