Commit d1d6a28b authored by 姜天宇's avatar 姜天宇

feat(v1.0.2): 增加注册页、增加网络模块

parent 42b4f006
......@@ -13,10 +13,13 @@
.cxx
local.properties
/build
/app/build/
/core/build/
/common/build/
/camera/build/
/data-local/build/
/data-remote/build/
/module-demo/build/
/module-setting/build/
/.idea/
/.gradle/
......@@ -65,6 +65,7 @@ dependencies {
implementation project(path: ':core')
implementation project(path: ':module-demo')
implementation project(path: ':module-setting')
implementation project(path: ':data-remote')
implementation project(path: ':data-local')
implementation 'com.alibaba:arouter-api:1.5.2'
......
......@@ -4,6 +4,7 @@ import android.icu.util.LocaleData;
import com.alibaba.android.arouter.launcher.ARouter;
import com.squareup.picasso.Picasso;
import com.wmdigit.NetworkModule;
import com.wmdigit.common.CommonModule;
import com.wmdigit.core.CoreModule;
import com.wmdigit.data.LocalDataModule;
......@@ -45,5 +46,7 @@ public class Application extends android.app.Application {
LocalDataModule.init(this);
// 初始化核心类
CoreModule.init(this);
// 初始化网络模块
NetworkModule.init(this);
}
}
......@@ -2,6 +2,7 @@ package com.wmdigit.common.base.mvvm;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
......
......@@ -11,6 +11,7 @@ import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.ViewModelProvider;
import com.hjq.toast.Toaster;
import com.wmdigit.common.base.BaseFragment;
......@@ -64,7 +65,9 @@ public abstract class BaseMvvmFragment<VM extends BaseViewModel, DB extends View
/**
* 注册观察对象
*/
protected abstract void initObserve();
protected void initObserve(){
mViewModel.toastMessage.observe(requireActivity(), Toaster::show);
}
/**
* 初始化View
......
......@@ -7,18 +7,18 @@ package com.wmdigit.common.base.mvvm;
public abstract class BaseMvvmNetworkRepository {
/**
* 用于在网络请求失败的情况下通知
* 用于在网络请求通知
*/
public SingleLiveEvent<String> mHttpRequestFailed = new SingleLiveEvent<>();
public SingleLiveEvent<String> mHttpToast = new SingleLiveEvent<>();
/**
* Http请求失败时,通知View层
* Http请求结果通知View层
* @param message
*/
protected void requestFailed(String message){
if (mHttpRequestFailed == null){
protected void showHttpToast(String message){
if (mHttpToast == null){
return;
}
mHttpRequestFailed.postValue(message);
mHttpToast.postValue(message);
}
}
package com.wmdigit.common.enums;
/**
* @author dizi
*/
public enum SnType {
FRESH_SDK("生鲜SDK"), CATERING_SDK("餐饮SDK"), LOSS_PREVENTION_SDK("防损SDK");
private String type;
SnType(String type) {
this.type = type;
}
}
package com.wmdigit.common.utils;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
/**
* EditText工具类
* @author dizi
*/
public class EditTextUtils {
public static void addTextToUpperWatcher(EditText editText, EditText nextEditText, int maxLength){
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
String text = "";
String nextText = "";
if (editable.length() > maxLength){
// 跳转到下一个edittext
text = editable.toString().substring(0, maxLength).toUpperCase();
nextText = editable.toString().substring(maxLength).toUpperCase();
editText.removeTextChangedListener(this);
// editText.setText(text);
editable.replace(0,editable.length(),text);
editText.addTextChangedListener(this);
if (nextEditText != null){
// 如果下一个edittext为空,则把超出得部分写入
if (nextEditText.getText()==null || nextEditText.getText().toString().equals("")){
nextEditText.setText(nextText);
}
nextEditText.requestFocus();
nextEditText.setSelection(nextEditText.getText().length());
}
}
else if (editable.length() == maxLength){
// 跳转到下一个edittext
text = editable.toString().toUpperCase();
editText.removeTextChangedListener(this);
editable.replace(0,editable.length(),text);
editText.addTextChangedListener(this);
if (nextEditText != null){
nextEditText.requestFocus();
nextEditText.setSelection(nextEditText.getText().length());
}
}
else{
text = editable.toString().toUpperCase();
editText.removeTextChangedListener(this);
editable.replace(0,editable.length(),text);
editText.addTextChangedListener(this);
editText.requestFocus();
editText.setSelection(editable.length());
}
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="@color/gray_999999"/>
<item android:color="@color/green_008e75"/>
</selector>
\ No newline at end of file
......@@ -17,4 +17,5 @@
<string name="not_crop">未标定</string>
<string name="please_confirm_whether_quit">请确认是否关闭页面</string>
<string name="please_check_input">请检查输入内容</string>
</resources>
\ No newline at end of file
......@@ -352,4 +352,9 @@
<item name="android:background">@color/gray_dfdfdf</item>
</style>
<style name="split_line_base.short">
<item name="android:layout_width">@dimen/dp_10</item>
<item name="android:layout_height">@dimen/dp_3</item>
<item name="android:background">@color/gray_676767</item>
</style>
</resources>
\ No newline at end of file
......@@ -11,11 +11,26 @@ android {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
ndk {
abiFilters 'armeabi-v7a'
}
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
......@@ -23,6 +38,12 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
version '3.18.1'
}
}
}
dependencies {
......@@ -46,5 +67,5 @@ dependencies {
// optional - Paging 3 Integration
implementation "androidx.room:room-paging:$room_version"
// mmkv
api 'com.tencent:mmkv:1.3.0'
implementation 'com.tencent:mmkv:1.3.0'
}
\ No newline at end of file
cmake_minimum_required(VERSION 3.18.1)
project("common")
include_directories(include)
#用于存放密钥
add_library(
access_keystore_lib
SHARED
access_keystore_lib.cpp
)
target_link_libraries(
access_keystore_lib
android
c++_shared
)
\ No newline at end of file
#include "include/access_keystore_lib.h"
/**
* 获取所有隐私数据
*/
extern "C"
JNIEXPORT jobjectArray JNICALL
Java_com_wmdigit_data_value_PrivateAccessValue_getAllPrivateAccessValue(JNIEnv *env, jclass clazz) {
// oss keyId
const char* accessKeyId = "LTAI4GFsbe2RiY4zbSL8DNF2";
// oss keySecret
const char* accessKeySecret = "hgrWfbwerrSORYMTrEc3WB8d8ZaEbp";
// bugly appId
const char* buglyAppId = "e497a8cbd2";
//oss://wmdigit-se-pics/wmsaas-prod/image/pro/WeightingAndPreventFile/
jclass stringClass = env -> FindClass("java/lang/String");
jobjectArray array = env -> NewObjectArray(3, stringClass, nullptr);
jstring accessKeyIdStr = env-> NewStringUTF(accessKeyId);
jstring accessKeySecretStr = env -> NewStringUTF(accessKeySecret);
jstring buglyAppIdStr = env->NewStringUTF(buglyAppId);
// 给数组赋值
env->SetObjectArrayElement(array, 0, accessKeyIdStr);
env->SetObjectArrayElement(array, 1, accessKeySecretStr);
env->SetObjectArrayElement(array, 2, buglyAppIdStr);
// 释放
// env->ReleaseStringUTFChars(accessKeyIdStr, accessKeyId);
// env->ReleaseStringUTFChars(accessKeySecretStr, accessKeySecret);
// env->ReleaseStringUTFChars(buglyAppIdStr, buglyAppId);
return array;
}
\ No newline at end of file
//
// Created by dizi on 2023/12/22.
//
#include <jni.h>
#include <string>
#ifndef DEPTHCAMERA_ACCESS_KEYSTORE_LIB_H
#define DEPTHCAMERA_ACCESS_KEYSTORE_LIB_H
extern "C"{
};
#endif //DEPTHCAMERA_ACCESS_KEYSTORE_LIB_H
package com.wmdigit.data.mmkv;
package com.wmdigit.data.mmkv.constant;
/**
* 存储MMKV主键
......@@ -14,10 +14,26 @@ public class MmkvCons {
* 租户号
*/
public static final String MMKV_KEY_TENANT = "MMKV_KEY_TENANT";
/**
* 客户输入的租户号
*/
public static final String MMKV_KEY_TEMP_TENANT = "MMKV_KEY_TEMP_TENANT";
/**
* 客户定义的门店编号
*/
public static final String MMKV_KEY_STORE_CODE = "MMKV_KEY_STORE_CODE";
/**
* 客户输入的自定义门店编号
*/
public static final String MMKV_KEY_TEMP_STORE_CODE = "MMKV_KEY_TEMP_STORE_CODE";
/**
* 客户定义的设备编号
*/
public static final String MMKV_KEY_DEVICE_CODE = "MMKV_KEY_DEVICE_CODE";
/**
* 客户输入的自定义设备编号
*/
public static final String MMKV_KEY_TEMP_DEVICE_CODE = "MMKV_KEY_TEMP_DEVICE_CODE";
/**
* 服务器生成的设备ID
*/
......@@ -26,6 +42,10 @@ public class MmkvCons {
* 激活密钥
*/
public static final String MMKV_KEY_SN_CODE = "MMKV_KEY_SN_CODE";
/**
* 客户输入的激活密钥
*/
public static final String MMKV_KEY_TEMP_SN_CODE = "MMKV_KEY_TEMP_SN_CODE";
/**
* 裁剪框左偏移量
*/
......
package com.wmdigit.data.mmkv.repository;
import com.tencent.mmkv.MMKV;
import com.wmdigit.data.mmkv.constant.MmkvCons;
/**
* 裁剪本地存储
* @author dizi
*/
public class CropLocalRepository {
private static CropLocalRepository instance;
public static CropLocalRepository getInstance(){
if (instance == null){
synchronized (CropLocalRepository.class){
if (instance == null){
instance = new CropLocalRepository();
}
}
}
return instance;
}
/**
* 获取是否裁剪
* @return
*/
public boolean getIsCrop(){
return MMKV.defaultMMKV().getInt(MmkvCons.MMKV_KEY_CROP_WIDTH, 0) > 0;
}
}
package com.wmdigit.data.mmkv.repository;
import android.text.TextUtils;
import com.tencent.mmkv.MMKV;
import com.wmdigit.data.mmkv.constant.MmkvCons;
/**
* @author dizi
*/
public class UserLocalRepository {
private static UserLocalRepository instance;
public static UserLocalRepository getInstance(){
if (instance == null){
synchronized (UserLocalRepository.class){
if (instance == null){
instance = new UserLocalRepository();
}
}
}
return instance;
}
/**
* 获取是否激活
* @return
*/
public boolean getIsActivation(){
return MMKV.defaultMMKV().getBoolean(MmkvCons.MMKV_KEY_ACTIVATION, false);
}
/**
* 获取租户
* @return
*/
public String getTenant(){
String tenant = MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_TENANT, "");
if (TextUtils.isEmpty(tenant)){
tenant = MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_TEMP_TENANT, "");
}
return tenant;
}
/**
* 获取租户,如果获取不到,则用0租户
* @return
*/
public String getTenant2(){
return MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_TENANT, "0");
}
/**
* 保存临时用户信息
* @param storeCode
* @param deviceCode
* @param snCode
* @param tenantCode
*/
public void saveTempUser(String storeCode, String deviceCode, String snCode, String tenantCode){
MMKV.defaultMMKV().putString(MmkvCons.MMKV_KEY_TEMP_STORE_CODE, storeCode);
MMKV.defaultMMKV().putString(MmkvCons.MMKV_KEY_TEMP_DEVICE_CODE, deviceCode);
MMKV.defaultMMKV().putString(MmkvCons.MMKV_KEY_TEMP_SN_CODE, snCode);
MMKV.defaultMMKV().putString(MmkvCons.MMKV_KEY_TEMP_TENANT, tenantCode);
}
/**
* 获取临时用户信息
* @return
*/
public String[] getTempUser(){
String[] result = new String[4];
result[0] = MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_TEMP_STORE_CODE, "");
result[1] = MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_TEMP_DEVICE_CODE, "");
result[2] = MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_TEMP_SN_CODE, "");
result[3] = MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_TEMP_TENANT, "");
return result;
}
/**
* 保存注册的用户信息
* @param posId
* @param deviceCode
* @param snCode
*/
public void saveUser(String posId, String deviceCode, String snCode){
MMKV.defaultMMKV().putBoolean(MmkvCons.MMKV_KEY_ACTIVATION, true);
MMKV.defaultMMKV().putString(MmkvCons.MMKV_KEY_DEVICE_ID, posId);
MMKV.defaultMMKV().putString(MmkvCons.MMKV_KEY_STORE_CODE, deviceCode.split("_")[0]);
MMKV.defaultMMKV().putString(MmkvCons.MMKV_KEY_DEVICE_CODE, deviceCode.split("_")[1]);
MMKV.defaultMMKV().putString(MmkvCons.MMKV_KEY_SN_CODE, snCode);
String tenantCode = MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_TEMP_TENANT, "");
MMKV.defaultMMKV().putString(MmkvCons.MMKV_KEY_TENANT, tenantCode);
}
/**
* 获取注册的用户信息
* @return
*/
public String[] getUser(){
String[] result = new String[4];
result[0] = MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_STORE_CODE, "");
result[1] = MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_DEVICE_CODE, "");
result[2] = MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_SN_CODE, "");
result[3] = MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_TENANT, "");
return result;
}
}
package com.wmdigit.data.value;
/**
* 隐私数据,存到.so里
* @author dizi
*/
public class PrivateAccessValue {
static {
System.loadLibrary("access_keystore_lib");
}
/**
* 获取所有隐私数据
* @return
*/
public static native String[] getAllPrivateAccessValue();
}
/build
\ No newline at end of file
......@@ -14,8 +14,14 @@ android {
}
buildTypes {
debug {
buildConfigField 'String', 'POS_URL', '"https://se.wmdigit.com/"'
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled false
buildConfigField 'String', 'POS_URL', '"https://se.wmdigit.com/"'
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
......@@ -26,10 +32,16 @@ android {
}
dependencies {
implementation project(":common")
implementation project(":data-local")
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0' //非必要依赖,log依赖,如果需要打印OkHttpLog需要添加
implementation 'com.aliyun.dpa:oss-android-sdk:2.9.18'
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# oss
-keep class com.alibaba.sdk.android.oss.** { *; }
-dontwarn okio.**
-dontwarn org.apache.commons.codec.binary.**
#
-keep class com.wmdigit.network.bean.**{*;}
\ No newline at end of file
package com.wmdigit;
import android.content.Context;
import com.wmdigit.data.value.PrivateAccessValue;
import com.wmdigit.network.oss.OSSManager;
/**
* 网络模块存放全局context的类
* @author dizi
*/
public class NetworkModule {
private static Context appContext;
public static void init(Context context){
if (appContext == null){
appContext = context.getApplicationContext();
// 初始化OSS
initOss();
}
}
public static Context getAppContext() {
return appContext;
}
/**
* 初始化OSS
*/
private static void initOss() {
String[] values = PrivateAccessValue.getAllPrivateAccessValue();
OSSManager.getInstance().init(values[0], values[1]);
}
}
package com.wmdigit.network.bean.request;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.HashMap;
public class ProductIdentifyRecord implements Serializable {
private String sessionId;
// private String code;
private BigDecimal accuracy;
private String posNo;
private String productName;
private String productId;
private String productCode;
private Integer topNo;
private String weighImageUrl;
// private String aiType;
// private Float value;
private String identifyTime;
// private HashMap<String, Object> identifyCode;
private String scanningType; // 0错扫 1漏扫
private String zipUrl;
private String snCode;
private String json;
private boolean reScan = false;
private String shadowType;
public String getShadowType() {
return shadowType;
}
public void setShadowType(String shadowType) {
this.shadowType = shadowType;
}
public boolean isReScan() {
return reScan;
}
public void setReScan(boolean reScan) {
this.reScan = reScan;
}
public String getJson() {
return json;
}
public void setJson(String json) {
this.json = json;
}
public String getIdentifyTime() {
return identifyTime;
}
public void setIdentifyTime(String identifyTime) {
this.identifyTime = identifyTime;
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public BigDecimal getAccuracy() {
return accuracy;
}
public void setAccuracy(BigDecimal accuracy) {
this.accuracy = accuracy;
}
public String getPosNo() {
return posNo;
}
public void setPosNo(String posNo) {
this.posNo = posNo;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public Integer getTopNo() {
return topNo;
}
public void setTopNo(Integer topNo) {
this.topNo = topNo;
}
public String getWeighImageUrl() {
return weighImageUrl;
}
public void setWeighImageUrl(String weighImageUrl) {
this.weighImageUrl = weighImageUrl;
}
public String getScanningType() {
return scanningType;
}
public void setScanningType(String scanningType) {
this.scanningType = scanningType;
}
public String getZipUrl() {
return zipUrl;
}
public void setZipUrl(String zipUrl) {
this.zipUrl = zipUrl;
}
public String getSnCode() {
return snCode;
}
public void setSnCode(String snCode) {
this.snCode = snCode;
}
}
package com.wmdigit.network.bean.request;
/**
* 查询POS命令接口newretail/api/pos/machine/command/getByPosCode的请求参数
* @author dizi
*/
public class QueryCommandParam {
private String posCode;
private String aiModelVersion;
private String osVersion;
private String posVersion;
public String getPosCode() {
return posCode;
}
public void setPosCode(String posCode) {
this.posCode = posCode;
}
public String getAiModelVersion() {
return aiModelVersion;
}
public void setAiModelVersion(String aiModelVersion) {
this.aiModelVersion = aiModelVersion;
}
public String getOsVersion() {
return osVersion;
}
public void setOsVersion(String osVersion) {
this.osVersion = osVersion;
}
public String getPosVersion() {
return posVersion;
}
public void setPosVersion(String posVersion) {
this.posVersion = posVersion;
}
}
package com.wmdigit.network.bean.request;
/**
* 查询新版APP接口newretail/api/sys/app/version/getLastest的请求参数
* @author dizi
*/
public class QueryLatestAppVersionParam {
private String type;
private String version;
private String osVersion;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getOsVersion() {
return osVersion;
}
public void setOsVersion(String osVersion) {
this.osVersion = osVersion;
}
}
package com.wmdigit.network.bean.request;
/**
* 注册请求参数
* @author dizi
*/
public class RegisterParams {
private String code;
private String macAddress;
private String weighSnCode;
private String snNo;
private String snType;
/**
* 非后台所需字段,租户号
*/
private String tenant;
public String getTenant() {
return tenant;
}
public void setTenant(String tenant) {
this.tenant = tenant;
}
public String getSnType() {
return snType;
}
public void setSnType(String snType) {
this.snType = snType;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMacAddress() {
return macAddress;
}
public void setMacAddress(String macAddress) {
this.macAddress = macAddress;
}
public String getWeighSnCode() {
return weighSnCode;
}
public void setWeighSnCode(String weighSnCode) {
this.weighSnCode = weighSnCode;
}
public String getSnNo() {
return snNo;
}
public void setSnNo(String snNo) {
this.snNo = snNo;
}
}
package com.wmdigit.network.bean.request;
import java.util.List;
public class ReplyCommandList {
private List<Long> commandIds;
public List<Long> getCommandIds() {
return commandIds;
}
public void setCommandIds(List<Long> commandIds) {
this.commandIds = commandIds;
}
}
package com.wmdigit.network.bean.request;
import java.io.Serializable;
public class SaveCommandResult implements Serializable {
private Long commandId;
private Integer elapsedTimeInSeconds;
private String result;
private Boolean success;
public Long getCommandId() {
return commandId;
}
public void setCommandId(Long commandId) {
this.commandId = commandId;
}
public Integer getElapsedTimeInSeconds() {
return elapsedTimeInSeconds;
}
public void setElapsedTimeInSeconds(Integer elapsedTimeInSeconds) {
this.elapsedTimeInSeconds = elapsedTimeInSeconds;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
}
package com.wmdigit.network.bean.request;
/**
* 解绑接口newretail/api/pos/machine/unbind的请求参数
* @author dizi
*/
public class UnbindSnParam {
private String mac;
private String snNo;
public String getMac() {
return mac;
}
public void setMac(String mac) {
this.mac = mac;
}
public String getSnNo() {
return snNo;
}
public void setSnNo(String snNo) {
this.snNo = snNo;
}
}
package com.wmdigit.network.bean.response;
import com.google.gson.annotations.SerializedName;
import java.util.Date;
/**
* App版本信息
**/
public class AppVersionDTO {
private Date createTime = null;
private Long creatorId = null;
private String creatorName = null;
private String desciption = null;
private String downloadUrl = null;
private Boolean forceUpdate = null;
private Long id = null;
private Long orgId = null;
public enum TypeEnum {
ipa, apk, manageIos, manageAndroid
}
private TypeEnum type = null;
private Date updateTime = null;
private Long updatorId = null;
private String updatorName = null;
private Long versionCode = null;
private String versionName = null;
/**
* 创建时间,格式: yyyy-MM-dd HH:mm:ss
**/
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
* 创建人ID,为避免JS客户端不支持Long类型,已将其转成String类型
**/
public Long getCreatorId() {
return creatorId;
}
public void setCreatorId(Long creatorId) {
this.creatorId = creatorId;
}
/**
* 创建人名称
**/
public String getCreatorName() {
return creatorName;
}
public void setCreatorName(String creatorName) {
this.creatorName = creatorName;
}
/**
* 升级内容
**/
public String getDesciption() {
return desciption;
}
public void setDesciption(String desciption) {
this.desciption = desciption;
}
/**
* 升级包下载地址
**/
public String getDownloadUrl() {
return downloadUrl;
}
public void setDownloadUrl(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
/**
* 是否强制更新
**/
public Boolean getForceUpdate() {
return forceUpdate;
}
public void setForceUpdate(Boolean forceUpdate) {
this.forceUpdate = forceUpdate;
}
/**
* 对象唯一标识,为避免JS客户端不支持Long类型,已将其转成String类型
**/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* 所属组织ID
**/
public Long getOrgId() {
return orgId;
}
public void setOrgId(Long orgId) {
this.orgId = orgId;
}
/**
* 安装包类型
**/
public TypeEnum getType() {
return type;
}
public void setType(TypeEnum type) {
this.type = type;
}
/**
* 最后更新时间,格式: yyyy-MM-dd HH:mm:ss
**/
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
/**
* 最后更新人,为避免JS客户端不支持Long类型,已将其转成String类型
**/
public Long getUpdatorId() {
return updatorId;
}
public void setUpdatorId(Long updatorId) {
this.updatorId = updatorId;
}
/**
* 最后更新人名称
**/
public String getUpdatorName() {
return updatorName;
}
public void setUpdatorName(String updatorName) {
this.updatorName = updatorName;
}
/**
* 版本号,约定规则为major(1位)+minor(2位)+point(3位) 例如:100000
**/
public Long getVersionCode() {
return versionCode;
}
public void setVersionCode(Long versionCode) {
this.versionCode = versionCode;
}
/**
* 版本名称,约定规则为major(1位).minor(2位).point(3位) 例如:1.00.000
**/
public String getVersionName() {
return versionName;
}
public void setVersionName(String versionName) {
this.versionName = versionName;
}
}
package com.wmdigit.network.bean.response;
public class BasePosResponse<T> {
private Integer code;
private String message;
private Long timestamp;
private String id;
private T data;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
package com.wmdigit.network.bean.response;
public class BaseResponse<T> {
private int error_code;
private String error_message;
private T obj;
private String session_id;
public int getError_code() {
return error_code;
}
public void setError_code(int error_code) {
this.error_code = error_code;
}
public String getError_message() {
return error_message;
}
public void setError_message(String error_message) {
this.error_message = error_message;
}
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
public boolean isCodeInvalid() {
return error_code == 0;
}
public String getSession_id() {
return session_id;
}
public void setSession_id(String session_id) {
this.session_id = session_id;
}
}
package com.wmdigit.network.bean.response;
import java.io.Serializable;
public class PosMachine implements Serializable {
private String brand;
private String code;
private String createTime;
private String creatorId;
private String creatorName;
private Boolean disabled;
private String id;
private String macAddress;
private String orgId;
private String remark;
private String storeId;
private String storeName;
private String version;
private String weighSnCode;
private String wmKeyUrl;
private String privateKeyUrl;
private String snCode;
public String getSnCode() {
return snCode;
}
public void setSnCode(String snCode) {
this.snCode = snCode;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getCreatorId() {
return creatorId;
}
public void setCreatorId(String creatorId) {
this.creatorId = creatorId;
}
public String getCreatorName() {
return creatorName;
}
public void setCreatorName(String creatorName) {
this.creatorName = creatorName;
}
public Boolean getDisabled() {
return disabled;
}
public void setDisabled(Boolean disabled) {
this.disabled = disabled;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMacAddress() {
return macAddress;
}
public void setMacAddress(String macAddress) {
this.macAddress = macAddress;
}
public String getOrgId() {
return orgId;
}
public void setOrgId(String orgId) {
this.orgId = orgId;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getStoreId() {
return storeId;
}
public void setStoreId(String storeId) {
this.storeId = storeId;
}
public String getStoreName() {
return storeName;
}
public void setStoreName(String storeName) {
this.storeName = storeName;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getWeighSnCode() {
return weighSnCode;
}
public void setWeighSnCode(String weighSnCode) {
this.weighSnCode = weighSnCode;
}
public String getWmKeyUrl() {
return wmKeyUrl;
}
public void setWmKeyUrl(String wmKeyUrl) {
this.wmKeyUrl = wmKeyUrl;
}
public String getPrivateKeyUrl() {
return privateKeyUrl;
}
public void setPrivateKeyUrl(String privateKeyUrl) {
this.privateKeyUrl = privateKeyUrl;
}
}
package com.wmdigit.network.bean.response;
/**
* 设备的注册信息
* @author dizi
*/
public class PosRegisterInfo {
private String posId;
private String code;
private String snCode;
/**
* 门店Code没有在后台存储
*/
private String storeCode;
public String getStoreCode() {
return storeCode;
}
public void setStoreCode(String storeCode) {
this.storeCode = storeCode;
}
public String getPosId() {
return posId;
}
public void setPosId(String posId) {
this.posId = posId;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getSnCode() {
return snCode;
}
public void setSnCode(String snCode) {
this.snCode = snCode;
}
}
package com.wmdigit.network.bean.response;
public class ResponseOss {
private String fileName;
private Long id;
private String url;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
package com.wmdigit.network.bean.response;
import java.io.Serializable;
public class SimplePosCommandDTO implements Serializable {
private Long id;//命令ID
private String parameters;//命令参数
private StatusEnum status;//命令状态
private TypeEnum type;//命令类型
/**
* 命令状态
*/
public enum StatusEnum implements Serializable {
CREATE, CANCELED, PROCESSING, FAILED, SUCCESS
}
/**
* 命令类型
*/
public enum TypeEnum implements Serializable {
UPLOAD_LOG
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getParameters() {
return parameters;
}
public void setParameters(String parameters) {
this.parameters = parameters;
}
public StatusEnum getStatus() {
return status;
}
public void setStatus(StatusEnum status) {
this.status = status;
}
public TypeEnum getType() {
return type;
}
public void setType(TypeEnum type) {
this.type = type;
}
}
package com.wmdigit.network.exception;
public class ServerException extends Exception{
private int code;
private String msg;
public ServerException(String message){
super(message);
}
public ServerException(int code, String mes){
super(mes);
this.code=code;
this.msg = mes;
}
public int getCode(){
return code;
}
@Override
public String toString(){
return "错误码:" + code +","+ msg;
}
}
package com.wmdigit.network.factory;
import androidx.annotation.NonNull;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import io.reactivex.Single;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Dns;
public class CustomDns implements Dns {
private long timeout = 3L;
public CustomDns() {
}
public CustomDns(long timeout) {
this.timeout = timeout;
}
@NonNull
@Override
public List<InetAddress> lookup(@NonNull String hostname) throws UnknownHostException {
return Single.fromCallable(new Callable<List<InetAddress>>() {
@Override
public List<InetAddress> call() throws Exception {
List<InetAddress> list;
try{
list = Arrays.asList(InetAddress.getAllByName(hostname));
} catch (Exception e){
list = new ArrayList<>();
}
return list;
}
})
.timeout(timeout, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.computation())
.onErrorReturnItem(new ArrayList<>())
.blockingGet();
}
}
package com.wmdigit.network.factory;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.elvishew.xlog.XLog;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.wmdigit.network.bean.response.BaseResponse;
import com.wmdigit.network.exception.ServerException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import okio.Buffer;
import retrofit2.Converter;
import retrofit2.Retrofit;
public class CustomGsonConverterFactory extends Converter.Factory {
private final Gson gson;
private CustomGsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
public static CustomGsonConverterFactory create() {
return create(new Gson());
}
public static CustomGsonConverterFactory create(Gson gson) {
return new CustomGsonConverterFactory(gson);
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new CustomGsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new CustomGsonRequestBodyConverter<>(gson, adapter);
}
final class CustomGsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
CustomGsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
final class CustomGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
CustomGsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public T convert(ResponseBody value) throws IOException {
String response = value.string();
XLog.d("response:" + response);
BaseResponse baseResponse = gson.fromJson(response, BaseResponse.class);
//核心代码: 判断 status 是否是后台定义的正常值
if (baseResponse.isCodeInvalid()) {
value.close();
try {
throw new ServerException(baseResponse.getError_code(), baseResponse.getError_message());
} catch (ServerException e) {
e.printStackTrace();
}
}
MediaType contentType = value.contentType();
Charset charset = contentType != null ? contentType.charset(UTF_8) : UTF_8;
InputStream inputStream = new ByteArrayInputStream(response.getBytes());
Reader reader = new InputStreamReader(inputStream, charset);
JsonReader jsonReader = gson.newJsonReader(reader);
try {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
}
}
package com.wmdigit.network.factory;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import okio.Buffer;
import retrofit2.Converter;
import retrofit2.Retrofit;
public class GsonConverterFactory extends Converter.Factory{
/**
* Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static GsonConverterFactory create() {
return create(new Gson());
}
/**
* Create an instance using {@code gson} for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
}
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
}
package com.wmdigit.network.factory;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;
public class NullOrEmptyConverterFactory extends Converter.Factory {
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
final Converter<ResponseBody,?> delegate = retrofit.nextResponseBodyConverter(this, type, annotations);
return new Converter<ResponseBody, Object>() {
@Override
public Object convert(ResponseBody value) throws IOException {
if (value.contentLength() <= 0)
return null;
return delegate.convert(value);
}
};
}
}
package com.wmdigit.network.factory;
import android.nfc.TagLostException;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.elvishew.xlog.XLog;
import com.wmdigit.data.mmkv.constant.MmkvCons;
import com.wmdigit.data.mmkv.repository.UserLocalRepository;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
/**
* @author dizi
*/
public class OKHttpClientFactory {
private static final Long TIMEOUT_CONNECT = 20L;
private static final Long TIMEOUT_DNS = 3L;
private static OkHttpClient defaultClient;
private static OkHttpClient defaultClientWithMasterTenant;
public static OkHttpClient getDefaultOkClient() {
SSLSocketFactory socketFactory=null;
if(defaultClient==null){
synchronized (OKHttpClientFactory.class){
if(defaultClient==null){
final TrustManager[] trustAllCerts=new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
try{
SSLContext sslContext=SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
socketFactory = sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(XLog::i);
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
defaultClient = new OkHttpClient.Builder()
.connectTimeout(TIMEOUT_CONNECT, TimeUnit.SECONDS)
.readTimeout(TIMEOUT_CONNECT, TimeUnit.SECONDS)
.writeTimeout(TIMEOUT_CONNECT, TimeUnit.SECONDS)
.dns(new CustomDns(TIMEOUT_DNS))
.retryOnConnectionFailure(true)
.addInterceptor(new Interceptor() {
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request.Builder requestBuilder = chain.request().newBuilder();
requestBuilder.addHeader("Content-Type", "application/json;charset=utf-8");
requestBuilder.addHeader("Accept", "application/json;charset=utf-8");
String tenant = UserLocalRepository.getInstance().getTenant();
requestBuilder.addHeader("tenant", tenant);
return chain.proceed(requestBuilder.build());
}
})
// .addInterceptor(new UnifiedRequestHead())
.addInterceptor(httpLoggingInterceptor)
.sslSocketFactory(socketFactory, (X509TrustManager) trustAllCerts[0])
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})
.build();
}
}
}
return defaultClient;
}
public static OkHttpClient getDefaultOkClientWithMasterTenant() {
SSLSocketFactory socketFactory=null;
if(defaultClientWithMasterTenant==null){
synchronized (OKHttpClientFactory.class){
if(defaultClientWithMasterTenant==null){
final TrustManager[] trustAllCerts=new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
try{
SSLContext sslContext=SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
socketFactory = sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(XLog::i);
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
defaultClientWithMasterTenant = new OkHttpClient.Builder()
.connectTimeout(TIMEOUT_CONNECT, TimeUnit.SECONDS)
.readTimeout(TIMEOUT_CONNECT, TimeUnit.SECONDS)
.writeTimeout(TIMEOUT_CONNECT, TimeUnit.SECONDS)
.dns(new CustomDns(TIMEOUT_DNS))
.retryOnConnectionFailure(true)
.addInterceptor(new Interceptor() {
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request.Builder requestBuilder = chain.request().newBuilder();
requestBuilder.addHeader("Content-Type", "application/json;charset=utf-8");
requestBuilder.addHeader("Accept", "application/json;charset=utf-8");
String tenant = UserLocalRepository.getInstance().getTenant2();
requestBuilder.addHeader("tenant", tenant);
return chain.proceed(requestBuilder.build());
}
})
// .addInterceptor(new UnifiedRequestHead())
.addInterceptor(httpLoggingInterceptor)
.sslSocketFactory(socketFactory, (X509TrustManager) trustAllCerts[0])
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
})
.build();
}
}
}
return defaultClientWithMasterTenant;
}
}
package com.wmdigit.network.factory;
import android.content.Context;
import com.wmdigit.network.BuildConfig;
import com.wmdigit.network.service.FileService;
import com.wmdigit.network.service.PosService;
import com.wmdigit.network.service.PosService2;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
/**
* @author dizi
*/
public class ServiceFactory {
private final static String POS_URL = BuildConfig.POS_URL;
public static int NET_SUCCESS_CODE = 0;
private static ServiceFactory serviceFactory;
private PosService posService;
private PosService2 posService2;
public static ServiceFactory getServiceFactory(){
if(serviceFactory==null){
synchronized (ServiceFactory.class){
if(serviceFactory==null){
serviceFactory=new ServiceFactory();
}
}
}
return serviceFactory;
}
public PosService getPosService(){
if (posService == null){
synchronized (ServiceFactory.class){
if (posService == null){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(POS_URL)
// .addConverterFactory(new NullOrEmptyConverterFactory())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(OKHttpClientFactory.getDefaultOkClient())
.build();
posService = retrofit.create(PosService.class);
}
}
}
return posService;
}
public PosService2 getPosService2(){
if (posService2 == null){
synchronized (ServiceFactory.class){
if (posService2 == null){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(POS_URL)
// .addConverterFactory(new NullOrEmptyConverterFactory())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(OKHttpClientFactory.getDefaultOkClientWithMasterTenant())
.build();
posService2 = retrofit.create(PosService2.class);
}
}
}
return posService2;
}
}
package com.wmdigit.network.oss;
import android.text.TextUtils;
import com.alibaba.sdk.android.oss.ClientConfiguration;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSPlainTextAKSKCredentialProvider;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.elvishew.xlog.XLog;
import com.wmdigit.NetworkModule;
import java.io.File;
import okhttp3.OkHttpClient;
/**
* OSS管理类
* @author dizi
*/
public class OSSManager {
private final String END_POINT = "http://oss-cn-beijing.aliyuncs.com";
private final String BUCKET_NAME = "wmdigit-se-pics";
/**
* OSS保存路径
*/
private final String STORAGE_PATH_ON_OSS = "wmsaas-prod/image/pro/WeightingAndPreventFile/";
/**
* 在服务器上存储的路径
*/
private final String STORAGE_URL_ON_SERVER = "https://wmdigit-se-pics.oss-cn-beijing.aliyuncs.com/wmsaas-prod/image/pro/WeightingAndPreventFile/";
private volatile static OSSManager instance;
public static OSSManager getInstance(){
if (instance == null){
synchronized (OSSManager.class){
if (instance == null){
instance = new OSSManager();
}
}
}
return instance;
}
/**
* oss主类
*/
private OSSClient ossClient;
/**
* 初始化
* @param accessKeyId
* @param accessKeySecret
*/
public void init(String accessKeyId, String accessKeySecret){
ClientConfiguration configuration = new ClientConfiguration();
// 设置最大并发数。
configuration.setMaxConcurrentRequest(2);
// 设置Socket层传输数据的超时时间。
configuration.setSocketTimeout(50000);
// 设置建立连接的超时时间。
configuration.setConnectionTimeout(10000);
// 设置日志文件大小。
configuration.setMaxLogSize(3 * 1024 * 1024);
// 请求失败后最大的重试次数。
configuration.setMaxErrorRetry(1);
// 是否开启httpDns。
configuration.setHttpDnsEnable(true);
// 是否开启CRC校验。
configuration.setCheckCRC64(true);
// 是否开启HTTP重定向。
configuration.setFollowRedirectsEnable(true);
// 设置自定义OkHttpClient。
OkHttpClient.Builder builder = new OkHttpClient.Builder();
configuration.setOkHttpClient(builder.build());
OSSCredentialProvider credentialProvider = new OSSPlainTextAKSKCredentialProvider(accessKeyId, accessKeySecret);
/* OSSCredentialProvider credentialProvider = new OSSFederationCredentialProvider() {
@Override
public OSSFederationToken getFederationToken() throws ClientException {
return null;
}
};*/
ossClient = new OSSClient(NetworkModule.getAppContext(), END_POINT, credentialProvider, configuration);
}
/**
* 同步上传文件到OSS
* @param file
* @return OSS保存的路径
*/
public String syncUploadFileToOSS(File file){
String ossUrl = "";
String fileName = file.getName();
PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, STORAGE_PATH_ON_OSS + fileName, file.getAbsolutePath());
try {
ossClient.putObject(putObjectRequest);
ossUrl = putObjectRequest.getObjectKey();
} catch (Exception e) {
XLog.e(e.toString());
}
if (TextUtils.isEmpty(ossUrl)){
return "";
}
else{
return STORAGE_URL_ON_SERVER + fileName;
}
}
}
package com.wmdigit.network.repository;
import android.text.TextUtils;
import com.wmdigit.NetworkModule;
import com.wmdigit.common.base.mvvm.BaseMvvmNetworkRepository;
import com.wmdigit.common.base.mvvm.SingleLiveEvent;
import com.wmdigit.common.utils.DeviceUtils;
import com.wmdigit.network.R;
import com.wmdigit.network.bean.response.PosMachine;
import com.wmdigit.network.factory.ServiceFactory;
import com.wmdigit.network.repository.impl.IUserRemoteRepository;
import com.wmdigit.network.bean.request.RegisterParams;
import com.wmdigit.network.bean.response.PosRegisterInfo;
import com.wmdigit.network.exception.ServerException;
import com.wmdigit.network.utils.RxHelper;
import java.net.UnknownHostException;
import io.reactivex.disposables.Disposable;
import retrofit2.HttpException;
/**
* 注册相关的网络请求
* @author dizi
*/
public class UserRemoteRepository extends BaseMvvmNetworkRepository implements IUserRemoteRepository {
private volatile static UserRemoteRepository instance;
public static UserRemoteRepository getInstance(){
if (instance == null){
synchronized (UserRemoteRepository.class){
if (instance == null){
instance = new UserRemoteRepository();
}
}
}
return instance;
}
/**
* 查询注册的信息
*/
public SingleLiveEvent<PosRegisterInfo> responseQueryRegisterInfo = new SingleLiveEvent<>();
/**
* 注册的设备信息
*/
public SingleLiveEvent<PosMachine> responseRegister = new SingleLiveEvent<>();
/**
* 请求查询注册信息
* @return
*/
@Override
public Disposable queryRegisterInfo(){
return ServiceFactory.getServiceFactory()
.getPosService2()
.queryPosByMac(DeviceUtils.getAndroidId())
.compose(RxHelper.handlePosResult())
.subscribe(
posRegisterInfo -> {
if (posRegisterInfo == null) {
showHttpToast(NetworkModule.getAppContext().getString(R.string.no_register_info));
return;
}
// 门店号_设备号
if (TextUtils.isEmpty(posRegisterInfo.getPosId())) {
showHttpToast(NetworkModule.getAppContext().getString(R.string.no_store_and_device_info));
return;
}
String[] storeIdAndPosId = posRegisterInfo.getPosId().split("_");
if (storeIdAndPosId.length != 2) {
showHttpToast(NetworkModule.getAppContext().getString(R.string.error_store_and_device_info));
return;
}
posRegisterInfo.setStoreCode(storeIdAndPosId[0]);
posRegisterInfo.setPosId(storeIdAndPosId[1]);
// SN
if (TextUtils.isEmpty(posRegisterInfo.getSnCode())) {
showHttpToast(NetworkModule.getAppContext().getString(R.string.no_sn_code));
return;
}
// 租户
if (TextUtils.isEmpty(posRegisterInfo.getCode())) {
showHttpToast(NetworkModule.getAppContext().getString(R.string.no_tenant_code));
return;
}
// 成功
showHttpToast(NetworkModule.getAppContext().getString(R.string.query_register_info_success));
// 拆分门店和设备
String code = posRegisterInfo.getPosId();
if (!TextUtils.isEmpty(code) && code.contains("_")){
posRegisterInfo.setPosId(code.split("_")[1]);
posRegisterInfo.setStoreCode(code.split("_")[0]);
}
responseQueryRegisterInfo.postValue(posRegisterInfo);
},
throwable -> {
if (throwable instanceof UnknownHostException) {
showHttpToast(NetworkModule.getAppContext().getString(R.string.please_check_network_connect));
} else {
showHttpToast(NetworkModule.getAppContext().getString(R.string.query_register_info_failed));
}
}
);
}
/**
* 注册
* @param
*/
@Override
public Disposable register(RegisterParams params){
params.setMacAddress(DeviceUtils.getAndroidId());
return ServiceFactory.getServiceFactory()
.getPosService()
.bindPos(params)
.compose(RxHelper.<PosMachine>handlePosResult())
.subscribe(posMachine -> {
if (posMachine != null) {
String privateKeyUrl = posMachine.getPrivateKeyUrl();
String wmKeyUrl = posMachine.getWmKeyUrl();
if (TextUtils.isEmpty(privateKeyUrl) || TextUtils.isEmpty(wmKeyUrl)) {
// 密钥下载链接为空,注册失败
showHttpToast(NetworkModule.getAppContext().getString(R.string.in_review_concat_manager));
return;
}
showHttpToast(NetworkModule.getAppContext().getString(R.string.register_success));
responseRegister.postValue(posMachine);
} else {
// 返回值为null, 注册失败
showHttpToast(NetworkModule.getAppContext().getString(R.string.response_empty));
}
}, throwable -> {
if (throwable instanceof UnknownHostException) {
showHttpToast(NetworkModule.getAppContext().getString(R.string.check_net));
} else if (throwable instanceof HttpException){
showHttpToast(NetworkModule.getAppContext().getString(R.string.please_check_input_tenant));
}else if(throwable instanceof ServerException){
showHttpToast(throwable.toString());
}
});
}
}
package com.wmdigit.network.repository.impl;
import com.wmdigit.network.bean.request.RegisterParams;
import io.reactivex.disposables.Disposable;
/**
* 用户相关的网络请求仓库的接口
* @author dizi
*/
public interface IUserRemoteRepository {
/**
* 请求注册信息
*/
Disposable queryRegisterInfo();
/**
* 注册
* @param params
*/
Disposable register(RegisterParams params);
}
package com.wmdigit.network.service;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Streaming;
import retrofit2.http.Url;
public interface FileService {
@Streaming
@GET
Call<ResponseBody> downloadFile(@Url String url);
}
package com.wmdigit.network.service;
import com.wmdigit.network.bean.request.ProductIdentifyRecord;
import com.wmdigit.network.bean.request.QueryCommandParam;
import com.wmdigit.network.bean.request.QueryLatestAppVersionParam;
import com.wmdigit.network.bean.request.RegisterParams;
import com.wmdigit.network.bean.request.ReplyCommandList;
import com.wmdigit.network.bean.request.SaveCommandResult;
import com.wmdigit.network.bean.request.UnbindSnParam;
import com.wmdigit.network.bean.response.AppVersionDTO;
import com.wmdigit.network.bean.response.BasePosResponse;
import com.wmdigit.network.bean.response.PosMachine;
import com.wmdigit.network.bean.response.ResponseOss;
import com.wmdigit.network.bean.response.SimplePosCommandDTO;
import java.util.List;
import io.reactivex.Observable;
import okhttp3.MultipartBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Part;
import retrofit2.http.Query;
public interface PosService {
/**
* 8位SN码绑定
* @param param
* @return
*/
@PUT("newretail/api/pos/machine/bind")
Observable<BasePosResponse<PosMachine>> bindPos(@Body RegisterParams param);
/**
* 解绑
* @param mac
* @param snCode
* @return
*/
@POST("newretail/api/pos/machine/unbind")
Call<BasePosResponse> unbindPos(@Body UnbindSnParam param);
/**
* 上传图像
* @param parts
* @return
*/
@Multipart
@POST("newretail/api/dfs/upload3")
Observable<BasePosResponse<ResponseOss>> uploadImageFile(@Part List<MultipartBody.Part> parts);
@POST("newretail/api/search/preLossRecord/saveProductIdentifyPreLossRecord")
Observable<BasePosResponse<String>> saveImageIdentify(@Body ProductIdentifyRecord record);
/**
* 根据pos机编号查询pos机命令
*/
@POST("newretail/api/pos/machine/command/getByPosCode")
Observable<BasePosResponse<List<SimplePosCommandDTO>>> getCommandByPosCode(@Body QueryCommandParam param);
/**
* 回复POS机命令,标记已收到命令,准备执行
*/
@POST("newretail/api/pos/machine/command/reply")
Observable<BasePosResponse<Void>> replyCommand(@Body ReplyCommandList commandIds);
/**
* 保存命令处理结果
*/
@POST("newretail/api/pos/machine/command/saveResult")
Observable<BasePosResponse<Void>> saveCommandResult(@Body SaveCommandResult saveCommandResult);
/**
* 更新APP版本
* @param type
* @param version
* @param osVersion
* @return
*/
@POST("newretail/api/sys/app/version/getLastest")
Observable<BasePosResponse<AppVersionDTO>> getAppLatestVersion(@Body QueryLatestAppVersionParam param);
/**
* 下载远程工具
* @param type
* @return
*/
@GET("newretail/api/sys/app/version/getLatestWithType")
Observable<BasePosResponse<AppVersionDTO>> getLatestRemoteToolWithType(@Query("type") String type);
}
package com.wmdigit.network.service;
import com.wmdigit.network.bean.response.BasePosResponse;
import com.wmdigit.network.bean.response.PosRegisterInfo;
import io.reactivex.Observable;
import retrofit2.http.GET;
import retrofit2.http.Query;
/**
* 后台接口,允许在没有租户的情况下使用0租户
* @author dizi
*/
public interface PosService2 {
/**
* 查询试用注册信息
* @param MacAddress
* @return
*/
@GET("newretail/api/pos/machine/getIdByMacAddress")
Observable<BasePosResponse<PosRegisterInfo>> queryPosByMac(@Query("MacAddress") String MacAddress);
}
//package com.wmdigit.network;
//
//import android.content.Context;
//
//import com.wmdigit.network.bean.request.ProductIdentifyRecord;
//import com.wmdigit.network.bean.request.QueryCommandParam;
//import com.wmdigit.network.bean.request.QueryLatestAppVersionParam;
//import com.wmdigit.network.bean.request.QueryLatestCropPointsParam;
//import com.wmdigit.network.bean.request.RegisterParams;
//import com.wmdigit.network.bean.request.ReplyCommandList;
//import com.wmdigit.network.bean.request.ReqLabel;
//import com.wmdigit.network.bean.request.ReqPredictParam;
//import com.wmdigit.network.bean.request.SaveCommandResult;
//import com.wmdigit.network.bean.request.SavePreLossPosExceptionRecordDTO;
//import com.wmdigit.network.bean.request.UnBindParams;
//import com.wmdigit.network.bean.request.UnbindSnParam;
//import com.wmdigit.network.bean.response.AppVersionDTO;
//import com.wmdigit.network.bean.response.BasePosResponse;
//import com.wmdigit.network.bean.response.GetPreLossPosCropJsonDTO;
//import com.wmdigit.network.bean.response.LossPreventRecordDetailPage;
//import com.wmdigit.common.model.PosMachine;
//import com.wmdigit.network.bean.response.RespPredict;
//import com.wmdigit.network.bean.response.ResponseOss;
//import com.wmdigit.network.bean.response.ResponsePosRegisterInfo;
//import com.wmdigit.network.bean.response.SimplePosCommandDTO;
//import com.wmdigit.network.factory.ServiceFactory;
//import com.wmdigit.network.oss.OSSManager;
//import com.wmdigit.network.utils.RxHelper;
//import com.wmdigit.common.utils.DeviceUtils;
//
//import java.io.File;
//import java.util.List;
//
//import io.reactivex.Observable;
//import okhttp3.MediaType;
//import okhttp3.MultipartBody;
//import okhttp3.RequestBody;
//import okhttp3.ResponseBody;
//import retrofit2.Callback;
//
//
///**
// * @author dizi
// */
//public class HttpClient {
//
// private static HttpClient instance;
//
// private Context context;
//
// public static HttpClient getInstance(Context context){
// if (instance == null){
// synchronized (HttpClient.class){
// if (instance == null){
// instance = new HttpClient(context);
// }
// }
// }
// return instance;
// }
//
// public static HttpClient getInstance() {
// return instance;
// }
//
// public HttpClient() {
// }
//
// public HttpClient(Context context) {
// this.context = context;
// }
//
// public Observable<RespPredict> imagePredict(ReqPredictParam param){
// return ServiceFactory.getServiceFactory()
// .getApiService(context)
// .detect(param)
// .compose(RxHelper.<RespPredict>handleResult());
// }
//
// public Observable<RespPredict> feedBack(ReqLabel label){
// return ServiceFactory.getServiceFactory()
// .getApiService(context)
// .feedBack(label)
// .compose(RxHelper.<RespPredict>handleResult());
// }
//
// /**
// * 绑定
// * @param params
// * @return
// */
// public Observable<PosMachine> bindPos(RegisterParams params){
// return ServiceFactory.getServiceFactory()
// .getPosService()
// .bindPos(params)
// .compose(RxHelper.<PosMachine>handlePosResult());
// }
//
// /**
// * 解绑
// * @param params
// * @param callback
// */
// public void unbindPos(UnBindParams params, Callback<BasePosResponse> callback){
// UnbindSnParam param = new UnbindSnParam();
// param.setMac(params.getMac());
// param.setSnNo(params.getSnNo());
// ServiceFactory.getServiceFactory()
// .getPosService()
// .unbindPos(param)
// .enqueue(callback);
//
// }
//
// /**
// * 上传防损记录
// * @param record
// * @return
// */
// public Observable<String> uploadPreLossScanRecord(ProductIdentifyRecord record){
// return ServiceFactory.getServiceFactory()
// .getPosService()
// .saveImageIdentify(record)
// .compose(RxHelper.<String>handlePosResult());
// }
//
// public void downloadFile(String url, Callback<ResponseBody> callback){
// ServiceFactory.getServiceFactory()
// .getFileService(context)
// .downloadFile(url)
// .enqueue(callback);
//
//
// }
//
// /**
// * 上传文件到OSS
// * @param file
// * @return
// */
// public Observable<String> uploadFileToOSS(File file){
// return Observable.create(emitter -> {
// String url = OSSManager.getInstance().syncUploadFileToOSS(file);
// emitter.onNext(url);
// });
// }
//
// /**
// * 上传文件到服务器
// * @param file
// * @param mediaType
// * @return
// */
// public Observable<ResponseOss> uploadFileToServer(File file, String mediaType){
// final String fileKey = "file";
// MultipartBody body = new MultipartBody.Builder()
// .addFormDataPart(fileKey, file.getName(), RequestBody.create(MediaType.parse(mediaType), file))
// .setType(MultipartBody.FORM)
// .build();
// return ServiceFactory.getServiceFactory()
// .getPosService()
// .uploadImageFile(body.parts())
// .compose(RxHelper.<ResponseOss>handlePosResult());
// }
//
// /**
// * 根据AndroidID查询POS信息
// * @return
// */
// public Observable<ResponsePosRegisterInfo> queryPosByAndroidID(){
// return ServiceFactory.getServiceFactory()
// .getPosService2()
// .queryPosByMac(DeviceUtils.getAndroidId())
// .compose(RxHelper.handlePosResult());
// }
//
// /**
// * 根据PosCode查命令
// * @param posCode
// * @param aiModelVersion
// * @param osVersion
// * @param posVersion
// * @return
// */
// public Observable<List<SimplePosCommandDTO>> getCommandByPosCode(String posCode, String aiModelVersion, String osVersion, String posVersion){
// QueryCommandParam param = new QueryCommandParam();
// param.setPosCode(posCode);
// param.setAiModelVersion(aiModelVersion);
// param.setOsVersion(osVersion);
// param.setPosVersion(posVersion);
// return ServiceFactory.getServiceFactory()
// .getPosService()
// .getCommandByPosCode(param)
// .compose(RxHelper.handlePosResult());
// }
//
// public Observable<Void> replyCommand(ReplyCommandList replyCommandList){
// return ServiceFactory.getServiceFactory()
// .getPosService()
// .replyCommand(replyCommandList)
// .compose(RxHelper.handlePosResult());
// }
//
// public Observable<Void> saveCommandResult(SaveCommandResult saveCommandResult){
// return ServiceFactory.getServiceFactory()
// .getPosService()
// .saveCommandResult(saveCommandResult)
// .compose(RxHelper.handlePosResult());
// }
//
// /**
// * 查询APP最新版本
// * @param appTypePosAndroid
// * @param versionCode
// * @param osVersion
// * @return
// */
// public Observable<AppVersionDTO> version(String appTypePosAndroid, String versionCode, String osVersion){
// QueryLatestAppVersionParam param = new QueryLatestAppVersionParam();
// param.setType(appTypePosAndroid);
// param.setVersion(versionCode);
// param.setOsVersion(osVersion);
// return ServiceFactory.getServiceFactory()
// .getPosService()
// .getAppLatestVersion(param)
// .compose(RxHelper.<AppVersionDTO>handlePosResult());
// }
//
// /**
// * 下载最新远程工具
// * @param type
// * @return
// */
// public Observable<AppVersionDTO> getLatestRemoteToolWithType(String type) {
// return ServiceFactory.getServiceFactory()
// .getPosService()
// .getLatestRemoteToolWithType(type)
// .compose(RxHelper.<AppVersionDTO>handlePosResult());
// }
//
// /**
// * 查询防损记录
// * @param page
// * @param pageSize
// * @param searchCount
// * @param beginDate
// * @param endDate
// * @param scanType
// * @return
// */
// public Observable<LossPreventRecordDetailPage> queryLossPreventRecord(int page, int pageSize, boolean searchCount, String beginDate, String endDate, String scanType, String codeEquals){
// return ServiceFactory.getServiceFactory().getPosService()
// .queryProductIdentifyPreLossImage(page, pageSize, searchCount, beginDate, endDate, scanType, codeEquals)
// .compose(RxHelper.handlePosResult());
// }
//
// /**
// * 上传摄像头异常记录
// * @param recordDTO
// * @return
// */
// public Observable<Void> saveCameraException(SavePreLossPosExceptionRecordDTO recordDTO){
// return ServiceFactory.getServiceFactory().getPosService()
// .saveCameraException(recordDTO)
// .compose(RxHelper.handlePosResult());
// }
//
// /**
// * 从服务器查询裁剪坐标
// * @param posId
// * @return
// */
// public Observable<GetPreLossPosCropJsonDTO> queryCropCoordinateFromServer(String posId){
// QueryLatestCropPointsParam param = new QueryLatestCropPointsParam();
// param.setPosId(posId);
// return ServiceFactory.getServiceFactory()
// .getPosService().queryCropCoordinateFromServer(param)
// .compose(RxHelper.handlePosResult());
// }
//}
package com.wmdigit.network.utils;
import com.wmdigit.network.bean.response.BasePosResponse;
import com.wmdigit.network.exception.ServerException;
import com.wmdigit.network.factory.ServiceFactory;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.functions.Function;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* RX辅助类
* @author dizi
*/
public class RxHelper {
/**
* 去壳,将BasePosResponse<T>转化为T
* @return
* @param <T>
*/
@SuppressWarnings("unchecked")
public static <T> ObservableTransformer<BasePosResponse<T>,T> handlePosResult(){
return upstream -> {
Observable<Object> observable = upstream.flatMap((Function<BasePosResponse<T>, ObservableSource<?>>) tBaseResponse -> {
int code=tBaseResponse.getCode();
String desc=tBaseResponse.getMessage();
T data=tBaseResponse.getData();
if(code == ServiceFactory.NET_SUCCESS_CODE){
return createObservable(data);
}else{
return createErrorObservable(new ServerException(code, desc));
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
return (ObservableSource<T>)observable;
};
}
/**
* 创建指定数据源的Observable
* 后端传来的数据,如果为空,则则直接走 onComplete(); 否则,走onNext(),即传数据
* @param t
* @return
* @param <T>
*/
private static <T> Observable<T> createObservable(final T t) {
return Observable.create(new ObservableOnSubscribe<T>() {
@Override
public void subscribe(ObservableEmitter<T> e) {
if (e != null) {
if (t != null) {
e.onNext(t); // 到observe的onNext()
}else {
e.onError(new Exception("data null"));
}
e.onComplete();
}
}
});
}
public static <T> Observable<T> createErrorObservable(ServerException exception) {
return Observable.create(new ObservableOnSubscribe<T>() {
@Override
public void subscribe(ObservableEmitter<T> e) {
if (e != null) {
e.onError(exception);
e.onComplete();
}
}
});
}
}
package com.wmdigit.socket.bean;
/**
* 奥乐齐Socket传输数据
* @author dizi
*/
public class AldiSocketMessage {
/**
* 消息类型
* scan-扫码
*/
private String type = "";
/**
* 消息内容
*/
private SocketData data;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public SocketData getData() {
return data;
}
public void setData(SocketData data) {
this.data = data;
}
public static class SocketData{
/**
* 设备ID
*/
private String deviceId;
/**
* 时间戳
*/
private String beginTime;
/**
* 条码
*/
private String barcode;
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getBeginTime() {
return beginTime;
}
public void setBeginTime(String beginTime) {
this.beginTime = beginTime;
}
public String getBarcode() {
return barcode;
}
public void setBarcode(String barcode) {
this.barcode = barcode;
}
}
}
package com.wmdigit.socket.client;
import android.text.TextUtils;
import com.elvishew.xlog.XLog;
import com.google.gson.Gson;
import com.wmdigit.socket.bean.AldiSocketMessage;
import com.wmdigit.socket.pool.SocketTransferBarcodeThreadPool;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
/**
* 奥乐齐Socket传输条码 客户端
* @author dizi
*/
public class AldiSocketClient {
private static AldiSocketClient instance;
public static AldiSocketClient getInstance(){
if (instance == null){
synchronized (AldiSocketClient.class){
if (instance == null){
instance = new AldiSocketClient();
}
}
}
return instance;
}
/**
* 客户端
*/
private Socket client;
private Gson gson;
public AldiSocketClient() {
gson = new Gson();
}
/**
* 连接服务器(请在子线程执行)
* @param ipAddress
* @param port
*/
public boolean connect(String ipAddress, int port) {
if (client != null && client.isConnected()) {
return true;
}
try {
client = new Socket(ipAddress, port);
XLog.i("ALDI服务端连接成功");
SocketTransferBarcodeThreadPool.getInstance().execute(() -> listenServerMessage());
} catch (Exception e) {
XLog.e("ALDI服务端连接异常:" + e.toString());
return false;
}
return true;
}
private void listenServerMessage(){
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line = "";
while ((line = in.readLine()) != null) {
// 监听服务器数据
XLog.i("收到服务器数据: %s", line);
// 解析收到的数据
AldiSocketMessage aldiSocketMessage = parseServerMessage(line);
if (aldiSocketMessage == null) {
continue;
}
XLog.d("" + aldiSocketMessage.getType());
switch (aldiSocketMessage.getType()) {
case "scan":
// 消息类型为接收条码
String barcode = "0";
if (aldiSocketMessage.getData() != null && !TextUtils.isEmpty(aldiSocketMessage.getData().getBarcode())) {
barcode = aldiSocketMessage.getData().getBarcode();
}
// 发送接收的条码
// EventBus.getDefault().post(new MessageEvent<String>(EventCode.EVENT_RECEIVE_BARCODE_FROM_SOCKET, barcode));
break;
default:
break;
}
}
XLog.i("服务器连接断开");
}
catch (Exception e) {
XLog.e("数据接收异常:" + e.toString());
}
finally {
if (client != null){
try {
client.close();
} catch (IOException e) {
XLog.e(e.toString());
} finally {
client = null;
}
}
}
}
/**
* 解析服务器数据
* @param message
* @return
*/
private AldiSocketMessage parseServerMessage(String message){
AldiSocketMessage aldiSocketMessage = null;
try {
aldiSocketMessage = gson.fromJson(message, AldiSocketMessage.class);
}
catch (Exception e){
XLog.e(e.toString());
}
return aldiSocketMessage;
}
/**
* 检查连接状态
* @return
*/
public boolean checkSocketConnected(){
if (client == null){
return false;
}
if (client.isClosed()){
return false;
}
return client.isConnected();
}
/**
* 关闭连接
*/
public void stopSocket(){
if (client != null){
try {
client.close();
client = null;
} catch (IOException e) {
XLog.e(e.toString());
}
}
}
}
package com.wmdigit.socket.client.listener;
/**
* 奥乐齐服务端监听
* @author dizi
*/
public interface AldiServerListener {
/**
* 接收条码
* @param barcode
*/
void onReceiveBarcode(String barcode);
}
package com.wmdigit.socket.pool;
import com.elvishew.xlog.XLog;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 网络传输条码线程池
* @author dizi
*/
public class SocketTransferBarcodeThreadPool {
private static SocketTransferBarcodeThreadPool instance;
private final int CORE_POOL_SIZE = 2;
private final int MAX_POOL_SIZE = 3;
private final int WAIT_QUEUE_SIZE = 1;
private final int KEEP_ALIVE_TIME = 1;
public static SocketTransferBarcodeThreadPool getInstance(){
if (instance == null){
synchronized (SocketTransferBarcodeThreadPool.class){
if (instance == null){
instance = new SocketTransferBarcodeThreadPool();
}
}
}
return instance;
}
/**
* 线程池对象
*/
private ExecutorService executorService;
public SocketTransferBarcodeThreadPool() {
executorService = new ThreadPoolExecutor(
CORE_POOL_SIZE,
MAX_POOL_SIZE,
KEEP_ALIVE_TIME,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(WAIT_QUEUE_SIZE),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy()
);
}
public void execute(Runnable runnable){
executorService.execute(runnable);
}
public void shutdown(){
if (executorService != null){
XLog.d("准备关闭线程池");
try{
executorService.shutdownNow();
}catch (Exception e){
XLog.e(e.toString());
}
executorService = null;
instance = null;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="in_review_concat_manager">审核中,请联系后台管理人员</string>
<string name="response_empty">请求数据返回为空</string>
<string name="check_net">请检查网络</string>
<string name="please_check_input_tenant">请检查输入的租户</string>
<string name="no_register_info">未查询到注册信息</string>
<string name="no_store_and_device_info">未查询门店和设备信息</string>
<string name="error_store_and_device_info">门店和设备信息异常</string>
<string name="no_sn_code">未查询到激活密钥</string>
<string name="no_tenant_code">未查询到该租户</string>
<string name="please_check_network_connect">请检查网络连接</string>
<string name="query_register_info_failed">查询注册信息失败</string>
<string name="query_register_info_success">查询注册信息成功</string>
<string name="register_success">注册成功</string>
</resources>
\ No newline at end of file
......@@ -21,4 +21,5 @@ kotlin.code.style=official
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.enableJetifier=true
\ No newline at end of file
android.enableJetifier=true
android.defaults.buildfeatures.buildconfig=true
\ No newline at end of file
......@@ -2,7 +2,7 @@ v1.0.0 2024/07/18 1.演示Demo
v1.0.1 2024/08/01 1.增加camerax
2.增加3568视频流算法
v1.0.2 2024/08/06 1.增加系统信息页
2.todo 增加设置-注册页
3.todo 对接注册、找回接口
2.增加设置-注册页
3.对接注册、找回接口
4.todo 增加秤盘裁剪页
5.todo 增加AIDL服务
\ No newline at end of file
......@@ -9,7 +9,8 @@
android:theme="@style/Theme.CateringDetect">
<activity
android:name=".SettingActivity"
android:exported="true">
android:exported="true"
android:windowSoftInputMode="stateVisible|adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
......
package com.wmdigit.setting.fragment;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.wmdigit.common.base.mvvm.BaseMvvmFragment;
import com.wmdigit.setting.R;
import com.wmdigit.setting.databinding.FragmentCameraCropBinding;
import com.wmdigit.setting.viewmodel.CameraCropViewModel;
/**
* A simple {@link Fragment} subclass.
* Use the {@link CameraCropFragment#newInstance} factory method to
* create an instance of this fragment.
* 相机裁剪页
* @author dizi
*/
public class CameraCropFragment extends Fragment {
public class CameraCropFragment extends BaseMvvmFragment<CameraCropViewModel, FragmentCameraCropBinding> {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
@Override
protected int getLayoutId() {
return R.layout.fragment_camera_crop;
}
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
@Override
protected void initView() {
public CameraCropFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment CameraCropFragment.
*/
// TODO: Rename and change types and number of parameters
public static CameraCropFragment newInstance(String param1, String param2) {
CameraCropFragment fragment = new CameraCropFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
@Override
protected void initData() {
mDataBinding.setViewModel(mViewModel);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
protected void initListener() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_camera_crop, container, false);
protected Class<CameraCropViewModel> getViewModel() {
return CameraCropViewModel.class;
}
}
\ No newline at end of file
package com.wmdigit.setting.fragment;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import com.wmdigit.common.base.mvvm.BaseMvvmFragment;
import com.wmdigit.common.utils.EditTextUtils;
import com.wmdigit.setting.R;
import com.wmdigit.setting.databinding.FragmentRegisterBinding;
import com.wmdigit.setting.viewmodel.RegisterViewModel;
/**
* A simple {@link Fragment} subclass.
* Use the {@link RegisterFragment#newInstance} factory method to
* create an instance of this fragment.
* 注册页
* @author dizi
*/
public class RegisterFragment extends Fragment {
public class RegisterFragment extends BaseMvvmFragment<RegisterViewModel, FragmentRegisterBinding> {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
@Override
protected int getLayoutId() {
return R.layout.fragment_register;
}
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
@Override
protected void initObserve() {
super.initObserve();
// 观察网络通知
mViewModel.httpToast.observe(this, this::showToast);
// 观察注册信息查询结果
mViewModel.responseQueryRegisterInfo.observe(this, posRegisterInfo -> {
mViewModel.showQueryRegisterInfo(posRegisterInfo);
});
// 观察注册结果
mViewModel.responseRegister.observe(this, posMachine -> {
// 保存注册结果
mViewModel.saveRegisterInfo(posMachine);
});
}
@Override
protected void initView() {
public RegisterFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment RegisterFragment.
*/
// TODO: Rename and change types and number of parameters
public static RegisterFragment newInstance(String param1, String param2) {
RegisterFragment fragment = new RegisterFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
@Override
protected void initData() {
mDataBinding.setViewModel(mViewModel);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
protected void initListener() {
// SN输入框增加监听
EditTextUtils.addTextToUpperWatcher(mDataBinding.edtSnCode1, mDataBinding.edtSnCode2, 8);
EditTextUtils.addTextToUpperWatcher(mDataBinding.edtSnCode2, mDataBinding.edtSnCode3, 4);
EditTextUtils.addTextToUpperWatcher(mDataBinding.edtSnCode3, mDataBinding.edtSnCode4, 4);
EditTextUtils.addTextToUpperWatcher(mDataBinding.edtSnCode4, mDataBinding.edtSnCode5, 4);
EditTextUtils.addTextToUpperWatcher(mDataBinding.edtSnCode5, null, 12);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_register, container, false);
protected Class<RegisterViewModel> getViewModel() {
return RegisterViewModel.class;
}
}
\ No newline at end of file
package com.wmdigit.setting.viewmodel;
import android.app.Application;
import androidx.annotation.NonNull;
import com.wmdigit.common.base.mvvm.BaseViewModel;
/**
* 相机裁剪ViewModel
* @author dizi
*/
public class CameraCropViewModel extends BaseViewModel {
public CameraCropViewModel(@NonNull Application application) {
super(application);
}
}
package com.wmdigit.setting.viewmodel;
import android.app.Application;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.databinding.ObservableField;
import com.wmdigit.common.base.mvvm.BaseViewModel;
import com.wmdigit.common.base.mvvm.SingleLiveEvent;
import com.wmdigit.common.enums.SnType;
import com.wmdigit.data.mmkv.repository.UserLocalRepository;
import com.wmdigit.network.bean.request.RegisterParams;
import com.wmdigit.network.bean.response.PosMachine;
import com.wmdigit.network.bean.response.PosRegisterInfo;
import com.wmdigit.network.repository.UserRemoteRepository;
/**
* 注册页的ViewModel
* @author dizi
*/
public class RegisterViewModel extends BaseViewModel {
/**
* 网络请求通知
*/
public SingleLiveEvent<String> httpToast;
/**
* 查询注册信息返回值
*/
public SingleLiveEvent<PosRegisterInfo> responseQueryRegisterInfo;
/**
* 注册返回值
*/
public SingleLiveEvent<PosMachine> responseRegister;
/**
* 门店代码
*/
public ObservableField<String> storeCode = new ObservableField<>();
/**
* 设备编号
*/
public ObservableField<String> deviceCode = new ObservableField<>();
/**
* 激活密钥 part1~5
*/
public ObservableField<String> snCodePart1 = new ObservableField<>();
public ObservableField<String> snCodePart2 = new ObservableField<>();
public ObservableField<String> snCodePart3 = new ObservableField<>();
public ObservableField<String> snCodePart4 = new ObservableField<>();
public ObservableField<String> snCodePart5 = new ObservableField<>();
/**
* 租户号
*/
public ObservableField<String> tenantCode = new ObservableField<>();
public RegisterViewModel(@NonNull Application application) {
super(application);
getData();
}
/**
* 初始化数据
*/
private void getData() {
httpToast = UserRemoteRepository.getInstance().mHttpToast;
responseQueryRegisterInfo = UserRemoteRepository.getInstance().responseQueryRegisterInfo;
responseRegister = UserRemoteRepository.getInstance().responseRegister;
// 判断用户是否激活
String[] user;
if (UserLocalRepository.getInstance().getIsActivation()){
// 获取本地注册的用户信息
user = UserLocalRepository.getInstance().getUser();
}
else{
// 获取本地临时用户信息
user = UserLocalRepository.getInstance().getTempUser();
}
storeCode.set(user[0]);
deviceCode.set(user[1]);
// 拆分SN
String snCode = user[2];
if (!TextUtils.isEmpty(snCode)){
String[] snCodes = snCode.split("-");
if (snCodes.length == 5){
snCodePart1.set(snCodes[0]);
snCodePart2.set(snCodes[1]);
snCodePart3.set(snCodes[2]);
snCodePart4.set(snCodes[3]);
snCodePart5.set(snCodes[4]);
}
}
tenantCode.set(user[3]);
}
/**
* 忘记注册信息
*/
public void forgetRegisterInfo(){
// 查询注册信息
compositeDisposable.add(UserRemoteRepository.getInstance().queryRegisterInfo());
}
/**
* 展示查询的注册信息
*/
public void showQueryRegisterInfo(PosRegisterInfo info){
// 展示查询的注册信息
storeCode.set(info.getStoreCode());
deviceCode.set(info.getPosId());
tenantCode.set(info.getCode());
// 拆分SN
String snCode = info.getSnCode();
String[] snCodes = snCode.split("-");
if (snCodes.length == 5){
snCodePart1.set(snCodes[0]);
snCodePart2.set(snCodes[1]);
snCodePart3.set(snCodes[2]);
snCodePart4.set(snCodes[3]);
snCodePart5.set(snCodes[4]);
}
}
/**
* 注册
*/
public void register(){
if (!checkInputsValid()){
toastMessage.postValue(getApplication().getString(com.wmdigit.common.R.string.please_check_input));
return;
}
// 组装请求参数
RegisterParams params = new RegisterParams();
params.setCode(storeCode.get() + "_" + deviceCode.get());
params.setSnNo(snCodePart1.get() + "-" + snCodePart2.get() + "-" + snCodePart3.get() + "-" + snCodePart4.get() + "-" + snCodePart5.get());
params.setWeighSnCode(params.getSnNo());
params.setTenant(tenantCode.get());
params.setSnType(SnType.CATERING_SDK.name());
// 保存临时数据到本地
UserLocalRepository.getInstance().saveTempUser(storeCode.get(), deviceCode.get(), params.getSnNo(), tenantCode.get());
// 调用注册接口
compositeDisposable.add(UserRemoteRepository.getInstance().register(params));
}
/**
* 检查输入信息合法性
* @return
*/
public boolean checkInputsValid(){
if (TextUtils.isEmpty(storeCode.get())){
return false;
}
if (TextUtils.isEmpty(deviceCode.get())){
return false;
}
if (TextUtils.isEmpty(snCodePart1.get())){
return false;
}
if (TextUtils.isEmpty(snCodePart2.get())){
return false;
}
if (TextUtils.isEmpty(snCodePart3.get())){
return false;
}
if (TextUtils.isEmpty(snCodePart4.get())){
return false;
}
if (TextUtils.isEmpty(snCodePart5.get())){
return false;
}
if (TextUtils.isEmpty(tenantCode.get())){
return false;
}
return true;
}
/**
* 保存注册结果
* @param pos
*/
public void saveRegisterInfo(PosMachine pos){
UserLocalRepository.getInstance().saveUser(pos.getId(), pos.getCode(), pos.getWeighSnCode());
}
}
\ No newline at end of file
......@@ -7,12 +7,11 @@ import androidx.annotation.NonNull;
import androidx.databinding.ObservableField;
import com.elvishew.xlog.XLog;
import com.tencent.mmkv.MMKV;
import com.wmdigit.common.base.mvvm.BaseViewModel;
import com.wmdigit.common.base.mvvm.SingleLiveEvent;
import com.wmdigit.common.utils.DeviceUtils;
import com.wmdigit.data.mmkv.MmkvCons;
import com.wmdigit.setting.R;
import com.wmdigit.data.mmkv.constant.MmkvCons;
import com.wmdigit.data.mmkv.repository.CropLocalRepository;
import com.wmdigit.data.mmkv.repository.UserLocalRepository;
/**
* 系统信息页的ViewModel
......@@ -35,6 +34,10 @@ public class SystemInfoViewModel extends BaseViewModel {
* 设备编号
*/
public ObservableField<String> deviceCode = new ObservableField<>();
/**
* 门店编码
*/
public ObservableField<String> storeCode = new ObservableField<>();
/**
* IP地址
*/
......@@ -74,15 +77,17 @@ public class SystemInfoViewModel extends BaseViewModel {
// 获取IP
ipAddress.set(DeviceUtils.getLocalIpAddress());
// 获取激活状态
isActive.set(MMKV.defaultMMKV().getBoolean(MmkvCons.MMKV_KEY_ACTIVATION, false));
isActive.set(UserLocalRepository.getInstance().getIsActivation());
if (Boolean.TRUE.equals(isActive.get())){
// 已激活,继续获取注册信息
tenant.set(MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_TENANT, ""));
deviceCode.set(MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_DEVICE_CODE, ""));
snCode.set(MMKV.defaultMMKV().getString(MmkvCons.MMKV_KEY_SN_CODE, ""));
String[] array = UserLocalRepository.getInstance().getUser();
storeCode.set(array[0]);
deviceCode.set(array[1]);
snCode.set(array[2]);
tenant.set(array[3]);
}
// 获取裁剪状态
isCrop.set(MMKV.defaultMMKV().getInt(MmkvCons.MMKV_KEY_CROP_WIDTH, 0) > 0);
isCrop.set(CropLocalRepository.getInstance().getIsCrop());
}
/**
......
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragment.CameraCropFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.wmdigit.setting.viewmodel.CameraCropViewModel" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
tools:context=".fragment.CameraCropFragment">
</FrameLayout>
\ No newline at end of file
</FrameLayout>
</layout>
\ No newline at end of file
......@@ -116,24 +116,24 @@
app:layout_constraintBottom_toBottomOf="@+id/edt_tenant"
/>
<!--设备编号编辑框-->
<!--门店编号编辑框-->
<EditText
android:id="@+id/edt_device_id"
android:id="@+id/edt_store_id"
style="@style/edittext_base.w492"
android:text="@{viewModel.deviceCode}"
android:text="@{viewModel.storeCode}"
android:layout_marginTop="@dimen/dp_28"
app:layout_constraintStart_toStartOf="@+id/edt_android_id"
app:layout_constraintEnd_toEndOf="@+id/edt_android_id"
app:layout_constraintTop_toBottomOf="@+id/edt_android_id"
/>
<!--设备编号-->
<!--门店编号-->
<TextView
android:id="@+id/tv_device_id"
android:id="@+id/tv_store_id"
style="@style/text_base.content"
android:text="@string/module_setting_device_id"
app:layout_constraintTop_toTopOf="@+id/edt_device_id"
app:layout_constraintBottom_toBottomOf="@+id/edt_device_id"
android:text="@string/module_setting_store_code"
app:layout_constraintTop_toTopOf="@+id/edt_store_id"
app:layout_constraintBottom_toBottomOf="@+id/edt_store_id"
app:layout_constraintEnd_toEndOf="@+id/tv_android_id"
/>
......@@ -158,24 +158,43 @@
app:layout_constraintBottom_toBottomOf="@+id/edt_ip_address"
/>
<!--设备编号编辑框-->
<EditText
android:id="@+id/edt_device_id"
style="@style/edittext_base.w492"
android:text="@{viewModel.deviceCode}"
android:layout_marginTop="@dimen/dp_28"
app:layout_constraintStart_toStartOf="@+id/edt_android_id"
app:layout_constraintEnd_toEndOf="@+id/edt_android_id"
app:layout_constraintTop_toBottomOf="@+id/edt_store_id"
/>
<!--设备编号-->
<TextView
android:id="@+id/tv_device_id"
style="@style/text_base.content"
android:text="@string/module_setting_device_code"
app:layout_constraintTop_toTopOf="@+id/edt_device_id"
app:layout_constraintBottom_toBottomOf="@+id/edt_device_id"
app:layout_constraintEnd_toEndOf="@+id/tv_android_id"
/>
<!--SN激活密钥编辑框-->
<EditText
android:id="@+id/edt_sn_code"
style="@style/edittext_base.w492"
android:text="@{viewModel.snCode}"
android:textSize="@dimen/sp_22"
android:layout_marginTop="@dimen/dp_28"
android:layout_width="@dimen/dp_0"
app:layout_constraintStart_toStartOf="@+id/edt_device_id"
app:layout_constraintEnd_toStartOf="@+id/tv_ip_address"
app:layout_constraintTop_toBottomOf="@+id/edt_device_id"
/>
app:layout_constraintStart_toStartOf="@+id/edt_tenant"
app:layout_constraintTop_toBottomOf="@+id/edt_tenant" />
<!--SN密钥-->
<TextView
android:id="@+id/tv_sn"
style="@style/text_base.content"
android:text="@string/module_setting_sn_code"
app:layout_constraintEnd_toEndOf="@+id/tv_device_id"
app:layout_constraintEnd_toEndOf="@+id/tv_tenant"
app:layout_constraintTop_toTopOf="@+id/edt_sn_code"
app:layout_constraintBottom_toBottomOf="@+id/edt_sn_code"
/>
......@@ -206,7 +225,7 @@
<EditText
android:id="@+id/edt_active_status"
style="@style/edittext_base.w492"
android:textColor="@{viewModel.isActive? @color/green : @color/red }"
android:textColor="@{viewModel.isActive? @color/green_008e75 : @color/red }"
android:text="@{viewModel.isActive? @string/activated : @string/not_active}"
android:layout_marginStart="@dimen/dp_200"
app:layout_constraintTop_toTopOf="@+id/tv_active_status"
......
......@@ -9,12 +9,23 @@
<string name="module_setting_app_version">SDK版本:</string>
<string name="module_setting_android_id">设备标识:</string>
<string name="module_setting_tenant">租户号:</string>
<string name="module_setting_device_id">设备编号:</string>
<string name="module_setting_tenant2">租户号</string>
<string name="module_setting_device_code">设备编号:</string>
<string name="module_setting_device_code2">设备编号</string>
<string name="module_setting_store_code">门店编号:</string>
<string name="module_setting_store_code2">门店编号</string>
<string name="module_setting_ip_address">IP地址:</string>
<string name="module_setting_sn_code">激活密钥:</string>
<string name="module_setting_sn_code2">激活密钥</string>
<string name="module_setting_status_info">状态信息</string>
<string name="module_setting_status_activation">激活状态:</string>
<string name="module_setting_camera_status">相机标定:</string>
<string name="module_setting_please_input_store_code">输入门店编号</string>
<string name="module_setting_please_input_device_code">输入设备编号</string>
<string name="module_setting_please_input_sn_code">输入激活密钥</string>
<string name="module_setting_please_input_tenant">输入租户号</string>
<string name="module_setting_forget_register_info">忘记注册信息</string>
<string name="module_setting_forget_register">注册</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources>
\ No newline at end of file
package com.wmdigit.setting;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
......@@ -27,8 +27,8 @@ rootProject.name = "CateringDetect"
include ':app'
include ':common'
include ':data-local'
include ':data-remote'
include ':core'
include ':module-demo'
include ':camera'
include ':module-setting'
include ':data-remote'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment