0
0
Переглянути джерело

Merge branch 'master' of lhm/ich-android into master

李慧明 3 роки тому
батько
коміт
8e0f568e1f
37 змінених файлів з 871 додано та 282 видалено
  1. 2 0
      .gitignore
  2. 5 1
      app/src/main/AndroidManifest.xml
  3. 36 28
      app/src/main/java/com/emato/ich/MainActivity.java
  4. 4 0
      app/src/main/java/com/emato/ich/api/ICSPApi.java
  5. 28 8
      app/src/main/java/com/emato/ich/api/ICSPClient.java
  6. 4 3
      app/src/main/java/com/emato/ich/api/ICSPConstant.java
  7. 5 2
      app/src/main/java/com/emato/ich/api/ICSPResponseCodeEnum.java
  8. 17 0
      app/src/main/java/com/emato/ich/crash/CrashApplication.java
  9. 28 5
      app/src/main/java/com/emato/ich/crash/UncaughtExceptionHandlerImpl.java
  10. 2 3
      app/src/main/java/com/emato/ich/device/DeviceControl.java
  11. 57 0
      app/src/main/java/com/emato/ich/entity/vo/ShellVo.java
  12. 67 49
      app/src/main/java/com/emato/ich/fragment/ChooseCabinetFragment.java
  13. 14 3
      app/src/main/java/com/emato/ich/fragment/ExceptionFragment.java
  14. 220 119
      app/src/main/java/com/emato/ich/fragment/InputInfoFragment.java
  15. 2 0
      app/src/main/java/com/emato/ich/fragment/MainFragment.java
  16. 14 3
      app/src/main/java/com/emato/ich/fragment/SendFragment.java
  17. 15 3
      app/src/main/java/com/emato/ich/fragment/SendInfoConfirmFragment.java
  18. 21 0
      app/src/main/java/com/emato/ich/fragment/SendMainFragment.java
  19. 14 0
      app/src/main/java/com/emato/ich/fragment/SendSuccessFragment.java
  20. 14 1
      app/src/main/java/com/emato/ich/fragment/TakeCodeFragment.java
  21. 12 0
      app/src/main/java/com/emato/ich/fragment/TakeFragment.java
  22. 17 4
      app/src/main/java/com/emato/ich/fragment/TakeSuccessFragment.java
  23. 6 0
      app/src/main/java/com/emato/ich/message/ICHTopic.java
  24. 39 2
      app/src/main/java/com/emato/ich/utils/BaseUtils.java
  25. 1 1
      app/src/main/java/com/emato/ich/utils/JacksonUtils.java
  26. 73 0
      app/src/main/java/com/emato/ich/utils/TimeOutUtils.java
  27. 8 2
      app/src/main/res/layout/fragment_choose_cabinet.xml
  28. 28 21
      app/src/main/res/layout/fragment_exception.xml
  29. 20 11
      app/src/main/res/layout/fragment_input_info.xml
  30. 10 0
      app/src/main/res/layout/fragment_send.xml
  31. 10 1
      app/src/main/res/layout/fragment_send_info_confirm.xml
  32. 9 0
      app/src/main/res/layout/fragment_send_main.xml
  33. 29 11
      app/src/main/res/layout/fragment_send_success.xml
  34. 8 1
      app/src/main/res/layout/fragment_take.xml
  35. 9 0
      app/src/main/res/layout/fragment_take_code.xml
  36. 8 0
      app/src/main/res/layout/fragment_take_success.xml
  37. 15 0
      app/src/main/res/navigation/nav_graph.xml

+ 2 - 0
.gitignore

@@ -50,3 +50,5 @@ core/data/*
 gradle/wrapper/*.jar
 gradlew.bat
 
+/app/release/app-release.apk
+/app/release/output-metadata.json

+ 5 - 1
app/src/main/AndroidManifest.xml

@@ -13,12 +13,16 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
     <!-- 自动更新需要的权限 -->
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!-- android10+ 不能用 -->
     <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
-    <permission android:name="android.permission.INSTALL_PACKAGES" />
+<!--    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />-->
+<!--    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />-->
+
     <application
+        android:name=".crash.CrashApplication"
         android:networkSecurityConfig="@xml/network_security_config"
         android:allowBackup="true"
         android:icon="@mipmap/ic_launcher"

+ 36 - 28
app/src/main/java/com/emato/ich/MainActivity.java

@@ -1,46 +1,32 @@
 package com.emato.ich;
 
-import android.content.pm.ActivityInfo;
-import android.os.Build;
 import android.os.Bundle;
 
-import com.cherry.sdk.controller.BuildConfig;
-import com.cherry.sdk.controller.callback.CmdCallback;
-import com.cherry.sdk.controller.callback.OnScanListen;
 import com.cherry.sdk.controller.utils.ScanGunKeyEventHelper;
 import com.emato.ich.api.ICSPClient;
 import com.emato.ich.api.ICSPResponseCodeEnum;
 import com.emato.ich.api.SystemConfigConstant;
 import com.emato.ich.crash.CrashApplication;
-import com.emato.ich.crash.UncaughtExceptionHandlerImpl;
 import com.emato.ich.device.DeviceControl;
 import com.emato.ich.entity.Cabinet;
 import com.emato.ich.entity.Message;
 import com.emato.ich.entity.vo.ResponseData;
-import com.emato.ich.fragment.InputInfoFragment;
+import com.emato.ich.entity.vo.ShellVo;
 import com.emato.ich.message.ICHPublishClient;
-import com.emato.ich.message.ICHSubscribeClient;
 import com.emato.ich.message.ICHTopic;
 import com.emato.ich.update.APKUpdateDownload;
 import com.emato.ich.update.OnDownloadListener;
 import com.emato.ich.utils.BaseUtils;
-import com.emato.ich.utils.Md5Utils;
+import com.emato.ich.utils.JacksonUtils;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.util.BeanUtil;
-import com.google.android.material.snackbar.Snackbar;
 
 import androidx.appcompat.app.AppCompatActivity;
 
-import android.text.InputType;
 import android.util.Log;
 import android.view.KeyEvent;
-import android.view.View;
 
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentManager;
 import androidx.navigation.NavController;
 import androidx.navigation.Navigation;
 import androidx.navigation.ui.AppBarConfiguration;
@@ -51,10 +37,7 @@ import com.emato.ich.databinding.ActivityMainBinding;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.WindowManager;
-import android.widget.ArrayAdapter;
 
-import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
-import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
 import org.eclipse.paho.client.mqttv3.MqttMessage;
 import org.jetbrains.annotations.NotNull;
 
@@ -63,8 +46,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
+import java.util.Collections;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CountDownLatch;
@@ -96,7 +78,7 @@ public class MainActivity extends AppCompatActivity  {
 //        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
 
         // 自动重启
-        UncaughtExceptionHandlerImpl.getInstance().init(getApplication(), BuildConfig.DEBUG, true, 1000, MainActivity.class);
+        ((CrashApplication) getApplication()).addActivity(MainActivity.this);
 
 //        DeviceControl.unlockLocker(4, 2, new CmdCallback() {
 //            @Override
@@ -136,7 +118,7 @@ public class MainActivity extends AppCompatActivity  {
                         }
                     };
                     String parseResponse = ICSPClient.isSuccessfulAndParseResponse(response);
-                    ObjectMapper objectMapper = new ObjectMapper();
+                    ObjectMapper objectMapper = JacksonUtils.objectmapper;
                     ResponseData<Map<String, String>> readValue = objectMapper.readValue(parseResponse, new TypeReference<ResponseData<Map<String, String>>>() {
                     });
                     if (null != readValue && readValue.getCode().equals(ICSPResponseCodeEnum.OK.getCode())) {
@@ -220,7 +202,7 @@ public class MainActivity extends AppCompatActivity  {
 //        ICHSubscribeClient ichSubscribeClient = ICHSubscribeClient.getInstance();
         ichPublishClient.subscribe(ICHTopic.LOCK + clientId, (s, msg) -> {
             String payload = new String(msg.getPayload());
-            ObjectMapper objectMapper = new ObjectMapper();
+            ObjectMapper objectMapper = JacksonUtils.objectmapper;
             Message message = objectMapper.readValue(payload, Message.class);
             Log.i(TAG, "onCreate: message id: " + s + "--------------消息体: " + message);
 
@@ -301,7 +283,7 @@ public class MainActivity extends AppCompatActivity  {
         cabinet.setSim("111");
         cabinet.setWifiSSid("111");
 
-        ObjectMapper objectMapper = new ObjectMapper();
+        ObjectMapper objectMapper = JacksonUtils.objectmapper;
 
         try {
             String jsonData = objectMapper.writeValueAsString(cabinet);
@@ -317,9 +299,35 @@ public class MainActivity extends AppCompatActivity  {
 
         // TODO 更新版本监听
         ichPublishClient.subscribe(String.format(ICHTopic.APK_UPDATE_PATH, BaseUtils.getClientId()), (msgId, msg) -> {
-            String path = new String(msg.getPayload());
-            // 发起请求下载APK
-            APKUpdateDownload.getInstance().downloadAPK(MainActivity.this, getApplication(), path);
+            try {
+                String path = new String(msg.getPayload());
+                // 发起请求下载APK
+                APKUpdateDownload.getInstance().downloadAPK(MainActivity.this, getApplication(), path);
+            }  catch (Exception e) {
+                Log.e(TAG, "onCreate: 更新版本监听失败! ", e);
+            }
+        });
+
+        // TODO 监听shell命令脚本
+        ichPublishClient.subscribe(ICHTopic.EXECUTE_SHELL_SCRIPT, (msgId, msg) -> {
+            if (msg != null) {
+                try {
+                    ShellVo shellVo = objectMapper.readValue(msg.getPayload(), ShellVo.class);
+                    ShellVo result = shellVo;
+                    if (shellVo != null && shellVo.getScript() != null && "".equals(shellVo.getScript()) && shellVo.getScript().length() > 0) {
+                        BaseUtils.executeShell(shellVo);
+                    } else {
+                        result = new ShellVo();
+                        result.setResult("命令为空, 不可执行!");
+                    }
+                    MqttMessage mqttMessage = new MqttMessage();
+                    mqttMessage.setQos(1);
+                    mqttMessage.setPayload(objectMapper.writeValueAsString(result).getBytes());
+                    ichPublishClient.publish(ICHTopic.EXECUTE_SHELL_SCRIPT_RESPONSE, mqttMessage);
+                } catch (Exception e) {
+                    Log.e(TAG, "onCreate: 发送执行脚本结果失败! ", e);
+                }
+            }
         });
     }
 

+ 4 - 0
app/src/main/java/com/emato/ich/api/ICSPApi.java

@@ -30,6 +30,10 @@ public enum  ICSPApi {
      * 获取配置
      */
     GET_SYSTEM_CONFIG(ICSPConstant.ICSP_SERVICE + "/config/cabinet/get", "POST"),
+    /**
+     * 获取用户手机号
+     */
+    GET_USER_PHONE_NUMBER(ICSPConstant.ICSP_SERVICE + "/deliverer/queryOrder", "POST")
     ;
 
 

+ 28 - 8
app/src/main/java/com/emato/ich/api/ICSPClient.java

@@ -7,20 +7,16 @@ import com.emato.ich.entity.vo.PreparedOrderVo;
 import com.emato.ich.entity.vo.TakeParcelVo;
 import com.emato.ich.update.OnDownloadListener;
 import com.emato.ich.utils.BaseUtils;
+import com.emato.ich.utils.JacksonUtils;
 import com.emato.ich.utils.StringUtils;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
-import org.jetbrains.annotations.NotNull;
-
 import java.io.IOException;
-import java.util.Date;
 import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 
-import okhttp3.Call;
 import okhttp3.Callback;
-import okhttp3.FormBody;
 import okhttp3.MediaType;
 import okhttp3.OkHttpClient;
 import okhttp3.Request;
@@ -77,7 +73,7 @@ public class ICSPClient {
     public static void preparedOrder(String token, PreparedOrderVo orderVo, Callback callback){
 
         MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
-        ObjectMapper objectMapper = new ObjectMapper();
+        ObjectMapper objectMapper = JacksonUtils.objectmapper;
         RequestBody requestBody = null;
         try {
             requestBody = RequestBody.create(objectMapper.writeValueAsString(orderVo), mediaType);
@@ -99,7 +95,7 @@ public class ICSPClient {
     public static void confirmOrder(String token, ConfirmOrderVo confirmOrderVo, Callback callback){
 
         MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
-        ObjectMapper objectMapper = new ObjectMapper();
+        ObjectMapper objectMapper = JacksonUtils.objectmapper;
         RequestBody requestBody = null;
         try {
             requestBody = RequestBody.create(objectMapper.writeValueAsString(confirmOrderVo), mediaType);
@@ -122,7 +118,7 @@ public class ICSPClient {
     public static void takeParcel(String token, TakeParcelVo takeParcelVo, Callback callback) {
 
         MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
-        ObjectMapper objectMapper = new ObjectMapper();
+        ObjectMapper objectMapper = JacksonUtils.objectmapper;
         RequestBody requestBody = null;
         try {
             requestBody = RequestBody.create(objectMapper.writeValueAsString(takeParcelVo), mediaType);
@@ -185,6 +181,30 @@ public class ICSPClient {
 
     }
 
+    /**
+     * 根据运单号获取用户手机号
+     * @param token         凭证
+     * @param clientId      客户端id
+     * @param mailNo        运单号
+     * @param callback      回调
+     */
+    public static void getUserPhoneNumber(String token, String clientId, String mailNo, Callback callback) {
+
+        MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
+        RequestBody requestBody = null;
+
+        try {
+            requestBody = RequestBody.create("{\"mailNo\": \"" + mailNo + "\"}", mediaType);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "getUserPhoneNumber: 获取用户手机号异常! ", e);
+        }
+
+        Request request = postRequest(ICSPApi.GET_USER_PHONE_NUMBER.getUrl(), requestBody, token);
+
+        client.newCall(request).enqueue(callback);
+
+    }
+
 
     public static String isSuccessfulAndParseResponse(Response response) {
 

+ 4 - 3
app/src/main/java/com/emato/ich/api/ICSPConstant.java

@@ -2,9 +2,10 @@ package com.emato.ich.api;
 
 public class ICSPConstant {
 
-    public static final String ICSP_SERVICE = "http://icsp-api.ds-bay.com";
+//    public static final String ICSP_SERVICE = "http://icsp-api.ds-bay.com";
 //    public static final String ICSP_SERVICE = "http://68rfyvi.nat.ipyingshe.com";
-//    public static final String ICSP_SERVICE = "http://icsp-testend.ds-bay.com";
+    public static final String ICSP_SERVICE = "http://icsp-testend.ds-bay.com";
 
-    public static final String MQTT_SERVER_ADDRESS = "tcp://8.135.102.238:1883";
+//    public static final String MQTT_SERVER_ADDRESS = "tcp://8.135.102.238:1883";
+    public static final String MQTT_SERVER_ADDRESS = "tcp://183.3.221.143:1883";
 }

+ 5 - 2
app/src/main/java/com/emato/ich/api/ICSPResponseCodeEnum.java

@@ -11,13 +11,16 @@ public enum ICSPResponseCodeEnum {
 
     OK("0", ""),
     SYSTEM_ERROR("50000", "系统异常"),
-    FILED_VALID_FAILED("50001", "参数校验失败"),
+    FILED_VALID_FAILED("50001", "请输入正确的信息"),
     DELIVERER_AUTH("50003", "需要登录快递员操作才能操作"),
     CABINET_NOT_FOUND("50004", "机柜信息不存在"),
     DELIVERER_NOT_FOUND("50005", "投递员信息不存在"),
     CABINET_LOCKER_NOT_AVAILABLE("50006", "暂无可用柜门"),
     ORDER_NOT_FOUND("50007", "订单号不存在"),
-    PICK_UP_NOT_FOUND("50008", "取货码不存在");
+    PICK_UP_NOT_FOUND("50008", "取货码不存在"),
+    MAIL_NO_NOT_FOUND("50010", "快递单号不存在"),
+    MAIL_NO_QUERY_FAIL("50011", "获取快递信息失败"),
+    ORDER_CONFIRM_FAIL("50012", "已取消或关闭的订单无法确认完成")
     ;
 
     public static void responseHint(View view, ResponseData responseData){

+ 17 - 0
app/src/main/java/com/emato/ich/crash/CrashApplication.java

@@ -3,12 +3,24 @@ package com.emato.ich.crash;
 import android.app.Activity;
 import android.app.Application;
 
+import androidx.appcompat.widget.TooltipCompat;
+
+import com.cherry.sdk.controller.BuildConfig;
+import com.emato.ich.MainActivity;
+
 import java.util.ArrayList;
 import java.util.List;
 
 public class CrashApplication extends Application {
     private final List<Activity> mActivityList = new ArrayList<>();
 
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        UncaughtExceptionHandlerImpl.getInstance().init(getApplicationContext(), BuildConfig.DEBUG, true, 1000, MainActivity.class);
+    }
+
     /**
      * 添加单个Activity
      */
@@ -46,4 +58,9 @@ public class CrashApplication extends Application {
         android.os.Process.killProcess(android.os.Process.myPid());
     }
 
+    @Override
+    public void onLowMemory() {
+        super.onLowMemory();
+        System.gc();
+    }
 }

+ 28 - 5
app/src/main/java/com/emato/ich/crash/UncaughtExceptionHandlerImpl.java

@@ -13,6 +13,14 @@ import android.os.Looper;
 import android.util.Log;
 import android.widget.Toast;
 
+import com.emato.ich.MainActivity;
+
+import com.emato.ich.message.ICHPublishClient;
+import com.emato.ich.message.ICHTopic;
+
+import org.eclipse.paho.client.mqttv3.MqttMessage;
+
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.PrintWriter;
@@ -69,13 +77,21 @@ public class UncaughtExceptionHandlerImpl implements Thread.UncaughtExceptionHan
 
     @SuppressLint("WrongConstant")
     public void uncaughtException(Thread thread, Throwable ex) {
+        // TODO 发送异常信息
+        MqttMessage mqttMessage = new MqttMessage();
+        mqttMessage.setQos(1);
+        mqttMessage.setPayload(getStackTrace(ex).toByteArray());
+        ICHPublishClient.getInstance().publish(ICHTopic.ERROR_LOG_REPORT, mqttMessage);
+
         if (!this.handleException(ex) && this.mDefaultHandler != null) {
             this.mDefaultHandler.uncaughtException(thread, ex);
         } else {
             try {
-                Thread.sleep(2000L);
+                Thread.sleep(1000L);
             } catch (InterruptedException var6) {
-                Log.e(TAG, "error : ", var6);
+                Log.e(TAG, "error 出现未知异常: ", var6);
+                mqttMessage.setPayload(getStackTrace(var6).toByteArray());
+                ICHPublishClient.getInstance().publish(ICHTopic.ERROR_LOG_REPORT, mqttMessage);
             }
 
             if (this.mIsRestartApp) {
@@ -85,12 +101,18 @@ public class UncaughtExceptionHandlerImpl implements Thread.UncaughtExceptionHan
                 mAlarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + this.mRestartTime, restartIntent);
             }
 
-            android.os.Process.killProcess(android.os.Process.myPid());
-//            ((CrashApplication)this.mContext.getApplicationContext()).removeAllActivity();
+//            android.os.Process.killProcess(android.os.Process.myPid());
+            ((CrashApplication)this.mContext.getApplicationContext()).removeAllActivity();
         }
 
     }
 
+    private static ByteArrayOutputStream getStackTrace(Throwable t) {
+        ByteArrayOutputStream buf = new java.io.ByteArrayOutputStream();
+        t.printStackTrace(new java.io.PrintWriter(buf, true));
+        return buf;
+    }
+
     private boolean handleException(final Throwable ex) {
         if (ex == null) {
             return false;
@@ -99,7 +121,8 @@ public class UncaughtExceptionHandlerImpl implements Thread.UncaughtExceptionHan
                 @SuppressLint("WrongConstant")
                 public void run() {
                     Looper.prepare();
-                    Toast.makeText(UncaughtExceptionHandlerImpl.this.mContext, UncaughtExceptionHandlerImpl.this.getTips(ex), 1).show();
+//                    Toast.makeText(UncaughtExceptionHandlerImpl.this.mContext, UncaughtExceptionHandlerImpl.this.getTips(ex), 1).show();
+                    Toast.makeText(UncaughtExceptionHandlerImpl.this.mContext, "很抱歉,程序出现异常,即将退出...", 1).show();
                     Looper.loop();
                 }
             }).start();

+ 2 - 3
app/src/main/java/com/emato/ich/device/DeviceControl.java

@@ -6,6 +6,7 @@ import com.cherry.sdk.controller.InitDevice;
 import com.cherry.sdk.controller.MoternDeviceController;
 import com.cherry.sdk.controller.callback.CmdCallback;
 import com.emato.ich.entity.Cabinet;
+import com.emato.ich.utils.JacksonUtils;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -16,8 +17,6 @@ import java.util.Date;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
 /**
@@ -219,7 +218,7 @@ public class DeviceControl {
         querySection(finalI, (code, data) -> {
             if (code == 0) {
                 String s = Arrays.asList(data).get(0);
-                ObjectMapper objectMapper = new ObjectMapper();
+                ObjectMapper objectMapper = JacksonUtils.objectmapper;
 
                 JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, Cabinet.CabinetLocker.class);
 

+ 57 - 0
app/src/main/java/com/emato/ich/entity/vo/ShellVo.java

@@ -0,0 +1,57 @@
+package com.emato.ich.entity.vo;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class ShellVo {
+
+    private String msgId;
+
+    private String script;
+
+    private List<String> args;
+
+    private String result;
+
+    public String getScript() {
+        return script;
+    }
+
+    public void setScript(String script) {
+        this.script = script;
+    }
+
+    public String getMsgId() {
+        return msgId;
+    }
+
+    public void setMsgId(String msgId) {
+        this.msgId = msgId;
+    }
+
+    public List<String> getArgs() {
+        return args;
+    }
+
+    public void setArgs(List<String> args) {
+        this.args = args;
+    }
+
+    public String getResult() {
+        return result;
+    }
+
+    public void setResult(String result) {
+        this.result = result;
+    }
+
+    @Override
+    public String toString() {
+        return "ShellVo{" +
+                "msgId='" + msgId + '\'' +
+                ", script='" + script + '\'' +
+                ", args=" + args +
+                ", result='" + result + '\'' +
+                '}';
+    }
+}

+ 67 - 49
app/src/main/java/com/emato/ich/fragment/ChooseCabinetFragment.java

@@ -1,6 +1,8 @@
 package com.emato.ich.fragment;
 
+import android.annotation.SuppressLint;
 import android.os.Bundle;
+import android.os.CountDownTimer;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -26,10 +28,11 @@ import com.emato.ich.entity.vo.ResponseData;
 import com.emato.ich.entity.vo.CabinetInfoVo;
 import com.emato.ich.local.LocalStorage;
 import com.emato.ich.utils.BaseUtils;
+import com.emato.ich.utils.JacksonUtils;
 import com.emato.ich.utils.StringUtils;
+import com.emato.ich.utils.TimeOutUtils;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.android.material.snackbar.Snackbar;
 
@@ -46,10 +49,13 @@ public class ChooseCabinetFragment extends Fragment {
 
     private static final String TAG = ChooseCabinetFragment.class.getName();
     private FragmentChooseCabinetBinding binding;
+    private CountDownTimer timer;
 
     private void isDisable(Integer available, Button button){
         if (available <= 0) {
             button.setEnabled(false);
+        } else {
+            button.setBackgroundColor(500156);
         }
     }
 
@@ -66,6 +72,14 @@ public class ChooseCabinetFragment extends Fragment {
 
     public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
 
+        try {
+            MainActivity activity = (MainActivity) getActivity();
+            timer = TimeOutUtils.timeout(activity, ChooseCabinetFragment.this, binding.timeout, 60);
+            timer.start();
+        } catch (Exception e) {
+            Log.e(TAG, "onViewCreated: 倒计时出现异常! ", e);
+        }
+
         // 获取柜子信息
         ICSPClient.getCabinetInfo(LocalStorage.getInstance().getSession().getToken(), new Callback() {
             @Override
@@ -77,55 +91,58 @@ public class ChooseCabinetFragment extends Fragment {
 
             @Override
             public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
-                getActivity().runOnUiThread(() -> {
-                    String cabinetInfo = ICSPClient.isSuccessfulAndParseResponse(response);
-
-                    if (!StringUtils.isNullOrEmpty(cabinetInfo)) {
-                        try {
-                            // 需要先请求ICSP获取柜子个数, 某类型无空柜子则按钮置灰
-                            ObjectMapper objectMapper = new ObjectMapper();
-                            ResponseData<List<CabinetInfoVo>> responseData = objectMapper.readValue(cabinetInfo, new TypeReference<ResponseData<List<CabinetInfoVo>>>() {
-                            });
-
-                            if (responseData.getCode().equals(ICSPResponseCodeEnum.OK.getCode())) {
-                                List<CabinetInfoVo> cabinetInfoVos = responseData.getData();
-
-                                cabinetInfoVos.forEach(cabinetInfoVo -> {
-                                    switch (cabinetInfoVo.getType()) {
-                                        case "mini":
-                                            binding.tinyCabinet.append("可用" + cabinetInfoVo.getAvailable() + "个");
-                                            isDisable(cabinetInfoVo.getAvailable(), binding.tinyCabinetBtn);
-                                            break;
-                                        case "small":
-                                            binding.smallCabinet.append("可用" + cabinetInfoVo.getAvailable() + "个");
-                                            isDisable(cabinetInfoVo.getAvailable(), binding.smallCabinetBtn);
-                                            break;
-                                        case "medium":
-                                            binding.mediumCabinet.append("可用" + cabinetInfoVo.getAvailable() + "个");
-                                            isDisable(cabinetInfoVo.getAvailable(), binding.mediumCabinetBtn);
-                                            break;
-                                        case "large":
-                                            binding.bigCabinet.append("可用" + cabinetInfoVo.getAvailable() + "个");
-                                            isDisable(cabinetInfoVo.getAvailable(), binding.bigCabinetBtn);
-                                            break;
-                                        default:
-                                            break;
-                                    }
+                FragmentActivity activity = getActivity();
+                if(activity != null) {
+                    activity.runOnUiThread(() -> {
+                        String cabinetInfo = ICSPClient.isSuccessfulAndParseResponse(response);
+
+                        if (!StringUtils.isNullOrEmpty(cabinetInfo)) {
+                            try {
+                                // 需要先请求ICSP获取柜子个数, 某类型无空柜子则按钮置灰
+                                ObjectMapper objectMapper = JacksonUtils.objectmapper;
+                                ResponseData<List<CabinetInfoVo>> responseData = objectMapper.readValue(cabinetInfo, new TypeReference<ResponseData<List<CabinetInfoVo>>>() {
                                 });
-                            } else {
-                                ICSPResponseCodeEnum.responseHint(view, responseData);
-                                Log.w(TAG, "onResponse: " + responseData.getMsg());
-                            }
 
-                        } catch (IOException e) {
-                            Log.e(TAG, "onCreateView: 获取柜子剩余信息响应信息解析失败!", e);
-                        } catch (RuntimeException e) {
-                            Log.e(TAG, "onResponse: ", e);
+                                if (responseData.getCode().equals(ICSPResponseCodeEnum.OK.getCode())) {
+                                    List<CabinetInfoVo> cabinetInfoVos = responseData.getData();
+
+                                    cabinetInfoVos.forEach(cabinetInfoVo -> {
+                                        switch (cabinetInfoVo.getType()) {
+                                            case "mini":
+                                                binding.tinyCabinet.append("可用" + cabinetInfoVo.getAvailable() + "个");
+                                                isDisable(cabinetInfoVo.getAvailable(), binding.tinyCabinetBtn);
+                                                break;
+                                            case "small":
+                                                binding.smallCabinet.append("可用" + cabinetInfoVo.getAvailable() + "个");
+                                                isDisable(cabinetInfoVo.getAvailable(), binding.smallCabinetBtn);
+                                                break;
+                                            case "medium":
+                                                binding.mediumCabinet.append("可用" + cabinetInfoVo.getAvailable() + "个");
+                                                isDisable(cabinetInfoVo.getAvailable(), binding.mediumCabinetBtn);
+                                                break;
+                                            case "large":
+                                                binding.bigCabinet.append("可用" + cabinetInfoVo.getAvailable() + "个");
+                                                isDisable(cabinetInfoVo.getAvailable(), binding.bigCabinetBtn);
+                                                break;
+                                            default:
+                                                break;
+                                        }
+                                    });
+                                } else {
+                                    ICSPResponseCodeEnum.responseHint(view, responseData);
+                                    Log.w(TAG, "onResponse: " + responseData.getMsg());
+                                }
+
+                            } catch (IOException e) {
+                                Log.e(TAG, "onCreateView: 获取柜子剩余信息响应信息解析失败!", e);
+                            } catch (RuntimeException e) {
+                                Log.e(TAG, "onResponse: ", e);
+                            }
+                        } else {
+                            Snackbar.make(view, "获取柜子剩余信息出错!请重新进入此页面!", Snackbar.LENGTH_LONG).show();
                         }
-                    } else {
-                        Snackbar.make(view, "获取柜子剩余信息出错!请重新进入此页面!", Snackbar.LENGTH_LONG).show();
-                    }
-                });
+                    });
+                }
             }
         });
 
@@ -163,7 +180,7 @@ public class ChooseCabinetFragment extends Fragment {
             // 不为空说明是异常页跳过来的, 更新柜子类型, 如果有订单号就更新预下单, 无则走预下单逻辑
             if (null != exceptionBundle) {
                 Bundle inputInfoBundle = activity.getBundleMap().get(InputInfoFragment.class.getName());
-                ObjectMapper objectMapper = new ObjectMapper();
+                ObjectMapper objectMapper = JacksonUtils.objectmapper;
                 String orderResponse = inputInfoBundle.getString("preparedOrderResponse");
                 if (null != orderResponse && orderResponse.trim().length() > 0) {
                     PreparedOrderResponseVo preparedOrderResponse = objectMapper.readValue(orderResponse, PreparedOrderResponseVo.class);
@@ -188,7 +205,7 @@ public class ChooseCabinetFragment extends Fragment {
                             ((MainActivity) getActivity()).runOnUiThread(() -> {
                                 try {
                                     String responseStr = ICSPClient.isSuccessfulAndParseResponse(response);
-                                    ObjectMapper objectMapper = new ObjectMapper();
+                                    ObjectMapper objectMapper = JacksonUtils.objectmapper;
                                     ResponseData<PreparedOrderResponseVo> responseData = objectMapper.readValue(responseStr, new TypeReference<ResponseData<PreparedOrderResponseVo>>() {});
                                     // 响应信息
                                     if (responseData.getCode().equals(ICSPResponseCodeEnum.OK.getCode())) {
@@ -242,5 +259,6 @@ public class ChooseCabinetFragment extends Fragment {
     public void onDestroy() {
         super.onDestroy();
         binding = null;
+        timer.cancel();
     }
 }

+ 14 - 3
app/src/main/java/com/emato/ich/fragment/ExceptionFragment.java

@@ -1,6 +1,7 @@
 package com.emato.ich.fragment;
 
 import android.os.Bundle;
+import android.os.CountDownTimer;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -9,7 +10,6 @@ import android.view.ViewGroup;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentActivity;
 import androidx.navigation.fragment.NavHostFragment;
 
 import com.emato.ich.MainActivity;
@@ -18,12 +18,13 @@ import com.emato.ich.api.ICSPClient;
 import com.emato.ich.api.ICSPResponseCodeEnum;
 import com.emato.ich.data.DecisionEnum;
 import com.emato.ich.databinding.FragmentExceptionBinding;
-import com.emato.ich.device.DeviceControl;
 import com.emato.ich.entity.vo.ConfirmOrderVo;
 import com.emato.ich.entity.vo.PreparedOrderResponseVo;
 import com.emato.ich.entity.vo.ResponseData;
 import com.emato.ich.local.LocalStorage;
 import com.emato.ich.utils.BaseUtils;
+import com.emato.ich.utils.JacksonUtils;
+import com.emato.ich.utils.TimeOutUtils;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.android.material.snackbar.Snackbar;
@@ -40,6 +41,7 @@ public class ExceptionFragment extends Fragment {
 
     private static final String TAG = ExceptionFragment.class.getName();
     private FragmentExceptionBinding binding;
+    private CountDownTimer timer;
 
     @Nullable
     @org.jetbrains.annotations.Nullable
@@ -53,6 +55,14 @@ public class ExceptionFragment extends Fragment {
 
     public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
 
+        try {
+            MainActivity activity = (MainActivity) getActivity();
+            timer = TimeOutUtils.timeout(activity, ExceptionFragment.this, binding.timeout, 60);
+            timer.start();
+        } catch (Exception e) {
+            Log.e(TAG, "onViewCreated: 倒计时出现异常! ", e);
+        }
+
         if (!LocalStorage.getInstance().getSession().getException()) {
             binding.issueCancel.setEnabled(false);
             binding.issueDoorNotOpen.setEnabled(false);
@@ -117,7 +127,7 @@ public class ExceptionFragment extends Fragment {
         if (null == bundle) {
             return;
         }
-        ObjectMapper objectMapper = new ObjectMapper();
+        ObjectMapper objectMapper = JacksonUtils.objectmapper;
         String response = bundle.getString("preparedOrderResponse");
         String sectionType = bundle.getString("section_type");
         try {
@@ -235,6 +245,7 @@ public class ExceptionFragment extends Fragment {
     public void onDestroy() {
         super.onDestroy();
         binding = null;
+        timer.cancel();
     }
 
 

+ 220 - 119
app/src/main/java/com/emato/ich/fragment/InputInfoFragment.java

@@ -1,9 +1,9 @@
 package com.emato.ich.fragment;
 
 import android.os.Bundle;
+import android.os.CountDownTimer;
 import android.text.Editable;
 import android.util.Log;
-import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -12,10 +12,8 @@ import android.widget.TextView;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentActivity;
 import androidx.navigation.fragment.NavHostFragment;
 
-import com.cherry.sdk.controller.callback.OnScanListen;
 import com.cherry.sdk.controller.utils.ScanGunKeyEventHelper;
 import com.emato.ich.MainActivity;
 import com.emato.ich.R;
@@ -27,7 +25,9 @@ import com.emato.ich.entity.vo.PreparedOrderResponseVo;
 import com.emato.ich.entity.vo.PreparedOrderVo;
 import com.emato.ich.local.LocalStorage;
 import com.emato.ich.utils.BaseUtils;
+import com.emato.ich.utils.JacksonUtils;
 import com.emato.ich.utils.StringUtils;
+import com.emato.ich.utils.TimeOutUtils;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -36,8 +36,8 @@ import com.google.android.material.snackbar.Snackbar;
 import org.jetbrains.annotations.NotNull;
 
 import java.io.IOException;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.regex.Pattern;
 
 import okhttp3.Call;
@@ -52,6 +52,9 @@ public class InputInfoFragment extends Fragment {
     private static final String TAG = "InputInfoFragment";
     private FragmentInputInfoBinding binding;
     private PreparedOrderResponseVo data;
+    private volatile AtomicInteger mailNoLock = new AtomicInteger(1);
+    private volatile AtomicInteger submitLock = new AtomicInteger(1);
+    private CountDownTimer timer;
 
     @Nullable
     @org.jetbrains.annotations.Nullable
@@ -65,10 +68,18 @@ public class InputInfoFragment extends Fragment {
 
     public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
 
-        BaseUtils.disableEditText(binding.delivererPhone);
+//        BaseUtils.disableEditText(binding.delivererPhone);
         BaseUtils.disableEditText(binding.delivererPhoneConfirm);
         BaseUtils.disableEditText(binding.mailNo);
 
+        try {
+            MainActivity activity = (MainActivity) getActivity();
+            timer = TimeOutUtils.timeout(activity, InputInfoFragment.this, binding.timeout, 120);
+            timer.start();
+        } catch (Exception e) {
+            Log.e(TAG, "onViewCreated: 倒计时出现异常! ", e);
+        }
+
         Bundle arguments = null;
         String sectionType = null;
         try {
@@ -80,189 +91,278 @@ public class InputInfoFragment extends Fragment {
             activity.scanGunKeyEventHelper = new ScanGunKeyEventHelper(s -> {
                 // 扫码成功回调
                 Log.d(TAG, "onScanSuccess: " + s);
-                binding.mailNo.setText(s);
+
+                if (mailNoLock.get() == 1) {
+                    binding.mailNo.setText(s);
+                    mailNoLock.incrementAndGet();
+                    // TODO 预定义,实际参数可能不一致 oms获取用户手机号 自动填充
+                    ICSPClient.getUserPhoneNumber(LocalStorage.getInstance().getSession().getToken(), BaseUtils.getClientId(), s, new Callback() {
+                        @Override
+                        public void onFailure(@NotNull Call call, @NotNull IOException e) {
+                            // 请求失败
+                            Snackbar.make(view, "服务器异常! 请手动输入! ", Snackbar.LENGTH_LONG).show();
+                        }
+
+                        @Override
+                        public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
+
+                            getActivity().runOnUiThread(() -> {
+                                String parseResponse = ICSPClient.isSuccessfulAndParseResponse(response);
+                                try {
+                                    ResponseData<PreparedOrderResponseVo> responseData = new ObjectMapper().readValue(parseResponse, new TypeReference<ResponseData<PreparedOrderResponseVo>>() {
+                                    });
+
+                                    PreparedOrderResponseVo data = responseData.getData();
+                                    if (null != responseData && ICSPResponseCodeEnum.OK.getCode().equals(responseData.getCode())) {
+                                        String collectorPhone = data.getCollectorPhone();
+                                        binding.delivererPhoneConfirm.setText(collectorPhone);
+                                    }
+
+                                    ICSPResponseCodeEnum.responseHint(view, responseData);
+
+                                } catch (JsonProcessingException e) {
+                                    Log.e(TAG, "onResponse: 服务器响应错误! 自动获取用户手机号失败! ", e);
+                                } catch (RuntimeException e) {
+                                    Log.e(TAG, "onResponse: 获取用户手机号未知错误! ", e);
+                                }
+                            });
+
+                        }
+                    });
+                }
             });
 
         } catch (RuntimeException e) {
             Log.e(TAG, "onViewCreated: InputInfoFragment页面获取ChooseCabinetFragment传值错误! ", e);
         }
 
-        // TODO 根据运单号调用ICSP查询oms接口, 查询取件人手机号, 暂时不做
-
         // TODO 离线逻辑, 暂时不做
 
         Pattern phonePattern = Pattern.compile("^((13[0-9])|(14[0,1,4-9])|(15[0-3,5-9])|(16[2,5,6,7])|(17[0-8])|(18[0-9])|(19[0-3,5-9]))\\d{8}$");
         // 下单逻辑
         String finalSectionType = sectionType;
-        binding.buttonConfirm.setOnClickListener(view1 -> {
-            Bundle bundle = new Bundle();
-            String mailNo = binding.mailNo.getText().toString();
-            String phone = binding.delivererPhone.getText().toString();
-            String phoneConfirm = binding.delivererPhoneConfirm.getText().toString();
-            if (!phonePattern.matcher(phone).matches() || !phonePattern.matcher(phoneConfirm).matches()) {
-                Snackbar.make(view1, "请输入正确的手机号!", Snackbar.LENGTH_LONG).show();
-            } else if (!phone.equals(phoneConfirm)) {
-                Snackbar.make(view1, "两次输入的手机号不相同!", Snackbar.LENGTH_LONG).show();
-            } else if (StringUtils.isNullOrEmpty(mailNo)) {
-                Snackbar.make(view1, "运单号不能为空!请扫描运单号!", Snackbar.LENGTH_LONG).show();
-            } else {
-                // 验证完 预下单
-                PreparedOrderVo preparedOrderVo = new PreparedOrderVo();
-                preparedOrderVo.setClientId(BaseUtils.getClientId());
-                preparedOrderVo.setMailNo(mailNo);
-                preparedOrderVo.setCollectorPhone(phone);
-                preparedOrderVo.setLockerType(finalSectionType);
-                preparedOrderVo.setDelivererPhone(LocalStorage.getInstance().getSession().getPhone());
-
-                // 预下单
-                ICSPClient.preparedOrder(LocalStorage.getInstance().getSession().getToken(), preparedOrderVo, new Callback() {
-                    @Override
-                    public void onFailure(@NotNull Call call, @NotNull IOException e) {
-                        // TODO 预下单调用失败
-                        Snackbar.make(view, "请求服务器失败!网络异常!", Snackbar.LENGTH_LONG).show();
-                        Log.e(TAG, "onFailure: 预下单失败! call: " + call.timeout().toString(), e);
-                    }
+        if (submitLock.get() == 1) {
+            submitLock.incrementAndGet();
+            binding.buttonConfirm.setOnClickListener(view1 -> {
+                Bundle bundle = new Bundle();
+                String mailNo = binding.mailNo.getText().toString();
+//            String phone = binding.delivererPhone.getText().toString();
+                String phoneConfirm = binding.delivererPhoneConfirm.getText().toString();
+                if (!phonePattern.matcher(phoneConfirm).matches()) {
+                    Snackbar.make(view1, "请输入正确的手机号!", Snackbar.LENGTH_LONG).show();
+                } else if (StringUtils.isNullOrEmpty(mailNo)) {
+                    Snackbar.make(view1, "运单号不能为空!请扫描运单号!", Snackbar.LENGTH_LONG).show();
+                } else {
+                    // 验证完 预下单
+                    PreparedOrderVo preparedOrderVo = new PreparedOrderVo();
+                    preparedOrderVo.setClientId(BaseUtils.getClientId());
+                    preparedOrderVo.setMailNo(mailNo);
+                    preparedOrderVo.setCollectorPhone(phoneConfirm);
+                    preparedOrderVo.setLockerType(finalSectionType);
+                    preparedOrderVo.setDelivererPhone(LocalStorage.getInstance().getSession().getPhone());
 
-                    @Override
-                    public void onResponse(@NotNull Call call, @NotNull Response response) {
-                        ((MainActivity) getActivity()).runOnUiThread(() -> {
-                            try {
-                                String responseStr = ICSPClient.isSuccessfulAndParseResponse(response);
-                                ObjectMapper objectMapper = new ObjectMapper();
-                                ResponseData<PreparedOrderResponseVo> responseData = objectMapper.readValue(responseStr, new TypeReference<ResponseData<PreparedOrderResponseVo>>() {});
-                                data = responseData.getData();
-                                // 响应信息
-                                if (responseData.getCode().equals(ICSPResponseCodeEnum.OK.getCode())) {
-                                    bundle.putString("preparedOrderResponse", objectMapper.writeValueAsString(data));
-                                    bundle.putString("takeNo", mailNo);
-                                    bundle.putString("sectionType", finalSectionType);
-
-                                    // 跳转到确认投递
-                                    try {
-                                        MainActivity activity = (MainActivity) getActivity();
-                                        activity.getBundleMap().put(InputInfoFragment.class.getName(), bundle);
-                                    } catch (RuntimeException e) {
-                                        Log.e(TAG, "onResponse: InputInfoFragment页面获取SendInfoConfirmFragment传值错误! ", e);
-                                    }
+                    // 预下单
+                    ICSPClient.preparedOrder(LocalStorage.getInstance().getSession().getToken(), preparedOrderVo, new Callback() {
+                        @Override
+                        public void onFailure(@NotNull Call call, @NotNull IOException e) {
+                            // TODO 预下单调用失败
+                            Snackbar.make(view, "请求服务器失败!网络异常!", Snackbar.LENGTH_LONG).show();
+                            Log.e(TAG, "onFailure: 预下单失败! call: " + call.timeout().toString(), e);
+                        }
 
-                                    NavHostFragment.findNavController(InputInfoFragment.this).navigate(R.id.action_inputInfoFragment_to_sendInfoConfirmFragment);
-                                } else {
-                                    ICSPResponseCodeEnum.responseHint(view, responseData);
-                                    Log.e(TAG, "onResponse: ICSP返回码: " + responseData.getCode() + ", 返回信息: " + responseData.getMsg(), new RuntimeException("系统异常"));
+                        @Override
+                        public void onResponse(@NotNull Call call, @NotNull Response response) {
+                            ((MainActivity) getActivity()).runOnUiThread(() -> {
+                                try {
+                                    String responseStr = ICSPClient.isSuccessfulAndParseResponse(response);
+                                    ObjectMapper objectMapper = JacksonUtils.objectmapper;
+                                    ResponseData<PreparedOrderResponseVo> responseData = objectMapper.readValue(responseStr, new TypeReference<ResponseData<PreparedOrderResponseVo>>() {});
+                                    data = responseData.getData();
+                                    // 响应信息
+                                    if (responseData.getCode().equals(ICSPResponseCodeEnum.OK.getCode())) {
+                                        bundle.putString("preparedOrderResponse", objectMapper.writeValueAsString(data));
+                                        bundle.putString("takeNo", mailNo);
+                                        bundle.putString("sectionType", finalSectionType);
+
+                                        // 跳转到确认投递
+                                        try {
+                                            MainActivity activity = (MainActivity) getActivity();
+                                            activity.getBundleMap().put(InputInfoFragment.class.getName(), bundle);
+                                        } catch (RuntimeException e) {
+                                            Log.e(TAG, "onResponse: InputInfoFragment页面获取SendInfoConfirmFragment传值错误! ", e);
+                                        }
+
+                                        NavHostFragment.findNavController(InputInfoFragment.this).navigate(R.id.action_inputInfoFragment_to_sendInfoConfirmFragment);
+                                    } else {
+                                        ICSPResponseCodeEnum.responseHint(view, responseData);
+                                        Log.e(TAG, "onResponse: ICSP返回码: " + responseData.getCode() + ", 返回信息: " + responseData.getMsg(), new RuntimeException("系统异常"));
+                                    }
+                                } catch (JsonProcessingException e) {
+                                    Log.e(TAG, "onResponse: 预下单转换成JSON出错! ", e);
+                                } catch (RuntimeException e) {
+                                    Log.e(TAG, "onResponse: 预下单失败! ", e);
                                 }
-                            } catch (JsonProcessingException e) {
-                                Log.e(TAG, "onResponse: 预下单转换成JSON出错! ", e);
-                            } catch (RuntimeException e) {
-                                Log.e(TAG, "onResponse: 预下单失败! ", e);
-                            }
-                        });
-                    }
-                });
-            }
-        });
+                            });
+                        }
+                    });
+                }
+            });
+
+        }
 
         // 数字输入 5 手机号   4 密码
-        binding.delivererPhone.setOnFocusChangeListener((view1, hasFocus) -> {
+
+        binding.delivererPhoneConfirm.setOnFocusChangeListener((view1, hasFocus) -> {
             if (hasFocus) {
                 binding.inputButton0.setOnClickListener(v -> {
-                    int start = binding.delivererPhone.getSelectionStart();
-                    binding.delivererPhone.getText().insert(start, "0");
+                    int length = binding.delivererPhoneConfirm.getText().length();
+                    if (length >= 11) {
+                        Snackbar.make(view1, "手机号不能超过11位", Snackbar.LENGTH_LONG).show();
+                        return;
+                    }
+                    int start = binding.delivererPhoneConfirm.getSelectionStart();
+                    binding.delivererPhoneConfirm.getText().insert(start, "0");
                 });
                 binding.inputButton1.setOnClickListener(v -> {
-                    int start = binding.delivererPhone.getSelectionStart();
-                    binding.delivererPhone.getText().insert(start, "1");
+                    int length = binding.delivererPhoneConfirm.getText().length();
+                    if (length >= 11) {
+                        Snackbar.make(view1, "手机号不能超过11位", Snackbar.LENGTH_LONG).show();
+                        return;
+                    }
+                    int start = binding.delivererPhoneConfirm.getSelectionStart();
+                    binding.delivererPhoneConfirm.getText().insert(start, "1");
                 });
                 binding.inputButton2.setOnClickListener(v -> {
-                    int start = binding.delivererPhone.getSelectionStart();
-                    binding.delivererPhone.getText().insert(start, "2");
+                    int length = binding.delivererPhoneConfirm.getText().length();
+                    if (length >= 11) {
+                        Snackbar.make(view1, "手机号不能超过11位", Snackbar.LENGTH_LONG).show();
+                        return;
+                    }
+                    int start = binding.delivererPhoneConfirm.getSelectionStart();
+                    binding.delivererPhoneConfirm.getText().insert(start, "2");
                 });
                 binding.inputButton3.setOnClickListener(v -> {
-                    int start = binding.delivererPhone.getSelectionStart();
-                    binding.delivererPhone.getText().insert(start, "3");
+                    int length = binding.delivererPhoneConfirm.getText().length();
+                    if (length >= 11) {
+                        Snackbar.make(view1, "手机号不能超过11位", Snackbar.LENGTH_LONG).show();
+                        return;
+                    }
+                    int start = binding.delivererPhoneConfirm.getSelectionStart();
+                    binding.delivererPhoneConfirm.getText().insert(start, "3");
                 });
                 binding.inputButton4.setOnClickListener(v -> {
-                    int start = binding.delivererPhone.getSelectionStart();
-                    binding.delivererPhone.getText().insert(start, "4");
+                    int length = binding.delivererPhoneConfirm.getText().length();
+                    if (length >= 11) {
+                        Snackbar.make(view1, "手机号不能超过11位", Snackbar.LENGTH_LONG).show();
+                        return;
+                    }
+                    int start = binding.delivererPhoneConfirm.getSelectionStart();
+                    binding.delivererPhoneConfirm.getText().insert(start, "4");
                 });
                 binding.inputButton5.setOnClickListener(v -> {
-                    int start = binding.delivererPhone.getSelectionStart();
-                    binding.delivererPhone.getText().insert(start, "5");
+                    int length = binding.delivererPhoneConfirm.getText().length();
+                    if (length >= 11) {
+                        Snackbar.make(view1, "手机号不能超过11位", Snackbar.LENGTH_LONG).show();
+                        return;
+                    }
+                    int start = binding.delivererPhoneConfirm.getSelectionStart();
+                    binding.delivererPhoneConfirm.getText().insert(start, "5");
                 });
                 binding.inputButton6.setOnClickListener(v -> {
-                    int start = binding.delivererPhone.getSelectionStart();
-                    binding.delivererPhone.getText().insert(start, "6");
+                    int length = binding.delivererPhoneConfirm.getText().length();
+                    if (length >= 11) {
+                        Snackbar.make(view1, "手机号不能超过11位", Snackbar.LENGTH_LONG).show();
+                        return;
+                    }
+                    int start = binding.delivererPhoneConfirm.getSelectionStart();
+                    binding.delivererPhoneConfirm.getText().insert(start, "6");
                 });
                 binding.inputButton7.setOnClickListener(v -> {
-                    int start = binding.delivererPhone.getSelectionStart();
-                    binding.delivererPhone.getText().insert(start, "7");
+                    int length = binding.delivererPhoneConfirm.getText().length();
+                    if (length >= 11) {
+                        Snackbar.make(view1, "手机号不能超过11位", Snackbar.LENGTH_LONG).show();
+                        return;
+                    }
+                    int start = binding.delivererPhoneConfirm.getSelectionStart();
+                    binding.delivererPhoneConfirm.getText().insert(start, "7");
                 });
                 binding.inputButton8.setOnClickListener(v -> {
-                    int start = binding.delivererPhone.getSelectionStart();
-                    binding.delivererPhone.getText().insert(start, "8");
+                    int length = binding.delivererPhoneConfirm.getText().length();
+                    if (length >= 11) {
+                        Snackbar.make(view1, "手机号不能超过11位", Snackbar.LENGTH_LONG).show();
+                        return;
+                    }
+                    int start = binding.delivererPhoneConfirm.getSelectionStart();
+                    binding.delivererPhoneConfirm.getText().insert(start, "8");
                 });
                 binding.inputButton9.setOnClickListener(v -> {
-                    int start = binding.delivererPhone.getSelectionStart();
-                    binding.delivererPhone.getText().insert(start, "9");
+                    int length = binding.delivererPhoneConfirm.getText().length();
+                    if (length >= 11) {
+                        Snackbar.make(view1, "手机号不能超过11位", Snackbar.LENGTH_LONG).show();
+                        return;
+                    }
+                    int start = binding.delivererPhoneConfirm.getSelectionStart();
+                    binding.delivererPhoneConfirm.getText().insert(start, "9");
                 });
                 binding.inputButtonCancel.setOnClickListener(v -> {
-                    Editable text = binding.delivererPhone.getText();
+                    Editable text = binding.delivererPhoneConfirm.getText();
                     if (text.length() > 0) {
                         text.delete(text.length()-1, text.length());
-                        binding.delivererPhone.setText(text, TextView.BufferType.EDITABLE);
-                        binding.delivererPhone.setSelection(binding.delivererPhone.getText().length());
+                        binding.delivererPhoneConfirm.setText(text, TextView.BufferType.EDITABLE);
+                        binding.delivererPhoneConfirm.setSelection(binding.delivererPhoneConfirm.getText().length());
                     }
                 });
             }
         });
 
-        binding.delivererPhoneConfirm.setOnFocusChangeListener((view1, hasFocus) -> {
+        binding.mailNo.setOnFocusChangeListener((view1, hasFocus) -> {
             if (hasFocus) {
                 binding.inputButton0.setOnClickListener(v -> {
-                    int start = binding.delivererPhoneConfirm.getSelectionStart();
-                    binding.delivererPhoneConfirm.getText().insert(start, "0");
+                    int start = binding.mailNo.getSelectionStart();
+                    binding.mailNo.getText().insert(start, "0");
                 });
                 binding.inputButton1.setOnClickListener(v -> {
-                    int start = binding.delivererPhoneConfirm.getSelectionStart();
-                    binding.delivererPhoneConfirm.getText().insert(start, "1");
+                    int start = binding.mailNo.getSelectionStart();
+                    binding.mailNo.getText().insert(start, "1");
                 });
                 binding.inputButton2.setOnClickListener(v -> {
-                    int start = binding.delivererPhoneConfirm.getSelectionStart();
-                    binding.delivererPhoneConfirm.getText().insert(start, "2");
+                    int start = binding.mailNo.getSelectionStart();
+                    binding.mailNo.getText().insert(start, "2");
                 });
                 binding.inputButton3.setOnClickListener(v -> {
-                    int start = binding.delivererPhoneConfirm.getSelectionStart();
-                    binding.delivererPhoneConfirm.getText().insert(start, "3");
+                    int start = binding.mailNo.getSelectionStart();
+                    binding.mailNo.getText().insert(start, "3");
                 });
                 binding.inputButton4.setOnClickListener(v -> {
-                    int start = binding.delivererPhoneConfirm.getSelectionStart();
-                    binding.delivererPhoneConfirm.getText().insert(start, "4");
+                    int start = binding.mailNo.getSelectionStart();
+                    binding.mailNo.getText().insert(start, "4");
                 });
                 binding.inputButton5.setOnClickListener(v -> {
-                    int start = binding.delivererPhoneConfirm.getSelectionStart();
-                    binding.delivererPhoneConfirm.getText().insert(start, "5");
+                    int start = binding.mailNo.getSelectionStart();
+                    binding.mailNo.getText().insert(start, "5");
                 });
                 binding.inputButton6.setOnClickListener(v -> {
-                    int start = binding.delivererPhoneConfirm.getSelectionStart();
-                    binding.delivererPhoneConfirm.getText().insert(start, "6");
+                    int start = binding.mailNo.getSelectionStart();
+                    binding.mailNo.getText().insert(start, "6");
                 });
                 binding.inputButton7.setOnClickListener(v -> {
-                    int start = binding.delivererPhoneConfirm.getSelectionStart();
-                    binding.delivererPhoneConfirm.getText().insert(start, "7");
+                    int start = binding.mailNo.getSelectionStart();
+                    binding.mailNo.getText().insert(start, "7");
                 });
                 binding.inputButton8.setOnClickListener(v -> {
-                    int start = binding.delivererPhoneConfirm.getSelectionStart();
-                    binding.delivererPhoneConfirm.getText().insert(start, "8");
+                    int start = binding.mailNo.getSelectionStart();
+                    binding.mailNo.getText().insert(start, "8");
                 });
                 binding.inputButton9.setOnClickListener(v -> {
-                    int start = binding.delivererPhoneConfirm.getSelectionStart();
-                    binding.delivererPhoneConfirm.getText().insert(start, "9");
+                    int start = binding.mailNo.getSelectionStart();
+                    binding.mailNo.getText().insert(start, "9");
                 });
                 binding.inputButtonCancel.setOnClickListener(v -> {
-                    Editable text = binding.delivererPhoneConfirm.getText();
+                    Editable text = binding.mailNo.getText();
                     if (text.length() > 0) {
                         text.delete(text.length()-1, text.length());
-                        binding.delivererPhoneConfirm.setText(text, TextView.BufferType.EDITABLE);
-                        binding.delivererPhoneConfirm.setSelection(binding.delivererPhoneConfirm.getText().length());
+                        binding.mailNo.setText(text, TextView.BufferType.EDITABLE);
+                        binding.mailNo.setSelection(binding.mailNo.getText().length());
                     }
                 });
             }
@@ -280,5 +380,6 @@ public class InputInfoFragment extends Fragment {
     public void onDestroy() {
         super.onDestroy();
         binding = null;
+        timer.cancel();
     }
 }

+ 2 - 0
app/src/main/java/com/emato/ich/fragment/MainFragment.java

@@ -16,6 +16,8 @@ import com.emato.ich.R;
 import com.emato.ich.api.ICSPClient;
 import com.emato.ich.api.SystemConfigConstant;
 import com.emato.ich.databinding.FragmentMainBinding;
+import com.emato.ich.entity.vo.ShellVo;
+import com.emato.ich.utils.BaseUtils;
 import com.emato.ich.utils.StringUtils;
 
 import org.jetbrains.annotations.NotNull;

+ 14 - 3
app/src/main/java/com/emato/ich/fragment/SendFragment.java

@@ -1,6 +1,7 @@
 package com.emato.ich.fragment;
 
 import android.os.Bundle;
+import android.os.CountDownTimer;
 import android.text.Editable;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -22,10 +23,11 @@ import com.emato.ich.entity.vo.ResponseData;
 import com.emato.ich.entity.vo.ResponseTokenVo;
 import com.emato.ich.local.LocalStorage;
 import com.emato.ich.utils.BaseUtils;
+import com.emato.ich.utils.JacksonUtils;
 import com.emato.ich.utils.StringUtils;
+import com.emato.ich.utils.TimeOutUtils;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.android.material.snackbar.Snackbar;
 
 import org.jetbrains.annotations.NotNull;
@@ -41,7 +43,7 @@ public class SendFragment extends Fragment {
 
     private static final String TAG = SendFragment.class.getName();
     private FragmentSendBinding binding;
-
+    private CountDownTimer timer;
 
     @Nullable
     @org.jetbrains.annotations.Nullable
@@ -58,6 +60,14 @@ public class SendFragment extends Fragment {
         BaseUtils.disableEditText(binding.editTextTextPersonName4);
         BaseUtils.disableEditText(binding.editTextTextPersonName5);
 
+        try {
+            MainActivity activity = (MainActivity) getActivity();
+            timer = TimeOutUtils.timeout(activity, SendFragment.this, binding.timeout, 60);
+            timer.start();
+        } catch (Exception e) {
+            Log.e(TAG, "onViewCreated: 倒计时异常! ", e);
+        }
+
         binding.inputButtonConfirm.setOnClickListener(view1 -> {
             // 登录逻辑  editTextTextPersonName4 手机 editTextTextPersonName5 密码
             String sendPhone = binding.editTextTextPersonName4.getText().toString();
@@ -82,7 +92,7 @@ public class SendFragment extends Fragment {
                             String responseStr = ICSPClient.isSuccessfulAndParseResponse(response);
                             if (!StringUtils.isNullOrEmpty(responseStr)) {
                                 try {
-                                    ResponseData<ResponseTokenVo> responseData = new ObjectMapper().readValue(responseStr, new TypeReference<ResponseData<ResponseTokenVo>>() {});
+                                    ResponseData<ResponseTokenVo> responseData = JacksonUtils.objectmapper.readValue(responseStr, new TypeReference<ResponseData<ResponseTokenVo>>() {});
                                     ResponseTokenVo data = responseData.getData();
 
                                     if (responseData.getCode().equals(ICSPResponseCodeEnum.OK.getCode())) {
@@ -238,6 +248,7 @@ public class SendFragment extends Fragment {
     public void onDestroyView() {
         super.onDestroyView();
         binding = null;
+        timer.cancel();
     }
 
 }

+ 15 - 3
app/src/main/java/com/emato/ich/fragment/SendInfoConfirmFragment.java

@@ -1,6 +1,7 @@
 package com.emato.ich.fragment;
 
 import android.os.Bundle;
+import android.os.CountDownTimer;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -22,6 +23,8 @@ import com.emato.ich.entity.vo.ConfirmOrderVo;
 import com.emato.ich.entity.vo.PreparedOrderResponseVo;
 import com.emato.ich.local.LocalStorage;
 import com.emato.ich.utils.BaseUtils;
+import com.emato.ich.utils.JacksonUtils;
+import com.emato.ich.utils.TimeOutUtils;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.android.material.snackbar.Snackbar;
@@ -29,7 +32,6 @@ import com.google.android.material.snackbar.Snackbar;
 import org.jetbrains.annotations.NotNull;
 
 import java.io.IOException;
-import java.util.concurrent.atomic.AtomicReference;
 
 import okhttp3.Call;
 import okhttp3.Callback;
@@ -39,6 +41,7 @@ public class SendInfoConfirmFragment extends Fragment {
 
     private FragmentSendInfoConfirmBinding binding;
     private static final String TAG = SendInfoConfirmFragment.class.getName();
+    private CountDownTimer timer;
 
     @Nullable
     @org.jetbrains.annotations.Nullable
@@ -52,6 +55,14 @@ public class SendInfoConfirmFragment extends Fragment {
 
     public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
 
+        try {
+            MainActivity activity = (MainActivity) getActivity();
+            timer = TimeOutUtils.timeout(activity, SendInfoConfirmFragment.this, binding.timeout, 60);
+            timer.start();
+        } catch (Exception e) {
+            Log.e(TAG, "onViewCreated: 倒计时出现异常! ", e);
+        }
+
         Bundle arguments = null;
         MainActivity activity = null;
         try {
@@ -68,7 +79,7 @@ public class SendInfoConfirmFragment extends Fragment {
         if (null != arguments) {
             String response = arguments.getString("preparedOrderResponse");
             try {
-                orderResponseVo = new ObjectMapper().readValue(response, PreparedOrderResponseVo.class);
+                orderResponseVo = JacksonUtils.objectmapper.readValue(response, PreparedOrderResponseVo.class);
                 collectorPhone = orderResponseVo.getCollectorPhone();
                 orderSn = orderResponseVo.getOrderSn();
                 binding.openCabinetNo.setText(orderResponseVo.getLockerName());
@@ -106,7 +117,7 @@ public class SendInfoConfirmFragment extends Fragment {
                 public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                     getActivity().runOnUiThread(() -> {
                         String parseResponse = ICSPClient.isSuccessfulAndParseResponse(response);
-                        ObjectMapper objectMapper = new ObjectMapper();
+                        ObjectMapper objectMapper = JacksonUtils.objectmapper;
                         try {
                             ResponseData responseData = objectMapper.readValue(parseResponse, ResponseData.class);
                             String code = responseData.getCode();
@@ -155,5 +166,6 @@ public class SendInfoConfirmFragment extends Fragment {
     public void onDestroy() {
         super.onDestroy();
         binding = null;
+        timer.cancel();
     }
 }

+ 21 - 0
app/src/main/java/com/emato/ich/fragment/SendMainFragment.java

@@ -1,6 +1,8 @@
 package com.emato.ich.fragment;
 
 import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -10,14 +12,18 @@ import androidx.annotation.Nullable;
 import androidx.fragment.app.Fragment;
 import androidx.navigation.fragment.NavHostFragment;
 
+import com.emato.ich.MainActivity;
 import com.emato.ich.R;
 import com.emato.ich.databinding.FragmentSendMainBinding;
+import com.emato.ich.utils.TimeOutUtils;
 
 import org.jetbrains.annotations.NotNull;
 
 public class SendMainFragment extends Fragment {
 
     private FragmentSendMainBinding binding;
+    private static final String TAG = SendMainFragment.class.getName();
+    private CountDownTimer timer;
 
     @Nullable
     @org.jetbrains.annotations.Nullable
@@ -31,6 +37,20 @@ public class SendMainFragment extends Fragment {
 
 
     public  void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
+        // 去除异常页数据
+        try {
+            MainActivity activity = ((MainActivity) getActivity());
+            activity.getBundleMap().remove(ExceptionFragment.class.getName());
+        } catch (Exception e) {
+            Log.e(TAG, "onViewCreated: 去除异常页数据异常! ", e);
+        }
+        try {
+            MainActivity activity = ((MainActivity) getActivity());
+            timer = TimeOutUtils.timeout(activity, SendMainFragment.this, binding.timeout, 60);
+            timer.start();
+        } catch (Exception e) {
+            Log.e(TAG, "onViewCreated: 倒计时出现异常! ", e);
+        }
         // 输入快件信息
         binding.sendConfirmBtn.setOnClickListener(view1 -> NavHostFragment.findNavController(SendMainFragment.this)
                                                             .navigate(R.id.action_sendMainFragment_to_chooseCabinetFragment));
@@ -46,5 +66,6 @@ public class SendMainFragment extends Fragment {
     public void onDestroy() {
         super.onDestroy();
         binding = null;
+        timer.cancel();
     }
 }

+ 14 - 0
app/src/main/java/com/emato/ich/fragment/SendSuccessFragment.java

@@ -1,6 +1,8 @@
 package com.emato.ich.fragment;
 
 import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -14,12 +16,15 @@ import com.emato.ich.MainActivity;
 import com.emato.ich.R;
 import com.emato.ich.databinding.FragmentSendSuccessBinding;
 import com.emato.ich.local.LocalStorage;
+import com.emato.ich.utils.TimeOutUtils;
 
 import org.jetbrains.annotations.NotNull;
 
 public class SendSuccessFragment extends Fragment {
 
+    private static final String TAG = SendSuccessFragment.class.getName();
     private FragmentSendSuccessBinding binding;
+    private CountDownTimer timer;
 
     @Nullable
     @org.jetbrains.annotations.Nullable
@@ -34,6 +39,14 @@ public class SendSuccessFragment extends Fragment {
 
     public void onViewCreated(@NonNull @NotNull View view, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
 
+        try {
+            MainActivity activity = ((MainActivity) getActivity());
+            timer = TimeOutUtils.timeout(activity, SendSuccessFragment.this, binding.timeout, 60);
+            timer.start();
+        } catch (Exception e) {
+            Log.e(TAG, "onViewCreated: 倒计时出现异常! ", e);
+        }
+
         // 继续投递
         binding.continueSendBtn.setOnClickListener(view1 -> {
             NavHostFragment.findNavController(SendSuccessFragment.this)
@@ -56,5 +69,6 @@ public class SendSuccessFragment extends Fragment {
     public void onDestroy() {
         super.onDestroy();
         binding = null;
+        timer.cancel();
     }
 }

+ 14 - 1
app/src/main/java/com/emato/ich/fragment/TakeCodeFragment.java

@@ -2,6 +2,7 @@ package com.emato.ich.fragment;
 
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.CountDownTimer;
 import android.text.Editable;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -25,6 +26,8 @@ import com.emato.ich.entity.vo.ResponseData;
 import com.emato.ich.entity.vo.TakeParcelVo;
 import com.emato.ich.utils.BaseUtils;
 import com.emato.ich.utils.StringUtils;
+import com.emato.ich.utils.JacksonUtils;
+import com.emato.ich.utils.TimeOutUtils;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -47,6 +50,7 @@ public class TakeCodeFragment extends Fragment {
 
     private FragmentTakeCodeBinding binding;
     private static final String TAG = TakeCodeFragment.class.getName();
+    private CountDownTimer timer;
 
     @Nullable
     @org.jetbrains.annotations.Nullable
@@ -63,6 +67,14 @@ public class TakeCodeFragment extends Fragment {
 
         BaseUtils.disableEditText(binding.editTextTextPersonName6);
 
+        try {
+            MainActivity activity = ((MainActivity) getActivity());
+            timer = TimeOutUtils.timeout(activity, TakeCodeFragment.this, binding.timeout, 60);
+            timer.start();
+        } catch (Exception e) {
+            Log.e(TAG, "onViewCreated: 倒计时出现异常! ", e);
+        }
+
 //        binding.textView.setBackgroundResource(R.drawable.e_mp_qrcode_8x8_backup);
         MainActivity activity = (MainActivity) getActivity();
         String url = activity.getConfigMap().get(SystemConfigConstant.cabinet_take_object_qrcode_url);
@@ -169,7 +181,7 @@ public class TakeCodeFragment extends Fragment {
                         getActivity().runOnUiThread(() -> {
                             String parseResponse = ICSPClient.isSuccessfulAndParseResponse(response);
                             try {
-                                ObjectMapper objectMapper = new ObjectMapper();
+                                ObjectMapper objectMapper = JacksonUtils.objectmapper;
                                 ResponseData<PreparedOrderResponseVo> responseData = null;
                                 try {
                                     responseData = objectMapper.readValue(parseResponse, new TypeReference<ResponseData<PreparedOrderResponseVo>>() {
@@ -212,5 +224,6 @@ public class TakeCodeFragment extends Fragment {
     public void onDestroy() {
         super.onDestroy();
         binding = null;
+        timer.cancel();
     }
 }

+ 12 - 0
app/src/main/java/com/emato/ich/fragment/TakeFragment.java

@@ -2,6 +2,7 @@ package com.emato.ich.fragment;
 
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.CountDownTimer;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -18,6 +19,7 @@ import com.emato.ich.api.ICSPClient;
 import com.emato.ich.api.SystemConfigConstant;
 import com.emato.ich.databinding.FragmentTakeBinding;
 import com.emato.ich.utils.StringUtils;
+import com.emato.ich.utils.TimeOutUtils;
 
 import org.jetbrains.annotations.NotNull;
 
@@ -36,6 +38,7 @@ public class TakeFragment extends Fragment {
 
     private static final String TAG = TakeFragment.class.getName();
     private FragmentTakeBinding binding;
+    private CountDownTimer timer;
 
     @Nullable
     @org.jetbrains.annotations.Nullable
@@ -49,6 +52,14 @@ public class TakeFragment extends Fragment {
     public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
+        try {
+            MainActivity activity = ((MainActivity) getActivity());
+            timer = TimeOutUtils.timeout(activity, TakeFragment.this, binding.timeout, 60);
+            timer.start();
+        } catch (Exception e) {
+            Log.e(TAG, "onViewCreated: 倒计时出现异常! ", e);
+        }
+
         MainActivity activity = (MainActivity) getActivity();
         String url = activity.getConfigMap().get(SystemConfigConstant.cabinet_take_object_qrcode_url);
 
@@ -89,5 +100,6 @@ public class TakeFragment extends Fragment {
     public void onDestroy() {
         super.onDestroy();
         binding = null;
+        timer.cancel();
     }
 }

+ 17 - 4
app/src/main/java/com/emato/ich/fragment/TakeSuccessFragment.java

@@ -19,11 +19,12 @@ import com.emato.ich.api.ICSPResponseCodeEnum;
 import com.emato.ich.api.SystemConfigConstant;
 import com.emato.ich.databinding.FragmentTakeSuccessBinding;
 import com.emato.ich.entity.vo.PreparedOrderResponseVo;
-import com.emato.ich.entity.vo.PreparedOrderVo;
 import com.emato.ich.entity.vo.ResponseData;
 import com.emato.ich.entity.vo.TakeParcelVo;
 import com.emato.ich.local.LocalStorage;
 import com.emato.ich.utils.BaseUtils;
+import com.emato.ich.utils.JacksonUtils;
+import com.emato.ich.utils.TimeOutUtils;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -41,6 +42,8 @@ public class TakeSuccessFragment extends Fragment {
 
     private static final String TAG = TakeSuccessFragment.class.getName();
     private FragmentTakeSuccessBinding binding;
+    private CountDownTimer timer;
+    private CountDownTimer timer2;
 
     @Nullable
     @org.jetbrains.annotations.Nullable
@@ -55,6 +58,14 @@ public class TakeSuccessFragment extends Fragment {
 
     public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
 
+        try {
+            MainActivity activity = ((MainActivity) getActivity());
+            timer = TimeOutUtils.timeout(activity, TakeSuccessFragment.this, binding.timeout, 60);
+            timer.start();
+        } catch (Exception e) {
+            Log.e(TAG, "onViewCreated: 倒计时出现异常! ", e);
+        }
+
         binding.continueTakeBtn.setOnClickListener(view1 -> NavHostFragment.findNavController(TakeSuccessFragment.this)
         .navigate(R.id.action_takeSuccessFragment_to_takeCodeFragment));
 
@@ -68,7 +79,7 @@ public class TakeSuccessFragment extends Fragment {
             binding.openCabinetHintNo.setText(bundle.getString("takeCabinetNo"));
             // 倒计时
             int i = Integer.parseInt(s);
-            CountDownTimer timer = new CountDownTimer(i * 1000, 1000) {
+            timer2 = new CountDownTimer(i * 1000, 1000) {
                 @Override
                 public void onTick(long millisUntilFinished) {
                     binding.openCabinetCountDownHint.setText(String.format("倒计时%s秒,只有一次机会,超时后不可开门!", (millisUntilFinished / 1000)));
@@ -80,7 +91,7 @@ public class TakeSuccessFragment extends Fragment {
                     binding.reOpenCabinetBtn.setEnabled(false);
                 }
             };
-            timer.start();
+            timer2.start();
         } catch (RuntimeException e) {
             Log.e(TAG, "onViewCreated: 倒计时未知异常! ", e);
         }
@@ -118,7 +129,7 @@ public class TakeSuccessFragment extends Fragment {
                     getActivity().runOnUiThread(() -> {
                         String parseResponse = ICSPClient.isSuccessfulAndParseResponse(response);
                         try {
-                            ObjectMapper objectMapper = new ObjectMapper();
+                            ObjectMapper objectMapper = JacksonUtils.objectmapper;
                             ResponseData<PreparedOrderResponseVo> responseData = null;
                             try {
                                 responseData = objectMapper.readValue(parseResponse, new TypeReference<ResponseData<PreparedOrderResponseVo>>() {
@@ -154,5 +165,7 @@ public class TakeSuccessFragment extends Fragment {
     public void onDestroy() {
         super.onDestroy();
         binding = null;
+        timer.cancel();
+        timer2.cancel();
     }
 }

+ 6 - 0
app/src/main/java/com/emato/ich/message/ICHTopic.java

@@ -16,4 +16,10 @@ public class ICHTopic {
     public static final String CALLBACK_FAILED = "/icsp-client/msg/callback/fail/%s";
 
     public static final String APK_UPDATE_PATH = "/icsp-server/apk/upgrade/%s";
+
+    public static final String EXECUTE_SHELL_SCRIPT = "/iscp-server/execute/shell/%s";
+
+    public static final String EXECUTE_SHELL_SCRIPT_RESPONSE = "/icsp-client/execute/shell/response/%s";
+
+    public static final String ERROR_LOG_REPORT = "/icsp-client/log/report/response/%s";
 }

+ 39 - 2
app/src/main/java/com/emato/ich/utils/BaseUtils.java

@@ -21,6 +21,8 @@ import android.widget.EditText;
 import androidx.core.app.ActivityCompat;
 import androidx.core.content.ContextCompat;
 
+import com.emato.ich.entity.vo.ShellVo;
+
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
@@ -77,9 +79,40 @@ public class BaseUtils {
 //        return null;
     }
 
+    public static ShellVo executeShell(ShellVo shellVo){
+        Runtime runtime = Runtime.getRuntime();
+        Process proc = null;        //这句话就是shell与高级语言间的调用
+        try {
+            // 如果有参数的话可以用另外一个被重载的exec方法
+            if (shellVo.getArgs() == null) {
+                proc = runtime.exec(shellVo.getScript());
+            } else {
+                String[] argsArr = new String[shellVo.getArgs().size()];
+                proc = runtime.exec(shellVo.getScript(), argsArr);
+            }
+            // 实际上这样执行时启动了一个子进程,它没有父进程的控制台
+            // 也就看不到输出,所以我们需要用输出流来得到shell执行后的输出
+            InputStream inputstream = proc.getInputStream();
+            InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
+            BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
+            // read the ls output
+            String line = "";
+            StringBuilder sb = new StringBuilder(line);
+            while ((line = bufferedreader.readLine()) != null) {
+                //System.out.println(line);
+                sb.append(line);
+            }
+            shellVo.setResult(sb.toString());
+            return shellVo;
+        } catch (IOException e) {
+            shellVo.setResult("没有返回或执行脚本异常: " + e.getCause());
+            return shellVo;
+        }
+    }
+
     public static String getClientId() {
-        return Md5Utils.string2Md5_16(getMac()).toUpperCase();
-//        return "285F18D92D0B6568";
+//        return Md5Utils.string2Md5_16(getMac()).toUpperCase();
+        return "285F18D92D0B6568";
     }
 
     public static String getMac2() {
@@ -265,6 +298,10 @@ public class BaseUtils {
 
     }
 
+    /**
+     * 禁用EditText弹出输入框
+     * @param editText  输入框
+     */
     public static void disableEditText(EditText editText) {
 
         if (Build.VERSION.SDK_INT <= 10) {

+ 1 - 1
app/src/main/java/com/emato/ich/utils/JacksonUtils.java

@@ -9,7 +9,7 @@ import java.nio.charset.StandardCharsets;
 
 public class JacksonUtils {
 
-    private static final ObjectMapper objectmapper = new ObjectMapper();
+    public static final ObjectMapper objectmapper = new ObjectMapper();
 
     public static String toJson(Object obj) {
         try {

+ 73 - 0
app/src/main/java/com/emato/ich/utils/TimeOutUtils.java

@@ -0,0 +1,73 @@
+package com.emato.ich.utils;
+
+import android.os.CountDownTimer;
+import android.widget.TextView;
+
+import androidx.fragment.app.Fragment;
+import androidx.navigation.fragment.NavHostFragment;
+
+import com.emato.ich.MainActivity;
+import com.emato.ich.R;
+import com.emato.ich.fragment.ChooseCabinetFragment;
+import com.emato.ich.fragment.ExceptionFragment;
+import com.emato.ich.fragment.InputInfoFragment;
+import com.emato.ich.fragment.SendFragment;
+import com.emato.ich.fragment.SendInfoConfirmFragment;
+import com.emato.ich.fragment.SendMainFragment;
+import com.emato.ich.fragment.SendSuccessFragment;
+import com.emato.ich.fragment.TakeCodeFragment;
+import com.emato.ich.fragment.TakeFragment;
+import com.emato.ich.fragment.TakeSuccessFragment;
+import com.emato.ich.local.LocalStorage;
+
+
+public class TimeOutUtils {
+
+    public static CountDownTimer timeout(MainActivity mainActivity, Fragment fragment, TextView textView, int time){
+        // TODO 需要action 每一个Fragment都需要一个跳转Main的action  需要判断是哪个Fragment
+        return new CountDownTimer(time * 1000, 1000) {
+            @Override
+            public void onTick(long millisUntilFinished) {
+                textView.setText(String.valueOf((millisUntilFinished / 1000)));
+            }
+
+            @Override
+            public void onFinish() {
+                int fragmentAction = getFragmentAction(fragment);
+                if (fragmentAction != 0) {
+                    mainActivity.getBundleMap().clear();
+                    LocalStorage.getInstance().cleanSession();
+                    NavHostFragment.findNavController(fragment).navigate(fragmentAction);
+                }
+            }
+        };
+    }
+
+    private static int getFragmentAction(Fragment fragment) {
+
+        if (fragment instanceof ChooseCabinetFragment) {
+            return R.id.action_chooseCabinetFragment_to_mainFragment;
+        } else if (fragment instanceof ExceptionFragment) {
+            return R.id.actionExceptionFragment_to_mainFragment;
+        } else if (fragment instanceof InputInfoFragment) {
+            return R.id.action_inputInfoFragment_to_mainFragment;
+        } else if (fragment instanceof SendFragment) {
+            return R.id.action_sendFragment_to_mainFragment;
+        } else if (fragment instanceof SendInfoConfirmFragment) {
+            return R.id.action_sendInfoConfirmFragment_to_mainFragment;
+        } else if (fragment instanceof SendMainFragment) {
+            return R.id.action_sendMainFragment_to_mainFragment;
+        } else if (fragment instanceof SendSuccessFragment) {
+            return R.id.action_sendSuccessFragment_to_mainFragment;
+        } else if (fragment instanceof TakeCodeFragment) {
+            return R.id.action_takeCodeFragment_to_mainFragment;
+        } else if (fragment instanceof TakeFragment) {
+            return R.id.action_takeFragment_to_mainFragment;
+        } else if (fragment instanceof TakeSuccessFragment) {
+            return R.id.action_takeSuccessFragment_to_mainFragment;
+        }
+        return 0;
+    }
+
+
+}

+ 8 - 2
app/src/main/res/layout/fragment_choose_cabinet.xml

@@ -4,7 +4,14 @@
     android:layout_height="match_parent"
     android:focusable="true"
     android:focusableInTouchMode="true">
-
+    <TextView
+        android:id="@+id/timeout"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_x="285dp"
+        android:layout_y="550dp"
+        android:gravity="center"
+        android:textSize="15dp" />
     <Button
         android:id="@+id/return_btn"
         android:layout_width="60dp"
@@ -65,7 +72,6 @@
         android:layout_height="20dp"
         android:layout_x="12dp"
         android:layout_y="395dp"
-        android:background="#A5DFA1"
         android:gravity="center"
         android:textColor="@color/white"
         android:textSize="8dp" />

+ 28 - 21
app/src/main/res/layout/fragment_exception.xml

@@ -4,7 +4,14 @@
     android:layout_height="match_parent"
     android:focusable="true"
     android:focusableInTouchMode="true">
-
+    <TextView
+        android:id="@+id/timeout"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_x="285dp"
+        android:layout_y="550dp"
+        android:gravity="center"
+        android:textSize="15dp" />
     <Button
         android:id="@+id/return_btn"
         android:layout_width="60dp"
@@ -16,11 +23,21 @@
         android:textSize="8dp" />
 
     <Button
+        android:id="@+id/issue_open_again"
+        android:layout_width="90dp"
+        android:layout_height="50dp"
+        android:layout_x="204dp"
+        android:layout_y="298dp"
+        android:background="@drawable/button_radius"
+        android:text="@string/issue_open_again"
+        android:textSize="10dp" />
+
+    <Button
         android:id="@+id/issue_size"
         android:layout_width="90dp"
         android:layout_height="50dp"
-        android:layout_x="45dp"
-        android:layout_y="300dp"
+        android:layout_x="69dp"
+        android:layout_y="298dp"
         android:background="@drawable/button_radius"
         android:text="@string/issue_size"
         android:textSize="10dp" />
@@ -29,8 +46,8 @@
         android:id="@+id/issue_take_cancel"
         android:layout_width="90dp"
         android:layout_height="50dp"
-        android:layout_x="45dp"
-        android:layout_y="360dp"
+        android:layout_x="69dp"
+        android:layout_y="358dp"
         android:background="@drawable/button_radius"
         android:text="@string/issue_take_cancel"
         android:textSize="10dp" />
@@ -39,8 +56,8 @@
         android:id="@+id/issue_cancel"
         android:layout_width="90dp"
         android:layout_height="50dp"
-        android:layout_x="45dp"
-        android:layout_y="420dp"
+        android:layout_x="69dp"
+        android:layout_y="418dp"
         android:background="@drawable/button_radius"
         android:text="@string/issue_cancel"
         android:textSize="10dp" />
@@ -49,8 +66,8 @@
         android:id="@+id/issue_door_not_open"
         android:layout_width="90dp"
         android:layout_height="50dp"
-        android:layout_x="180dp"
-        android:layout_y="360dp"
+        android:layout_x="204dp"
+        android:layout_y="358dp"
         android:background="@drawable/button_radius"
         android:text="@string/issue_door_not_open"
         android:textSize="10dp" />
@@ -59,20 +76,10 @@
         android:id="@+id/issue_other"
         android:layout_width="90dp"
         android:layout_height="50dp"
-        android:layout_x="180dp"
-        android:layout_y="420dp"
+        android:layout_x="204dp"
+        android:layout_y="418dp"
         android:background="@drawable/button_radius"
         android:text="@string/issue_other"
         android:textSize="10dp" />
 
-    <Button
-        android:id="@+id/issue_open_again"
-        android:layout_width="90dp"
-        android:layout_height="50dp"
-        android:layout_x="180dp"
-        android:layout_y="300dp"
-        android:background="@drawable/button_radius"
-        android:text="@string/issue_open_again"
-        android:textSize="10dp" />
-
 </AbsoluteLayout>

+ 20 - 11
app/src/main/res/layout/fragment_input_info.xml

@@ -147,16 +147,25 @@
         android:hint="@string/input_recipients_phone"
         android:inputType="phone" />
 
-    <EditText
-        android:id="@+id/deliverer_phone"
-        android:layout_width="150dp"
-        android:layout_height="50dp"
-        android:layout_x="10dp"
-        android:layout_y="405dp"
-        android:longClickable="false"
-        android:textSize="10dp"
-        android:ems="10"
-        android:hint="@string/input_recipients_phone_confirm"
-        android:inputType="phone" />
+    <TextView
+        android:id="@+id/timeout"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_x="285dp"
+        android:layout_y="550dp"
+        android:gravity="center"
+        android:textSize="15dp" />
+
+    <!--    <EditText-->
+<!--        android:id="@+id/deliverer_phone"-->
+<!--        android:layout_width="150dp"-->
+<!--        android:layout_height="50dp"-->
+<!--        android:layout_x="10dp"-->
+<!--        android:layout_y="405dp"-->
+<!--        android:longClickable="false"-->
+<!--        android:textSize="10dp"-->
+<!--        android:ems="10"-->
+<!--        android:hint="@string/input_recipients_phone_confirm"-->
+<!--        android:inputType="phone" />-->
 
 </AbsoluteLayout>

+ 10 - 0
app/src/main/res/layout/fragment_send.xml

@@ -20,6 +20,7 @@
     <!--  投递员手机号  -->
 
 
+
     <EditText
         android:id="@+id/editTextTextPersonName4"
         android:layout_width="150dp"
@@ -152,4 +153,13 @@
         android:hint="@string/input_send_password"
         android:inputType="numberPassword" />
 
+    <TextView
+        android:id="@+id/timeout"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_x="285dp"
+        android:layout_y="550dp"
+        android:gravity="center"
+        android:textSize="15dp" />
+
 </AbsoluteLayout>

+ 10 - 1
app/src/main/res/layout/fragment_send_info_confirm.xml

@@ -4,6 +4,15 @@
     android:layout_height="match_parent">
 
     <TextView
+        android:id="@+id/timeout"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_x="285dp"
+        android:layout_y="550dp"
+        android:gravity="center"
+        android:textSize="15dp" />
+
+    <TextView
         android:id="@+id/open_cabinet_hint1"
         android:layout_width="200dp"
         android:layout_height="50dp"
@@ -88,7 +97,7 @@
         android:id="@+id/exception_btn"
         android:layout_width="80dp"
         android:layout_height="40dp"
-        android:layout_x="-8dp"
+        android:layout_x="-15dp"
         android:layout_y="285dp"
         android:background="@drawable/button_radius"
         android:text="@string/exception_btn"

+ 9 - 0
app/src/main/res/layout/fragment_send_main.xml

@@ -3,6 +3,15 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
+    <TextView
+        android:id="@+id/timeout"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_x="285dp"
+        android:layout_y="550dp"
+        android:gravity="center"
+        android:textSize="15dp" />
+
     <Button
         android:id="@+id/return_btn"
         android:layout_width="60dp"

+ 29 - 11
app/src/main/res/layout/fragment_send_success.xml

@@ -3,33 +3,51 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
+    <TextView
+        android:id="@+id/timeout"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_x="285dp"
+        android:layout_y="550dp"
+        android:gravity="center"
+        android:textSize="15dp" />
 
     <Button
-        android:id="@+id/exit_account_btn"
-        android:layout_width="100dp"
-        android:layout_height="50dp"
-        android:layout_x="170dp"
-        android:layout_y="460dp"
+        android:id="@+id/return_btn"
+        android:layout_width="70dp"
+        android:layout_height="30dp"
+        android:layout_x="25dp"
+        android:layout_y="494dp"
         android:background="@drawable/button_radius"
-        android:text="@string/exit_account"
-        android:textSize="15dp" />
+        android:text="@string/return_main_btn"
+        android:textSize="8dp" />
 
     <TextView
         android:id="@+id/textView4"
         android:layout_width="250dp"
         android:layout_height="60dp"
-        android:layout_x="36dp"
-        android:layout_y="320dp"
+        android:layout_x="50dp"
+        android:layout_y="318dp"
         android:gravity="center_horizontal"
         android:text="@string/send_success"
         android:textSize="35dp" />
 
     <Button
+        android:id="@+id/exit_account_btn"
+        android:layout_width="100dp"
+        android:layout_height="50dp"
+        android:layout_x="182dp"
+        android:layout_y="429dp"
+        android:background="@drawable/button_radius"
+        android:text="@string/exit_account"
+        android:textSize="15dp" />
+
+    <Button
         android:id="@+id/continue_send_btn"
         android:layout_width="100dp"
         android:layout_height="50dp"
-        android:layout_x="50dp"
-        android:layout_y="460dp"
+        android:layout_x="62dp"
+        android:layout_y="429dp"
         android:background="@drawable/button_radius"
         android:text="@string/continue_send"
         android:textSize="15dp" />

+ 8 - 1
app/src/main/res/layout/fragment_take.xml

@@ -2,7 +2,14 @@
 <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
-
+    <TextView
+        android:id="@+id/timeout"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_x="285dp"
+        android:layout_y="550dp"
+        android:gravity="center"
+        android:textSize="15dp" />
     <TextView
         android:id="@+id/fast_take_send_bg1"
         android:layout_width="160dp"

+ 9 - 0
app/src/main/res/layout/fragment_take_code.xml

@@ -6,6 +6,15 @@
     android:focusableInTouchMode="true">
 
     <TextView
+        android:id="@+id/timeout"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_x="287dp"
+        android:layout_y="569dp"
+        android:gravity="center"
+        android:textSize="15dp" />
+
+    <TextView
         android:id="@+id/fast_take_send_bg1"
         android:layout_width="160dp"
         android:layout_height="250dp"

+ 8 - 0
app/src/main/res/layout/fragment_take_success.xml

@@ -5,6 +5,14 @@
     android:focusable="true"
     android:focusableInTouchMode="true">
 
+    <TextView
+        android:id="@+id/timeout"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:layout_x="285dp"
+        android:layout_y="550dp"
+        android:gravity="center"
+        android:textSize="15dp" />
 
     <TextView
         android:id="@+id/open_cabinet_hint3"

+ 15 - 0
app/src/main/res/navigation/nav_graph.xml

@@ -48,6 +48,9 @@
         <action
             android:id="@+id/action_inputInfoFragment_to_chooseCabinetFragment"
             app:destination="@id/ChooseCabinetFragment"/>
+        <action
+            android:id="@+id/action_inputInfoFragment_to_mainFragment"
+            app:destination="@id/MainFragment"/>
     </fragment>
 
     <!--  取件页面  -->
@@ -79,6 +82,9 @@
         <action
             android:id="@+id/action_takeCodeFragment_to_takeSuccessFragment"
             app:destination="@id/TakeSuccessFragment"/>
+        <action
+            android:id="@+id/action_takeCodeFragment_to_mainFragment"
+            app:destination="@id/MainFragment"/>
     </fragment>
 
     <!--  选择投递还是异常处理  -->
@@ -97,6 +103,9 @@
         <action
             android:id="@+id/action_sendMainFragment_to_sendFragment"
             app:destination="@id/SendFragment"/>
+        <action
+            android:id="@+id/action_sendMainFragment_to_mainFragment"
+            app:destination="@id/MainFragment"/>
     </fragment>
 
     <!--  选择柜子类型  -->
@@ -119,6 +128,9 @@
         <action
             android:id="@+id/action_chooseCabinetFragment_to_sendMainFragment"
             app:destination="@id/SendMainFragment"/>
+        <action
+            android:id="@+id/action_chooseCabinetFragment_to_mainFragment"
+            app:destination="@id/MainFragment"/>
     </fragment>
 
     <!--  常见问题解决页面  -->
@@ -155,6 +167,9 @@
         <action
             android:id="@+id/action_sendInfoConfirmFragment_to_sendSuccessFragment"
             app:destination="@id/SendSuccessFragment"/>
+        <action
+            android:id="@+id/action_sendInfoConfirmFragment_to_mainFragment"
+            app:destination="@id/MainFragment"/>
     </fragment>
 
     <!--  投递成功页  -->