仿微信音频录入和播放

仿微信音频录入和播放
录音 播放 暂停
lib中导入so文件和lib库
在这里插入图片描述

libs文件下载地址
链接: https://pan.baidu.com/s/1D1q2PV1IQArK79zAt1cfOw 提取码: f7jg 复制这段内容后打开百度网盘手机App,操作更方便哦
页面主类

package com.example.test_voaacencoder;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Toast;

import com.example.test_voaacencoder.util.HttpOperateUtil;
import com.sinaapp.bashell.VoAACEncoder;

public class MainActivity extends Activity {

	private AudioRecord recordInstance;
	private boolean isStartRecord;
	private FileOutputStream fos;

	private int SAMPLERATE = 8000;

	private ImageButton imageButton = null;
	private Button mStartPlayBtn;
	private Button mStopPlayBtn;

	private MediaPlayer mMediaPlayer;

	private String mRecordFileName;

	String URL_UPLOAD_FILE = "http://192.168.1.147/receive_file.php";

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// initView
		imageButton = (ImageButton) findViewById(R.id.imageButtonDial);
		imageButton.setBackgroundResource(R.drawable.btn_speak_normal);

		imageButton.setOnLongClickListener(new OnLongClickListener() {
			@Override
			public boolean onLongClick(View v) {
				Log.i("keanbin", "onLongClick()");
				setTalkBtnBackground(true);

				// 停止播放声音
				stopPlay();
				// 开始录音
				startRecord();

				return true;
			}
		});
		imageButton.setOnTouchListener(new MyClickListener());

		mStartPlayBtn = (Button) findViewById(R.id.btn_mian_startPlay);
		mStartPlayBtn.setOnClickListener(mOnClickListener);
		mStopPlayBtn = (Button) findViewById(R.id.btn_mian_stopPlay);
		mStopPlayBtn.setOnClickListener(mOnClickListener);
	}

	private OnClickListener mOnClickListener = new OnClickListener() {

		@Override
		public void onClick(View v) {
			switch (v.getId()) {
			case R.id.btn_mian_startPlay:
				if (isStartRecord) {
					stopRecord();
				}

				startPlay();
				break;

			case R.id.btn_mian_stopPlay:
				stopPlay();
				break;

			default:
				break;
			}
		}
	};

	public void startRecord() {
		if (!Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED)) {
			Toast.makeText(MainActivity.this, "请插入SD卡!", Toast.LENGTH_SHORT)
					.show();
			return;
		}

		try {
			// mRecordFileName = Environment.getExternalStorageDirectory()
			// .toString()
			// + "/testAAC"
			// + System.currentTimeMillis()
			// + ".aac";

			mRecordFileName = Environment.getExternalStorageDirectory()
					.toString() + "/testAAC.aac";

			fos = new FileOutputStream(mRecordFileName);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		System.out.println("fos = " + fos);
		new Thread(new Runnable() {
			@Override
			public void run() {
				VoAACEncoder vo = new VoAACEncoder();
				vo.Init(SAMPLERATE, 16000, (short) 1, (short) 1);// 采样率:16000,bitRate:32k,声道数:1,编码:0.raw
				// 1.ADTS
				int min = AudioRecord.getMinBufferSize(SAMPLERATE,
						AudioFormat.CHANNEL_IN_MONO,
						AudioFormat.ENCODING_PCM_16BIT);
				if (min < 2048) {
					min = 2048;
				}
				byte[] tempBuffer = new byte[2048];
				recordInstance = new AudioRecord(MediaRecorder.AudioSource.MIC,
						SAMPLERATE, AudioFormat.CHANNEL_IN_MONO,
						AudioFormat.ENCODING_PCM_16BIT, min);
				recordInstance.startRecording();
				isStartRecord = true;
				while (isStartRecord) {
					int bufferRead = recordInstance.read(tempBuffer, 0, 2048);
					byte[] ret = vo.Enc(tempBuffer);
					if (bufferRead > 0) {
						System.out.println("ret:" + ret.length);
						try {
							fos.write(ret);
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
				recordInstance.stop();
				recordInstance.release();
				recordInstance = null;
				vo.Uninit();
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}).start();

	}

	public void stopRecord() {
		isStartRecord = false;
	}

	public void startPlay() {
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				
				Looper.prepare();
				// TODO Auto-generated method stub
				String fileUrl = "http://192.168.1.147/upload/testAAC.aac";

				String fileName = HttpOperateUtil.downLoadFile(fileUrl,
						fileUrl.substring(fileUrl.lastIndexOf("/") + 1));

				Log.i("keanbin", "fileName = " + fileName); 
				File file = new File(fileName);

				if (!file.exists()) {
					Toast.makeText(MainActivity.this, "没有音乐文件!", Toast.LENGTH_SHORT)
							.show();
					return;
				}

				mMediaPlayer = MediaPlayer.create(MainActivity.this,
						Uri.parse(fileName));
				mMediaPlayer.setLooping(false);
				mMediaPlayer.start();
				
				Looper.loop();
			}
		}).start();

	}

	public void stopPlay() {
		if (mMediaPlayer != null) {
			mMediaPlayer.stop();
		}
	}

	@Override
	protected void onDestroy() {

		stopPlay();
		stopRecord();
		super.onDestroy();
	}

	class MyClickListener implements OnTouchListener {
		public boolean onTouch(View v, MotionEvent event) {
			Log.i("keanbin", "event.getAction() = " + event.getAction());
			switch (event.getAction()) {
			case MotionEvent.ACTION_UP:
				setTalkBtnBackground(false);
				// TODO 正常放开,接下来一般做以下事情:发送录音文件到服务器
				if (isStartRecord) {
					// 停止录音
					stopRecord();

					Toast.makeText(MainActivity.this, "开始上传文件!",
							Toast.LENGTH_SHORT).show();
					// 上传文件
					HttpOperateUtil
							.uploadFile(URL_UPLOAD_FILE, mRecordFileName);
					Toast.makeText(MainActivity.this, "上传完文件!",
							Toast.LENGTH_SHORT).show();
				}
				break;

			case MotionEvent.ACTION_CANCEL:
				setTalkBtnBackground(false);
				// TODO 异常放开,接下来一般做以下事情:删除录音文件

				// 停止录音
				stopRecord();
				break;

			default:
				break;
			}
			return false;
		}

	}

	public void setTalkBtnBackground(boolean isTalk) {
		if (isTalk) {
			imageButton.setBackgroundResource(R.drawable.btn_speak_pressed);
		} else {
			imageButton.setBackgroundResource(R.drawable.btn_speak_normal);
		}

	}

}

Utli类 上传音频文件和下载音频文件

package com.example.test_voaacencoder.util;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import android.os.Environment;
import android.util.Log;

public class HttpOperateUtil {

	public static boolean uploadFile(String uploadUrl, String srcPath) {
		String end = "\r\n";
		String twoHyphens = "--";
		String boundary = "******";
		try {
			URL url = new URL(uploadUrl);
			HttpURLConnection httpURLConnection = (HttpURLConnection) url
					.openConnection();
			// 设置每次传输的流大小,可以有效防止手机因为内存不足崩溃
			// 此方法用于在预先不知道内容长度时启用,没有进行内部缓冲的 HTTP 请求正文的流。
			httpURLConnection.setChunkedStreamingMode(128 * 1024);// 128K
			// 允许输入输出流
			httpURLConnection.setDoInput(true);
			httpURLConnection.setDoOutput(true);
			httpURLConnection.setUseCaches(false);
			// 使用POST方法
			httpURLConnection.setRequestMethod("POST");
			httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
			httpURLConnection.setRequestProperty("Charset", "UTF-8");
			httpURLConnection.setRequestProperty("Content-Type",
					"multipart/form-data;boundary=" + boundary);

			DataOutputStream dos = new DataOutputStream(
					httpURLConnection.getOutputStream());
			dos.writeBytes(twoHyphens + boundary + end);
			dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\"; filename=\""
					+ srcPath.substring(srcPath.lastIndexOf("/") + 1)
					+ "\""
					+ end);
			dos.writeBytes(end);

			// 上传文件内容
			FileInputStream fis = new FileInputStream(srcPath);
			byte[] buffer = new byte[8192]; // 8k
			int count = 0;
			// 读取文件
			while ((count = fis.read(buffer)) != -1) {
				dos.write(buffer, 0, count);
			}
			fis.close();

			dos.writeBytes(end);
			dos.writeBytes(twoHyphens + boundary + twoHyphens + end);
			dos.flush();

			// 服务器返回结果
			InputStream is = httpURLConnection.getInputStream();
			InputStreamReader isr = new InputStreamReader(is, "utf-8");
			BufferedReader br = new BufferedReader(isr);
			String result = br.readLine();

			// Toast.makeText(this, result, Toast.LENGTH_LONG).show();
			Log.i("uploadFile", "uploadFile result = " + result);

			try {
				dos.close();
			} catch (Exception e) {
				e.printStackTrace();
				// setTitle(e.getMessage());
			}
			is.close();

			return true;

		} catch (Exception e) {
			e.printStackTrace();
			// setTitle(e.getMessage());
		}

		return false;
	}

	public static String downLoadFile(String fileUrl, String fileName) {
		String fileDir = "";
		try {
			// 判断SD卡是否存在,并且是否具有读写权限
			if (Environment.getExternalStorageState().equals(
					Environment.MEDIA_MOUNTED)) {
				// 获得存储卡的路径
				String sdpath = Environment.getExternalStorageDirectory() + "/";
				String savePath = sdpath + "download";
				URL url = new URL(fileUrl);
				// 创建连接
				HttpURLConnection conn = (HttpURLConnection) url
						.openConnection();
				conn.connect();
				// 获取文件大小
				int contentLength = conn.getContentLength();
				// 创建输入流
				InputStream is = conn.getInputStream();

				File file = new File(savePath);
				// 判断文件目录是否存在
				if (!file.exists()) {
					file.mkdir();
				}
				File apkFile = new File(savePath, fileName);
				FileOutputStream fos = new FileOutputStream(apkFile);
				int count = 0;
				// 缓存
				byte buf[] = new byte[1024];
				// 写入到文件中
				do {
					int numread = is.read(buf);
					// count += numread;
					// // 计算进度条位置
					// mPercent = (int) (((float) count / contentLength) * 100);
					// // 更新进度
					// mHandler.sendEmptyMessage(DOWNLOAD_PERCENT);
					if (numread <= 0) {
						// 下载完成
						fileDir = savePath + "/" + fileName;
						// if (checkUpdateResult(apkFile)) {
						// // 下载成功
						//
						// } else {
						// // 下载失败
						// fos.close();
						// is.close();
						// // throw new RuntimeException("下载文件出错");
						// }
						break;
					}
					// 写入文件
					fos.write(buf, 0, numread);
				} while (true);// !mCancelUpdate);// 点击取消就停止下载.
				fos.close();
				is.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return fileDir;
	}
}

main.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="仿照米聊和微信中语音通话时按住按钮是一个状态和松开手是一个状态的效果,加入防止用户手jian狂按按钮导致的异常" />

    <Button 
        android:id="@+id/btn_mian_startPlay"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="播放录音" />
    
    <Button 
        android:id="@+id/btn_mian_stopPlay"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="停止播放" />
    
    <ImageButton
        android:id="@+id/imageButtonDial"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginLeft="20dip"
        android:layout_marginTop="20dip" />

</LinearLayout>

录音按钮图片
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值