Android 语音播放和录制以及转换mp3,上传服务器,ios亲测可用

最近在做一个类似微信,QQ语音录制,上传数据库,并进行播放,根据录制的时间长短,显示出来的语音条长短也会发生变化,以及在录制时动画等,以及适应iOS,对录制的音频,进行格式转换.

下面就让我们看一下具体的实现吧

先看需要添加的权限,

  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <!-- 用于获取wifi的获取权限,wifi信息会用来进行网络定位 -->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <!-- 用于访问网络,网络定位需要上网 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 在SD卡中创建与删除文件权限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <!-- 用于写入缓存数据到扩展存储卡 -->
    <uses-permission android:name="android.permission.USE_FINGERPRINT" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

有些权限需要动态申请的

 /**
     * 动态添加权限
     */
    public void getPression() {
        int checkSelfPermission = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (checkSelfPermission == PackageManager.PERMISSION_DENIED) {
            //没有权限,申请权限
            ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.CAMERA,
                    Manifest.permission.WRITE_SETTINGS,
                    Manifest.permission.RECORD_AUDIO,
                    Manifest.permission.CALL_PHONE}, 100);
        } else if (checkSelfPermission == PackageManager.PERMISSION_GRANTED) {
            //已经有了权限 ,不需要申请
        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 100:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(getContext(), "已经授权成功了", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }

下面就是正式的来写代码

先在页面上定义个按钮,用来录音

这有一个工具类

public class RecordUtil {
    public static final String AUDIO_DIR = Environment
            .getExternalStorageDirectory().getAbsolutePath() + "/Horusch/audio";
    private String mName;
    private String mAudioPath; // 要播放的声音的路�?
    private boolean recording = false;// 是否正在录音
    private boolean playing = false;// 是否正在播放
    public MediaRecorder mRecorder;
    public MediaPlayer mPlay;

    public boolean isRecording() {
        return recording;
    }

    public void setRecording(boolean recording) {
        this.recording = recording;
    }

    public boolean isPlaying() {
        return playing;
    }

    public void setPlaying(boolean playing) {
        this.playing = playing;
    }

    public String getmName() {
        return mName;
    }

    public void setmName(String mName) {
        this.mName = mName;
    }

    public String getmAudioPath() {
        return mAudioPath;
    }

    public void setmAudioPath(String mAudioPath) {
        this.mAudioPath = mAudioPath;
    }

    // 初始�?录音�?
    private void initRecorder() {

    }

    // �?��录音
    public void startRecord() {
        if (mRecorder != null)
            return;
        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
        mName = "audio_" + 1;
        mAudioPath = AUDIO_DIR + "/" + mName + ".mp3";

        // 判断是否存在文件�?
        File folder = new File(AUDIO_DIR);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        // 判断文件是否存在
        File file = new File(mAudioPath);
        if (file.exists()) {
            int count = 2;
            while (true) {
                mName = "audio_" + count;
                mAudioPath = AUDIO_DIR + "/" + mName + ".mp3";
                file = new File(mAudioPath);
                if (file.exists()) {
                    count++;
                } else {
                    break;
                }
            }
        }
        mRecorder.setOutputFile(file.getAbsolutePath());
        recording = true;
        try {
            mRecorder.prepare();
            mRecorder.start();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    // 停止录音
    public void stopRecord() {
        try {
            if (mRecorder != null && recording) {
                //设置异常时不崩溃
                mRecorder.setOnErrorListener(null);
                mRecorder.setOnInfoListener(null);
                mRecorder.setPreviewDisplay(null);
                mRecorder.stop();
                mRecorder.release();
                mRecorder = null;
                recording = false;
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    // 获取音量值,只是针对录音音量
    public int getVolume() {
        int volume = 0;
        // 录音
        if (mRecorder != null && recording) {
            volume = mRecorder.getMaxAmplitude() / 650;
            Log.d("sdfgasd", volume + "");
            if (volume != 0)
                // volume = (int) (10 * Math.log(volume) / Math.log(10)) / 7;
                volume = (int) (10 * Math.log10(volume)) / 3;
            Log.d("db", volume + "");
        }
        return volume;
    }

    // �?��播放
    public void startPlay(String path, boolean isLooping) {
        if (!path.equals("")) {
            mPlay = new MediaPlayer();
            try {
                mPlay.setDataSource(path);
                mPlay.prepare();
                mPlay.start();
                mPlay.setLooping(isLooping);
                playing = true;
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalStateException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    // 停止播放
    public void stopPlay() {
        if (mPlay != null && mPlay.isPlaying()) {
            mPlay.stop();
            mPlay.release();
            mPlay = null;
            playing = false;
        }
    }

}


下面是按钮的触摸事件,我们需要计算录音的时间,所以需要重写这个按钮的触摸事件,,这里还牵扯到当你手移动出去这个按钮,录制录音就会被中断,而不是都是在up的时候停止,所以我们重新复写触摸事件的,应该多重写一个状态MotionEvent.ACTION_CANCEL,下面就这个按钮的触摸事件


/**
     * 录音的触摸事件
     */
    private void initEvent() {
        btnEventRecording.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {

                int action = event.getAction();
                switch (action) {
                    case MotionEvent.ACTION_DOWN:
                        currentTime = System.currentTimeMillis();
                        tvTack.setText("请开始说话");
                        mRecorduUtil.startRecord();
                        if (mRecorduUtil.isRecording()) {
                            //将step2中的linearlayout设为可视
                            ll_record.setVisibility(View.VISIBLE);
                            /**
                             *启动线程<注意!这里不能用handler.post启动Runnable,否则无法removeCallBack>
                             */
                            Thread t = new Thread(mPollTask);
                            t.start();
                        }
                        break;

                    case MotionEvent.ACTION_UP:
                        myRecording(currentTime);
                        break;

                    case MotionEvent.ACTION_CANCEL:
                        myRecording(currentTime);
                        break;
                }
                return true;
            }
        });
    }

当你在Dwon时,防止阻塞主线程,需要开启一个线程更改语音图片,在录制的时候会有录制的动画,根据声音的变化,而改变,下面是这个线程

/**
     * 开启一个线程更改语音图片
     */
    private Runnable mPollTask = new Runnable() {
        public void run() {
            int mVolume = mRecorduUtil.getVolume();
            Log.d("volume", mVolume + "");
            updateVolume(mVolume);
            mHandler.postDelayed(mPollTask, 100);
        }
    };

这个是语音的图片


// 更新音量图
    private void updateVolume(int volume) {
        switch (volume) {
            case 1:
                iv_volume.setImageResource(R.drawable.volume_icon1);
                break;
            case 2:
                iv_volume.setImageResource(R.drawable.volume_icon2);
                break;
            case 3:
                iv_volume.setImageResource(R.drawable.volume_icon3);
                break;
            case 4:
                iv_volume.setImageResource(R.drawable.volume_icon4);
                break;
            case 5:
                iv_volume.setImageResource(R.drawable.volume_icon5);
                break;
            case 6:
                iv_volume.setImageResource(R.drawable.volume_icon6);
                break;
            case 7:
                iv_volume.setImageResource(R.drawable.volume_icon7);
                break;
            default:
                break;
        }
    }

下面就是开始录音的代码


/**
     * 开始录音
     *
     * @param DownTime
     */
    private void myRecording(long DownTime) {
        long thisTime = System.currentTimeMillis();
        long recordingTime = thisTime - DownTime;
        time = (int) (recordingTime / 1000);
        ll_record.setVisibility(View.GONE);
        if (recordingTime < 1000) {
            tvTack.setText("说话时间太短");
            ShowToast.show(EventReportActivity.this, "录音时间太短");
            mRecorduUtil.stopRecord();
            return;
        } else {
            if(time<=1){
                ViewGroup.LayoutParams layoutParams = startRecding.getLayoutParams();
                layoutParams.width = 160;
                startRecding.setLayoutParams(layoutParams);
            }else if (time>1){
                int s = time - 1;
                ViewGroup.LayoutParams pp = startRecding.getLayoutParams();
                if (160 + s * 9 < 500) {
                    pp.width = 160 + s * 9;
                    startRecding.setLayoutParams(pp);

                } else if (160 + s * 9 >= 500) {
                    pp.width = 500;
                    startRecding.setLayoutParams(pp);

            }
            }
            tvStartRecding.setText(time + "''");
            mRecorduUtil.stopRecord();
            btnEventRecording.setVisibility(View.GONE);
            rlStartRecding.setVisibility(View.VISIBLE);
        }
        mHandler.removeCallbacks(mPollTask);
        File folder = new File(RecordUtil.AUDIO_DIR);
        File[] files = folder.listFiles();
        if (files.length != 0) {
            path1 = files[files.length - 1].getAbsolutePath();
            File flacFile = new File(path1);
            IConvertCallback callback = new IConvertCallback() {
                @Override
                public void onSuccess(File convertedFile) {
                    // So fast? Love it!
                    LogUtils.d("voice-222---", "So fast? Love it!");
                    LogUtils.d("voice--222--", convertedFile.getAbsolutePath());
                    path = convertedFile.getAbsolutePath();
                }

                @Override
                public void onFailure(Exception error) {
                    // Oops! Something went wrong
                    LogUtils.d("voice-11---", "Oops! Something went wrong");
                    LogUtils.d("voice-sss---", error.toString());
                }
            };
            AndroidAudioConverter.with(this)
                    // Your current audio file
                    .setFile(flacFile)

                    // Your desired audio format
                    .setFormat(AudioFormat.MP3)

                    // An callback to know when conversion is finished
                    .setCallback(callback)

                    // Start conversion
                    .convert();
        }
    }

录制基本就绪,我们看一下 效果

录音前:



录音中:


录音后:



大致的效果就是这样

下面就是播放了

//TODO:播放录音
                    ivVoice.setVisibility(View.GONE);
                    ivVoiceAnimal.setVisibility(View.VISIBLE);
                    mRecorduUtil.startPlay(path, false);
                    ivVoiceAnimal.setImageResource(R.drawable.animation_yunyin);
                    animationDrawable = (AnimationDrawable) ivVoiceAnimal.getDrawable();
                    animationDrawable.start();
                    if (time != 0) {
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        ivVoiceAnimal.setVisibility(View.GONE);
                                        ivVoice.setVisibility(View.VISIBLE);
                                    }
                                });

                            }
                        }, time * 1000);//up时间
                    } else if (canceltTime != 0) {
                        new Handler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        ivVoiceAnimal.setVisibility(View.GONE);
                                        ivVoice.setVisibility(View.VISIBLE);
                                    }
                                });

                            }
                        }, canceltTime * 1000);//touch:MotionEvent.ACTION_CANCEL时间
                    }

转换格式:

添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Application里面添加

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        AndroidAudioConverter.load(this, new ILoadCallback() {
            @Override
            public void onSuccess() {
                // Great!
            }
            @Override
            public void onFailure(Exception error) {
                // FFmpeg is not supported by device
            }
        });
    }

在用到的地方调用

File folder = new File(RecordUtil.AUDIO_DIR);
        File[] files = folder.listFiles();
        if (files.length != 0) {
            path1 = files[files.length - 1].getAbsolutePath();
            File flacFile = new File(path1);
            IConvertCallback callback = new IConvertCallback() {
                @Override
                public void onSuccess(File convertedFile) {
                    // So fast? Love it!
                    LogUtils.d("voice-222---", "So fast? Love it!");
                    LogUtils.d("voice--222--", convertedFile.getAbsolutePath());
                    path = convertedFile.getAbsolutePath();
                }

                @Override
                public void onFailure(Exception error) {
                    // Oops! Something went wrong
                    LogUtils.d("voice-11---", "Oops! Something went wrong");
                    LogUtils.d("voice-sss---", error.toString());
                }
            };
            AndroidAudioConverter.with(this)
                    // Your current audio file
                    .setFile(flacFile)

                    // Your desired audio format
                    .setFormat(AudioFormat.MP3)

                    // An callback to know when conversion is finished
                    .setCallback(callback)

                    // Start conversion
                    .convert();
        }


基本的录音和播放,以及转换格式就可以了,赶快去试试吧

下面是转换格式的GitHub地址:https://github.com/adrielcafe/AndroidAudioConverter,

图片什么的就不上传了








  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值