Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
A
appzxhy
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wanglei
appzxhy
Commits
c7f9596a
Commit
c7f9596a
authored
Jun 11, 2025
by
wanglei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[新增]病毒扫描功能
parent
fa7c8d39
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
567 additions
and
0 deletions
+567
-0
cloudscan_sdk_5.0.5.20240708.aar
app/libs/cloudscan_sdk_5.0.5.20240708.aar
+0
-0
AppInfoBean.kt
app/src/main/java/com/base/appzxhy/bean/AppInfoBean.kt
+13
-0
CloudScan.kt
app/src/main/java/com/base/appzxhy/ui/malware/CloudScan.kt
+22
-0
ErrorScanDialog.kt
.../main/java/com/base/appzxhy/ui/malware/ErrorScanDialog.kt
+38
-0
MalwareCleanActivity.kt
.../java/com/base/appzxhy/ui/malware/MalwareCleanActivity.kt
+326
-0
MalwareDialog.kt
...rc/main/java/com/base/appzxhy/ui/malware/MalwareDialog.kt
+38
-0
antivirus_delete.png
app/src/main/res/drawable-xxhdpi/antivirus_delete.png
+0
-0
activity_malware_clean.xml
app/src/main/res/layout/activity_malware_clean.xml
+130
-0
No files found.
app/libs/cloudscan_sdk_5.0.5.20240708.aar
0 → 100644
View file @
c7f9596a
File added
app/src/main/java/com/base/appzxhy/bean/AppInfoBean.kt
0 → 100644
View file @
c7f9596a
package
com.base.appzxhy.bean
import
android.graphics.drawable.Drawable
data class
AppInfoBean
(
val
appName
:
String
,
val
icon
:
Drawable
,
val
packageName
:
String
,
var
isSelected
:
Boolean
=
false
,
val
isInstall
:
Boolean
?=
null
,
val
score
:
Int
?=
null
,
val
apkPath
:
String
?=
null
)
app/src/main/java/com/base/appzxhy/ui/malware/CloudScan.kt
0 → 100644
View file @
c7f9596a
package
com.base.appzxhy.ui.malware
import
com.base.appzxhy.MyApplication
import
com.trustlook.sdk.cloudscan.CloudScanClient
import
com.trustlook.sdk.data.Region
/**
*Create by SleepDog on 2025-01-24
*/
object
CloudScan
{
val
scanClient
by
lazy
(
LazyThreadSafetyMode
.
NONE
)
{
CloudScanClient
.
Builder
(
MyApplication
.
appContext
)
// 设置服务地区,
// 海外地区设置:Region.INTL,百度用户设置:Region.BAIDU
.
setRegion
(
Region
.
INTL
)
// 设置连接超时时长,单位为毫秒
.
setConnectionTimeout
(
30000
)
//设置传输超时时长,单位为毫秒
.
setSocketTimeout
(
30000
)
.
build
()
}
}
\ No newline at end of file
app/src/main/java/com/base/appzxhy/ui/malware/ErrorScanDialog.kt
0 → 100644
View file @
c7f9596a
package
com.base.appzxhy.ui.malware
import
android.app.Activity
import
android.view.LayoutInflater
import
androidx.appcompat.app.AlertDialog
import
androidx.constraintlayout.widget.ConstraintLayout
import
com.base.appzxhy.R
import
com.base.appzxhy.business.ads.AdsMgr
import
com.base.appzxhy.databinding.DialogErrBinding
class
ErrorScanDialog
(
val
activity
:
Activity
)
{
val
dialog
=
AlertDialog
.
Builder
(
activity
).
create
()
val
binding
=
DialogErrBinding
.
inflate
(
LayoutInflater
.
from
(
activity
))
var
action
:
(()
->
Unit
)?
=
null
fun
showDialog
()
{
dialog
.
setView
(
binding
.
root
)
dialog
.
setCanceledOnTouchOutside
(
false
)
dialog
.
show
()
val
params
=
dialog
.
window
?.
attributes
// params?.width = ConstraintLayout.LayoutParams.MATCH_PARENT
params
?.
width
=
activity
.
resources
.
getDimensionPixelSize
(
R
.
dimen
.
dp_295
)
params
?.
height
=
ConstraintLayout
.
LayoutParams
.
WRAP_CONTENT
// params?.gravity = Gravity.BOTTOM
dialog
.
window
?.
attributes
=
params
dialog
.
window
?.
setBackgroundDrawableResource
(
android
.
R
.
color
.
transparent
)
AdsMgr
.
showNative
(
binding
.
flAd
,
R
.
layout
.
layout_admob_native_custom
)
binding
.
tvSure
.
setOnClickListener
{
dialog
.
dismiss
()
action
?.
invoke
()
}
}
}
\ No newline at end of file
app/src/main/java/com/base/appzxhy/ui/malware/MalwareCleanActivity.kt
0 → 100644
View file @
c7f9596a
package
com.base.appzxhy.ui.malware
import
android.annotation.SuppressLint
import
android.content.Intent
import
android.content.pm.PackageManager
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
androidx.appcompat.content.res.AppCompatResources
import
androidx.core.content.ContextCompat
import
androidx.lifecycle.lifecycleScope
import
androidx.recyclerview.widget.LinearLayoutManager
import
androidx.recyclerview.widget.RecyclerView
import
com.base.appzxhy.R
import
com.base.appzxhy.base.BaseActivity
import
com.base.appzxhy.bean.AppInfoBean
import
com.base.appzxhy.business.ads.AdsMgr
import
com.base.appzxhy.business.ads.AdsShowCallBack
import
com.base.appzxhy.databinding.ActivityMalwareCleanBinding
import
com.base.appzxhy.databinding.ItemMalwareCleanBinding
import
com.base.appzxhy.utils.FileUtils
import
com.trustlook.sdk.cloudscan.CloudScanListener
import
com.trustlook.sdk.data.AppInfo
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.delay
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.withContext
import
kotlin.random.Random
import
androidx.core.net.toUri
import
androidx.core.view.ViewCompat
import
androidx.core.view.WindowInsetsCompat
import
com.base.appzxhy.BuildConfig
import
com.base.appzxhy.base.LottieEnum
import
com.base.appzxhy.bean.FeatureBean.Companion.ANTIVIRUS
import
com.base.appzxhy.ui.cleanresult.CleanResultActivity
import
com.base.appzxhy.utils.LogEx
class
MalwareCleanActivity
:
BaseActivity
<
ActivityMalwareCleanBinding
>(
ActivityMalwareCleanBinding
::
inflate
)
{
private
var
appList
=
mutableListOf
<
AppInfoBean
>()
private
val
adapter
by
lazy
(
LazyThreadSafetyMode
.
NONE
)
{
class
ViewHolder
(
val
binding
:
ItemMalwareCleanBinding
)
:
RecyclerView
.
ViewHolder
(
binding
.
root
)
object
:
RecyclerView
.
Adapter
<
ViewHolder
>()
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
ViewHolder
{
val
binding
=
ItemMalwareCleanBinding
.
inflate
(
LayoutInflater
.
from
(
parent
.
context
),
parent
,
false
)
return
ViewHolder
(
binding
)
}
override
fun
getItemCount
():
Int
=
appList
.
size
override
fun
onBindViewHolder
(
holder
:
ViewHolder
,
position
:
Int
)
{
val
item
=
appList
[
position
]
holder
.
binding
.
ivIcon
.
setImageDrawable
(
item
.
icon
)
holder
.
binding
.
tvName
.
text
=
item
.
appName
holder
.
binding
.
tvLevel
.
text
=
getLevel
(
item
.
score
?:
0
)
holder
.
binding
.
viewLine
.
visibility
=
if
(
position
==
itemCount
-
1
)
View
.
GONE
else
View
.
VISIBLE
holder
.
itemView
.
setOnClickListener
{
item
.
isSelected
=
!
item
.
isSelected
AdsMgr
.
showInsert
(
this
@MalwareCleanActivity
,
showCallBack
=
object
:
AdsShowCallBack
()
{
override
fun
next
()
{
uninstall
(
0
,
listOf
(
item
))
}
})
}
}
}
}
private
fun
getLevel
(
score
:
Int
):
String
{
return
if
(
score
<=
5
)
{
"safe"
}
else
if
(
score
in
6
..
7
)
{
"Risk"
}
else
{
"malware"
}
}
@SuppressLint
(
"NotifyDataSetChanged"
)
private
fun
uninstall
(
position
:
Int
,
list
:
List
<
AppInfoBean
>)
{
val
packageName
=
list
[
position
].
packageName
val
intent
=
Intent
(
Intent
.
ACTION_DELETE
,
"package:$packageName"
.
toUri
())
launcher
.
launch
(
intent
)
{
if
(
isUninstall
(
packageName
))
{
appList
.
removeIf
{
it
.
packageName
==
packageName
}
runOnUiThread
{
adapter
.
notifyDataSetChanged
()
updateUninstall
()
}
}
if
(
position
<
list
.
size
-
1
)
uninstall
(
position
+
1
,
list
)
else
{
updateView
(
false
)
}
}
}
private
fun
isUninstall
(
packageName
:
String
):
Boolean
{
val
intent
=
packageManager
.
getLaunchIntentForPackage
(
packageName
)
return
intent
==
null
}
@SuppressLint
(
"SetTextI18n"
)
private
fun
updateUninstall
()
{
val
list
=
appList
.
filter
{
it
.
isSelected
}
val
size
=
if
(
list
.
isEmpty
())
""
else
" ${list.size} ${getString(R.string.apps)}"
}
@SuppressLint
(
"NotifyDataSetChanged"
)
private
fun
malwareClean
(
list
:
List
<
AppInfoBean
>)
{
lifecycleScope
.
launch
(
Dispatchers
.
Default
)
{
val
installApps
=
mutableListOf
<
AppInfoBean
>()
list
.
forEach
{
if
(
it
.
isInstall
==
true
)
installApps
.
add
(
it
)
else
{
it
.
apkPath
?.
also
{
launch
(
Dispatchers
.
IO
)
{
FileUtils
.
deleteFile
(
it
)
}
}
appList
.
remove
(
it
)
}
}
if
(
installApps
.
isNotEmpty
())
{
uninstall
(
0
,
installApps
)
}
else
{
withContext
(
Dispatchers
.
Main
)
{
adapter
.
notifyDataSetChanged
()
updateUninstall
()
}
}
}
}
private
var
isScanning
=
false
private
fun
initData
(
isScan
:
Boolean
=
isScanning
)
{
if
(
isScan
)
return
isScanning
=
true
CloudScan
.
scanClient
.
startQuickScan
(
object
:
CloudScanListener
()
{
override
fun
onScanStarted
()
{
LogEx
.
logDebug
(
TAG
,
"onScanStarted"
)
}
override
fun
onScanCanceled
()
{
LogEx
.
logDebug
(
TAG
,
"onScanCanceled"
)
scanFinish
()
}
override
fun
onScanProgress
(
p0
:
Int
,
p1
:
Int
,
p2
:
AppInfo
?)
{
LogEx
.
logDebug
(
TAG
,
"onScanProgress"
)
}
@SuppressLint
(
"NotifyDataSetChanged"
)
override
fun
onScanFinished
(
dataList
:
MutableList
<
AppInfo
>?)
{
//Log.e("CloudScan", "onScanFinished")
scanFinishData
(
dataList
)
}
override
fun
onScanError
(
p0
:
Int
,
p1
:
String
?)
{
LogEx
.
logDebug
(
TAG
,
"onScanError"
)
isScanning
=
false
scanError
()
}
override
fun
onScanInterrupt
()
{
isScanning
=
false
scanError
()
}
})
}
fun
scanError
()
{
if
(
BuildConfig
.
DEBUG
)
return
val
dialog
=
ErrorScanDialog
(
this
@MalwareCleanActivity
)
dialog
.
action
=
{
finish
()
}
dialog
.
showDialog
()
}
@SuppressLint
(
"NotifyDataSetChanged"
)
fun
scanFinishData
(
dataList
:
MutableList
<
AppInfo
>?)
{
lifecycleScope
.
launch
(
Dispatchers
.
Default
)
{
val
realList
=
mutableListOf
<
AppInfoBean
>()
dataList
?.
forEach
{
if
(!
it
.
isSystemApp
&&
(
it
.
score
>
5
||
BuildConfig
.
DEBUG
))
{
var
isInstall
:
Boolean
// Log.e("CloudScan", "${it.source} ${it.apkPath} ${it.toJSON(this@MalwareCleanActivity)}")
val
icon
=
try
{
val
res
=
packageManager
.
getApplicationIcon
(
it
.
packageName
)
isInstall
=
true
res
}
catch
(
e
:
PackageManager
.
NameNotFoundException
)
{
isInstall
=
false
val
info
=
packageManager
.
getPackageArchiveInfo
(
it
.
apkPath
,
PackageManager
.
GET_ACTIVITIES
)
if
(
info
!=
null
)
{
info
.
applicationInfo
?.
let
{
packageManager
.
getApplicationIcon
(
it
)
}
}
else
{
AppCompatResources
.
getDrawable
(
this
@MalwareCleanActivity
,
R
.
drawable
.
icon_apk
)
}
}
realList
.
add
(
AppInfoBean
(
it
.
appName
,
icon
!!
,
it
.
packageName
,
false
,
isInstall
,
it
.
score
,
it
.
apkPath
)
)
// withContext(Dispatchers.Main) {
// adapter.notifyItemInserted(appList.size)
// }
}
}
if
(
BuildConfig
.
DEBUG
)
{
realList
.
add
(
AppInfoBean
(
"AntiVirus Phone Manager"
,
AppCompatResources
.
getDrawable
(
this
@MalwareCleanActivity
,
R
.
drawable
.
icon_apk
)
!!
,
"com.tool.fast.phone"
,
false
,
true
,
5
,
"apkPath/apkPath/apkPath"
)
)
}
withContext
(
Dispatchers
.
Main
)
{
val
durationTime
=
Random
.
nextLong
(
3000
,
3500
)
delay
(
durationTime
)
appList
.
clear
()
appList
.
addAll
(
realList
)
scanFinish
()
adapter
.
notifyDataSetChanged
()
updateView
(
true
)
}
}
}
private
fun
scanFinish
()
{
isScanning
=
false
stopAnimation
()
}
fun
stopAnimation
()
{
binding
.
layoutAnimation
.
lottieAnimation
.
clearAnimation
()
binding
.
layoutAnimation
.
root
.
visibility
=
View
.
GONE
isBackDisable
=
false
}
@SuppressLint
(
"SetTextI18n"
)
private
fun
updateView
(
jump
:
Boolean
)
{
binding
.
ivLogo
.
visibility
=
if
(
appList
.
isEmpty
())
View
.
GONE
else
View
.
VISIBLE
binding
.
tvCount
.
visibility
=
if
(
appList
.
isEmpty
())
View
.
GONE
else
{
binding
.
tvCount
.
text
=
"${appList.size} issue"
View
.
VISIBLE
}
binding
.
tvUnit
.
visibility
=
if
(
appList
.
isEmpty
())
View
.
GONE
else
View
.
VISIBLE
binding
.
rvMalware
.
visibility
=
if
(
appList
.
isEmpty
())
View
.
GONE
else
View
.
VISIBLE
binding
.
ivEmpty
.
visibility
=
if
(
appList
.
isEmpty
())
View
.
VISIBLE
else
View
.
GONE
if
(
appList
.
isEmpty
())
{
if
(
jump
)
{
CleanResultActivity
.
functionKey
=
ANTIVIRUS
CleanResultActivity
.
titleName
=
getString
(
R
.
string
.
malware_scan
)
goToAc
(
CleanResultActivity
::
class
.
java
)
}
}
else
{
AdsMgr
.
showNative
(
binding
.
flAd
,
R
.
layout
.
layout_admob_native_custom
)
}
}
override
fun
useDefaultImmersive
()
{
ViewCompat
.
setOnApplyWindowInsetsListener
(
binding
.
root
)
{
v
,
insets
->
val
systemBars
=
insets
.
getInsets
(
WindowInsetsCompat
.
Type
.
systemBars
())
v
.
setPadding
(
systemBars
.
left
,
0
,
systemBars
.
right
,
systemBars
.
bottom
)
binding
.
clTop
.
setPadding
(
0
,
systemBars
.
top
,
0
,
0
)
insets
}
}
override
fun
initView
()
{
super
.
initView
()
showAdAnimation
(
LottieEnum
.
MALWARE_SCAN
)
binding
.
rvMalware
.
adapter
=
adapter
binding
.
rvMalware
.
layoutManager
=
LinearLayoutManager
(
this
)
initData
()
if
(
BuildConfig
.
DEBUG
)
{
scanFinishData
(
null
)
}
}
override
fun
initListener
()
{
super
.
initListener
()
binding
.
flBack
.
setOnClickListener
{
onBackPressedDispatcher
.
onBackPressed
()
}
}
override
fun
handleBackCallBack
()
{
super
.
handleBackCallBack
()
}
}
\ No newline at end of file
app/src/main/java/com/base/appzxhy/ui/malware/MalwareDialog.kt
0 → 100644
View file @
c7f9596a
package
com.base.appzxhy.ui.malware
import
android.app.Activity
import
android.view.LayoutInflater
import
androidx.appcompat.app.AlertDialog
import
com.base.appzxhy.databinding.DialogMalwareTipBinding
class
MalwareDialog
(
val
activity
:
Activity
)
{
val
dialog
=
AlertDialog
.
Builder
(
activity
).
create
()
val
binding
=
DialogMalwareTipBinding
.
inflate
(
LayoutInflater
.
from
(
activity
))
var
action
:
(()
->
Unit
)?
=
null
fun
showDialog
()
{
dialog
.
setView
(
binding
.
root
)
dialog
.
setCanceledOnTouchOutside
(
false
)
dialog
.
show
()
val
params
=
dialog
.
window
?.
attributes
// params?.width = ConstraintLayout.LayoutParams.MATCH_PARENT
// params?.width = activity.resources.getDimensionPixelSize(R.dimen.dp_295)
// params?.height = ConstraintLayout.LayoutParams.WRAP_CONTENT
// params?.gravity = Gravity.BOTTOM
dialog
.
window
?.
attributes
=
params
dialog
.
window
?.
setBackgroundDrawableResource
(
android
.
R
.
color
.
transparent
)
binding
.
tvCancel
.
setOnClickListener
{
dialog
.
dismiss
()
}
binding
.
tvSure
.
setOnClickListener
{
dialog
.
dismiss
()
action
?.
invoke
()
}
}
}
\ No newline at end of file
app/src/main/res/drawable-xxhdpi/antivirus_delete.png
0 → 100644
View file @
c7f9596a
1.99 KB
app/src/main/res/layout/activity_malware_clean.xml
0 → 100644
View file @
c7f9596a
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@color/color_f7fafa"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:id=
"@+id/cl_top"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:background=
"@color/colorPrimary"
app:layout_constraintTop_toTopOf=
"parent"
>
<androidx.appcompat.widget.LinearLayoutCompat
android:id=
"@+id/ll_title"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:gravity=
"center_vertical"
android:orientation=
"horizontal"
android:paddingVertical=
"6dp"
app:layout_constraintTop_toTopOf=
"parent"
>
<ImageView
android:id=
"@+id/fl_back"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"12dp"
android:importantForAccessibility=
"no"
android:padding=
"4dp"
android:src=
"@drawable/icon_return_w"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"@string/malware_scan"
android:textColor=
"@color/white"
android:textSize=
"20sp"
android:textStyle=
"bold"
app:layout_constraintBottom_toBottomOf=
"@id/fl_back"
app:layout_constraintStart_toEndOf=
"@id/fl_back"
app:layout_constraintTop_toTopOf=
"@id/fl_back"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.base.appzxhy.business.ads.NativeParentView
android:id=
"@+id/flAd"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginHorizontal=
"12dp"
android:layout_marginTop=
"10dp"
android:visibility=
"gone"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@id/cl_top"
/>
<ImageView
android:id=
"@+id/iv_logo"
android:layout_width=
"@dimen/dp_150"
android:layout_height=
"@dimen/dp_150"
android:importantForAccessibility=
"no"
android:src=
"@drawable/img_antivirus_scan"
android:visibility=
"gone"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@id/flAd"
tools:visibility=
"visible"
/>
<TextView
android:id=
"@+id/tv_count"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:textColor=
"#F8461A"
android:textSize=
"20sp"
android:textStyle=
"bold"
android:visibility=
"gone"
app:layout_constraintBottom_toBottomOf=
"@id/tv_unit"
app:layout_constraintHorizontal_chainStyle=
"packed"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toLeftOf=
"@id/tv_unit"
app:layout_constraintTop_toTopOf=
"@id/tv_unit"
tools:text=
"3 issue"
/>
<TextView
android:id=
"@+id/tv_unit"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"12dp"
android:text=
" found"
android:textColor=
"@color/black"
android:textSize=
"20sp"
android:textStyle=
"bold"
android:visibility=
"gone"
app:layout_constraintLeft_toRightOf=
"@id/tv_count"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@id/iv_logo"
/>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/iv_empty"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:src=
"@drawable/img_antivirus_scan_kong"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
<androidx.recyclerview.widget.RecyclerView
android:id=
"@+id/rv_malware"
android:layout_width=
"match_parent"
android:layout_height=
"0dp"
android:layout_marginTop=
"10dp"
android:layout_marginBottom=
"12dp"
android:background=
"@color/white"
android:paddingVertical=
"6dp"
android:scrollbars=
"none"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@id/tv_unit"
/>
<include
android:id=
"@+id/layout_animation"
layout=
"@layout/layout_animation"
tools:visibility=
"gone"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
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