Commit b37d8503 authored by wanglei's avatar wanglei

...

parent aaf76cdb
package com.base.browserwhite.ui.activity.cleanjunk
import android.graphics.Color
import android.os.Environment
import android.view.View
import androidx.activity.addCallback
import androidx.lifecycle.lifecycleScope
import com.base.browserwhite.R
......@@ -9,9 +11,17 @@ import com.base.browserwhite.databinding.ActivityScanJunkBinding
import com.base.browserwhite.ui.activity.BaseActivity
import com.base.browserwhite.ui.adapter.JunkScanAdapter
import com.base.browserwhite.utils.BarUtils
import com.base.browserwhite.utils.FileHelp.getFileFolder
import com.base.browserwhite.utils.KotlinExt.toFormatSize
import com.base.browserwhite.utils.MediaStoreUtils.queryFiles
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import java.io.File
class ScanJunkActivity : BaseActivity<ActivityScanJunkBinding>() {
......@@ -20,6 +30,12 @@ class ScanJunkActivity : BaseActivity<ActivityScanJunkBinding>() {
override val binding: ActivityScanJunkBinding by lazy {
ActivityScanJunkBinding.inflate(layoutInflater)
}
private val mPathFlow = MutableSharedFlow<String>(
replay = 5,//当新的订阅者Collect时,发送几个已经发送过的数据给它
extraBufferCapacity = 5,//减去replay,MutableSharedFlow还缓存多少数据,缓冲池容量 = replay + extraBufferCapacity
onBufferOverflow = BufferOverflow.DROP_OLDEST//缓存策略,三种 丢掉最新值、丢掉最旧值和挂起
)
val pathFlow: SharedFlow<String> = mPathFlow
override fun initView() {
BarUtils.setStatusBarLightMode(this, true)
......@@ -30,6 +46,12 @@ class ScanJunkActivity : BaseActivity<ActivityScanJunkBinding>() {
junkScanAdapter = JunkScanAdapter()
binding.rv.adapter = junkScanAdapter
lifecycleScope.launch(Dispatchers.Main) {
pathFlow.collectLatest {
binding.tvPath.text = it
}
}
beginScan()
}
......@@ -45,8 +67,8 @@ class ScanJunkActivity : BaseActivity<ActivityScanJunkBinding>() {
}
private fun beginScan() {
lifecycleScope.launch(Dispatchers.Main) {
private fun beginScan() = lifecycleScope.launch(Dispatchers.Main) {
var size = 0L
junkScanAdapter.addData(ParentBean(R.mipmap.x_residual, "Residual File"), 0)
delay(300)
junkScanAdapter.addData(ParentBean(R.mipmap.x_useless, "Useless installation package"), 1)
......@@ -55,9 +77,45 @@ class ScanJunkActivity : BaseActivity<ActivityScanJunkBinding>() {
delay(300)
junkScanAdapter.addData(ParentBean(R.mipmap.x_residual, "Log Files"), 3)
val emptyFolder = arrayListOf<File>()
arrayOf(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES),
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC),
).forEach { dir ->
val list = getFileFolder(mPathFlow, dir, filter = { it.listFiles().isNullOrEmpty() }).await()
emptyFolder.addAll(list)
}
size = emptyFolder.sumOf { it.length() }
setSize(size)
junkScanAdapter.setFinishScan(0)
val apkList = queryFiles(this@ScanJunkActivity, ".apk", mPathFlow).await()
size += apkList.sumOf { it.length() }
setSize(size)
junkScanAdapter.setFinishScan(1)
val tempList = queryFiles(this@ScanJunkActivity, ".temp", mPathFlow).await()
size += tempList.sumOf { it.length() }
setSize(size)
junkScanAdapter.setFinishScan(2)
val logList = queryFiles(this@ScanJunkActivity, ".log", mPathFlow).await()
size += logList.sumOf { it.length() }
setSize(size)
junkScanAdapter.setFinishScan(3)
binding.tvPath.visibility = View.GONE
binding.tvBtn.isEnabled=true
}
private fun setSize(size: Long) {
val split = size.toFormatSize().split(" ")
binding.tvSize.text = split[0]
binding.tvUnit.text = split[1]
}
......
......@@ -64,5 +64,11 @@ class JunkScanAdapter : RecyclerView.Adapter<JunkScanAdapter.ParentViewHolder>()
notifyItemChanged(position)
}
fun setFinishScan(position: Int) {
val bean = beanList[position]
bean.finished = true
notifyItemChanged(position)
}
}
\ No newline at end of file
package com.base.browserwhite.utils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableSharedFlow
import java.io.File
import java.util.LinkedList
object FileHelp {
fun CoroutineScope.getFileFolder(
flow: MutableSharedFlow<String>,
file: File,
filter: (file: File) -> Boolean
) = async(Dispatchers.IO) {
val set = HashSet<File>()
//添加第一层文件到链表
val linkList = LinkedList<File>()
val fileList = file.listFiles()
fileList?.forEach {
if (it.isDirectory) {
flow.emit(it.absolutePath)
linkList.add(it)
if (filter.invoke(it)) {
set.add(it)
}
}
}
//链表取文件
var tempFile: File
while (!linkList.isEmpty()) {
tempFile = linkList.removeFirst()
val tempFileList = tempFile.listFiles()
tempFileList?.forEach {
if (it.isDirectory) {
flow.emit(it.absolutePath)
linkList.add(it)
if (filter.invoke(it)) {
set.add(it)
}
}
}
}
set.toList()
}
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ package com.base.browserwhite.utils
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_APK
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_AUDIO
......@@ -17,6 +18,12 @@ import com.base.browserwhite.bean.ConstObject.MIME_TYPE_XLS
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_XLSX
import com.base.browserwhite.bean.ConstObject.MIME_TYPE_ZIP
import com.base.browserwhite.bean.MediaBean
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import java.io.File
object MediaStoreUtils {
......@@ -351,4 +358,37 @@ object MediaStoreUtils {
}
return count
}
private fun getFileTypeSelection(fileSuffix: String): String {
return (MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_NONE + " AND "
+ MediaStore.Files.FileColumns.DATA + " LIKE '%" + fileSuffix + "'")
}
fun CoroutineScope.queryFiles(context: Context, fileSuffix: String, flow: MutableSharedFlow<String>? = null) =
async(Dispatchers.IO) {
val selection = getFileTypeSelection(fileSuffix)
val fileList: MutableList<File> = ArrayList()
val projection = arrayOf(
MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.DATA,
)
val sortOrder = MediaStore.Files.FileColumns._ID + " DESC"
val queryUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
} else {
MediaStore.Files.getContentUri("external")
}
val cursor = context.contentResolver.query(queryUri, projection, selection, null, sortOrder)
if (cursor != null) {
while (cursor.moveToNext()) {
delay(150)
val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA))
flow?.emit(path)
fileList.add(File(path))
}
cursor.close()
}
fileList
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_0571ed_25" android:state_enabled="true" />
<item android:drawable="@drawable/bg_f3f4f6_25" android:state_enabled="false" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#F3F4F6" />
<corners android:radius="25dp" />
</shape>
\ No newline at end of file
......@@ -82,8 +82,10 @@
android:layout_width="match_parent"
android:layout_height="35dp"
android:background="#1A000000"
android:ellipsize="middle"
android:gravity="center_vertical"
android:paddingStart="15dp"
android:paddingHorizontal="15dp"
android:singleLine="true"
android:textColor="@color/white"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
......@@ -111,8 +113,16 @@
android:layout_width="338dp"
android:layout_height="50dp"
android:layout_marginBottom="30dp"
android:background="@drawable/bg_clean_btn"
android:enabled="false"
android:gravity="center"
android:text="Scan in progress"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#AEAEB0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
app:layout_constraintStart_toStartOf="parent"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment