Demo下载链接:https://download.csdn.net/download/a8856621/10911209
一、 首先实现android原生的录音功能,这里使用Android的Service服务,可保证unity切换到后台仍然录音。我将上传录音文件时所需要附带的信息全部保存在文件名中,这样即使上传文件的过程因为退出程序而导致本次上传失败,在下次进入程序后,可以通过读取文件名来获取相应的信息,再次上传服务器。
/**
* 录音的 Service
*
*
*/
public class RecordingService extends Service {
private static final String LOG_TAG = "RecordingService";
//录音开始时间
private String startTime=null;
//录音结束时间
private String endTime=null;
//文件保存路径
public String mFilePath = null;
private MediaRecorder mRecorder = null;
private TimerTask mIncrementTimerTask = null;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startTime=intent.getStringExtra("startTime");
saleID=intent.getStringExtra("saleID");
startRecording();
return START_STICKY;
}
@Override
public void onDestroy() {
if (mRecorder != null) {
//Toast.makeText(getApplicationContext(), "结束录音", Toast.LENGTH_LONG).show();
stopRecording();
}
super.onDestroy();
}
public void startRecording() {
mFilePath= Tools.getAudioFilePath()+"/"+System.currentTimeMillis() + ".aac";
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AAC_ADTS);
mRecorder.setOutputFile(mFilePath);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);//保存成aac格式
mRecorder.setAudioChannels(1);//录音通道数
mRecorder.setAudioSamplingRate(8000);//录音质量 8000即可,可减少产生文件的大小
mRecorder.setAudioEncodingBitRate(192000);
try {
mRecorder.prepare();
mRecorder.start();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
}
public void stopRecording() {
if(mRecorder!=null)
{
try {
endTime=Tools.DateFormat("yyyy-MM-dd HH:mm:ss");
mRecorder.stop();
mRecorder.release();
mRecorder = null;
//修改文件名,并将文件路径广播出去
String fileName=Tools.getAudioFilePath()+"/"+saleID+"_"+startTime+"_"+endTime+"_video"+".aac";
File file=new File(mFilePath);
file.renameTo(new File(fileName));
//发送广播
Intent intent=new Intent();
intent.putExtra("filePath", fileName);
intent.setAction("com.ideepwise.zhztbusiness.RecordingService");
sendBroadcast(intent);
} catch (IllegalStateException e) {
// TODO 如果当前java状态和jni里面的状态不一致,
//e.printStackTrace();
mRecorder = null;
mRecorder = new MediaRecorder();
}
if (mIncrementTimerTask != null) {
mIncrementTimerTask.cancel();
mIncrementTimerTask = null;
}
}
}
}
二、在MainActivity界面添加服务侦听,用来处理文件的读取和上传功能
三、记得在Android配置文件中配置相应的权限和Service服务
<service android:name=".RecordingService"
android:enabled="true"
android:exported="true"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
public class MainActivity extends UnityPlayerActivity {
public static final int GET_OK = 1,GET_ERROR = 2;
private MyReceiver receiver=null;
private boolean isRecording=false;
private String postURL=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注册广播接收器
receiver=new MyReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction("com.ideepwise.zhztbusiness.RecordingService");
MainActivity.this.registerReceiver(receiver,filter);
}
@Override
protected void onDestroy(){
super.onDestroy();
}
//在Unity端调用,用来检查上传失败的文件,并重新上传(此处我是将文件删除了,你们可自行修改)
public void CheckLoaclRecord()
{
File file=new File(Tools.getAudioFilePath());
if(file.isDirectory())
{
File[] files= file.listFiles();
if(files.length>0)
{
try {
for (int i = 0; i < files.length; i++) {
files[i].delete();
}
}catch (Exception e)
{
}
}
}
}
//unity端调用开始录音功能,传入需要上传的参数和上传的地址
public void StartRecord(String saleID,String postURL)
{
if(isRecording)
return;
isRecording=true;
this.postURL=postURL;
String startTime=Tools.DateFormat("yyyy-MM-dd HH:mm:ss");
Intent intent = new Intent(MainActivity.this, RecordingService.class);
intent.putExtra("saleID",saleID);
intent.putExtra("startTime",startTime);
startService(intent);
}
//unity端调用停止露营并上传
public void StopRecord()
{
Intent intent = new Intent(MainActivity.this, RecordingService.class);
stopService(intent);
}
/**
* 广播接受录音文件存储完后才能
*/
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
isRecording=false;
String recordPath=intent.getExtras().getString("filePath");
UpdateRecord(recordPath);
}
}
// 使用handler处理接收到的消息
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what ==GET_OK)
{
ShowToast("文件保存成功");
deleteRecord(msg.obj.toString());
}
}
};
// 显示Toast消息
public void ShowToast(final String message){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
});
}
//上传文件
public void UpdateRecord(String data)
{
try{
String fileName= data.substring(data.lastIndexOf("/")+1);
String[] record= fileName.split("_");
Map<String, String> map = new HashMap();
map.put("salerId", record[0]);
map.put("startTime", record[1]);
map.put("endTime", record[2]);
Map<String, File> mapFile = new HashMap();
mapFile.put("file", new File(data));
req_multi_form form=new req_multi_form();
form.setFileField(mapFile);
form.setNormalField(map);
form.setAction(postURL);
UploadFile(form,data);
}catch (Exception e)
{
ShowToast("上传出问题啦");
}
}
/**
* android上传文件到服务器
*
* @param form 需要上传的文件
* @return 返回响应的内容
*/
public void UploadFile(final req_multi_form form,final String data)
{
new Thread(){
@Override
public void run() {
super.run();
String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
String PREFIX = "--", LINE_END = "\r\n";
String CONTENT_TYPE = "multipart/form-data"; // 内容类型
Map<String, File> files = form.getFileField();
String RequestURL = form.getAction();
Map<String, String> param = form.getNormalField();
try {
URL url = new URL(RequestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(10000);
conn.setDoInput(true); // 允许输入流
conn.setDoOutput(true); // 允许输出流
conn.setUseCaches(false); // 不允许使用缓存
conn.setRequestMethod("POST"); // 请求方式
conn.setRequestProperty("Charset", "utf-8"); // 设置编码
conn.setRequestProperty("connection", "keep-alive");
conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);
if (files != null) {
/**
* 当文件不为空,把文件包装并且上传
*/
DataOutputStream dos = new DataOutputStream(
conn.getOutputStream());
StringBuffer sb = new StringBuffer();
String params = "";
if (param != null && param.size() > 0) {
Iterator<String> it = param.keySet().iterator();
while (it.hasNext()) {
sb = null;
sb = new StringBuffer();
String key = it.next();
String value = param.get(key);
sb.append(PREFIX).append(BOUNDARY).append(LINE_END);
sb.append("Content-Disposition: form-data; name=\"")
.append(key).append("\"").append(LINE_END)
.append(LINE_END);
sb.append(value).append(LINE_END);
params = sb.toString();
dos.write(params.getBytes());
// dos.flush();
}
}
/**
* 这里重点注意: name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件
* filename是文件的名字,包含后缀名的 比如:abc.png
*/
if( files != null && files.size() > 0)
{
Iterator<String> it = files.keySet().iterator();
while (it.hasNext())
{
sb = new StringBuffer();
sb.append(PREFIX);
sb.append(BOUNDARY);
sb.append(LINE_END);
String key = it.next();
File file = files.get(key);
sb.append("Content-Disposition: form-data; name=\""+key+"\";filename=\"" + file.getName() + "\"" + LINE_END);
if (file.getName().contains("mp4")) {
sb.append("Content-Type: video/mpeg4; charset=" + "utf-8" + LINE_END);
}
sb.append(LINE_END);
dos.write(sb.toString().getBytes());
InputStream is = new FileInputStream(file);
byte[] bytes = new byte[1024];
int len = 0;
while ((len = is.read(bytes)) != -1) {
dos.write(bytes, 0, len);
}
is.close();
dos.write(LINE_END.getBytes());
}
}
byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END)
.getBytes();
dos.write(end_data);
dos.flush();
/**
* 获取响应码 200=成功 当响应成功,获取响应的流
*/
int res = conn.getResponseCode();
if (res == 200) {
Message msg = new Message();
msg.what = GET_OK;
msg.obj=data;
mHandler.sendMessage(msg);
} else {
mHandler.sendEmptyMessage(GET_ERROR);
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
mHandler.sendEmptyMessage(GET_ERROR);
} catch (IOException e) {
e.printStackTrace();
mHandler.sendEmptyMessage(GET_ERROR);
}
}
}.start();
}
private void deleteRecord(String filePath) {
if(filePath!=null&&filePath!="") {
File file = new File(filePath);
// 路径为文件且不为空则进行删除
if (file.isFile() && file.exists()) {
file.delete();
}
}
}