安卓开发中,实现了题目描述功能。
@Override
// 文件上传的请求体封装
MultipartBody multipartBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("image", image.getName(), requestBody)
.addFormDataPart("imagepath",imagePath)
.addFormDataPart("time",time)
.addFormDataPart("deviceId", mDeviceId)
.addFormDataPart("longitude", String.valueOf(longitude))
.addFormDataPart("latitude", String.valueOf(latitude))
.addFormDataPart("actionCodes", actionCodes)
.addFormDataPart("speed", String.valueOf(mSpeed))
.build();
doUpload(UPLOAD_ACTION_URL, multipartBody);
首先是封装请求body的部分代码,将数据进行打包。然后调用upload方法。
private void doUpload(String url, RequestBody body)
{
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
// Call call = client.newCall(request);
// call.enqueue(mDataUploaderCallback);
client.newCall(request).enqueue(mDataUploaderCallback);
}
这是upload方法。
当发送request失败时,会调用onFailure方法。目的是当失败时拿到发送的包,然后保存起来,然后可以从onFailure中获取到已经封装好的包。(因为数据地方太分散,在不同类中,为确保数据的统一对应,只能去获取完整的request请求包)
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.e(TAG, "onFailure: "+e.getMessage() );
Log.i(TAG, "onFailure: "+call.request() );
if(String.valueOf(call.request()).contains("actionUpload")){
cachedRequestBody.SaveRequestBody(call);
}
}
通过测试,得知call中包含完整的request的请求包。
获取到call后,下面是一个新的类,里面是完整的处理过程
package cn.nmgbns.anjiatongservice.entity;
import android.text.TextUtils;
import org.opencv.core.Mat;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import cn.nmgbns.anjiatongservice.ActionDetectionService;
import okhttp3.Call;
import okhttp3.MultipartBody;
import okio.Buffer;
import static org.opencv.imgcodecs.Imgcodecs.imread;
import static org.opencv.imgcodecs.Imgcodecs.imwrite;
public class CachedRequestBody implements Serializable {
Queue<String> queue = null;//用队列存放文件的名字,读取文件和确保文件存储个数不超过最大值
ActionDetectionService mactionDetectionService;
private static final String NO_NETWORK_PICTURE_SAVE_PATH = "这里是需要保存文件的路径";
private static int SAVEFILEMAX = 10;//能保存文件个数的最大值
public CachedRequestBody(){
queue = new LinkedList<String>();
mactionDetectionService = new ActionDetectionService();
File root =new File(NO_NETWORK_PICTURE_SAVE_PATH);
//初始化,需提前遍历一遍手机里已经存了多少包了,防止存的过多。
listFiles(root);
}
public void listFiles( File dir){
File[] listFiles = dir.listFiles();
for(File f: listFiles){
if(f.isDirectory()){
queue.offer(String.valueOf(f));
System.out.println("我把文件添加进去了"+f);
}
}
}
//失败后,从已经封装好的requestBody中获取到值
public void SaveRequestBody(Call call){
//存放获取到的值
Map<String, String> data = new HashMap<>();
//requestBody无法直接获取,得强转成multipartBody
MultipartBody multipartBody=(MultipartBody)call.request().body();
Buffer buffer = new Buffer();
//循环从part中取出key和value
for (int i = 2;i<multipartBody.parts().size();i++){
// for (MultipartBody.Part part : multipartBody.parts()){
String key = multipartBody.part(i).headers().value(0);
// System.out.println("lalalala每个head"+key);
key = key.substring(16).replace("\"","");
// System.out.println("lalalala每个head"+key);
try {
multipartBody.part(i).body().writeTo(buffer);
} catch (IOException ioException) {
ioException.printStackTrace();
}
String value = buffer.readUtf8();
// byte value = buffer.getByte(0);
data.put(key,value);
}
//读取图片路径
Buffer buffer2 = new Buffer();
try {
multipartBody.part(1).body().writeTo(buffer2);
} catch (IOException e) {
e.printStackTrace();
}
String imagepath = buffer2.readUtf8();
Mat img = imread(imagepath);
// System.out.println("所有的body"+data.values());
// System.out.println("l图片路径"+imagepath);
//将获取到的map与图片保存,因为保存图片的body没办法序列化,就将图片单独获取与其他信息分开保存。
writeMap(data,img);
}
public void writeMap(Map map,Mat img){
//若文件数达到最大值,删除最旧的
if(queue.size()>= SAVEFILEMAX)
{
String dir = queue.element();
deleteFolderFile(dir);
queue.poll();
}
//将图片和信息保存到同一个文件夹中
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//用日期来当做文件的名字
String newFile = NO_NETWORK_PICTURE_SAVE_PATH+"data_"+df.format(new Date());
queue.offer(newFile);//向队列添加元素
File rootFile =new File(newFile);
if (!rootFile.exists()) {
rootFile.mkdirs();
}
//保存图片
String imageSavePath = rootFile+"/image.jpg";
imwrite(imageSavePath,img);
//保存图片相关信息(map)
File dataFile = new File(newFile+"/data.txt");
FileOutputStream out;
try {
out = new FileOutputStream(dataFile);
ObjectOutputStream objOut=new ObjectOutputStream(out);
objOut.writeObject(map);
objOut.flush();
objOut.close();
// System.out.println("write object success!");
} catch (IOException e) {
// System.out.println("write object failed");
e.printStackTrace();
}
}
//当网络畅通时,调用此方法,读取文件并发送,发送后删除
public void readMap(){
String str = queue.element();
Map myDataMap = null;
//读相关信息
try
{
File file =new File(str+"/data.txt");
FileInputStream fileInputStream ;
fileInputStream = new FileInputStream(file);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
myDataMap = (Map)objectInputStream.readObject();
System.out.println("lalalala"+"读到了"+myDataMap);
}
catch(ClassNotFoundException | IOException | ClassCastException e) {
System.out.println("lalalala"+"读出错了");
e.printStackTrace();
}
//获取图片路径
String imgPath = str+"/image.jpg";
String time = String.valueOf(myDataMap.get("time"));
String deviceId = String.valueOf(myDataMap.get("deviceId"));
String longitude = String.valueOf(myDataMap.get("longitude"));
String latitude = String.valueOf(myDataMap.get("latitude"));
String actionCodes = String.valueOf(myDataMap.get("actionCodes"));
String speed = String.valueOf(myDataMap.get("speed"));
//发送文件
mactionDetectionService.mDataUploader.uploadOldActionData(imgPath,
time, deviceId,longitude
,latitude, actionCodes,speed);
System.out.println("lalalal"+"imagePath:"+imgPath+","+
"time:"+time+","
+"devicedId:"+deviceId+","
+"longitude:"+longitude+","
+"latitude:"+latitude+","
+"actionCodes:"+actionCodes+","
+"speed:"+speed);
//把地址出队删除
deleteFolderFile(queue.element());
queue.poll();
}
public void deleteFolderFile(String filePath) {
if (!TextUtils.isEmpty(filePath)) {
try {
File file = new File(filePath);
if (file.isDirectory()) {// 处理目录
File files[] = file.listFiles();
for (int i = 0; i < files.length; i++) {
deleteFolderFile(files[i].getAbsolutePath());
}
}
if (!file.isDirectory()) {// 如果是文件,删除
file.delete();
} else {// 目录
if (file.listFiles().length == 0) {// 目录下没有文件或者目录,删除
file.delete();
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}