zh 10 месяцев назад
Родитель
Сommit
e473bccfa4

+ 16 - 0
.idea/deploymentTargetSelector.xml

@@ -4,6 +4,22 @@
     <selectionStates>
       <SelectionState runConfigName="app">
         <option name="selectionMode" value="DROPDOWN" />
+        <DropdownSelection timestamp="2025-05-30T06:42:02.710870900Z">
+          <Target type="DEFAULT_BOOT">
+            <handle>
+              <DeviceId pluginId="PhysicalDevice" identifier="serial=1a41f5baec1e896" />
+            </handle>
+          </Target>
+        </DropdownSelection>
+        <DialogSelection>
+          <targets>
+            <Target type="DEFAULT_BOOT">
+              <handle>
+                <DeviceId pluginId="PhysicalDevice" identifier="serial=1a41f5baec1e896" />
+              </handle>
+            </Target>
+          </targets>
+        </DialogSelection>
       </SelectionState>
     </selectionStates>
   </component>

+ 10 - 0
app/build.gradle

@@ -21,12 +21,16 @@ android {
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
             buildConfigField "String", "WEB_URL", "\"http://192.168.2.175:5173/\""
+            buildConfigField "String", "APK_URL", "\"http://sit.swms.baoshi56.com/\""
+            buildConfigField "String", "APK_CNF", '"piece.cnf"'
             signingConfig signingConfigs.debug
         }
         release {
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
             buildConfigField "String", "WEB_URL", "\"https://app.baoshi56.com/\""
+            buildConfigField "String", "APK_URL", "\"https://swms.baoshi56.com/\""
+            buildConfigField "String", "APK_CNF", '"piece.cnf"'
             signingConfig signingConfigs.debug
             // 设置release构建类型的输出文件名
             android.applicationVariants.all { variant ->
@@ -86,4 +90,10 @@ dependencies {
      * 提供 Java 常用工具类
      */
     implementation ("org.apache.commons:commons-lang3:3.12.0")
+
+    /**
+     * 更新版本工具库(UpdateAppUtilsX)
+     * 实现版本更新功能
+     */
+    implementation ("com.teprinciple:updateapputilsx:2.3.0")
 }

+ 6 - 6
app/src/main/AndroidManifest.xml

@@ -2,15 +2,15 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools">
     <!-- 网络权限 -->
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.VIBRATE" />
     <!--允许应用读取公共目录(如 Documents)中的文件-->
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
-    <!-- Android 11+ 需要声明 MANAGE_EXTERNAL_STORAGE 以获取完整文件访问权限 -->
-    <uses-permission
-        android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
-        tools:ignore="ScopedStorage" />
-
+    <!-- 需要声明 MANAGE_EXTERNAL_STORAGE 以获取完整文件访问权限 -->
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
+        android:maxSdkVersion="30" /> <!-- 仅限 Android 10 及以下需要 -->
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
+        tools:ignore="ScopedStorage" /> <!-- 针对 Android 11+ 的特殊情况 -->
     <application
         android:name=".base.BaseApplication"
         android:allowBackup="true"

+ 4 - 0
app/src/main/java/com/baoshi/piece/MainActivity.java

@@ -1,8 +1,12 @@
 package com.baoshi.piece;
 
+import android.util.Log;
+
 import com.baoshi.piece.base.BaseWebViewActivity;
 import com.baoshi.piece.db.dao.DeliveryDao;
 import com.baoshi.piece.utils.AppConfig;
+import com.yechaoa.yutils.DisplayUtil;
+import com.yechaoa.yutils.LogUtil;
 
 public class MainActivity extends BaseWebViewActivity {
     @Override

+ 3 - 0
app/src/main/java/com/baoshi/piece/base/BaseWebViewActivity.java

@@ -22,6 +22,7 @@ import com.baoshi.piece.db.dao.DeliveryDao;
 import com.baoshi.piece.db.po.DeliveryRecord;
 import com.baoshi.piece.utils.JavaScriptInterface;
 import com.baoshi.piece.utils.MacAddressUtils;
+import com.baoshi.piece.utils.UpdateUtils;
 import com.yechaoa.yutils.LogUtil;
 import com.yechaoa.yutils.ToastUtil;
 import com.yechaoa.yutils.YUtils;
@@ -67,6 +68,8 @@ public abstract class BaseWebViewActivity extends BaseActivity<ActivityWebViewBi
         YUtils.showLoading(this, "加载中...");
         deliveryDao = new DeliveryDao(this);
         super.onCreate(savedInstanceState);
+        // 更新检查
+        new UpdateUtils().init();
     }
 
     // 在活动由不可见变为可见的时候调用

+ 4 - 3
app/src/main/java/com/baoshi/piece/db/DBHelper.java

@@ -7,16 +7,17 @@ import android.util.Log;
 
 public class DBHelper extends SQLiteOpenHelper {
     private static final String DB_NAME = "delivery_db.db";
-    private static final int DB_VERSION = 2;
+    private static final int DB_VERSION = 4;
     // 送货记录表结构
     private static final String CREATE_TABLE_DELIVERY =
             "CREATE TABLE delivery (" +
                     "id INTEGER PRIMARY KEY AUTOINCREMENT," +
-                    "deliveryNo TEXT NOT NULL UNIQUE," +  // 送货单号(唯一)
+                    "deliveryNo TEXT NOT NULL UNIQUE," + // 送货单号(唯一)
                     "machine TEXT NOT NULL," +           // 机器编号
                     "operator TEXT NOT NULL," +          // 操作员
                     "operatorName TEXT NOT NULL," +      // 操作员名称
-                    "operationTime TEXT NOT NULL)";     // 操作时间(ISO8601格式)
+                    "operationTime TEXT NOT NULL," +     // 操作时间(ISO8601格式)
+                    "isPush INTEGER DEFAULT 1)";         // 0=待上传, 1=已上传
 
     public DBHelper(Context context) {
         super(context, DB_NAME, null, DB_VERSION);

+ 105 - 24
app/src/main/java/com/baoshi/piece/db/dao/DeliveryDao.java

@@ -21,6 +21,21 @@ public class DeliveryDao {
         dbHelper = new DBHelper(context);
     }
 
+    // 从Cursor解析记录(复用方法)
+    private DeliveryRecord parseRecordFromCursor(Cursor cursor) {
+        DeliveryRecord record = new DeliveryRecord(
+                cursor.getString(cursor.getColumnIndexOrThrow("deliveryNo")),
+                cursor.getString(cursor.getColumnIndexOrThrow("machine")),
+                cursor.getString(cursor.getColumnIndexOrThrow("operator")),
+                cursor.getString(cursor.getColumnIndexOrThrow("operatorName")),
+                cursor.getInt(cursor.getColumnIndexOrThrow("isPush"))
+        );
+        record.setId(cursor.getLong(cursor.getColumnIndexOrThrow("id")));
+        record.setOperationTime(cursor.getString(cursor.getColumnIndexOrThrow("operationTime")));
+
+        return record;
+    }
+
     // 添加送货记录
     public long addDelivery(DeliveryRecord record) {
         // 1. 先检查是否存在
@@ -35,6 +50,7 @@ public class DeliveryDao {
         values.put("operator", record.getOperator());
         values.put("operatorName", record.getOperatorName());
         values.put("operationTime", record.getOperationTime());
+        values.put("isPush", record.isPush() ? 1 : 0); // 布尔转INT
 
         try {
             long id = db.insertOrThrow("delivery", null, values);
@@ -50,6 +66,7 @@ public class DeliveryDao {
         }
     }
 
+
     /**
      * 检查送货单号是否存在
      */
@@ -85,14 +102,7 @@ public class DeliveryDao {
 
         DeliveryRecord record = null;
         if (cursor != null && cursor.moveToFirst()) {
-            record = new DeliveryRecord(
-                cursor.getString(cursor.getColumnIndexOrThrow("deliveryNo")),
-                cursor.getString(cursor.getColumnIndexOrThrow("machine")),
-                cursor.getString(cursor.getColumnIndexOrThrow("operator")),
-                cursor.getString(cursor.getColumnIndexOrThrow("operatorName"))
-            );
-            record.setId(cursor.getLong(cursor.getColumnIndexOrThrow("id")));
-            record.setOperationTime(cursor.getString(cursor.getColumnIndexOrThrow("operationTime")));
+            record = parseRecordFromCursor(cursor);
             cursor.close();
         }
         db.close();
@@ -113,14 +123,7 @@ public class DeliveryDao {
 
             if (cursor != null && cursor.moveToFirst()) {
                 do {
-                    DeliveryRecord record = new DeliveryRecord(
-                            cursor.getString(cursor.getColumnIndexOrThrow("deliveryNo")),
-                            cursor.getString(cursor.getColumnIndexOrThrow("machine")),
-                            cursor.getString(cursor.getColumnIndexOrThrow("operator")),
-                            cursor.getString(cursor.getColumnIndexOrThrow("operatorName"))
-                    );
-                    record.setId(cursor.getLong(cursor.getColumnIndexOrThrow("id")));
-                    record.setOperationTime(cursor.getString(cursor.getColumnIndexOrThrow("operationTime")));
+                    DeliveryRecord record = parseRecordFromCursor(cursor);
                     records.add(record);
                 } while (cursor.moveToNext());
             }
@@ -131,6 +134,91 @@ public class DeliveryDao {
         return records;
     }
 
+    // 根据送货单号更新上传状态
+    public int markAsPushed(String deliveryNo) {
+        SQLiteDatabase db = dbHelper.getWritableDatabase();
+        ContentValues values = new ContentValues();
+        values.put("isPush", 1); // 标记为已上传
+
+        return db.update(
+                "delivery",
+                values,
+                "deliveryNo = ?",
+                new String[]{deliveryNo}
+        );
+    }
+
+    // 根据送货单号更新上传状态为失败
+    public int updateDeliveryPushFail(String deliveryNo) {
+        SQLiteDatabase db = dbHelper.getWritableDatabase();
+        ContentValues values = new ContentValues();
+        values.put("isPush", 0); // 标记为已上传
+
+        return db.update(
+                "delivery",
+                values,
+                "deliveryNo = ?",
+                new String[]{deliveryNo}
+        );
+    }
+
+    // 批量标记为已上传
+    public int markMultipleAsPushed(List<String> deliveryNos) {
+        SQLiteDatabase db = dbHelper.getWritableDatabase();
+        db.beginTransaction();
+        int successCount = 0;
+
+        try {
+            for (String deliveryNo : deliveryNos) {
+                ContentValues values = new ContentValues();
+                values.put("isPush", 1);
+
+                int updated = db.update(
+                        "delivery",
+                        values,
+                        "deliveryNo = ? AND isPush = 0", // 只更新待上传的记录
+                        new String[]{deliveryNo}
+                );
+
+                if (updated > 0) {
+                    successCount++;
+                }
+            }
+            db.setTransactionSuccessful();
+            return successCount;
+        } finally {
+            db.endTransaction();
+            db.close();
+        }
+    }
+
+    // 查询所有待上传的记录
+    public List<DeliveryRecord> listPendingUploadRecords() {
+        List<DeliveryRecord> records = new ArrayList<>();
+        SQLiteDatabase db = dbHelper.getReadableDatabase();
+
+        Cursor cursor = db.query(
+                "delivery",
+                null,
+                "isPush = 0", // 待上传状态
+                null, null, null,
+                "operationTime ASC" // 按时间升序(最早优先)
+        );
+
+        try {
+            if (cursor != null && cursor.moveToFirst()) {
+                do {
+                    DeliveryRecord record = parseRecordFromCursor(cursor);
+                    records.add(record);
+                } while (cursor.moveToNext());
+            }
+            return records;
+        } finally {
+            if (cursor != null) cursor.close();
+            db.close();
+        }
+    }
+
     // 获取总记录数
     public int getTotalRecordsCount() {
         SQLiteDatabase db = dbHelper.getReadableDatabase();
@@ -162,14 +250,7 @@ public class DeliveryDao {
 
         if (cursor != null) {
             while (cursor.moveToNext()) {
-                DeliveryRecord record = new DeliveryRecord(
-                    cursor.getString(cursor.getColumnIndexOrThrow("deliveryNo")),
-                    cursor.getString(cursor.getColumnIndexOrThrow("machine")),
-                    cursor.getString(cursor.getColumnIndexOrThrow("operator")),
-                    cursor.getString(cursor.getColumnIndexOrThrow("operatorName"))
-                );
-                record.setId(cursor.getLong(cursor.getColumnIndexOrThrow("id")));
-                record.setOperationTime(cursor.getString(cursor.getColumnIndexOrThrow("operationTime")));
+                DeliveryRecord record = parseRecordFromCursor(cursor);
                 records.add(record);
             }
             cursor.close();

+ 21 - 0
app/src/main/java/com/baoshi/piece/db/po/DeliveryRecord.java

@@ -11,6 +11,7 @@ public class DeliveryRecord {
     private String operator;
     private String operatorName;
     private String operationTime;
+    private Boolean isPush;
 
     // 构造方法
     public DeliveryRecord(String deliveryNo, String machine, String operator, String operatorName) {
@@ -18,10 +19,22 @@ public class DeliveryRecord {
         this.machine = machine;
         this.operator = operator;
         this.operatorName = operatorName;
+        this.isPush = true;
         this.operationTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
                                 .format(new Date());
     }
 
+    // 构造方法
+    public DeliveryRecord(String deliveryNo, String machine, String operator, String operatorName, int isPush) {
+        this.deliveryNo = deliveryNo;
+        this.machine = machine;
+        this.operator = operator;
+        this.operatorName = operatorName;
+        this.isPush = isPush == 1;
+        this.operationTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
+                .format(new Date());
+    }
+
     // Getters
     public long getId() { return id; }
     public String getDeliveryNo() { return deliveryNo; }
@@ -40,4 +53,12 @@ public class DeliveryRecord {
     public void setOperatorName(String operatorName) {
         this.operatorName = operatorName;
     }
+
+    public Boolean isPush() {
+        return isPush;
+    }
+
+    public void setPushed(Boolean push) {
+        isPush = push;
+    }
 }

+ 6 - 0
app/src/main/java/com/baoshi/piece/utils/AppConfig.java

@@ -6,4 +6,10 @@ public class AppConfig {
     public static String getWebUrl() {
         return BuildConfig.WEB_URL;
     }
+    public static String getApkUrl() {
+        return BuildConfig.APK_URL;
+    }
+    public static String getApkCnf() {
+        return BuildConfig.APK_CNF;
+    }
 }

+ 23 - 4
app/src/main/java/com/baoshi/piece/utils/JavaScriptInterface.java

@@ -22,6 +22,7 @@ public class JavaScriptInterface {
     private final Activity activity;
     private final WebView webView;
     private final Map<String, String> headerParams;
+    private final String SAVE_USER_ID = "USER_ID";
 
     public JavaScriptInterface(Activity activity, Map<String, String> headerParams, WebView webView, DeliveryDao deliveryDao) {
         this.activity = activity;
@@ -61,7 +62,9 @@ public class JavaScriptInterface {
      */
     @JavascriptInterface
     public String readMacAddress() {
-        return MacAddressUtils.readMacAddress(activity);
+        String s = MacAddressUtils.readMacAddress(activity);
+        Log.i("JavaScriptInterface", s);
+        return s;
     }
 
     /**
@@ -131,16 +134,32 @@ public class JavaScriptInterface {
 
     @JavascriptInterface
     public void saveUserId(String userId) {
-        SpUtil.setString("userId", userId);
+        SpUtil.setString(SAVE_USER_ID, userId);
     }
 
     @JavascriptInterface
-    public void getUserId() {
-        SpUtil.getString("userId");
+    public String getUserId() {
+        return SpUtil.getString(SAVE_USER_ID);
+    }
+
+    @JavascriptInterface
+    public int updateDeliveryPushFail(String deliveryNo) {
+        return deliveryDao.updateDeliveryPushFail(deliveryNo);
+    }
+
+    @JavascriptInterface
+    public int markAsPushed(String deliveryNo) {
+        return deliveryDao.markAsPushed(deliveryNo);
     }
 
     @JavascriptInterface
     public String getVersionName() {
         return YUtils.getVersionName();
     }
+
+    @JavascriptInterface
+    public void checkUpdate() {
+        // 更新检查
+        new UpdateUtils().init();
+    }
 }

+ 4 - 0
app/src/main/java/com/baoshi/piece/utils/MacAddressUtils.java

@@ -8,6 +8,9 @@ import android.provider.MediaStore;
 import android.content.ContentResolver;
 import android.os.Build;
 import android.util.Log;
+
+import com.yechaoa.yutils.GsonUtil;
+
 import java.io.InputStream;
 
 import java.io.OutputStream;
@@ -87,6 +90,7 @@ public class MacAddressUtils {
                     selectionArgs,
                     null
             )) {
+                Log.e(TAG, "cursor count: " + GsonUtil.GsonString(cursor));
                 if (cursor == null || !cursor.moveToFirst()) {
                     Log.d(TAG, "File not found");
                     return null;

+ 28 - 0
app/src/main/java/com/baoshi/piece/utils/NetUtils.java

@@ -0,0 +1,28 @@
+package com.baoshi.piece.utils;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkCapabilities;
+
+import com.yechaoa.yutils.LogUtil;
+
+/**
+ * 网络相关工具
+ */
+public class NetUtils {
+    public static boolean isNetworkConnected(Context context) {;
+        if (context == null) {
+            return true;
+        }
+        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        if (manager != null) {
+            NetworkCapabilities networkCapabilities = manager.getNetworkCapabilities(manager.getActiveNetwork());
+            if (networkCapabilities != null) {
+                return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
+                        || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+                        || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET);
+            }
+        }
+        return false;
+    }
+}

+ 140 - 0
app/src/main/java/com/baoshi/piece/utils/UpdateUtils.java

@@ -0,0 +1,140 @@
+package com.baoshi.piece.utils;
+
+import android.app.Activity;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Environment;
+import android.os.Looper;
+import android.os.StrictMode;
+import android.util.Log;
+
+import com.baoshi.piece.R;
+import com.yechaoa.yutils.ActivityUtil;
+import com.yechaoa.yutils.GsonUtil;
+import com.yechaoa.yutils.LogUtil;
+import com.yechaoa.yutils.ToastUtil;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.Map;
+
+import constant.UiType;
+import model.UiConfig;
+import model.UpdateConfig;
+import update.UpdateAppUtils;
+
+public class UpdateUtils {
+    private static final String APK_URL = AppConfig.getApkUrl() + "statics/storage/app/" +  AppConfig.getApkCnf();
+    public void init(){
+        //检查更新
+        new Thread() {
+            @Override
+            public void run() {
+                try{
+                    Thread.sleep(500);
+                }catch (Exception ignored){}
+                checkUpdate();
+            }
+        }.start();
+    }
+
+    /**
+     * 发生错误或者服务器问题都跳过此次更新
+     * */
+    private void checkUpdate() {
+        Activity activity = ActivityUtil.getCurrentActivity();
+        if (!NetUtils.isNetworkConnected(activity)){
+            Looper.prepare();
+            ToastUtil.show("请检查您的网络是否正常!");
+            Looper.loop();
+            return;
+        }
+        String conf = this.readCnf();
+        Log.d("checkUpdate", "conf: " + conf);
+        if (conf==null){
+            return;
+        }
+        try {
+            PackageInfo packInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), 0);
+            Map<String,String> map = GsonUtil.GsonToMaps(conf);
+            if (packInfo.versionName.equals(map.get("version"))){
+                return;
+            }
+            executeUpdate(map.get("url"),map.get("title"),map.get("content"),map.get("force"));
+        }catch (PackageManager.NameNotFoundException ignored) {
+        }
+    }
+
+    private void executeUpdate(String url, String title, String content, String force) {
+        UpdateAppUtils.init(ActivityUtil.getCurrentActivity());
+
+        //更新配置信息
+        UpdateConfig updateConfig = new UpdateConfig();
+        //检查Wifi状态
+        updateConfig.setCheckWifi(true);
+        //开启MD5校验 目前过不了MD5签名校验,所以先FALSE
+        updateConfig.setNeedCheckMd5(false);
+        //apk下载存放位置
+        updateConfig.setApkSavePath(this.getSavePath());
+        // 是否强制更新
+        updateConfig.setForce(!StringUtils.isEmpty(force) && Boolean.parseBoolean(force));
+        // 通知栏图标
+        updateConfig.setNotifyImgRes(R.drawable.ic_update_logo);
+        //开启下载进度条
+        updateConfig.setAlwaysShowDownLoadDialog(true);
+        //关闭通知栏进度条
+        updateConfig.setShowNotification(false);
+        //关闭下载提示框
+        updateConfig.setShowDownloadingToast(false);
+
+        //UI配置信息
+        UiConfig uiConfig = new UiConfig();
+        uiConfig.setUiType(UiType.PLENTIFUL);
+
+        //功能Api
+        UpdateAppUtils
+                .getInstance()
+                .apkUrl(url)
+                .updateTitle(title)
+                .updateContent(content)
+                .uiConfig(uiConfig)
+                .updateConfig(updateConfig)
+                .update();
+    }
+
+    private String getSavePath() {
+        String path;
+        if (Build.VERSION.SDK_INT > 29) {
+            path = ActivityUtil.getCurrentActivity().getExternalFilesDir(null).getAbsolutePath() + "/app/";
+        } else {
+            path = Environment.getExternalStorageDirectory().getPath() + "/app/";
+        }
+        return path;
+    }
+
+    public String readCnf() {
+        try {
+            StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build();
+            StrictMode.setThreadPolicy(policy);
+            URL url = new URL(APK_URL);
+            BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
+            StringBuilder str = new StringBuilder();
+            String s;
+            while ((s = in.readLine()) != null) {
+                str.append(s);
+            }
+            in.close();
+            return str.toString();
+        } catch (Exception e) {
+            Log.e("readCnf", e.getMessage());
+            Looper.prepare();
+            ToastUtil.show("请检查您的网络是否正常!");
+            Looper.loop();
+            return null;
+        }
+    }
+}

BIN
app/src/main/res/drawable/ic_update_logo.png


+ 3 - 0
build.gradle

@@ -1,4 +1,7 @@
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
 plugins {
 alias(libs.plugins.android.application) apply false
+}
+task clean(type: Delete) {
+    delete rootProject.buildDir
 }

+ 6 - 0
config/.env

@@ -0,0 +1,6 @@
+alias=PIECE
+password=bsgood888
+
+#TODO apk.cnf使用 \n来分隔行 无需空格 == bAOSHI123!
+scp app/release/PIECE.1.0.apk root@api.baoshi56.com:/bssoft/bsshare/storage/app
+scp config/piece.cnf root@api.baoshi56.com:/bssoft/bsshare/storage/app

+ 6 - 0
config/piece.cnf

@@ -0,0 +1,6 @@
+{
+	"version" 	: "2.0",
+	"url"	: "https://swms.baoshi56.com/statics/storage/app/SIGN.apk",
+	"title"	: "宝时计件",
+	"content"	: "宝时计件"
+}

BIN
config/piece.jks