热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

Android实现多媒体录音笔

这篇文章主要介绍了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:

 
 
 
   
 
   
 
   
 
    

list_item:

<&#63;xml version="1.0" encoding="utf-8"&#63;> 
 
 
   
 
  

以上就是本文的全部内容,希望对大家实现Android软件编程有所帮助。


推荐阅读
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 深入理解 Oracle 存储函数:计算员工年收入
    本文介绍如何使用 Oracle 存储函数查询特定员工的年收入。我们将详细解释存储函数的创建过程,并提供完整的代码示例。 ... [详细]
  • 本文总结了2018年的关键成就,包括职业变动、购车、考取驾照等重要事件,并分享了读书、工作、家庭和朋友方面的感悟。同时,展望2019年,制定了健康、软实力提升和技术学习的具体目标。 ... [详细]
  • 在计算机技术的学习道路上,51CTO学院以其专业性和专注度给我留下了深刻印象。从2012年接触计算机到2014年开始系统学习网络技术和安全领域,51CTO学院始终是我信赖的学习平台。 ... [详细]
  • CSS 布局:液态三栏混合宽度布局
    本文介绍了如何使用 CSS 实现液态的三栏布局,其中各栏具有不同的宽度设置。通过调整容器和内容区域的属性,可以实现灵活且响应式的网页设计。 ... [详细]
  • Linux 系统启动故障排除指南:MBR 和 GRUB 问题
    本文详细介绍了 Linux 系统启动过程中常见的 MBR 扇区和 GRUB 引导程序故障及其解决方案,涵盖从备份、模拟故障到恢复的具体步骤。 ... [详细]
  • 本文介绍了如何使用jQuery根据元素的类型(如复选框)和标签名(如段落)来获取DOM对象。这有助于更高效地操作网页中的特定元素。 ... [详细]
  • 本文将详细介绍如何使用剪映应用中的镜像功能,帮助用户轻松实现视频的镜像效果。通过简单的步骤,您可以快速掌握这一实用技巧。 ... [详细]
  • 本文介绍如何在 Xcode 中使用快捷键和菜单命令对多行代码进行缩进,包括右缩进和左缩进的具体操作方法。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • 本文介绍如何通过Windows批处理脚本定期检查并重启Java应用程序,确保其持续稳定运行。脚本每30分钟检查一次,并在需要时重启Java程序。同时,它会将任务结果发送到Redis。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 本文介绍如何通过SQL查询从JDE(JD Edwards)系统中提取所有字典数据,涵盖关键表的关联和字段选择。具体包括F0004和F0005系列表的数据提取方法。 ... [详细]
  • 本文详细介绍了如何通过命令行启动MySQL服务,包括打开命令提示符窗口、进入MySQL的bin目录、输入正确的连接命令以及注意事项。文中还提供了更多相关命令的资源链接。 ... [详细]
author-avatar
从容面对天下事
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有