Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
A
Android_Catering_service
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
姜天宇
Android_Catering_service
Commits
255716f8
Commit
255716f8
authored
May 22, 2025
by
姜天宇
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(轮询JOB):增加日志轮询上传任务
parent
51c65b50
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
416 additions
and
4 deletions
+416
-4
build.gradle
app/build.gradle
+3
-2
Application.java
...src/main/java/com/wmdigit/cateringdetect/Application.java
+3
-0
UserRemoteRepository.java
...wmdigit/core/network/repository/UserRemoteRepository.java
+144
-0
IUserRemoteRepository.java
...t/core/network/repository/impl/IUserRemoteRepository.java
+6
-0
RxHelper.java
...rc/main/java/com/wmdigit/core/network/utils/RxHelper.java
+21
-0
.gitignore
feature-worker-schedule/.gitignore
+1
-0
build.gradle.kts
feature-worker-schedule/build.gradle.kts
+44
-0
consumer-rules.pro
feature-worker-schedule/consumer-rules.pro
+0
-0
proguard-rules.pro
feature-worker-schedule/proguard-rules.pro
+21
-0
ExampleInstrumentedTest.kt
...a/com/wmdigit/feature/schedule/ExampleInstrumentedTest.kt
+24
-0
AndroidManifest.xml
feature-worker-schedule/src/main/AndroidManifest.xml
+4
-0
WorkerScheduleModule.kt
...java/com/wmdigit/feature/schedule/WorkerScheduleModule.kt
+77
-0
BaseWorker.kt
...main/java/com/wmdigit/feature/schedule/base/BaseWorker.kt
+29
-0
UploadLogWorker.kt
...a/com/wmdigit/feature/schedule/workers/UploadLogWorker.kt
+20
-0
ExampleUnitTest.kt
...test/java/com/wmdigit/feature/schedule/ExampleUnitTest.kt
+17
-0
history.txt
history.txt
+1
-2
settings.gradle
settings.gradle
+1
-0
No files found.
app/build.gradle
View file @
255716f8
...
...
@@ -3,8 +3,8 @@ plugins {
id
'org.jetbrains.kotlin.android'
}
def
APP_VERSION_CODE
=
100020
4
def
APP_VERSION_NAME
=
"1.0.2.
4
"
def
APP_VERSION_CODE
=
100020
5
def
APP_VERSION_NAME
=
"1.0.2.
5
"
android
{
namespace
'com.wmdigit.cateringdetect'
...
...
@@ -106,6 +106,7 @@ dependencies {
implementation
project
(
path:
':core-network'
)
implementation
project
(
path:
':core-storage'
)
implementation
project
(
path:
':service-aidl'
)
implementation
project
(
path:
':feature-worker-schedule'
)
implementation
'com.alibaba:arouter-api:1.5.2'
annotationProcessor
'com.alibaba:arouter-compiler:1.5.2'
...
...
app/src/main/java/com/wmdigit/cateringdetect/Application.java
View file @
255716f8
...
...
@@ -5,6 +5,7 @@ import com.wmdigit.core.NetworkModule;
import
com.wmdigit.common.CommonModule
;
import
com.wmdigit.feature.ai.CoreModule
;
import
com.wmdigit.core.storage.LocalDataModule
;
import
com.wmdigit.feature.schedule.WorkerScheduleModule
;
import
com.wmdigit.service.ServiceModule
;
/**
...
...
@@ -48,5 +49,7 @@ public class Application extends android.app.Application {
NetworkModule
.
init
(
this
);
// 初始化服务模块
ServiceModule
.
init
(
this
);
// 初始化worker模块
WorkerScheduleModule
.
INSTANCE
.
init
(
this
);
}
}
core-network/src/main/java/com/wmdigit/core/network/repository/UserRemoteRepository.java
View file @
255716f8
package
com
.
wmdigit
.
core
.
network
.
repository
;
import
android.annotation.SuppressLint
;
import
android.content.pm.PackageInfo
;
import
android.content.pm.PackageManager
;
import
android.os.Environment
;
import
android.text.TextUtils
;
import
com.elvishew.xlog.XLog
;
import
com.wmdigit.common.utils.DateUtils
;
import
com.wmdigit.common.utils.ZipUtils
;
import
com.wmdigit.core.NetworkModule
;
import
com.wmdigit.common.base.mvvm.BaseMvvmNetworkRepository
;
import
com.wmdigit.common.base.mvvm.SingleLiveEvent
;
import
com.wmdigit.common.utils.DeviceUtils
;
import
com.wmdigit.core.network.bean.request.QueryCommandParam
;
import
com.wmdigit.core.network.bean.request.ReplyCommandList
;
import
com.wmdigit.core.network.bean.request.SaveCommandResult
;
import
com.wmdigit.core.network.bean.response.BasePosResponse
;
import
com.wmdigit.core.network.bean.response.SimplePosCommandDTO
;
import
com.wmdigit.core.network.oss.OSSManager
;
import
com.wmdigit.core.storage.mmkv.repository.UserLocalRepository
;
import
com.wmdigit.core.network.R
;
import
com.wmdigit.core.network.bean.request.UnbindSnParam
;
...
...
@@ -18,9 +30,19 @@ import com.wmdigit.core.network.bean.response.PosRegisterInfo;
import
com.wmdigit.core.network.exception.ServerException
;
import
com.wmdigit.core.network.utils.RxHelper
;
import
java.io.File
;
import
java.net.UnknownHostException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
io.reactivex.Observable
;
import
io.reactivex.ObservableSource
;
import
io.reactivex.Observer
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.disposables.Disposable
;
import
io.reactivex.functions.Consumer
;
import
io.reactivex.functions.Function
;
import
io.reactivex.schedulers.Schedulers
;
import
retrofit2.HttpException
;
/**
...
...
@@ -189,5 +211,127 @@ public class UserRemoteRepository extends BaseMvvmNetworkRepository implements I
});
}
/**
* 查询服务器指令,根据查询结果决定是否上传日志
* @return
*/
@Override
public
Disposable
queryServerCommandAndUploadLog
()
{
// 查询本地注册信息
String
[]
array
=
UserLocalRepository
.
getInstance
().
getUser
();
if
(
TextUtils
.
isEmpty
(
array
[
0
])
||
TextUtils
.
isEmpty
(
array
[
1
])){
return
null
;
}
String
posCode
=
array
[
0
]
+
"_"
+
array
[
1
];
QueryCommandParam
queryCommandParam
=
new
QueryCommandParam
();
// 设备CODE
queryCommandParam
.
setPosCode
(
posCode
);
// 模型版本号,暂时没用
queryCommandParam
.
setAiModelVersion
(
"20250519"
);
PackageInfo
info
=
null
;
try
{
String
packageName
=
NetworkModule
.
getAppContext
().
getPackageName
();
info
=
NetworkModule
.
getAppContext
().
getPackageManager
().
getPackageInfo
(
packageName
,
0
);
}
catch
(
PackageManager
.
NameNotFoundException
e
)
{
XLog
.
e
(
e
.
toString
());
}
// App版本号
if
(
info
!=
null
){
queryCommandParam
.
setPosVersion
(
info
.
versionName
);
}
else
{
queryCommandParam
.
setPosVersion
(
""
);
}
// 系统版本号
queryCommandParam
.
setOsVersion
(
android
.
os
.
Build
.
VERSION
.
RELEASE
);
return
ServiceFactory
.
getServiceFactory
().
getPosService
()
// 查询服务器指令
.
getCommandByPosCode
(
queryCommandParam
)
.
compose
(
RxHelper
.
syncHandlePosResult
())
.
flatMap
(
obj
->
{
List
<
SimplePosCommandDTO
>
simplePosCommandDTOs
=
(
List
<
SimplePosCommandDTO
>)
obj
;
return
Observable
.
create
(
emitter
->
{
if
(
simplePosCommandDTOs
!=
null
&&
simplePosCommandDTOs
.
size
()
>
0
){
// 遍历后台指令
for
(
SimplePosCommandDTO
dto
:
simplePosCommandDTOs
){
// 先回复命令
replyServerCommand
(
dto
.
getId
());
// 判断后台是否需要上传日志
if
(
dto
.
getType
()
==
SimplePosCommandDTO
.
TypeEnum
.
UPLOAD_LOG
){
uploadLog
(
dto
);
}
}
}
});
}).
subscribe
(
unUsed
->{
},
throwable
->
{
XLog
.
e
(
"轮询上传日志任务失败: %s"
,
throwable
);
});
}
/**
* 回复后台指令
* @param commandId
*/
@SuppressLint
(
"CheckResult"
)
private
void
replyServerCommand
(
Long
commandId
){
if
(
commandId
==
null
){
return
;
}
// 组装请求参数
ReplyCommandList
replyCommandList
=
new
ReplyCommandList
();
List
<
Long
>
list
=
new
ArrayList
<>();
list
.
add
(
commandId
);
replyCommandList
.
setCommandIds
(
list
);
// 回复后台
ServiceFactory
.
getServiceFactory
().
getPosService
()
.
replyCommand
(
replyCommandList
)
.
compose
(
RxHelper
.
syncHandlePosResult
())
.
subscribe
(
unused
->
{
},
throwable
->
{
XLog
.
e
(
throwable
);
});
}
/**
* 上传日志
* @param dto
*/
private
void
uploadLog
(
SimplePosCommandDTO
dto
){
String
date
=
DateUtils
.
getTodayDate
();
if
(!
TextUtils
.
isEmpty
(
dto
.
getParameters
()))
{
date
=
dto
.
getParameters
();
}
// 日志文件
String
path
=
NetworkModule
.
getAppContext
().
getExternalFilesDir
(
"Log"
).
getPath
()
+
File
.
separator
+
date
;
File
logFile
=
new
File
(
path
);
if
(!
logFile
.
exists
()){
return
;
}
// 压缩文件
String
zipPath
=
path
+
".zip"
;
ZipUtils
.
zipFile
(
path
,
zipPath
);
File
zipFile
=
new
File
(
zipPath
);
Disposable
disposable
=
Observable
.
create
(
emitter
->
{
// 上传压缩文件
String
url
=
OSSManager
.
getInstance
().
syncUploadFileToOSS
(
zipFile
);
// 组装请求参数
SaveCommandResult
saveCommandResult
=
new
SaveCommandResult
();
saveCommandResult
.
setCommandId
(
dto
.
getId
());
saveCommandResult
.
setSuccess
(
true
);
saveCommandResult
.
setResult
(
url
);
emitter
.
onNext
(
saveCommandResult
);
}).
flatMap
(
obj
->{
// 保存命令执行结果
SaveCommandResult
saveCommandResult
=
(
SaveCommandResult
)
obj
;
return
ServiceFactory
.
getServiceFactory
().
getPosService
().
saveCommandResult
(
saveCommandResult
);
}).
subscribe
(
response
->
{
XLog
.
i
(
"上传日志code:%s, message:%s"
,
response
.
getCode
(),
response
.
getMessage
());
},
throwable
->
{
XLog
.
e
(
throwable
);
});
}
}
core-network/src/main/java/com/wmdigit/core/network/repository/impl/IUserRemoteRepository.java
View file @
255716f8
...
...
@@ -28,4 +28,10 @@ public interface IUserRemoteRepository {
* @return
*/
Disposable
unbindPos
();
/**
* 查询服务器指令,根据查询结果决定是否上传日志
* @return
*/
Disposable
queryServerCommandAndUploadLog
();
}
core-network/src/main/java/com/wmdigit/core/network/utils/RxHelper.java
View file @
255716f8
...
...
@@ -41,6 +41,27 @@ public class RxHelper {
};
}
/**
* 同步去壳,不切换线程
* @return
* @param <T>
*/
public
static
<
T
>
ObservableTransformer
<
BasePosResponse
<
T
>,
T
>
syncHandlePosResult
(){
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
));
}
});
return
(
ObservableSource
<
T
>)
observable
;
};
}
/**
* 创建指定数据源的Observable
* 后端传来的数据,如果为空,则则直接走 onComplete(); 否则,走onNext(),即传数据
...
...
feature-worker-schedule/.gitignore
0 → 100644
View file @
255716f8
/build
\ No newline at end of file
feature-worker-schedule/build.gradle.kts
0 → 100644
View file @
255716f8
plugins
{
id
(
"com.android.library"
)
id
(
"org.jetbrains.kotlin.android"
)
}
android
{
namespace
=
"com.wmdigit.feature.schedule"
compileSdk
=
33
defaultConfig
{
minSdk
=
24
testInstrumentationRunner
=
"androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles
(
"consumer-rules.pro"
)
}
buildTypes
{
release
{
isMinifyEnabled
=
false
proguardFiles
(
getDefaultProguardFile
(
"proguard-android-optimize.txt"
),
"proguard-rules.pro"
)
}
}
compileOptions
{
sourceCompatibility
=
JavaVersion
.
VERSION_1_8
targetCompatibility
=
JavaVersion
.
VERSION_1_8
}
kotlinOptions
{
jvmTarget
=
"1.8"
}
}
dependencies
{
implementation
(
project
(
":core-common"
))
implementation
(
project
(
":core-network"
))
androidTestImplementation
(
"androidx.test.ext:junit:1.2.1"
)
androidTestImplementation
(
"androidx.test.espresso:espresso-core:3.6.1"
)
implementation
(
"androidx.work:work-runtime:2.8.1"
)
}
\ No newline at end of file
feature-worker-schedule/consumer-rules.pro
0 → 100644
View file @
255716f8
feature-worker-schedule/proguard-rules.pro
0 → 100644
View file @
255716f8
# 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
\ No newline at end of file
feature-worker-schedule/src/androidTest/java/com/wmdigit/feature/schedule/ExampleInstrumentedTest.kt
0 → 100644
View file @
255716f8
package
com.wmdigit.feature.schedule
import
androidx.test.platform.app.InstrumentationRegistry
import
androidx.test.ext.junit.runners.AndroidJUnit4
import
org.junit.Test
import
org.junit.runner.RunWith
import
org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith
(
AndroidJUnit4
::
class
)
class
ExampleInstrumentedTest
{
@Test
fun
useAppContext
()
{
// Context of the app under test.
val
appContext
=
InstrumentationRegistry
.
getInstrumentation
().
targetContext
assertEquals
(
"com.wmdigit.feature.workerschedule.test"
,
appContext
.
packageName
)
}
}
\ No newline at end of file
feature-worker-schedule/src/main/AndroidManifest.xml
0 → 100644
View file @
255716f8
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
</manifest>
\ No newline at end of file
feature-worker-schedule/src/main/java/com/wmdigit/feature/schedule/WorkerScheduleModule.kt
0 → 100644
View file @
255716f8
package
com.wmdigit.feature.schedule
import
android.content.Context
import
androidx.work.BackoffPolicy
import
androidx.work.Constraints
import
androidx.work.ExistingPeriodicWorkPolicy
import
androidx.work.ListenableWorker
import
androidx.work.NetworkType
import
androidx.work.PeriodicWorkRequest
import
androidx.work.WorkManager
import
com.wmdigit.feature.schedule.workers.UploadLogWorker
import
java.util.concurrent.TimeUnit
/**
* WorkerScheduleModule 是一个用于调度后台任务的模块,主要用于初始化和调度日志上传等后台工作.
*/
object
WorkerScheduleModule
{
// 应用上下文,用于全局初始化和访问
private
var
appContext
:
Context
?
=
null
/**
* 初始化WorkerScheduleModule.
*
* @param context 应用上下文,用于全局初始化
*/
fun
init
(
context
:
Context
){
// 首次初始化时,设置appContext并构建日志上传的后台任务
if
(
appContext
==
null
)
{
appContext
=
context
buildSimpleWorkerSchedule
(
UploadLogWorker
::
class
.
java
,
15
,
10
)
}
}
/**
* 获取全局应用上下文.
*
* @return 应用上下文,如果未初始化则抛出异常
*/
fun
getContext
():
Context
{
// 如果appContext为空,表示模块未初始化,抛出异常
return
appContext
?:
throw
IllegalStateException
(
"WorkerScheduleModule has not been initialized"
)
}
/**
* 构建并调度一个周期性后台任务.
*
* @param workerClass 后台任务的类,必须是ListenableWorker的子类
* @param repeatIntervalMinutes 任务重复执行的间隔时间(分钟)
* @param initialDelaySeconds 任务首次执行的延迟时间(秒)
*/
private
fun
buildSimpleWorkerSchedule
(
workerClass
:
Class
<
out
ListenableWorker
>,
repeatIntervalMinutes
:
Long
,
initialDelaySeconds
:
Long
){
// 构建任务约束条件,包括网络状态、电池状态、存储状态和充电状态
val
constraints
:
Constraints
=
Constraints
.
Builder
()
.
setRequiredNetworkType
(
NetworkType
.
CONNECTED
)
.
setRequiresBatteryNotLow
(
false
)
.
setRequiresStorageNotLow
(
false
)
.
setRequiresCharging
(
true
)
.
build
()
// 使用worker类的简单名称作为标签
val
workerTag
:
String
=
workerClass
.
simpleName
// 构建周期性任务请求,包括任务执行的间隔时间、约束条件、初始延迟等
val
request
:
PeriodicWorkRequest
=
PeriodicWorkRequest
.
Builder
(
workerClass
,
repeatIntervalMinutes
,
TimeUnit
.
MINUTES
)
.
setConstraints
(
constraints
)
.
setInitialDelay
(
initialDelaySeconds
,
TimeUnit
.
SECONDS
)
// 退避策略(已注释)
// .setBackoffCriteria(BackoffPolicy.LINEAR, 5, TimeUnit.MINUTES)
.
addTag
(
workerTag
)
.
build
()
// 如果appContext不为空,获取WorkManager实例并调度任务
appContext
?.
let
{
WorkManager
.
getInstance
(
it
).
enqueueUniquePeriodicWork
(
workerTag
,
ExistingPeriodicWorkPolicy
.
UPDATE
,
request
)
}
}
}
feature-worker-schedule/src/main/java/com/wmdigit/feature/schedule/base/BaseWorker.kt
0 → 100644
View file @
255716f8
package
com.wmdigit.feature.schedule.base
import
android.content.Context
import
androidx.work.Worker
import
androidx.work.WorkerParameters
import
com.elvishew.xlog.XLog
/**
* Worker基类
*/
abstract
class
BaseWorker
(
context
:
Context
,
workerParams
:
WorkerParameters
)
:
Worker
(
context
,
workerParams
){
override
fun
doWork
():
Result
{
val
startTime
=
System
.
currentTimeMillis
()
val
jobName
=
this
::
class
.
simpleName
?:
"unknown"
XLog
.
i
(
"%s JOB准备执行"
,
jobName
)
synchronized
(
this
::
class
){
try
{
return
doJob
()
}
finally
{
val
endTime
=
System
.
currentTimeMillis
()
XLog
.
i
(
"%s JOB执行耗时:%sms"
,
jobName
,
endTime
-
startTime
)
}
}
}
protected
abstract
fun
doJob
():
Result
;
}
\ No newline at end of file
feature-worker-schedule/src/main/java/com/wmdigit/feature/schedule/workers/UploadLogWorker.kt
0 → 100644
View file @
255716f8
package
com.wmdigit.feature.schedule.workers
import
android.content.Context
import
androidx.work.WorkerParameters
import
com.wmdigit.core.network.repository.UserRemoteRepository
import
com.wmdigit.feature.schedule.base.BaseWorker
import
io.reactivex.Observer
/**
* 上传日志worker
* 15分钟一次
*/
class
UploadLogWorker
(
context
:
Context
,
workerParams
:
WorkerParameters
)
:
BaseWorker
(
context
,
workerParams
)
{
override
fun
doJob
():
Result
{
UserRemoteRepository
.
getInstance
().
queryServerCommandAndUploadLog
()
return
Result
.
success
()
}
}
\ No newline at end of file
feature-worker-schedule/src/test/java/com/wmdigit/feature/schedule/ExampleUnitTest.kt
0 → 100644
View file @
255716f8
package
com.wmdigit.feature.schedule
import
org.junit.Test
import
org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class
ExampleUnitTest
{
@Test
fun
addition_isCorrect
()
{
assertEquals
(
4
,
2
+
2
)
}
}
\ No newline at end of file
history.txt
View file @
255716f8
...
...
@@ -29,7 +29,6 @@ v1.0.2.3 2025/05/08 1.增加GPU推理
3.学习页增加重置背景功能
4.修复部分设备USB相机格式不兼容的问题
v1.0.2.4 2025/05/13 1.增加arm64支持
v1.0.2.5 2025/05/22 1.增加日志轮询上传任务
todo 增加轮询JOB
todo 限制学习列表图片展示数量
settings.gradle
View file @
255716f8
...
...
@@ -36,3 +36,4 @@ include ':service-aidl'
include
':library-opencv'
include
':aidl-sdk'
include
':ui-upgrade'
include
':feature-worker-schedule'
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment