Android使用request发送数据包,当网络无法连接时,实现数据包自动保存,等网络连接后自动发送。

安卓开发中,实现了题目描述功能。

        @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();
            }
        }
    }
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值