android录音实现

效果图:


一、实现录音的 Service 关键代码:

// 开始录音
    public void startRecording() {
        setFileNameAndPath();
        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); //录音文件保存的格式,这里保存为 mp4
        mRecorder.setOutputFile(mFilePath); // 设置录音文件的保存路径
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mRecorder.setAudioChannels(1);
        // 设置录音文件的清晰度
        mRecorder.setAudioSamplingRate(44100);
        mRecorder.setAudioEncodingBitRate(192000);
        try {
            mRecorder.prepare();
            mRecorder.start();
            mStartingTimeMillis = System.currentTimeMillis();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
        }
    }
    // 设置录音文件的名字和保存路径
    public void setFileNameAndPath() {
        File f;
        do {
            count++;
            mFileName = getString(R.string.default_file_name)
                    + "_" + (System.currentTimeMillis()) + ".mp4";
            mFilePath = Environment.getExternalStorageDirectory().getAbsolutePath();
            mFilePath += "/SoundRecorder/" + mFileName;
            f = new File(mFilePath);
        } while (f.exists() && !f.isDirectory());
    }
    // 停止录音
    public void stopRecording() {
        mRecorder.stop();
        mElapsedMillis = (System.currentTimeMillis() - mStartingTimeMillis);
        mRecorder.release();
        getSharedPreferences("sp_name_audio", MODE_PRIVATE)
                .edit()
                .putString("audio_path", mFilePath)
                .putLong("elpased", mElapsedMillis)
                .apply();
        if (mIncrementTimerTask != null) {
            mIncrementTimerTask.cancel();
            mIncrementTimerTask = null;
        }
        mRecorder = null;
    }

二、显示录音界面的 RecordAudioDialogFragment

用户进行的时候,总不能让 App 跳转到另外一个界面吧,这样用户体验并不是很好,比较好的方法是显示一个对话框,让用户进行操作,既然要用对话框,必然离不开 DialogFragment

在 RecordAudioDialogFragment 有一个 newInstance(int maxTime) 的静态方法供外部调用,如果想设置录音的最大时长,直接传参数进去就行了。

好的,敲黑板,重点来了,其实这个对话框的重点部分就是在 onCreateDialog()中,我们先加载了我们自定义的对话框的布局,当点击录音的按钮的时候,先进行相关权限的申请,这里有个巨坑,录音权限 android.permission.RECORD_AUDIO 在不久前还是普通权限的,不知道什么时候突然变成了危险权限,需要我们进行申请,Google 真是会玩。

public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_record_audio, null);
        mFabRecord.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(getActivity()
                            , new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, 1);
                }else {
                    onRecord(mStartRecording);
                    mStartRecording = !mStartRecording;
                }
            }
        });
        builder.setView(view);
        return builder.create();
    }

三、播放录音的 PlaybackDialogFragment

其实,如果只是录音这一块的话,写个 MediaPlayer 就可以了,然而还要写播放的时间进度,以及显示一个稍微好看点的进度条,我能怎样,我也很烦啊。

外部调用这个对话框的时候,只需要传入一个包含录音文件信息的 RecordingItem,因为包含的信息比较多,所以最好将 RecordingItem 进行序列化。

public static PlaybackDialogFragment newInstance(RecordingItem item) {
        PlaybackDialogFragment fragment = new PlaybackDialogFragment();
        Bundle bundle = new Bundle();
        bundle.putParcelable(ARG_ITEM, item);
        fragment.setArguments(b);
        return fragment;
    }
好,重点又来了,来看看 onCreateDialog() 方法,在加载了布局之后,给 mSeekBar 设置监听,mSeekBar 是一个显示进度条的控件,当开始播放录音时候,将录音文件的时长,设置进 mSeekBar 里面,播放录音的同时,运行 mSeekBar,通过监听 mSeekBar 的进度,刷新显示的播放进度。
public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_media_playback, null);
        mFileLengthTextView.setText(String.valueOf(mFileLength));
        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if(mMediaPlayer != null && fromUser) {
                    mMediaPlayer.seekTo(progress);
                    mHandler.removeCallbacks(mRunnable);
                    long minutes = TimeUnit.MILLISECONDS.toMinutes(mMediaPlayer.getCurrentPosition());
                    long seconds = TimeUnit.MILLISECONDS.toSeconds(mMediaPlayer.getCurrentPosition())
                            - TimeUnit.MINUTES.toSeconds(minutes);
                    mCurrentProgressTextView.setText(String.format("%02d:%02d", minutes,seconds));
                    updateSeekBar();
                } else if (mMediaPlayer == null && fromUser) {
                    prepareMediaPlayerFromPoint(progress);
                    updateSeekBar();
                }
            }
        });
        mPlayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onPlay(isPlaying);
                isPlaying = !isPlaying;
            }
        });
        mFileLengthTextView.setText(String.format("%02d:%02d", minutes,seconds));
        builder.setView(view);
        return builder.create();
    }

当点击播放录音的按钮之后,会调用 onPlay() 方法,然后根据 isPlaying(标识当前是否播放录音)的值,来调用不同的方法

 private void onPlay(boolean isPlaying){
        if (!isPlaying) {
            //currently MediaPlayer is not playing audio
            if(mMediaPlayer == null) {
                startPlaying(); //start from beginning
            } 
        } else {
            pausePlaying();
        }
    }

我们最关心的,莫过于 startPlaying() 这个方法,这个方法便是来开启播放录音的,我们首先将外部传入的有关的录音信息,设置给 MediaPlayer,然后开始调用 mMediaPlayer.start() 进行录音的播放,然后调用 updateSeekbar() 实时更新进度条的内容。当 MediaPlayer 的内容播放完成后,调用 stopPlaying() 方法,关闭 mMediaPlayer。。。。

### 回答1: Keil MDK PackKeil 公司为其集成开发环境(MDK-ARM)提供的一种软件格式。MDK-Pack 文件将一组软件组件打,这些组件括设备支持文件(Device Support Pack,DSP)、软件库(Software Component)、中间件(Middleware)其他软件工具。 Keil MDK Pack 提供了简化嵌入式软件开发流程的工具资源。通过将相关软件组件打成一个文件,开发者可以在 MDK-ARM 环境中快速导入使用这些组件。MDK-Pack 文件具有统一的格式,可以直接在 MDK-ARM 软件中心进行下载安装。 使用 Keil MDK Pack,开发者可以快速集成设备支持文件、软件库中间件到他们的项目中。设备支持文件提供了特定芯片或开发板的相关信息配置文件,软件库提供了丰富的功能模块算法库,中间件则提供了通用的功能组件,如文件系统、网络协议栈等。通过使用 MDK-Pack,开发者可以减少集成配置的工作量,加快项目的开发进度。 Keil MDK Pack 还提供了一些其他的软件工具,如独立的调试器仿真器,以及用于性能分析优化的工具。这些工具可以帮助开发者更好地调试优化他们的嵌入式软件。 总结来说,Keil MDK Pack 是一种用于 Keil MDK-ARM 开发环境的软件格式,通过打软件组件,提供了快速集成使用的工具资源,方便开发者在嵌入式软件开发中快速导入配置相关组件,加快了项目的开发进度。 ### 回答2: Keil MDK PackKeil公司开发的一种软件开发工具。它是一款集成开发环境(IDE),用于嵌入式系统的软件开发。Keil MDK Pack提供了一系列的软件,用于支持各种不同的处理器架构嵌入式系统。 Keil MDK Pack的软件含了一些常用的编译器、调试器工具链。它还提供了各种各样的软件组件库,括设备驱动、中间件应用程序框架等。这些软件可以帮助开发人员更快地开发嵌入式系统,并提供了丰富的功能组件,以满足不同项目的需求。 通过使用Keil MDK Pack,开发人员可以轻松地构建嵌入式系统的软件部分。它提供了直观的用户界面,使开发人员能够快速配置生成项目代码。它还支持各种不同的嵌入式处理器架构,括ARM、Cortex-M8051等。这使得开发人员可以根据项目的需求选择最适合的硬件平台。 总之,Keil MDK Pack是一种强大的嵌入式软件开发工具,提供了广泛的软件组件,使开发人员能够更高效地开发嵌入式系统。它是嵌入式软件开发领域中不可或缺的工具之一,为开发人员提供了快速、可靠全面的开发环境。 ### 回答3: Keil MDK PackKeil公司针对其开发环境MDK(Microcontroller Development Kit)所提供的软件Keil MDK Pack是为嵌入式系统开发提供了一个集成的解决方案。它含了许多必要的工具资源,可以帮助开发人员更方便地进行嵌入式软件开发。 Keil MDK Pack含了许多常用的软件组件驱动程序,以及支持多种芯片的设备驱动程序。这些软件组件驱动程序可以通过集成开发环境(IDE)进行配置调试,从而简化开发过程。除此之外,Keil MDK Pack还提供了大量的例程示例代码,帮助开发人员更容易地理解使用各种功能。 使用Keil MDK Pack,开发人员可以快速构建嵌入式应用程序。它提供了丰富的软件硬件支持,括各种外围设备传感器的驱动程序。此外,Keil MDK Pack还提供了强大的调试工具,如仿真器调试器,以帮助开发人员进行测试调试。 总之,Keil MDK PackKeil公司为嵌入式系统开发提供的一个综合工具。它含了许多必要的软件组件驱动程序,可以帮助开发人员更方便地进行嵌入式软件开发。通过使用Keil MDK Pack,开发人员可以快速构建嵌入式应用程序,并且可以方便地进行测试调试。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值