Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
machine
Overview
Overview
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
hooloo
android
machine
Commits
14c8c12e
Commit
14c8c12e
authored
Oct 22, 2022
by
wjg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
v2
parent
00b09a2b
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
178 additions
and
71 deletions
+178
-71
app/build.gradle
+2
-2
app/src/main/java/com/ihaoin/hooloo/device/data/vo/CheckUpdateVo.java
+24
-15
app/src/main/java/com/ihaoin/hooloo/device/data/vo/UpdateDataVo.java
+33
-0
app/src/main/java/com/ihaoin/hooloo/device/home/view/LauncherActivity.java
+2
-2
app/src/main/java/com/ihaoin/hooloo/device/interaction/view/FrameView.java
+2
-2
app/src/main/java/com/ihaoin/hooloo/device/network/HttpUtil.java
+6
-3
app/src/main/java/com/ihaoin/hooloo/device/update/UpdateService.java
+56
-39
app/src/main/java/com/ihaoin/hooloo/device/update/UpdateSocket.java
+37
-6
app/src/main/java/com/ihaoin/hooloo/device/util/Utils.java
+14
-0
app/src/main/res/values-w800dp/dimens.xml
+1
-1
app/src/main/res/values/dimens.xml
+1
-1
No files found.
app/build.gradle
View file @
14c8c12e
...
...
@@ -10,8 +10,8 @@ android {
applicationId
"com.ihaoin.hooloo.device"
minSdkVersion
26
targetSdkVersion
30
versionCode
10
versionName
"1.0.
10
"
versionCode
5
versionName
"1.0.
5
"
ndk
{
//选择要添加的对应 cpu 类型的 .so 库。
...
...
app/src/main/java/com/ihaoin/hooloo/device/data/vo/CheckUpdateVo.java
View file @
14c8c12e
...
...
@@ -3,31 +3,40 @@ package com.ihaoin.hooloo.device.data.vo;
import
java.io.Serializable
;
public
class
CheckUpdateVo
implements
Serializable
{
private
String
url
;
private
Integer
versionCode
;
private
String
version
;
private
String
requestId
;
private
Integer
code
;
private
String
message
;
private
UpdateDataVo
data
;
public
String
get
Url
()
{
return
url
;
public
String
get
RequestId
()
{
return
requestId
;
}
public
void
set
Url
(
String
url
)
{
this
.
url
=
url
;
public
void
set
RequestId
(
String
requestId
)
{
this
.
requestId
=
requestId
;
}
public
Integer
get
Version
Code
()
{
return
versionC
ode
;
public
Integer
getCode
()
{
return
c
ode
;
}
public
void
set
VersionCode
(
Integer
versionC
ode
)
{
this
.
versionCode
=
versionC
ode
;
public
void
set
Code
(
Integer
c
ode
)
{
this
.
code
=
c
ode
;
}
public
String
get
Version
()
{
return
version
;
public
String
get
Message
()
{
return
message
;
}
public
void
setVersion
(
String
version
)
{
this
.
version
=
version
;
public
void
setMessage
(
String
message
)
{
this
.
message
=
message
;
}
public
UpdateDataVo
getData
()
{
return
data
;
}
public
void
setData
(
UpdateDataVo
data
)
{
this
.
data
=
data
;
}
}
app/src/main/java/com/ihaoin/hooloo/device/data/vo/UpdateDataVo.java
0 → 100644
View file @
14c8c12e
package
com
.
ihaoin
.
hooloo
.
device
.
data
.
vo
;
import
java.io.Serializable
;
public
class
UpdateDataVo
implements
Serializable
{
private
String
url
;
private
Integer
versionCode
;
private
String
version
;
public
String
getUrl
()
{
return
url
;
}
public
void
setUrl
(
String
url
)
{
this
.
url
=
url
;
}
public
Integer
getVersionCode
()
{
return
versionCode
;
}
public
void
setVersionCode
(
Integer
versionCode
)
{
this
.
versionCode
=
versionCode
;
}
public
String
getVersion
()
{
return
version
;
}
public
void
setVersion
(
String
version
)
{
this
.
version
=
version
;
}
}
app/src/main/java/com/ihaoin/hooloo/device/home/view/LauncherActivity.java
View file @
14c8c12e
...
...
@@ -127,8 +127,8 @@ public class LauncherActivity extends Activity {
startMachineClient
();
startTimeoutThread
();
getMachineCode
();
//
startUpdateSocket();
// new UpdateService().start();
startUpdateSocket
();
// new UpdateService(
this
).start();
View
.
OnClickListener
l
=
v
->
{
InteractionMsg
msg
=
new
InteractionMsg
();
...
...
app/src/main/java/com/ihaoin/hooloo/device/interaction/view/FrameView.java
View file @
14c8c12e
...
...
@@ -135,13 +135,13 @@ public class FrameView extends SurfaceView implements SurfaceHolder.Callback {
if
(
mod
==
frameCount
-
1
)
{
// 每次播放的最后一帧
repeatCount
++;
Utils
.
i
(
"play last, onAnimationRepeat "
+
(
animatorListener
!=
null
));
//
Utils.i("play last, onAnimationRepeat " + (animatorListener != null));
if
(
animatorListener
!=
null
)
{
animatorListener
.
onAnimationRepeat
(
null
);
}
}
}
Utils
.
i
(
"play end, onAnimationEnd "
+
(
animatorListener
!=
null
));
//
Utils.i("play end, onAnimationEnd " + (animatorListener != null));
if
(
animatorListener
!=
null
)
{
animatorListener
.
onAnimationEnd
(
null
);
}
...
...
app/src/main/java/com/ihaoin/hooloo/device/network/HttpUtil.java
View file @
14c8c12e
...
...
@@ -6,9 +6,9 @@ import android.os.Handler;
import
android.os.Message
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.ihaoin.hooloo.device.base.BizException
;
import
com.ihaoin.hooloo.device.HLApplication
;
import
com.ihaoin.hooloo.device.base.AppConfig
;
import
com.ihaoin.hooloo.device.base.BizException
;
import
com.ihaoin.hooloo.device.data.po.CheckUpdate
;
import
com.ihaoin.hooloo.device.util.JsonUtils
;
import
com.ihaoin.hooloo.device.util.SharedPreferencesUtils
;
...
...
@@ -17,6 +17,7 @@ import com.ihaoin.hooloo.device.util.Utils;
import
java.io.File
;
import
java.io.IOException
;
import
java.util.HashMap
;
import
java.util.concurrent.TimeUnit
;
import
okhttp3.Call
;
...
...
@@ -202,9 +203,11 @@ public class HttpUtil {
checkUpdate
.
setVersionCode
(
packageInfo
.
versionCode
);
checkUpdate
.
setVersionName
(
packageInfo
.
versionName
);
checkUpdate
.
setType
(
String
.
valueOf
(
SharedPreferencesUtils
.
getScreenNo
(
HLApplication
.
SELF
)));
String
content
=
JsonUtils
.
toString
(
checkUpdate
).
replaceAll
(
"\""
,
"'"
);
String
params
=
String
.
format
(
"{\"params\": \"%s\"}"
,
content
);
String
content
=
JsonUtils
.
toString
(
checkUpdate
);
HashMap
<
String
,
String
>
map
=
new
HashMap
<>();
map
.
put
(
"params"
,
content
);
String
params
=
JsonUtils
.
toString
(
map
);
post
(
HttpParams
.
POST_CHECK_UPDATE
,
params
,
handler
);
}
...
...
app/src/main/java/com/ihaoin/hooloo/device/update/UpdateService.java
View file @
14c8c12e
package
com
.
ihaoin
.
hooloo
.
device
.
update
;
import
android.annotation.SuppressLint
;
import
android.
content.Context
;
import
android.
app.Activity
;
import
android.content.pm.PackageInfo
;
import
android.os.Environment
;
import
android.os.Handler
;
import
android.os.Message
;
import
android.widget.Toast
;
import
androidx.annotation.NonNull
;
import
com.ihaoin.hooloo.device.HLApplication
;
import
com.ihaoin.hooloo.device.base.AppConfig
;
import
com.ihaoin.hooloo.device.data.vo.
CheckUpdate
Vo
;
import
com.ihaoin.hooloo.device.data.vo.
UpdateData
Vo
;
import
com.ihaoin.hooloo.device.network.HttpUtil
;
import
com.ihaoin.hooloo.device.network.NetworkHandler
;
import
com.ihaoin.hooloo.device.util.ApkUtils
;
...
...
@@ -23,34 +24,15 @@ import java.io.File;
@SuppressLint
(
"HandlerLeak"
)
public
class
UpdateService
extends
Thread
{
private
Context
mContext
;
private
Activity
mContext
;
public
UpdateService
(
Context
context
)
{
public
UpdateService
(
Activity
context
)
{
this
.
mContext
=
context
;
}
// @Nullable
// @Override
// public IBinder onBind(Intent intent) {
// checkUpdate();
// return null;
// }
@Override
public
void
run
()
{
HttpUtil
.
checkUpdate
(
checkUpdateHandler
);
// while (true) {
// try {
// if (System.currentTimeMillis() / 1000 % 60 == 0) {
// Utils.i("check");
// }
// checkUpdate();
// Thread.sleep(1000);
// } catch (Exception e) {
// e.printStackTrace();
// Utils.i("check update error");
// }
// }
}
private
CheckUpdateHandler
checkUpdateHandler
=
new
CheckUpdateHandler
();
...
...
@@ -65,46 +47,74 @@ public class UpdateService extends Thread {
// updateVo.setVersionCode(10);
Object
obj
=
msg
.
obj
;
if
(
msg
.
what
==
0
||
obj
==
null
)
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"检查更新返回¬失败"
);
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"检查更新返回失败"
);
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"检查更新返回失败"
,
Toast
.
LENGTH_LONG
);
}
return
;
}
CheckUpdateVo
updateVo
=
JsonUtils
.
readValue
(
obj
,
CheckUpdateVo
.
class
);
if
(
updateVo
.
getVersionCode
()
==
null
||
updateVo
.
getVersionCode
()
<=
0
)
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"version code 为空"
);
UpdateDataVo
dataVo
=
JsonUtils
.
readValue
(
obj
,
UpdateDataVo
.
class
);
if
(
dataVo
==
null
)
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"检查更新返回为空"
);
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"检查更新返回为空"
,
Toast
.
LENGTH_LONG
);
}
return
;
}
if
(
StringUtils
.
isEmpty
(
updateVo
.
getUrl
()))
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"url 为空"
);
if
(
dataVo
.
getVersionCode
()
==
null
||
dataVo
.
getVersionCode
()
<=
0
)
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"version code为空"
);
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"version code为空"
,
Toast
.
LENGTH_LONG
);
}
return
;
}
if
(
StringUtils
.
isEmpty
(
updateVo
.
getVersion
()))
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"version 为空"
);
if
(
StringUtils
.
isEmpty
(
dataVo
.
getUrl
()))
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"url为空"
);
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"url为空"
,
Toast
.
LENGTH_LONG
);
}
return
;
}
if
(
StringUtils
.
isEmpty
(
dataVo
.
getVersion
()))
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"version为空"
);
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"version为空"
,
Toast
.
LENGTH_LONG
);
}
return
;
}
PackageInfo
packageInfo
=
Utils
.
getPackageInfo
();
if
(
updateVo
.
getVersionCode
()
<=
packageInfo
.
versionCode
)
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
String
.
format
(
"不需要更新, current: %s, update: %s"
,
packageInfo
.
versionCode
,
updateVo
.
getVersionCode
()));
if
(
dataVo
.
getVersionCode
()
<=
packageInfo
.
versionCode
)
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
String
.
format
(
"不需要更新, current: %s, update: %s"
,
packageInfo
.
versionCode
,
dataVo
.
getVersionCode
()));
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
String
.
format
(
"不需要更新, current: %s, update: %s"
,
packageInfo
.
versionCode
,
dataVo
.
getVersionCode
()),
Toast
.
LENGTH_LONG
);
}
return
;
}
startDownload
(
update
Vo
);
startDownload
(
data
Vo
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"检查更新失败"
);
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"检查更新失败"
,
Toast
.
LENGTH_LONG
);
}
}
}
}
private
void
startDownload
(
CheckUpdateVo
update
Vo
)
{
String
filename
=
"hooloo-device_"
+
updateVo
.
getVersion
()
+
"_"
+
update
Vo
.
getVersionCode
()
+
"_"
+
System
.
currentTimeMillis
()
+
".apk"
;
private
void
startDownload
(
UpdateDataVo
data
Vo
)
{
String
filename
=
"hooloo-device_"
+
dataVo
.
getVersion
()
+
"_"
+
data
Vo
.
getVersionCode
()
+
"_"
+
System
.
currentTimeMillis
()
+
".apk"
;
String
path
=
Environment
.
getExternalStorageDirectory
().
getAbsolutePath
()
+
"/hooloo"
;
if
(!
new
File
(
path
).
exists
())
{
new
File
(
path
).
mkdirs
();
}
String
file
=
path
+
"/"
+
filename
;
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
String
.
format
(
"开始下载文件 url: %s, file: %s"
,
updateVo
.
getUrl
(),
file
));
HttpUtil
.
download
(
updateVo
.
getUrl
(),
file
,
downloadHandler
);
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
String
.
format
(
"开始下载文件 url: %s, file: %s"
,
dataVo
.
getUrl
(),
file
));
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
String
.
format
(
"开始下载文件 url: %s, file: %s"
,
dataVo
.
getUrl
(),
file
),
Toast
.
LENGTH_LONG
);
}
HttpUtil
.
download
(
dataVo
.
getUrl
(),
file
,
downloadHandler
);
}
private
Handler
downloadHandler
=
new
Handler
()
{
...
...
@@ -113,17 +123,24 @@ public class UpdateService extends Thread {
try
{
Object
obj
=
msg
.
obj
;
if
(
msg
.
what
==
0
||
obj
==
null
)
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"download file error"
);
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"下载文件失败"
);
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"下载文件失败"
,
Toast
.
LENGTH_LONG
);
}
return
;
}
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"下载文件完成,测试版本不能自动升级"
,
Toast
.
LENGTH_LONG
);
return
;
// 测试不实际升级
}
ApkUtils
.
install
(
HLApplication
.
SELF
,
obj
.
toString
());
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"下载文件错误"
);
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"下载文件错误"
,
Toast
.
LENGTH_LONG
);
}
}
}
};
...
...
app/src/main/java/com/ihaoin/hooloo/device/update/UpdateSocket.java
View file @
14c8c12e
package
com
.
ihaoin
.
hooloo
.
device
.
update
;
import
android.content.Context
;
import
android.annotation.SuppressLint
;
import
android.app.Activity
;
import
android.os.Handler
;
import
android.os.Message
;
import
android.widget.Toast
;
import
androidx.annotation.NonNull
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.ihaoin.hooloo.device.base.AppConfig
;
...
...
@@ -19,10 +25,10 @@ import io.socket.emitter.Emitter;
/** Linux通信 检查更新 */
public
class
UpdateSocket
extends
Thread
{
private
Context
mContext
;
private
Activity
mContext
;
private
Socket
mSocket
;
public
UpdateSocket
(
Context
context
)
{
public
UpdateSocket
(
Activity
context
)
{
this
.
mContext
=
context
;
}
...
...
@@ -34,25 +40,39 @@ public class UpdateSocket extends Thread {
private
void
connectSocket
()
{
try
{
mSocket
=
IO
.
socket
(
Base
.
NSP_UPGRADE
);
mSocket
.
connect
();
mSocket
.
on
(
"connect"
,
onConnect
);
mSocket
.
on
(
"disconnect"
,
onDisconnect
);
mSocket
.
on
(
"upgrade"
,
onUpgrade
);
mSocket
.
connect
();
}
catch
(
Exception
e
)
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"连接server失败,错误原因:"
+
e
.
getMessage
());
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"连接server失败,错误原因:"
+
e
.
getMessage
(),
Toast
.
LENGTH_LONG
);
}
e
.
printStackTrace
();
}
}
private
Emitter
.
Listener
onConnect
=
args
->
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"update socket connected"
);
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"update socket, 成功连接"
,
Toast
.
LENGTH_LONG
);
}
mSocket
.
emit
(
"state"
,
""
,
(
Ack
)
ack
->
process
(
"state"
,
ack
));
};
private
Emitter
.
Listener
onDisconnect
=
args
->
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"update socket disconnected"
);
private
Emitter
.
Listener
onDisconnect
=
args
->
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"update socket disconnected"
);
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"update socket, 断开连接"
,
Toast
.
LENGTH_LONG
);
}
};
private
Emitter
.
Listener
onUpgrade
=
args
->
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
"update socket upgrade"
);
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"update socket, onUpgrade"
,
Toast
.
LENGTH_LONG
);
}
process
(
"upgrade"
,
args
);
};
...
...
@@ -79,6 +99,9 @@ public class UpdateSocket extends Thread {
return
;
}
String
content
=
args
[
0
].
toString
();
if
(
AppConfig
.
DEBUG
)
{
Utils
.
showToast
(
mContext
,
"update socket, 接收消息: "
+
content
,
Toast
.
LENGTH_LONG
);
}
if
(
StringUtils
.
isEmpty
(
content
))
{
Utils
.
i
(
AppConfig
.
TAG_UPDATE
,
func
+
" content empty"
);
return
;
...
...
@@ -90,10 +113,18 @@ public class UpdateSocket extends Thread {
return
;
}
if
(
node
.
get
(
"upgrade"
)
!=
null
&&
node
.
get
(
"upgrade"
).
asBoolean
())
{
new
UpdateService
(
mContext
).
start
(
);
startUpdateServiceHandler
.
sendEmptyMessage
(
0
);
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
@SuppressLint
(
"HandlerLeak"
)
private
Handler
startUpdateServiceHandler
=
new
Handler
()
{
@Override
public
void
handleMessage
(
@NonNull
Message
msg
)
{
new
UpdateService
(
mContext
).
start
();
}
};
}
app/src/main/java/com/ihaoin/hooloo/device/util/Utils.java
View file @
14c8c12e
package
com
.
ihaoin
.
hooloo
.
device
.
util
;
import
android.annotation.SuppressLint
;
import
android.app.Activity
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.content.pm.PackageInfo
;
...
...
@@ -305,6 +306,19 @@ public class Utils {
showToast
(
context
,
text
,
Toast
.
LENGTH_SHORT
);
}
public
static
void
showToast
(
Activity
activity
,
String
text
,
int
t
)
{
activity
.
runOnUiThread
(()
->
{
View
view
=
LayoutInflater
.
from
(
activity
).
inflate
(
R
.
layout
.
view_toast
,
null
);
TextView
textView
=
view
.
findViewById
(
R
.
id
.
txt_toast
);
textView
.
setText
(
text
);
Toast
toast
=
Toast
.
makeText
(
activity
,
text
,
t
);
toast
.
setGravity
(
Gravity
.
CENTER
,
0
,
0
);
toast
.
setView
(
view
);
toast
.
show
();
});
}
public
static
void
showToast
(
Context
context
,
String
text
,
int
t
)
{
View
view
=
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
view_toast
,
null
);
TextView
textView
=
view
.
findViewById
(
R
.
id
.
txt_toast
);
...
...
app/src/main/res/values-w800dp/dimens.xml
View file @
14c8c12e
...
...
@@ -150,7 +150,7 @@
<dimen
name=
"interaction_recommend_margin_bottom"
>
140px
</dimen>
<dimen
name=
"interaction_recommend_image_margin"
>
80px
</dimen>
<dimen
name=
"interaction_goods_icon_width"
>
260px
</dimen>
<dimen
name=
"interaction_goods_icon_height"
>
260
px
</dimen>
<dimen
name=
"interaction_goods_icon_height"
>
195
px
</dimen>
<dimen
name=
"ts_interaction_line1"
>
260px
</dimen>
<dimen
name=
"ts_interaction_line2"
>
100px
</dimen>
...
...
app/src/main/res/values/dimens.xml
View file @
14c8c12e
...
...
@@ -166,7 +166,7 @@
<dimen
name=
"interaction_recommend_margin_bottom"
>
140px
</dimen>
<dimen
name=
"interaction_recommend_image_margin"
>
80px
</dimen>
<dimen
name=
"interaction_goods_icon_width"
>
260px
</dimen>
<dimen
name=
"interaction_goods_icon_height"
>
260
px
</dimen>
<dimen
name=
"interaction_goods_icon_height"
>
195
px
</dimen>
<dimen
name=
"ts_interaction_line1"
>
260px
</dimen>
<dimen
name=
"ts_interaction_line2"
>
100px
</dimen>
...
...
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