安卓移动端-后端数据通信api介绍
此demo是为了让大家快速地部署android移动端-flask后端科研框架,把自己的算法部署到计算能力更好的服务器上。是一个面向移动client—服务器server的简易科研数据分析平台。
相关链接
【搭建属于你的科研平台】(一)基于flask的服务器端算法框架搭建
【搭建属于你的科研平台】(二)基于flask-gunicorn的demo介绍
demo讲解
本项目基于此demo,实现一个sendFile
第三方库。主要特性如下:
- 基于okhttp3,传输文件到服务器端。【可设定目标服务器、超时时间等】
- 配合【搭建属于你的科研平台】(二)基于flask-gunicorn的demo介绍 提到的demo-backend 进行数据处理、返回结果
- Target Android Api-level = 26+ 均通过测试
- 移动安卓端例程基于: IdealRecoder
使用方法
1. 打开自己的移动端项目:File->new->import module
2. 打开source directory:
3.导入后,项目开始合成
可以看到出现了error,是因为此处使用的idealRecoder最新版本,已经支持compileSdkVersion 28
,只需要把build.gradle(sendfile)
改为同样的28
。同理,你所在的项目是sdk多少,sendfile也改为相同的。遇到报错问题可以用android studio强大的Alt+Enter
进行智能修复。
4. IdealRecoder 添加了调用sendfile的代码
package tech.oom.idealrecorder;
/*--------------------------------------Add SendFile Code-----------------------------------*/
import org.letterli.sendfile.SendFiletoServer;
import okhttp3.MediaType;
/*--------------------------------------Add SendFile Code-----------------------------------*/
/**
* 录音功能的核心类
*/
public class IdealRecorder implements RecorderCallback, AudioFileListener {
private static final String TAG = "IdealRecorder";
/*--------------------------------------Add SendFile Code-----------------------------------*/
private SendFiletoServer sendFiletoServer;
/*--------------------------------------Add SendFile Code-----------------------------------*/
private IdealRecorder() {
idealHandler = new Handler();
recorder = new Recorder(config, this);
audioFileHelper = new AudioFileHelper(this);
/*--------------------------------------Add SendFile Code-----------------------------------*/
sendFiletoServer = new SendFiletoServer();
// sendFiletoServer.setTimeOut(350); //60 means 60 seconds, 120 means 2 minutes
sendFiletoServer.setFile("/storage/emulated/0/Audio/ideal.wav",
"ideal.wav", MediaType.parse("audio/x-wav"),
"http://10.0.2.2:5000/api/upload");
/*--------------------------------------Add SendFile Code-----------------------------------*/
}
//-----------------------------Here jumps to the core function calling the SendFile Class-------------------------------//
//-----------------------------Here jumps to the core function calling the SendFile Class-------------------------------//
/**
* 停止录音
*/
public void stop() {
Log.d(TAG, "Stop Ideal Recorder is called");
if (this.isStarted.get()) {
this.isStarted.set(false);
this.recorder.immediateStop();
/*--------------------------------------Add SendFile Code-----------------------------------*/
sendFiletoServer.start();
/*--------------------------------------Add SendFile Code-----------------------------------*/
} else if (this.recorder != null) {
this.recorder.immediateStop();
/*--------------------------------------Add SendFile Code-----------------------------------*/
sendFiletoServer.start();
/*--------------------------------------Add SendFile Code-----------------------------------*/
}
}
5. 运行代码。查看Logcat发现报错:
2020-02-07 15:58:05.291 15308-15353/tech.oom.idealrecorderdemo W/System.err: java.net.SocketException: socket failed: EACCES (Permission denied)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at java.net.Socket.createImpl(Socket.java:492)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at java.net.Socket.getImpl(Socket.java:552)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at java.net.Socket.setSoTimeout(Socket.java:1180)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at okhttp3.internal.io.RealConnection.connectSocket(RealConnection.java:138)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at okhttp3.internal.io.RealConnection.connect(RealConnection.java:111)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:188)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:127)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:289)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:241)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at okhttp3.RealCall.getResponse(RealCall.java:240)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:198)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:160)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at okhttp3.RealCall.execute(RealCall.java:57)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at org.letterli.sendfile.SendFiletoServer$1.run(SendFiletoServer.java:64)
2020-02-07 15:58:05.292 15308-15353/tech.oom.idealrecorderdemo W/System.err: at java.lang.Thread.run(Thread.java:764)
2020-02-07 15:58:05.989 15308-15343/tech.oom.idealrecorderdemo D/EGL_emulation: eglMakeCurrent: 0xec9ff160: ver 2 0 (tinfo 0xe8a60ad0)
2020-02-07 15:58:07.271 15308-15343/tech.oom.idealrecorderdemo D/EGL_emulation: eglMakeCurrent: 0xec9ff160: ver 2 0 (tinfo 0xe8a60ad0)
2020-02-07 15:58:05.291 15308-15353/tech.oom.idealrecorderdemo W/System.err: java.net.SocketException: socket failed: EACCES (Permission denied)
查看说明是没有访问socket的权限,添加如下代码到 app/Manifest.xml即可
/*--------------------------------------Add SendFile Code-----------------------------------*/
<uses-permission android:name="android.permission.INTERNET"/>
/*--------------------------------------Add SendFile Code-----------------------------------*/
6. 重新运行,移动端logcat 收到处理结果信息
7. 后端demo-backend 收到上传文件并处理,记录log
sendfile代码:
package org.letterli.sendfile;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import okhttp3.Connection;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class SendFiletoServer {
private final String TAG = "AsrFile";
// 需要识别的文件
private String FILE_NAME;
private String FILE_PATH;
private MediaType MEDIA_TYPE;
private String TO_URL;
private static int TIME_OUT = 60*1000; //超时时间为60s*1000 = 1000min
private static final String CHARSET = "utf-8"; //编码格式
private static final String PREFIX = "--"; //前缀
private static final String BOUNDARY = UUID.randomUUID().toString(); //边界标识 随机生成
private static final String CONTENT_TYPE = "multipart/form-data"; //内容类型
private static final String LINE_END = "\r\n"; //换行
private static final String IMGUR_CLIENT_ID = "...";
private String responseData;
private OkHttpClient client;
// 运行子线程
public Runnable fileSend = new Runnable() {
@Override
public void run() {
//准备文件与传入参数
// Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("myfile", FILE_NAME,
RequestBody.create(MEDIA_TYPE, new File(FILE_PATH)))
.build();
try {
Log.d(TAG+" requestBody", String.valueOf(requestBody.contentLength()));
} catch (IOException e) {
e.printStackTrace();
}
Request request = new Request.Builder()
.addHeader("Connection","keep-alive")
.url(TO_URL)
.post(requestBody)
.build();
Log.i(TAG+" request", String.valueOf(request.body()));
Response response = null;
try {
response = client.newCall(request).execute();
responseData = response.body().string();
Log.i(TAG, responseData);
} catch (IOException e) {
e.printStackTrace();
}
}
};
public void start() {
Log.i(TAG+"timeout-set-test", String.valueOf(TIME_OUT));
client = new OkHttpClient.Builder()
.connectTimeout(TIME_OUT, TimeUnit.SECONDS)
.readTimeout(TIME_OUT,TimeUnit.SECONDS)
.build();
synchronized (this) {
new Thread(fileSend).start();
}
}
//-------------------------- API functions-------------------------//
// 如下所示:
}
1. API one ---- setFile
public void setFile(String filePath, String fileName, MediaType mediaType, String to_url) {
this.FILE_PATH = filePath;
this.MEDIA_TYPE = mediaType;
this.TO_URL = to_url;
this.FILE_NAME = fileName;
}
2. API two ---- setTimeOut
public void setTimeOut(int time){
Log.i(TAG+"timeout-set-test", String.valueOf(TIME_OUT));
this.TIME_OUT = time;
}
总结:
- 使用sendfile 库的方法如上所示。IdealRecoder 修改后的demo 位于 myrecoder-demo分支