Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
huangzhicong
/
SmartCanteen
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
9c6290b4
authored
May 13, 2020
by
pye52
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1、所有指令采取worker的方式重构
2、目前更新方案存在一定问题
parent
f2198266
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
327 additions
and
341 deletions
+327
-341
app/src/main/java/com/bgycc/smartcanteen/activity/MainActivity.java
+93
-22
app/src/main/java/com/bgycc/smartcanteen/command/CommandHandler.java
+0
-43
app/src/main/java/com/bgycc/smartcanteen/command/CommandHelper.java
+65
-0
app/src/main/java/com/bgycc/smartcanteen/command/CommandProgressCallback.java
+0
-11
app/src/main/java/com/bgycc/smartcanteen/command/CommandWorker.java
+71
-0
app/src/main/java/com/bgycc/smartcanteen/command/LogCommandWorker.java
+33
-57
app/src/main/java/com/bgycc/smartcanteen/command/UpdateCommandWorker.java
+22
-50
app/src/main/java/com/bgycc/smartcanteen/command/WifiConfigCommandWorker.java
+23
-50
app/src/main/java/com/bgycc/smartcanteen/monitor/DatabaseMonitor.java
+1
-1
app/src/main/java/com/bgycc/smartcanteen/monitor/LogFileMonitor.java
+1
-1
app/src/main/java/com/bgycc/smartcanteen/utils/MonitorUtils.java
+3
-4
app/src/main/java/com/bgycc/smartcanteen/viewModel/CommandViewModel.java
+15
-102
No files found.
app/src/main/java/com/bgycc/smartcanteen/activity/MainActivity.java
View file @
9c6290b4
package
com
.
bgycc
.
smartcanteen
.
activity
;
import
androidx.appcompat.app.AppCompatActivity
;
import
androidx.lifecycle.LiveData
;
import
androidx.lifecycle.Observer
;
import
androidx.lifecycle.ViewModelProvider
;
import
androidx.work.Data
;
import
androidx.work.ExistingWorkPolicy
;
import
androidx.work.OneTimeWorkRequest
;
import
androidx.work.WorkInfo
;
import
androidx.work.WorkManager
;
import
android.content.Context
;
import
android.content.pm.PackageInfo
;
...
...
@@ -24,10 +31,11 @@ import android.widget.TextView;
import
com.bgycc.smartcanteen.BuildConfig
;
import
com.bgycc.smartcanteen.Injection
;
import
com.bgycc.smartcanteen.R
;
import
com.bgycc.smartcanteen.command.CommandHelper
;
import
com.bgycc.smartcanteen.entity.Command
;
import
com.bgycc.smartcanteen.entity.PayData
;
import
com.bgycc.smartcanteen.executor.SCTaskExecutor
;
import
com.bgycc.smartcanteen.socket.SCWebSocketClient
;
import
com.bgycc.smartcanteen.state.CommandState
;
import
com.bgycc.smartcanteen.state.ConnectState
;
import
com.bgycc.smartcanteen.state.PayOfflineState
;
import
com.bgycc.smartcanteen.state.PayOnlineState
;
...
...
@@ -35,7 +43,7 @@ import com.bgycc.smartcanteen.state.QRCodeState;
import
com.bgycc.smartcanteen.utils.NetworkUtils
;
import
com.bgycc.smartcanteen.utils.SmartCanteenUtils
;
import
com.bgycc.smartcanteen.utils.TTSHelper
;
import
com.bgycc.smartcanteen.utils.
Worke
rUtils
;
import
com.bgycc.smartcanteen.utils.
Monito
rUtils
;
import
com.bgycc.smartcanteen.viewModel.CommandViewModel
;
import
com.bgycc.smartcanteen.viewModel.PayOfflineViewModel
;
import
com.bgycc.smartcanteen.viewModel.PayOnlineViewModel
;
...
...
@@ -77,6 +85,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
private
TextView
message
;
private
AudioManager
audioManager
;
private
WorkManager
workManager
;
private
Handler
handler
=
new
Handler
();
private
SimpleDateFormat
payDateFormat
=
new
SimpleDateFormat
(
"HH:mm:ss.SSS"
,
Locale
.
getDefault
());
private
SimpleDateFormat
socketConnectedTimeDateFormat
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
,
Locale
.
getDefault
());
...
...
@@ -110,6 +119,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
getWindow
().
addFlags
(
WindowManager
.
LayoutParams
.
FLAG_FULLSCREEN
);
getWindow
().
addFlags
(
WindowManager
.
LayoutParams
.
FLAG_KEEP_SCREEN_ON
);
workManager
=
WorkManager
.
getInstance
(
this
);
ViewModelFactory
factory
=
Injection
.
injectFactory
(
deviceSN
);
ViewModelProvider
provider
=
new
ViewModelProvider
(
this
,
factory
);
payOnlineViewModel
=
provider
.
get
(
PayOnlineViewModel
.
class
);
...
...
@@ -243,23 +253,84 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
}
});
commandViewModel
.
getCommandStateEvent
().
observe
(
this
,
event
->
{
switch
(
event
.
getState
())
{
case
CommandState
.
IDLE
:
settingLayout
.
animate
().
setDuration
(
300
).
alpha
(
0
f
);
break
;
case
CommandState
.
WAIT
:
settingText
.
setText
(
event
.
getMessage
());
settingLayout
.
animate
().
setDuration
(
300
).
alpha
(
1
f
);
break
;
case
CommandState
.
SUCCESS
:
case
CommandState
.
FAILED
:
settingText
.
setText
(
event
.
getMessage
());
settingLayout
.
animate
().
setDuration
(
300
).
alpha
(
1
f
);
break
;
case
CommandState
.
TOGGLE_DEBUG
:
commandViewModel
.
getCommandTask
().
observe
(
this
,
new
Observer
<
Command
>()
{
private
static
final
String
WORKER_NAME
=
"smartcanteen_command"
;
private
LiveData
<
WorkInfo
>
runningLiveData
;
private
Command
runningCommand
;
private
OneTimeWorkRequest
runningRequest
;
@Override
public
void
onChanged
(
Command
command
)
{
// 若为debug模式切换命令,则直接执行即可
if
(
CommandHelper
.
isLogConfig
(
command
))
{
toggleDebugLayout
();
break
;
commandViewModel
.
commandFinish
(
command
);
return
;
}
// 检查当前是否有在执行的任务
if
(
runningCommand
!=
null
)
{
// 若已经有在执行的任务,则跳过该次响应
return
;
}
reset
();
runningCommand
=
command
;
runningRequest
=
commandViewModel
.
getCommandWorker
(
command
);
workManager
.
beginUniqueWork
(
WORKER_NAME
,
ExistingWorkPolicy
.
REPLACE
,
runningRequest
)
.
enqueue
();
runningLiveData
=
workManager
.
getWorkInfoByIdLiveData
(
runningRequest
.
getId
());
runningLiveData
.
observe
(
MainActivity
.
this
,
workInfoObserver
);
}
private
Observer
<
WorkInfo
>
workInfoObserver
=
new
Observer
<
WorkInfo
>()
{
@Override
public
void
onChanged
(
WorkInfo
workInfo
)
{
if
(
workInfo
==
null
)
{
settingLayout
.
animate
().
setDuration
(
50
).
alpha
(
0
f
);
return
;
}
WorkInfo
.
State
state
=
workInfo
.
getState
();
if
(
state
.
isFinished
())
{
Data
data
=
workInfo
.
getOutputData
();
switch
(
state
)
{
case
SUCCEEDED:
case
FAILED:
String
message
=
CommandHelper
.
getMessage
(
data
);
settingText
.
setText
(
message
);
settingLayout
.
animate
().
setDuration
(
50
).
alpha
(
1
f
);
break
;
}
// 任务完成后,隐藏提示语
settingLayout
.
animate
()
.
setStartDelay
(
50
)
.
setDuration
(
1300
)
.
alpha
(
0
f
);
// 通知数据库更新命令的执行状态
if
(
runningCommand
!=
null
)
{
commandViewModel
.
commandFinish
(
runningCommand
);
}
// 重置所有变量,使下次命令能成功执行
reset
();
return
;
}
if
(
workInfo
.
getState
()
==
WorkInfo
.
State
.
RUNNING
)
{
Data
data
=
workInfo
.
getProgress
();
String
message
=
CommandHelper
.
getMessage
(
data
);
settingText
.
setText
(
message
);
settingLayout
.
animate
().
setDuration
(
300
).
alpha
(
1
f
);
return
;
}
}
};
private
void
reset
()
{
runningCommand
=
null
;
runningRequest
=
null
;
if
(
runningLiveData
!=
null
)
{
runningLiveData
.
removeObserver
(
workInfoObserver
);
runningLiveData
=
null
;
}
}
});
...
...
@@ -270,8 +341,8 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
commandViewModel
.
initialize
();
handler
.
post
(
updateTimeRunnable
);
Worke
rUtils
.
startLogFilesMonitor
(
this
);
Worke
rUtils
.
startDatabaseMonitor
(
this
);
Monito
rUtils
.
startLogFilesMonitor
(
this
);
Monito
rUtils
.
startDatabaseMonitor
(
this
);
SCWebSocketClient
.
getInstance
().
tryConnect
();
}
...
...
@@ -335,8 +406,8 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
TTSHelper
.
release
();
SCWebSocketClient
.
getInstance
().
realClose
();
SCTaskExecutor
.
getInstance
().
quit
();
Worke
rUtils
.
stopDatabaseMonitor
(
this
);
Worke
rUtils
.
stopLogFilesMonitor
(
this
);
Monito
rUtils
.
stopDatabaseMonitor
(
this
);
Monito
rUtils
.
stopLogFilesMonitor
(
this
);
}
private
void
initViews
()
{
...
...
app/src/main/java/com/bgycc/smartcanteen/command/CommandHandler.java
deleted
100644 → 0
View file @
f2198266
package
com
.
bgycc
.
smartcanteen
.
command
;
import
com.bgycc.smartcanteen.entity.Command
;
import
com.bgycc.smartcanteen.entity.CommandResponse
;
import
com.google.gson.Gson
;
public
abstract
class
CommandHandler
{
protected
Command
command
;
protected
Gson
gson
;
protected
CommandProgressCallback
commandProgressCallback
;
public
CommandHandler
(
Command
command
,
Gson
gson
,
CommandProgressCallback
commandProgressCallback
)
{
this
.
command
=
command
;
this
.
gson
=
gson
;
this
.
commandProgressCallback
=
commandProgressCallback
;
}
public
abstract
CommandResponse
run
()
throws
Exception
;
void
idle
(
String
message
,
int
progress
)
{
commandProgressCallback
.
idle
(
message
,
progress
);
}
void
wait
(
String
message
,
int
progress
)
{
commandProgressCallback
.
wait
(
message
,
progress
);
}
void
success
(
String
message
,
int
progress
)
{
commandProgressCallback
.
success
(
message
,
progress
);
}
void
failed
(
String
message
,
int
progress
)
{
commandProgressCallback
.
failed
(
message
,
progress
);
}
CommandResponse
failedResult
(
String
reason
)
{
return
CommandResponse
.
failed
(
reason
);
}
CommandResponse
successResult
(
String
reason
)
{
return
CommandResponse
.
success
(
reason
);
}
}
app/src/main/java/com/bgycc/smartcanteen/command/CommandHelper.java
0 → 100644
View file @
9c6290b4
package
com
.
bgycc
.
smartcanteen
.
command
;
import
androidx.work.Data
;
import
androidx.work.ListenableWorker
;
import
androidx.work.OneTimeWorkRequest
;
import
com.bgycc.smartcanteen.entity.Command
;
import
com.google.gson.Gson
;
import
java.util.HashSet
;
import
java.util.Set
;
public
class
CommandHelper
{
private
static
final
String
LOG_UPLOAD
=
"LOG_PULL"
;
private
static
final
String
APP_UPDATE
=
"CONFIG_UPDATE"
;
private
static
final
String
CONFIG_WIFI
=
"CONFIG_WIFI"
;
private
static
final
String
CONFIG_LOG
=
"CONFIG_LOG"
;
// 设备指令白名单
private
static
final
Set
<
String
>
COMMAND_WHITELIST
=
new
HashSet
<
String
>()
{
{
add
(
LOG_UPLOAD
);
add
(
APP_UPDATE
);
add
(
CONFIG_WIFI
);
add
(
CONFIG_LOG
);
}
};
public
static
String
getMessage
(
Data
data
)
{
return
CommandWorker
.
getMessage
(
data
);
}
public
static
boolean
isLogConfig
(
Command
command
)
{
return
command
.
getAction
().
equals
(
CONFIG_LOG
);
}
public
static
boolean
isCommand
(
String
action
)
{
return
COMMAND_WHITELIST
.
contains
(
action
);
}
public
static
OneTimeWorkRequest
createWorker
(
Gson
gson
,
Command
command
,
String
deviceSN
)
{
OneTimeWorkRequest
worker
=
null
;
Class
<?
extends
ListenableWorker
>
workerClass
=
null
;
switch
(
command
.
getAction
())
{
case
LOG_UPLOAD:
workerClass
=
LogCommandWorker
.
class
;
break
;
case
APP_UPDATE:
workerClass
=
UpdateCommandWorker
.
class
;
break
;
case
CONFIG_WIFI:
workerClass
=
WifiConfigCommandWorker
.
class
;
break
;
}
if
(
workerClass
!=
null
)
{
Data
inputData
=
CommandWorker
.
createBaseData
(
gson
.
toJson
(
command
),
deviceSN
);
worker
=
new
OneTimeWorkRequest
.
Builder
(
workerClass
)
.
setInputData
(
inputData
)
.
addTag
(
command
.
getAction
())
.
build
();
}
return
worker
;
}
}
app/src/main/java/com/bgycc/smartcanteen/command/CommandProgressCallback.java
deleted
100644 → 0
View file @
f2198266
package
com
.
bgycc
.
smartcanteen
.
command
;
public
interface
CommandProgressCallback
{
void
idle
(
String
message
,
int
progress
);
void
wait
(
String
message
,
int
progress
);
void
success
(
String
message
,
int
progress
);
void
failed
(
String
message
,
int
progress
);
}
app/src/main/java/com/bgycc/smartcanteen/command/CommandWorker.java
0 → 100644
View file @
9c6290b4
package
com
.
bgycc
.
smartcanteen
.
command
;
import
android.content.Context
;
import
androidx.annotation.NonNull
;
import
androidx.work.Data
;
import
androidx.work.Worker
;
import
androidx.work.WorkerParameters
;
import
com.bgycc.smartcanteen.Injection
;
import
com.bgycc.smartcanteen.entity.Command
;
import
com.google.gson.Gson
;
public
abstract
class
CommandWorker
extends
Worker
{
private
static
final
String
INPUT_DEVICESN
=
"input_devcesn"
;
private
static
final
String
INPUT_COMMAND
=
"input_command"
;
private
static
final
String
OUTPUT_MESSAGE
=
"output_message"
;
protected
Gson
gson
;
protected
Command
command
;
protected
String
deviceSN
;
public
static
Data
createBaseData
(
String
jsonCommand
,
String
deviceSN
)
{
return
new
Data
.
Builder
()
.
putString
(
INPUT_DEVICESN
,
deviceSN
)
.
putString
(
INPUT_COMMAND
,
jsonCommand
)
.
build
();
}
public
static
String
getMessage
(
Data
data
)
{
return
data
.
getString
(
OUTPUT_MESSAGE
);
}
public
CommandWorker
(
@NonNull
Context
context
,
@NonNull
WorkerParameters
workerParams
)
{
super
(
context
,
workerParams
);
gson
=
Injection
.
provideGson
();
deviceSN
=
getInputData
().
getString
(
INPUT_DEVICESN
);
command
=
gson
.
fromJson
(
getInputData
().
getString
(
INPUT_COMMAND
),
Command
.
class
);
}
protected
void
inProgress
(
String
message
)
{
Data
data
=
new
Data
.
Builder
()
.
putString
(
OUTPUT_MESSAGE
,
message
)
.
build
();
setProgressAsync
(
data
);
}
protected
Result
success
()
{
return
Result
.
success
();
}
protected
Result
success
(
String
message
)
{
Data
data
=
new
Data
.
Builder
()
.
putString
(
OUTPUT_MESSAGE
,
message
)
.
build
();
return
Result
.
success
(
data
);
}
protected
Result
failed
()
{
return
Result
.
failure
();
}
protected
Result
failed
(
String
message
)
{
Data
data
=
new
Data
.
Builder
()
.
putString
(
OUTPUT_MESSAGE
,
message
)
.
build
();
return
Result
.
failure
(
data
);
}
}
app/src/main/java/com/bgycc/smartcanteen/command/LogCommand
Handl
er.java
→
app/src/main/java/com/bgycc/smartcanteen/command/LogCommand
Work
er.java
View file @
9c6290b4
package
com
.
bgycc
.
smartcanteen
.
command
;
import
android.content.Context
;
import
androidx.annotation.NonNull
;
import
androidx.work.WorkerParameters
;
import
com.bgycc.smartcanteen.api.SCApi
;
import
com.bgycc.smartcanteen.api.SCRetrofit
;
import
com.bgycc.smartcanteen.entity.Command
;
import
com.bgycc.smartcanteen.entity.CommandLog
;
import
com.bgycc.smartcanteen.entity.CommandResponse
;
import
com.blankj.utilcode.util.FileUtils
;
import
com.blankj.utilcode.util.LogUtils
;
import
com.blankj.utilcode.util.PathUtils
;
import
com.blankj.utilcode.util.ZipUtils
;
import
com.google.gson.Gson
;
import
org.jetbrains.annotations.NotNull
;
...
...
@@ -33,49 +35,39 @@ import static com.bgycc.smartcanteen.utils.SmartCanteenUtils.TAG;
/**
* 设备指令: 上传日志
*/
public
class
LogCommand
Handler
extends
CommandHandl
er
{
public
class
LogCommand
Worker
extends
CommandWork
er
{
private
static
final
String
BOOT_LOG
=
"system"
;
private
static
final
String
ZIP_FILE
=
"log.zip"
;
private
static
final
String
UPLOAD_DIR
=
"upload_log"
;
private
static
final
long
DEFAULT_DELAY
=
1000
;
private
volatile
boolean
start
=
false
;
private
SimpleDateFormat
parseFormat
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
,
Locale
.
getDefault
());
private
SimpleDateFormat
nameFormat
=
new
SimpleDateFormat
(
"yyyy-MM-dd"
,
Locale
.
getDefault
());
private
String
deviceSN
;
private
CommandLog
commandLog
;
private
File
uploadDir
;
private
Date
startTime
;
private
Date
endTime
;
private
static
LogCommandHandler
instance
;
public
static
synchronized
LogCommandHandler
getInstance
(
Command
command
,
Gson
gson
,
String
deviceSN
,
CommandProgressCallback
callback
)
{
if
(
instance
==
null
)
{
instance
=
new
LogCommandHandler
(
command
,
gson
,
deviceSN
,
callback
);
}
else
{
if
(!
instance
.
start
)
{
instance
.
init
(
command
,
gson
,
deviceSN
,
callback
);
}
}
return
instance
;
}
private
void
init
(
Command
command
,
Gson
gson
,
String
deviceSN
,
CommandProgressCallback
callback
)
{
this
.
command
=
command
;
this
.
gson
=
gson
;
this
.
commandProgressCallback
=
callback
;
this
.
deviceSN
=
deviceSN
;
public
LogCommandWorker
(
@NonNull
Context
context
,
@NonNull
WorkerParameters
workerParams
)
{
super
(
context
,
workerParams
);
this
.
commandLog
=
gson
.
fromJson
(
command
.
getData
(),
CommandLog
.
class
);
parseDate
();
}
private
LogCommandHandler
(
Command
command
,
Gson
gson
,
String
deviceSN
,
CommandProgressCallback
callback
)
{
super
(
command
,
gson
,
callback
);
this
.
deviceSN
=
deviceSN
;
this
.
commandLog
=
gson
.
fromJson
(
command
.
getData
(),
CommandLog
.
class
);
@NonNull
@Override
public
Result
doWork
()
{
parseDate
();
if
(!
checkLogCommand
())
{
return
failed
(
"日志上传指令不符合规范"
);
}
File
logFile
=
getZipLogs
();
if
(
logFile
!=
null
)
{
inProgress
(
"上传压缩文件至服务器"
);
upload
(
logFile
);
return
success
();
}
return
failed
();
}
private
void
parseDate
()
{
...
...
@@ -101,14 +93,17 @@ public class LogCommandHandler extends CommandHandler {
}
// 获取指定类型及日期的日志文件
private
File
getZipLogs
()
throws
InterruptedException
{
private
File
getZipLogs
()
{
CommandLog
.
CommandLogData
data
=
commandLog
.
getData
();
File
logDir
=
getLogDirByType
(
data
.
getLogType
());
wait
(
"建立临时目录"
,
0
);
inProgress
(
"建立临时目录"
);
uploadDir
=
tempDirInit
();
Thread
.
sleep
(
DEFAULT_DELAY
);
try
{
Thread
.
sleep
(
DEFAULT_DELAY
);
}
catch
(
Exception
ignored
)
{
}
if
(
uploadDir
==
null
)
return
null
;
if
(!
copyTargetFiles
(
logDir
,
uploadDir
))
{
...
...
@@ -116,10 +111,13 @@ public class LogCommandHandler extends CommandHandler {
return
null
;
}
Thread
.
sleep
(
DEFAULT_DELAY
);
try
{
Thread
.
sleep
(
DEFAULT_DELAY
);
}
catch
(
Exception
ignored
)
{
}
File
zip
=
new
File
(
PathUtils
.
getExternalStoragePath
()
+
File
.
separator
+
ZIP_FILE
);
try
{
wait
(
"开始压缩"
,
40
);
inProgress
(
"开始压缩"
);
ZipUtils
.
zipFile
(
uploadDir
,
zip
);
}
catch
(
IOException
e
)
{
LogUtils
.
e
(
TAG
,
"压缩日志文件失败: "
+
e
.
getMessage
(),
e
);
...
...
@@ -164,7 +162,7 @@ public class LogCommandHandler extends CommandHandler {
};
List
<
File
>
logFiles
=
FileUtils
.
listFilesInDirWithFilter
(
src
,
filter
,
false
,
null
);
boolean
copyResult
=
true
;
wait
(
"筛选目标日志文件"
,
10
);
inProgress
(
"筛选目标日志文件"
);
int
count
=
0
;
File
descFile
;
boolean
tempCopyResult
;
...
...
@@ -200,26 +198,4 @@ public class LogCommandHandler extends CommandHandler {
FileUtils
.
delete
(
zip
);
}
}
@Override
public
synchronized
CommandResponse
run
()
throws
InterruptedException
{
if
(
start
)
{
LogUtils
.
w
(
TAG
,
"日志上传任务已启动"
);
return
null
;
}
start
=
true
;
if
(!
checkLogCommand
())
{
start
=
false
;
return
failedResult
(
"日志上传指令不符合规范"
);
}
File
logFile
=
getZipLogs
();
if
(
logFile
!=
null
)
{
wait
(
"上传压缩文件至服务器"
,
60
);
upload
(
logFile
);
start
=
false
;
return
successResult
(
""
);
}
start
=
false
;
return
failedResult
(
""
);
}
}
app/src/main/java/com/bgycc/smartcanteen/command/UpdateCommand
Handl
er.java
→
app/src/main/java/com/bgycc/smartcanteen/command/UpdateCommand
Work
er.java
View file @
9c6290b4
package
com
.
bgycc
.
smartcanteen
.
command
;
import
android.content.Context
;
import
androidx.annotation.NonNull
;
import
androidx.work.WorkerParameters
;
import
com.bgycc.smartcanteen.BuildConfig
;
import
com.bgycc.smartcanteen.entity.Command
;
import
com.bgycc.smartcanteen.entity.CommandResponse
;
import
com.bgycc.smartcanteen.entity.CommandUpdate
;
import
com.bgycc.smartcanteen.utils.DeviceProxy
;
import
com.blankj.utilcode.util.AppUtils
;
...
...
@@ -10,63 +13,38 @@ import com.blankj.utilcode.util.FileUtils;
import
com.blankj.utilcode.util.LogUtils
;
import
com.blankj.utilcode.util.PathUtils
;
import
com.blankj.utilcode.util.Utils
;
import
com.google.gson.Gson
;
import
com.liulishuo.filedownloader.BaseDownloadTask
;
import
com.liulishuo.filedownloader.FileDownloadListener
;
import
com.liulishuo.filedownloader.FileDownloadSampleListener
;
import
com.liulishuo.filedownloader.FileDownloader
;
import
java.io.File
;
import
static
com
.
bgycc
.
smartcanteen
.
utils
.
SmartCanteenUtils
.
TAG
;
/**
* 设备指令: 更新 <br/>
* 更新任务处理为单例,避免多个更新任务同时进行浪费资源
*/
public
class
UpdateCommand
Handler
extends
CommandHandl
er
{
public
class
UpdateCommand
Worker
extends
CommandWork
er
{
private
static
final
String
UPDATE_APK
=
"SmartCanteen-update.apk"
;
private
static
final
String
UPDATE_APK_PATH
=
PathUtils
.
getExternalStoragePath
()
+
File
.
separator
+
UPDATE_APK
;
private
static
final
long
DEFAULT_DELAY
=
5
*
1000
;
// 保证更新任务不会在同一时间内重复执行
private
volatile
boolean
start
=
false
;
private
CommandUpdate
commandUpdate
;
private
static
UpdateCommandHandler
instance
;
public
static
synchronized
UpdateCommandHandler
getInstance
(
Command
command
,
Gson
gson
,
CommandProgressCallback
callback
)
{
if
(
instance
==
null
)
{
instance
=
new
UpdateCommandHandler
(
command
,
gson
,
callback
);
}
else
{
if
(!
instance
.
start
)
{
instance
.
init
(
command
,
gson
,
callback
);
}
}
return
instance
;
}
private
UpdateCommandHandler
(
Command
command
,
Gson
gson
,
CommandProgressCallback
callback
)
{
super
(
command
,
gson
,
callback
);
this
.
commandUpdate
=
gson
.
fromJson
(
command
.
getData
(),
CommandUpdate
.
class
);
}
private
void
init
(
Command
command
,
Gson
gson
,
CommandProgressCallback
callback
)
{
this
.
command
=
command
;
this
.
gson
=
gson
;
this
.
commandProgressCallback
=
callback
;
this
.
commandUpdate
=
gson
.
fromJson
(
command
.
getData
(),
CommandUpdate
.
class
);
public
UpdateCommandWorker
(
@NonNull
Context
context
,
@NonNull
WorkerParameters
workerParams
)
{
super
(
context
,
workerParams
);
commandUpdate
=
gson
.
fromJson
(
command
.
getData
(),
CommandUpdate
.
class
);
}
@NonNull
@Override
public
synchronized
CommandResponse
run
()
{
if
(
start
)
{
LogUtils
.
w
(
TAG
,
"更新任务已启动"
);
return
null
;
}
start
=
true
;
public
Result
doWork
()
{
if
(
commandUpdate
.
getData
()
==
null
||
commandUpdate
.
getData
().
getUrl
()
==
null
)
{
LogUtils
.
d
(
TAG
,
"更新包地址异常: "
+
commandUpdate
.
toString
());
return
failed
Result
(
"更新包地址异常"
);
return
failed
(
"更新包地址异常"
);
}
String
url
=
commandUpdate
.
getData
().
getUrl
();
FileDownloader
.
setup
(
Utils
.
getApp
());
...
...
@@ -77,33 +55,31 @@ public class UpdateCommandHandler extends CommandHandler {
.
setSyncCallback
(
true
)
.
setForceReDownload
(
true
)
.
setListener
(
listener
)
.
setSyncCallback
(
true
)
.
start
();
return
success
Result
(
"开始下载"
);
return
success
(
"开始下载"
);
}
private
FileDownloadListener
listener
=
new
FileDownloadSampleListener
()
{
@Override
protected
void
started
(
BaseDownloadTask
task
)
{
LogUtils
.
d
(
TAG
,
"更新包开始下载: "
+
task
.
getUrl
());
UpdateCommandHandler
.
this
.
wait
(
"开始下载"
,
0
);
inProgress
(
"开始下载"
);
}
@Override
protected
void
progress
(
BaseDownloadTask
task
,
int
soFarBytes
,
int
totalBytes
)
{
int
per
=
(
int
)
(
soFarBytes
*
1
f
/
totalBytes
*
100
);
UpdateCommandHandler
.
this
.
wait
(
"下载进度: "
+
per
+
"%"
,
per
);
inProgress
(
"下载进度: "
+
per
+
"%"
);
}
@Override
protected
void
error
(
BaseDownloadTask
task
,
Throwable
e
)
{
LogUtils
.
e
(
TAG
,
"下载失败: "
+
e
.
getMessage
(),
e
);
failed
(
"下载失败"
,
0
);
inProgress
(
"更新包下载失败"
);
try
{
Thread
.
sleep
(
DEFAULT_DELAY
);
}
catch
(
Exception
ignored
)
{
}
finally
{
idle
(
""
,
0
);
start
=
false
;
}
}
...
...
@@ -114,8 +90,7 @@ public class UpdateCommandHandler extends CommandHandler {
LogUtils
.
d
(
TAG
,
"更新包下载成功,开始安装: "
+
(
info
==
null
?
"null"
:
info
.
getPackageName
()));
if
(
info
==
null
||
!
info
.
getPackageName
().
equals
(
BuildConfig
.
APPLICATION_ID
))
{
FileUtils
.
delete
(
updateApk
);
idle
(
""
,
0
);
start
=
false
;
inProgress
(
"安装包包名异常"
);
return
;
}
if
(
info
.
getVersionCode
()
==
BuildConfig
.
VERSION_CODE
)
{
...
...
@@ -124,20 +99,17 @@ public class UpdateCommandHandler extends CommandHandler {
}
else
if
(
info
.
getVersionCode
()
<
BuildConfig
.
VERSION_CODE
)
{
FileUtils
.
delete
(
updateApk
);
LogUtils
.
d
(
TAG
,
"不允许安装低版本"
);
failed
(
"不允许安装低版本"
,
0
);
inProgress
(
"不允许安装低版本"
);
}
else
{
if
(
DeviceProxy
.
updateApp
(
updateApk
))
{
success
(
"开始安装"
,
100
);
inProgress
(
"开始安装"
);
}
else
{
failed
(
"安装文件权限修改失败"
,
0
);
inProgress
(
"安装文件权限修改失败"
);
}
}
try
{
Thread
.
sleep
(
DEFAULT_DELAY
);
}
catch
(
Exception
ignored
)
{
}
finally
{
idle
(
""
,
0
);
start
=
false
;
}
}
};
...
...
app/src/main/java/com/bgycc/smartcanteen/command/WifiConfigCommand
Handl
er.java
→
app/src/main/java/com/bgycc/smartcanteen/command/WifiConfigCommand
Work
er.java
View file @
9c6290b4
package
com
.
bgycc
.
smartcanteen
.
command
;
import
android.content.Context
;
import
android.net.wifi.WifiInfo
;
import
com.bgycc.smartcanteen.entity.Command
;
import
com.bgycc.smartcanteen.entity.CommandResponse
;
import
androidx.annotation.NonNull
;
import
androidx.work.WorkerParameters
;
import
com.bgycc.smartcanteen.entity.CommandWifiConfig
;
import
com.bgycc.smartcanteen.utils.NetworkUtils
;
import
com.blankj.utilcode.util.LogUtils
;
import
com.google.gson.Gson
;
import
static
com
.
bgycc
.
smartcanteen
.
utils
.
SmartCanteenUtils
.
TAG
;
public
class
WifiConfigCommand
Handler
extends
CommandHandl
er
{
public
class
WifiConfigCommand
Worker
extends
CommandWork
er
{
private
static
final
long
DEFAULT_DELAY
=
3000
;
private
static
final
long
POLLING_DELAY
=
100
;
private
CommandWifiConfig
wifiConfig
;
private
volatile
boolean
start
=
false
;
private
static
WifiConfigCommandHandler
instance
;
public
static
synchronized
WifiConfigCommandHandler
getInstance
(
Command
command
,
Gson
gson
,
CommandProgressCallback
callback
)
{
if
(
instance
==
null
)
{
instance
=
new
WifiConfigCommandHandler
(
command
,
gson
,
callback
);
}
else
{
if
(!
instance
.
start
)
{
instance
.
init
(
command
,
gson
,
callback
);
}
}
return
instance
;
}
private
WifiConfigCommandHandler
(
Command
command
,
Gson
gson
,
CommandProgressCallback
callback
)
{
super
(
command
,
gson
,
callback
);
this
.
wifiConfig
=
gson
.
fromJson
(
command
.
getData
(),
CommandWifiConfig
.
class
);
}
private
void
init
(
Command
command
,
Gson
gson
,
CommandProgressCallback
callback
)
{
this
.
command
=
command
;
this
.
gson
=
gson
;
this
.
commandProgressCallback
=
callback
;
this
.
wifiConfig
=
gson
.
fromJson
(
command
.
getData
(),
CommandWifiConfig
.
class
);
public
WifiConfigCommandWorker
(
@NonNull
Context
context
,
@NonNull
WorkerParameters
workerParams
)
{
super
(
context
,
workerParams
);
wifiConfig
=
gson
.
fromJson
(
command
.
getData
(),
CommandWifiConfig
.
class
);
}
@NonNull
@Override
public
synchronized
CommandResponse
run
()
throws
InterruptedException
{
if
(
start
)
{
LogUtils
.
w
(
TAG
,
"Wifi配置任务已启动"
);
return
null
;
}
start
=
true
;
public
Result
doWork
()
{
CommandWifiConfig
.
CommandWifiConfigData
data
=
wifiConfig
.
getData
();
if
(
data
==
null
)
{
start
=
false
;
return
null
;
return
failed
();
}
if
(!
NetworkUtils
.
isWifiEnabled
())
{
wait
(
"正在启动Wifi"
,
5
);
inProgress
(
"正在启动Wifi"
);
if
(!
NetworkUtils
.
setEnable
(
true
))
{
String
failedMessage
=
"无法启动Wifi"
;
wait
(
failedMessage
,
5
);
inProgress
(
failedMessage
);
LogUtils
.
e
(
TAG
,
failedMessage
);
Thread
.
sleep
(
DEFAULT_DELAY
);
start
=
false
;
return
failedResult
(
failedMessage
);
try
{
Thread
.
sleep
(
DEFAULT_DELAY
);
}
catch
(
Exception
ignored
)
{
}
return
failed
(
failedMessage
);
}
}
...
...
@@ -73,7 +49,7 @@ public class WifiConfigCommandHandler extends CommandHandler {
String
pwd
=
data
.
getPwd
();
String
type
=
data
.
getType
();
wait
(
"正在配置Wifi"
,
10
);
inProgress
(
"正在配置Wifi"
);
LogUtils
.
d
(
TAG
,
"开始配置wifi, ssid: "
+
ssid
+
", identity: "
+
identity
+
", pwd: "
+
pwd
+
", type: "
+
type
);
try
{
NetworkUtils
.
connect
(
ssid
,
identity
,
pwd
,
type
);
...
...
@@ -85,18 +61,15 @@ public class WifiConfigCommandHandler extends CommandHandler {
continue
;
}
String
message
=
"Wifi配置成功"
;
wait
(
message
,
50
);
inProgress
(
message
);
LogUtils
.
d
(
TAG
,
message
);
Thread
.
sleep
(
DEFAULT_DELAY
);
return
success
Result
(
message
);
return
success
(
message
);
}
}
catch
(
Exception
e
)
{
LogUtils
.
e
(
TAG
,
"链接wifi过程出错: "
+
e
.
getMessage
(),
e
);
Thread
.
sleep
(
DEFAULT_DELAY
);
return
failedResult
(
e
.
getMessage
());
}
finally
{
start
=
false
;
return
failed
(
e
.
getMessage
());
}
return
failed
Result
(
"无法连接Wifi"
);
return
failed
(
"无法连接Wifi"
);
}
}
app/src/main/java/com/bgycc/smartcanteen/
worke
r/DatabaseMonitor.java
→
app/src/main/java/com/bgycc/smartcanteen/
monito
r/DatabaseMonitor.java
View file @
9c6290b4
package
com
.
bgycc
.
smartcanteen
.
worke
r
;
package
com
.
bgycc
.
smartcanteen
.
monito
r
;
import
android.content.Context
;
...
...
app/src/main/java/com/bgycc/smartcanteen/
worke
r/LogFileMonitor.java
→
app/src/main/java/com/bgycc/smartcanteen/
monito
r/LogFileMonitor.java
View file @
9c6290b4
package
com
.
bgycc
.
smartcanteen
.
worke
r
;
package
com
.
bgycc
.
smartcanteen
.
monito
r
;
import
android.content.Context
;
...
...
app/src/main/java/com/bgycc/smartcanteen/utils/
Worke
rUtils.java
→
app/src/main/java/com/bgycc/smartcanteen/utils/
Monito
rUtils.java
View file @
9c6290b4
...
...
@@ -2,16 +2,15 @@ package com.bgycc.smartcanteen.utils;
import
android.content.Context
;
import
androidx.work.ExistingWorkPolicy
;
import
androidx.work.PeriodicWorkRequest
;
import
androidx.work.WorkManager
;
import
com.bgycc.smartcanteen.
worke
r.DatabaseMonitor
;
import
com.bgycc.smartcanteen.
worke
r.LogFileMonitor
;
import
com.bgycc.smartcanteen.
monito
r.DatabaseMonitor
;
import
com.bgycc.smartcanteen.
monito
r.LogFileMonitor
;
import
java.util.concurrent.TimeUnit
;
public
class
Worke
rUtils
{
public
class
Monito
rUtils
{
private
static
final
String
LOG_MONITOR_WORKER
=
"worker_log_monitor"
;
private
static
final
String
DATABASE_MONITOR_WORKER
=
"database_log_monitor"
;
...
...
app/src/main/java/com/bgycc/smartcanteen/viewModel/CommandViewModel.java
View file @
9c6290b4
...
...
@@ -4,27 +4,20 @@ import androidx.lifecycle.LiveData;
import
androidx.lifecycle.MutableLiveData
;
import
androidx.lifecycle.Observer
;
import
androidx.lifecycle.ViewModel
;
import
androidx.work.OneTimeWorkRequest
;
import
com.bgycc.smartcanteen.command.CommandProgressCallback
;
import
com.bgycc.smartcanteen.command.CommandHandler
;
import
com.bgycc.smartcanteen.command.LogCommandHandler
;
import
com.bgycc.smartcanteen.command.UpdateCommandHandler
;
import
com.bgycc.smartcanteen.command.WifiConfigCommandHandler
;
import
com.bgycc.smartcanteen.command.CommandHelper
;
import
com.bgycc.smartcanteen.entity.Command
;
import
com.bgycc.smartcanteen.entity.CommandResponse
;
import
com.bgycc.smartcanteen.executor.SCTaskExecutor
;
import
com.bgycc.smartcanteen.socket.SCWebSocketClient
;
import
com.bgycc.smartcanteen.socket.SCWebSocketListener
;
import
com.bgycc.smartcanteen.socket.SCWebSocketListenerAdapter
;
import
com.bgycc.smartcanteen.state.CommandState
;
import
com.bgycc.smartcanteen.repository.CommandRepository
;
import
com.blankj.utilcode.util.LogUtils
;
import
com.google.gson.Gson
;
import
com.google.gson.JsonObject
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
static
com
.
bgycc
.
smartcanteen
.
utils
.
SmartCanteenUtils
.
TAG
;
...
...
@@ -33,31 +26,16 @@ import static com.bgycc.smartcanteen.utils.SmartCanteenUtils.TAG;
* 监听Command数据库的变动,按如下流程进行处理: <br/>
* 从数据库读取 -> 解析执行 -> 更新到数据库
*/
public
class
CommandViewModel
extends
ViewModel
implements
CommandProgressCallback
{
private
static
final
String
LOG_UPLOAD
=
"LOG_PULL"
;
private
static
final
String
APP_UPDATE
=
"CONFIG_UPDATE"
;
private
static
final
String
CONFIG_WIFI
=
"CONFIG_WIFI"
;
private
static
final
String
CONFIG_LOG
=
"CONFIG_LOG"
;
// 设备指令白名单
private
static
final
Set
<
String
>
COMMAND_WHITELIST
=
new
HashSet
<
String
>()
{
{
add
(
LOG_UPLOAD
);
add
(
APP_UPDATE
);
add
(
CONFIG_WIFI
);
add
(
CONFIG_LOG
);
}
};
public
class
CommandViewModel
extends
ViewModel
{
private
CommandRepository
commandRepository
;
private
Gson
gson
;
private
String
deviceSN
;
private
MutableLiveData
<
Command
State
>
commandState
=
new
MutableLiveData
<>();
private
MutableLiveData
<
Command
>
commandWorker
=
new
MutableLiveData
<>();
private
LiveData
<
List
<
Command
>>
dataLiveData
;
public
LiveData
<
Command
State
>
getCommandStateEvent
()
{
return
command
State
;
public
LiveData
<
Command
>
getCommandTask
()
{
return
command
Worker
;
}
public
CommandViewModel
(
CommandRepository
commandRepository
,
Gson
gson
,
String
deviceSN
)
{
...
...
@@ -67,7 +45,6 @@ public class CommandViewModel extends ViewModel implements CommandProgressCallba
// 监听数据库的变动,并执行未完成的指令
this
.
dataLiveData
=
commandRepository
.
queryUndoneCommand
();
this
.
dataLiveData
.
observeForever
(
dataObserver
);
this
.
commandState
.
postValue
(
new
CommandState
(
CommandState
.
IDLE
));
}
public
void
initialize
()
{
...
...
@@ -84,104 +61,40 @@ public class CommandViewModel extends ViewModel implements CommandProgressCallba
private
Observer
<
List
<
Command
>>
dataObserver
=
commands
->
{
if
(
commands
==
null
||
commands
.
isEmpty
())
{
commandState
.
postValue
(
new
CommandState
(
CommandState
.
IDLE
));
return
;
}
Command
first
=
commands
.
get
(
0
);
RequestRunnable
runnable
=
new
RequestRunnable
(
first
);
SCTaskExecutor
.
getInstance
().
executeOnDiskIO
(
runnable
);
commandWorker
.
postValue
(
first
);
};
@Override
public
void
idle
(
String
message
,
int
progress
)
{
commandState
.
postValue
(
new
CommandState
(
CommandState
.
IDLE
,
message
,
progress
));
}
@Override
public
void
wait
(
String
message
,
int
progress
)
{
commandState
.
postValue
(
new
CommandState
(
CommandState
.
WAIT
,
message
,
progress
));
public
OneTimeWorkRequest
getCommandWorker
(
Command
command
)
{
return
CommandHelper
.
createWorker
(
gson
,
command
,
deviceSN
);
}
@Override
public
void
success
(
String
message
,
int
progress
)
{
commandState
.
postValue
(
new
CommandState
(
CommandState
.
SUCCESS
,
message
,
progress
));
}
@Override
public
void
failed
(
String
message
,
int
progress
)
{
commandState
.
postValue
(
new
CommandState
(
CommandState
.
FAILED
,
message
,
progress
));
public
void
commandFinish
(
Command
command
)
{
UpdateDatabaseRunnable
runnable
=
new
UpdateDatabaseRunnable
(
command
);
SCTaskExecutor
.
getInstance
().
executeOnDiskIO
(
runnable
);
}
private
SCWebSocketListener
listener
=
new
SCWebSocketListenerAdapter
()
{
private
static
final
String
RESPONSE_PAY_RESULT
=
"PAY_RESULT"
;
@Override
public
void
onMessage
(
String
action
,
JsonObject
obj
,
String
original
)
{
if
(!
C
OMMAND_WHITELIST
.
contains
(
action
))
return
;
if
(!
C
ommandHelper
.
isCommand
(
action
))
return
;
LogUtils
.
d
(
TAG
,
"设备下发指令: "
+
original
);
ResponseRunnable
runnable
=
new
ResponseRunnable
(
original
,
action
);
SCTaskExecutor
.
getInstance
().
executeOnDiskIO
(
runnable
);
}
};
private
class
Request
Runnable
implements
Runnable
{
private
class
UpdateDatabase
Runnable
implements
Runnable
{
private
Command
command
;
Request
Runnable
(
Command
command
)
{
UpdateDatabase
Runnable
(
Command
command
)
{
this
.
command
=
command
;
}
@Override
public
void
run
()
{
CommandHandler
handler
=
null
;
LogUtils
.
d
(
TAG
,
"开始执行指令: "
+
command
.
toString
());
try
{
switch
(
command
.
getAction
())
{
case
LOG_UPLOAD:
handler
=
LogCommandHandler
.
getInstance
(
command
,
gson
,
deviceSN
,
CommandViewModel
.
this
);
break
;
case
APP_UPDATE:
handler
=
UpdateCommandHandler
.
getInstance
(
command
,
gson
,
CommandViewModel
.
this
);
break
;
case
CONFIG_WIFI:
handler
=
WifiConfigCommandHandler
.
getInstance
(
command
,
gson
,
CommandViewModel
.
this
);
break
;
case
CONFIG_LOG:
// CONFIG_LOG后直接return
commandState
.
postValue
(
new
CommandState
(
CommandState
.
TOGGLE_DEBUG
));
commandFinishAndUpdateDB
();
return
;
}
}
catch
(
Exception
e
)
{
commandState
.
postValue
(
new
CommandState
(
CommandState
.
FAILED
,
e
.
getMessage
()));
handler
=
null
;
}
if
(
handler
==
null
)
{
LogUtils
.
w
(
TAG
,
"无法识别指令: "
+
command
.
toString
());
commandFinishAndUpdateDB
();
return
;
}
try
{
commandState
.
postValue
(
new
CommandState
(
CommandState
.
WAIT
));
CommandResponse
response
=
handler
.
run
();
if
(
response
==
null
)
{
LogUtils
.
d
(
TAG
,
"指令无返回结果: "
+
command
.
toString
());
return
;
}
if
(
response
.
success
())
{
commandState
.
postValue
(
new
CommandState
(
CommandState
.
SUCCESS
,
response
.
getMessage
()));
}
else
{
commandState
.
postValue
(
new
CommandState
(
CommandState
.
FAILED
,
response
.
getMessage
()));
}
}
catch
(
Exception
e
)
{
commandState
.
postValue
(
new
CommandState
(
CommandState
.
FAILED
,
e
.
getMessage
()));
}
finally
{
commandFinishAndUpdateDB
();
}
}
// 将执行完毕的指令更新到数据库,此时会触发dataObserver的动作(会继续搜索下一条未执行完毕的指令)
private
void
commandFinishAndUpdateDB
()
{
command
.
finish
();
LogUtils
.
d
(
TAG
,
"指令执行完毕: "
+
command
.
toString
());
commandRepository
.
updateCommand
(
command
);
...
...
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