Commit d00f1ecb authored by wanglei's avatar wanglei

...

parent 5d17874e
...@@ -29,9 +29,8 @@ ...@@ -29,9 +29,8 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.AppTheme" android:theme="@style/Theme.AppTheme"
tools:targetApi="31"> tools:targetApi="31">
<activity
android:name=".ui.TestActivity"
android:exported="false" />
<activity <activity
android:name=".ui.splash.SplashActivity" android:name=".ui.splash.SplashActivity"
android:exported="true" android:exported="true"
...@@ -49,6 +48,11 @@ ...@@ -49,6 +48,11 @@
android:exported="false" android:exported="false"
android:screenOrientation="portrait" android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" /> tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.language.LanguageActivity"
android:exported="false"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity <activity
android:name=".ui.guide.GuideActivity" android:name=".ui.guide.GuideActivity"
android:exported="false" android:exported="false"
...@@ -93,18 +97,6 @@ ...@@ -93,18 +97,6 @@
android:exported="false" android:exported="false"
android:screenOrientation="portrait" android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" /> tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.recovery.FileScanResultActivity"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.recovery.FileRecoveredActivity"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.recovery.FileRecoveryActivity"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity <activity
android:name=".ui.set.SettingActivity" android:name=".ui.set.SettingActivity"
android:exported="false" android:exported="false"
...@@ -115,11 +107,6 @@ ...@@ -115,11 +107,6 @@
android:exported="false" android:exported="false"
android:screenOrientation="portrait" android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" /> tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.recyclebin.RecycleBinDetailActivity"
android:exported="false"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
......
...@@ -33,7 +33,6 @@ import com.base.appzxhy.SpConstObject.appLanguageCountrySp ...@@ -33,7 +33,6 @@ import com.base.appzxhy.SpConstObject.appLanguageCountrySp
import com.base.appzxhy.SpConstObject.appLanguageSp import com.base.appzxhy.SpConstObject.appLanguageSp
import com.base.appzxhy.R import com.base.appzxhy.R
import com.base.appzxhy.SpConstObject.cleanedSize import com.base.appzxhy.SpConstObject.cleanedSize
import com.base.appzxhy.base.goToAc
import com.base.appzxhy.bean.FeatureBean.Companion.BATTERY_INFO import com.base.appzxhy.bean.FeatureBean.Companion.BATTERY_INFO
import com.base.appzxhy.bean.FeatureBean.Companion.JUNK_CLEAN import com.base.appzxhy.bean.FeatureBean.Companion.JUNK_CLEAN
import com.base.appzxhy.bean.FeatureBean.Companion.LARGE_FILE_CLEAN import com.base.appzxhy.bean.FeatureBean.Companion.LARGE_FILE_CLEAN
...@@ -56,12 +55,6 @@ import com.base.appzxhy.ui.dialog.FunctionBackDialog ...@@ -56,12 +55,6 @@ import com.base.appzxhy.ui.dialog.FunctionBackDialog
import com.base.appzxhy.ui.largefile.LargeFileCleanActivity import com.base.appzxhy.ui.largefile.LargeFileCleanActivity
import com.base.appzxhy.ui.main.MainActivity import com.base.appzxhy.ui.main.MainActivity
import com.base.appzxhy.ui.photocompression.PhotoCompressionActivity import com.base.appzxhy.ui.photocompression.PhotoCompressionActivity
import com.base.appzxhy.ui.recovery.FileScanResultActivity
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_AUDIOS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_DOCUMENTS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_PHOTOS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_VIDEOS
import com.base.appzxhy.ui.recyclebin.RecycleBinUtils
import com.base.appzxhy.ui.screenshot.ScreenshotCleanActivity import com.base.appzxhy.ui.screenshot.ScreenshotCleanActivity
import com.base.appzxhy.ui.similar.SimilarPhotosActivity import com.base.appzxhy.ui.similar.SimilarPhotosActivity
import com.base.appzxhy.utils.ActivityLauncher import com.base.appzxhy.utils.ActivityLauncher
...@@ -462,29 +455,6 @@ fun Activity.jumpAction(key: String) { ...@@ -462,29 +455,6 @@ fun Activity.jumpAction(key: String) {
goToAc(PhotoCompressionActivity::class.java) goToAc(PhotoCompressionActivity::class.java)
} }
RECOVERY_PHOTOS -> {
goToAc(FileScanResultActivity::class.java, exb = {
putExtra("ScanType", SCAN_PHOTOS)
})
}
RECOVERY_VIDEOS -> {
goToAc(FileScanResultActivity::class.java, exb = {
putExtra("ScanType", SCAN_VIDEOS)
})
}
RECOVERY_DOCUMENTS -> {
goToAc(FileScanResultActivity::class.java, exb = {
putExtra("ScanType", SCAN_DOCUMENTS)
})
}
RECOVERY_AUDIOS -> {
goToAc(FileScanResultActivity::class.java, exb = {
putExtra("ScanType", SCAN_AUDIOS)
})
}
} }
} }
...@@ -509,7 +479,6 @@ fun AppCompatActivity.cleanFileBeans(list: List<FileBean>) { ...@@ -509,7 +479,6 @@ fun AppCompatActivity.cleanFileBeans(list: List<FileBean>) {
paths.forEach { paths.forEach {
val file = File(it) val file = File(it)
cleanedSize = cleanedSize + file.length() cleanedSize = cleanedSize + file.length()
RecycleBinUtils.addRecycleBinFile(file)
FileUtils.deleteFile(it) FileUtils.deleteFile(it)
} }
launch(Dispatchers.Main) { MediaUtils.updateMedia(applicationContext, paths) } launch(Dispatchers.Main) { MediaUtils.updateMedia(applicationContext, paths) }
......
package com.base.appzxhy.bean.recovery //package com.base.appzxhy.bean.recovery
//
//
data class FolderBean( //data class FolderBean(
val folder: String = "", // val folder: String = "",
val time: String = "", // val time: String = "",
val recoveryList: ArrayList<RecoveryBean> = arrayListOf() // val recoveryList: ArrayList<RecoveryBean> = arrayListOf()
) { //) {
var isSelect: Boolean = false // var isSelect: Boolean = false
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.bean.recovery //package com.base.appzxhy.bean.recovery
//
import com.base.appzxhy.ui.recovery.FileHexEx.isDoc //import com.base.appzxhy.ui.recovery.FileHexEx.isDoc
import com.base.appzxhy.ui.recovery.FileHexEx.isDocx //import com.base.appzxhy.ui.recovery.FileHexEx.isDocx
import com.base.appzxhy.ui.recovery.FileHexEx.isFlac //import com.base.appzxhy.ui.recovery.FileHexEx.isFlac
import com.base.appzxhy.ui.recovery.FileHexEx.isMp3 //import com.base.appzxhy.ui.recovery.FileHexEx.isMp3
import com.base.appzxhy.ui.recovery.FileHexEx.isPPT //import com.base.appzxhy.ui.recovery.FileHexEx.isPPT
import com.base.appzxhy.ui.recovery.FileHexEx.isPPTX //import com.base.appzxhy.ui.recovery.FileHexEx.isPPTX
import com.base.appzxhy.ui.recovery.FileHexEx.isPdf //import com.base.appzxhy.ui.recovery.FileHexEx.isPdf
import com.base.appzxhy.ui.recovery.FileHexEx.isWav //import com.base.appzxhy.ui.recovery.FileHexEx.isWav
import com.base.appzxhy.ui.recovery.FileHexEx.isXls //import com.base.appzxhy.ui.recovery.FileHexEx.isXls
import com.base.appzxhy.ui.recovery.FileHexEx.isXlsx //import com.base.appzxhy.ui.recovery.FileHexEx.isXlsx
import java.io.File //import java.io.File
//
data class RecoveryBean( //data class RecoveryBean(
val path: String = "", // val path: String = "",
) { //) {
var isSelect: Boolean = false // var isSelect: Boolean = false
var isThumbnails: Boolean = false // var isThumbnails: Boolean = false
var type: String = "" // var type: String = ""
//
companion object { // companion object {
fun RecoveryBean.setDocumentType() { // fun RecoveryBean.setDocumentType() {
val file = File(path) // val file = File(path)
if (isPdf(file)) { // if (isPdf(file)) {
type = "PDF" // type = "PDF"
} // }
if (isDocx(file) || isDoc(file)) { // if (isDocx(file) || isDoc(file)) {
type = "DOC" // type = "DOC"
} // }
if (isXlsx(file) || isXls(file)) { // if (isXlsx(file) || isXls(file)) {
type = "XLS" // type = "XLS"
} // }
if (isPPTX(file) || isPPT(file)) { // if (isPPTX(file) || isPPT(file)) {
type = "PPT" // type = "PPT"
} // }
} // }
//
fun RecoveryBean.setAudioType() { // fun RecoveryBean.setAudioType() {
val file = File(path) // val file = File(path)
if (isMp3(file)) { // if (isMp3(file)) {
type = "MP3" // type = "MP3"
} // }
if (isWav(file)) { // if (isWav(file)) {
type = "WAV" // type = "WAV"
} // }
if (isFlac(file)) { // if (isFlac(file)) {
type = "FLAC" // type = "FLAC"
} // }
} // }
//
} // }
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.bean.recovery //package com.base.appzxhy.bean.recovery
//
class RecoveryFilterBean( //class RecoveryFilterBean(
val tittle: String = "ALL", // val tittle: String = "ALL",
var type: String, // var type: String,
var isSelect: Boolean = false, // var isSelect: Boolean = false,
) //)
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.language
import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.databinding.ActivityLanguageBinding
class LanguageActivity : BaseActivity<ActivityLanguageBinding>(ActivityLanguageBinding::inflate) {
override fun initView() {
super.initView()
}
override fun initListener() {
super.initListener()
}
}
\ No newline at end of file
package com.base.appzxhy.ui.main
import android.annotation.SuppressLint
import android.view.View
import androidx.lifecycle.lifecycleScope
import com.base.appzxhy.R
import com.base.appzxhy.base.BaseFragment
import com.base.appzxhy.base.goToAc
import com.base.appzxhy.base.jumpAction
import com.base.appzxhy.bean.FeatureBean.Companion.BATTERY_INFO
import com.base.appzxhy.bean.FeatureBean.Companion.JUNK_CLEAN
import com.base.appzxhy.bean.FeatureBean.Companion.LARGE_FILE_CLEAN
import com.base.appzxhy.bean.FeatureBean.Companion.PHOTO_COMPRESSION
import com.base.appzxhy.bean.FeatureBean.Companion.SCREENSHOT_CLEAN
import com.base.appzxhy.bean.FeatureBean.Companion.SIMILAR_PHOTOS
import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.databinding.FragmentHome2Binding
import com.base.appzxhy.ui.dialog.permissionStorageJump
import com.base.appzxhy.ui.set.SettingActivity
import com.base.appzxhy.ui.similar.SimilarPhotosActivity
import com.base.appzxhy.utils.KotlinExt.toFormatSize
import com.base.appzxhy.utils.Utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
class Home2Fragment : BaseFragment<FragmentHome2Binding>(FragmentHome2Binding::inflate) {
override fun initView() {
super.initView()
AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom)
initData()
}
override fun initListener() {
super.initListener()
binding.ivSet.setOnClickListener {
goToAc(SettingActivity::class.java)
}
binding.flClean.setOnClickListener {
(requireActivity() as MainActivity).permissionStorageJump(JUNK_CLEAN)
}
binding.tvClean.setOnClickListener {
(requireActivity() as MainActivity).permissionStorageJump(JUNK_CLEAN)
}
binding.llClean.setOnClickListener {
(requireActivity() as MainActivity).permissionStorageJump(JUNK_CLEAN)
}
binding.llBattery.setOnClickListener {
(requireActivity() as MainActivity).jumpAction(BATTERY_INFO)
}
binding.llLarge.setOnClickListener {
(requireActivity() as MainActivity).permissionStorageJump(LARGE_FILE_CLEAN)
}
binding.llDuplicate.setOnClickListener {
(requireActivity() as MainActivity).permissionStorageJump(SIMILAR_PHOTOS)
}
binding.llScreenshot.setOnClickListener {
(requireActivity() as MainActivity).permissionStorageJump(SCREENSHOT_CLEAN)
}
binding.llPhotoCompression.setOnClickListener {
(requireActivity() as MainActivity).permissionStorageJump(PHOTO_COMPRESSION)
}
binding.ivScrollBottom.setOnClickListener {
binding.scrollView.smoothScrollTo(0, binding.scrollView.getChildAt(0).measuredHeight)
}
}
@SuppressLint("SetTextI18n")
private fun initData() {
lifecycleScope.launch(Dispatchers.IO) {
val totalStorageSize = async { Utils.getTotalStorageSize() }.await()
val availableStorageSize = async { Utils.getAvailableStorageSize() }.await()
val usedStorageSize = totalStorageSize - availableStorageSize
val totalStorage = Utils.getSizeFormat(totalStorageSize)
val usedStorage = Utils.getSizeFormat(usedStorageSize)
val percent = (usedStorageSize * 100 / totalStorageSize).toInt()
launch(Dispatchers.Main) {
binding.tvUsed.text = usedStorage
binding.tvTotal.text = " / $totalStorage"
binding.circleProgress.setProgressWithAnimation(percent.toFloat(), 1000)
}
}
}
override fun onResume() {
super.onResume()
if (SimilarPhotosActivity.similarSize != 0L) {
binding.tvDupSize.visibility = View.VISIBLE
binding.tvDupSize.text = SimilarPhotosActivity.similarSize.toFormatSize()
} else {
binding.tvDupSize.visibility = View.INVISIBLE
}
}
}
\ No newline at end of file
package com.base.appzxhy.ui.main package com.base.appzxhy.ui.main
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ConcatAdapter
import com.base.appzxhy.R
import com.base.appzxhy.base.BaseFragment import com.base.appzxhy.base.BaseFragment
import com.base.appzxhy.base.jumpAction
import com.base.appzxhy.bean.FeatureBean
import com.base.appzxhy.bean.FeatureBean.Companion.BATTERY_INFO
import com.base.appzxhy.bean.FeatureBean.Companion.JUNK_CLEAN
import com.base.appzxhy.bean.FeatureBean.Companion.LARGE_FILE_CLEAN
import com.base.appzxhy.bean.FeatureBean.Companion.PHOTO_COMPRESSION
import com.base.appzxhy.bean.FeatureBean.Companion.SCREENSHOT_CLEAN
import com.base.appzxhy.bean.FeatureBean.Companion.SIMILAR_PHOTOS
import com.base.appzxhy.databinding.FragmentHomeBinding import com.base.appzxhy.databinding.FragmentHomeBinding
import com.base.appzxhy.ui.dialog.permissionStorageJump
import com.base.appzxhy.utils.Utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::inflate) { class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::inflate) {
private val concatAdapter = ConcatAdapter()
private val featureList = listOf(
FeatureBean(JUNK_CLEAN, R.string.junk_clean, R.drawable.h_junkclean).apply { span = 1 },
FeatureBean(BATTERY_INFO, R.string.battery_info, R.drawable.h_battery).apply { span = 1 },
FeatureBean(LARGE_FILE_CLEAN, R.string.large_file_clean, R.drawable.h_lagre).apply { span = 1 },
FeatureBean(SCREENSHOT_CLEAN, R.string.screenshot_clean, R.drawable.h_screenshot).apply { span = 3 },
FeatureBean(PHOTO_COMPRESSION, R.string.photo_compression, R.drawable.h_compression).apply { span = 3 },
FeatureBean(SIMILAR_PHOTOS, R.string.similar_photos, R.drawable.h_similar).apply { span = 3 },
)
override fun initView() {
super.initView()
binding.rv.adapter = concatAdapter
concatAdapter.addAdapter(YuanAdapter2().apply {
submitList(listOf(arrayOf("", "")))
cleanClick = {
(requireActivity() as MainActivity).permissionStorageJump(JUNK_CLEAN)
}
initData(this)
})
concatAdapter.addAdapter(FeatureAdapter().apply {
submitList(listOf(featureList))
itemClick = { bean ->
if (bean.key == BATTERY_INFO) {
requireActivity().jumpAction(bean.key)
} else {
requireActivity().permissionStorageJump(bean.key)
}
}
})
}
override fun initListener() {
super.initListener()
}
private fun initData(adapter: YuanAdapter2) {
lifecycleScope.launch(Dispatchers.IO) {
val totalStorageSize = async { Utils.getTotalStorageSize() }.await()
val availableStorageSize = async { Utils.getAvailableStorageSize() }.await()
val usedStorageSize = totalStorageSize - availableStorageSize
val totalStorage = Utils.getSizeFormat(totalStorageSize)
val usedStorage = Utils.getSizeFormat(usedStorageSize)
val percent = (usedStorageSize * 100 / totalStorageSize).toInt()
launch(Dispatchers.Main) {
adapter.submitList(
listOf(arrayOf(usedStorage, totalStorage, "$percent"))
)
}
}
}
} }
\ No newline at end of file
package com.base.appzxhy.ui.main package com.base.appzxhy.ui.main
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.base.appzxhy.R
import com.base.appzxhy.SpConstObject.mainPageCount
import com.base.appzxhy.base.BaseActivity import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.bean.FeatureBean.Companion.JUNK_CLEAN
import com.base.appzxhy.bean.HomeTabUIBean
import com.base.appzxhy.bean.config.AdConfigBean
import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.databinding.ActivityMainBinding import com.base.appzxhy.databinding.ActivityMainBinding
import com.base.appzxhy.databinding.ItemHomeTabBinding
import com.base.appzxhy.ui.dialog.AppExitDialog
import com.base.appzxhy.ui.dialog.NotificationTurnOnDialog
import com.base.appzxhy.ui.dialog.RateDialog
import com.base.appzxhy.ui.dialog.StoragePermissionDialog
import com.base.appzxhy.ui.dialog.permissionStorageJump
import com.base.appzxhy.ui.recyclebin.RecycleBinFragment
import com.base.appzxhy.utils.PermissionUtils.requestNotificationPermission
import com.base.appzxhy.utils.PermissionUtils.requestStoragePermission
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate) { class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate) {
val viewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] }
private val fragmentList = listOf(
Home2Fragment(),
RecoveryFragment(),
RecycleBinFragment()
)
private val viewPagerAdapter by lazy {
object : FragmentStateAdapter(this) {
override fun getItemCount(): Int = fragmentList.size
override fun createFragment(position: Int): Fragment = fragmentList[position]
}
}
override fun initView() { override fun initView() {
super.initView() super.initView()
initTab()
initViewPager2()
initDialogFlow()
AdsMgr.showBanner(binding.flBanner, false)
val lp = binding.flBottom.layoutParams as ConstraintLayout.LayoutParams
if (!AdConfigBean.adsConfigBean.isAdShow) {
lp.setMargins(0, 0, 0, 0)
} else {
lp.setMargins(0, 0, 0, resources.getDimensionPixelSize(R.dimen.dp_60))
}
binding.flBottom.layoutParams = lp
}
private fun initDialogFlow() {
lifecycleScope.launch {
viewModel.dialogFlow.collectLatest { dialogType ->
when (dialogType) {
"StoreDialog" -> {
val dialog = StoragePermissionDialog(this@MainActivity)
dialog.action = {
requestStoragePermission(launcher) {
viewModel.nextShowDialog = false
}
}
dialog.showDialog()
}
"NotificationDialog" -> {
val dialog = NotificationTurnOnDialog(this@MainActivity)
dialog.action = {
requestNotificationPermission(launcher) {
viewModel.nextShowDialog = false
}
}
dialog.showDialog()
}
"RateDialog" -> {
val dialog = RateDialog(this@MainActivity)
dialog.showDialog(false)
}
}
}
}
} }
private fun initViewPager2() { override fun initListener() {
binding.viewPager2.adapter = viewPagerAdapter super.initListener()
binding.viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
val defaultTab = binding.tabLayout.getTabAt(position)
defaultTab?.select()
defaultTab?.setSelected()
} }
})
}
private fun initTab() {
arrayOf(
HomeTabUIBean(R.drawable.tab_clean_selector, getString(R.string.clean)),
HomeTabUIBean(R.drawable.tab_recovery_selector, getString(R.string.recovery)),
HomeTabUIBean(R.drawable.tab_recyclebin_selector, getString(R.string.recyclebin)),
).forEachIndexed { index, homeTab ->
val tab = binding.tabLayout.newTab()
val view = LayoutInflater.from(this).inflate(R.layout.item_home_tab, null)
val tabBinding = ItemHomeTabBinding.bind(view)
tabBinding.ivIcon.setImageResource(homeTab.icon)
tabBinding.tvTab.text = homeTab.tab
// tabBinding.tvTab.setTextColor(ContextCompat.getColor(this, R.color.color_tab_home))
tab.customView = tabBinding.root
tab.id = index
if (index == 1) {
tabBinding.vDian.visibility = View.VISIBLE
} else {
tabBinding.vDian.visibility = View.GONE
}
binding.tabLayout.addTab(tab)
}
binding.tabLayout.addOnTabSelectedListener(object : OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
tab?.let {
if (binding.viewPager2.currentItem == tab.id) return
binding.viewPager2.setCurrentItem(tab.id, false)
}
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
tab?.setUnselected()
}
override fun onTabReselected(tab: TabLayout.Tab?) {
}
})
}
fun TabLayout.Tab.setSelected() {
val textView = customView?.findViewById<TextView>(R.id.tv_tab)
textView?.setTextColor(
ContextCompat.getColor(this@MainActivity, R.color.colorPrimary)
)
}
fun TabLayout.Tab.setUnselected() {
val textView = customView?.findViewById<TextView>(R.id.tv_tab)
textView?.setTextColor(Color.parseColor("#999999"))
}
override fun onResumeOneShoot() {
super.onResumeOneShoot()
mainPageCount = mainPageCount + 1
viewModel.checkDialog(this)
viewModel.refreshRecycleBin()
}
override fun handleBackCallBack() {
val dialog = AppExitDialog(this)
dialog.action = {
permissionStorageJump(JUNK_CLEAN)
}
dialog.showDialog()
}
} }
\ No newline at end of file
...@@ -2,17 +2,12 @@ package com.base.appzxhy.ui.main ...@@ -2,17 +2,12 @@ package com.base.appzxhy.ui.main
import android.content.Context import android.content.Context
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.base.appzxhy.SpConstObject.isScoreRated import com.base.appzxhy.SpConstObject.isScoreRated
import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.getRecycleBinData
import com.base.appzxhy.utils.PermissionUtils.areNotificationsEnabled import com.base.appzxhy.utils.PermissionUtils.areNotificationsEnabled
import com.base.appzxhy.utils.PermissionUtils.checkNotificationPermission import com.base.appzxhy.utils.PermissionUtils.checkNotificationPermission
import com.base.appzxhy.utils.PermissionUtils.checkStorePermission import com.base.appzxhy.utils.PermissionUtils.checkStorePermission
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import java.io.File
class MainViewModel : ViewModel() { class MainViewModel : ViewModel() {
...@@ -44,10 +39,4 @@ class MainViewModel : ViewModel() { ...@@ -44,10 +39,4 @@ class MainViewModel : ViewModel() {
return return
} }
} }
var recycleBinFileFlow: MutableStateFlow<List<File>> = MutableStateFlow(listOf())
fun refreshRecycleBin() = viewModelScope.launch(Dispatchers.IO) {
recycleBinFileFlow.update { getRecycleBinData() }
}
} }
\ No newline at end of file
package com.base.appzxhy.ui.main //package com.base.appzxhy.ui.main
//
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.base.BaseFragment //import com.base.appzxhy.base.BaseFragment
import com.base.appzxhy.base.goToAc //import com.base.appzxhy.base.goToAc
import com.base.appzxhy.business.ads.AdsMgr //import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.databinding.FragmentRecoveryBinding //import com.base.appzxhy.databinding.FragmentRecoveryBinding
import com.base.appzxhy.ui.recovery.FileScanResultActivity //import com.base.appzxhy.ui.recovery.FileScanResultActivity
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_AUDIOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_AUDIOS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_DOCUMENTS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_DOCUMENTS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_PHOTOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_PHOTOS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_VIDEOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_VIDEOS
//
class RecoveryFragment : BaseFragment<FragmentRecoveryBinding>(FragmentRecoveryBinding::inflate) { //class RecoveryFragment : BaseFragment<FragmentRecoveryBinding>(FragmentRecoveryBinding::inflate) {
//
//
override fun initView() { // override fun initView() {
super.initView() // super.initView()
AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom) // AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom)
} // }
//
override fun initListener() { // override fun initListener() {
super.initListener() // super.initListener()
binding.llPhoto.setOnClickListener { // binding.llPhoto.setOnClickListener {
goToAc(FileScanResultActivity::class.java) { // goToAc(FileScanResultActivity::class.java) {
putExtra("ScanType", SCAN_PHOTOS) // putExtra("ScanType", SCAN_PHOTOS)
} // }
} // }
binding.llVideo.setOnClickListener { // binding.llVideo.setOnClickListener {
goToAc(FileScanResultActivity::class.java) { // goToAc(FileScanResultActivity::class.java) {
putExtra("ScanType", SCAN_VIDEOS) // putExtra("ScanType", SCAN_VIDEOS)
} // }
} // }
binding.llDocument.setOnClickListener { // binding.llDocument.setOnClickListener {
goToAc(FileScanResultActivity::class.java) { // goToAc(FileScanResultActivity::class.java) {
putExtra("ScanType", SCAN_DOCUMENTS) // putExtra("ScanType", SCAN_DOCUMENTS)
} // }
} // }
binding.llAudio.setOnClickListener { // binding.llAudio.setOnClickListener {
goToAc(FileScanResultActivity::class.java) { // goToAc(FileScanResultActivity::class.java) {
putExtra("ScanType", SCAN_AUDIOS) // putExtra("ScanType", SCAN_AUDIOS)
} // }
} // }
//
} // }
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.recovery //package com.base.appzxhy.ui.recovery
//
import android.annotation.SuppressLint //import android.annotation.SuppressLint
import android.content.Context //import android.content.Context
import android.view.LayoutInflater //import android.view.LayoutInflater
import android.view.View //import android.view.View
import android.view.ViewGroup //import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView //import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder //import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.bean.recovery.FolderBean //import com.base.appzxhy.bean.recovery.FolderBean
import com.base.appzxhy.databinding.ItemFolderBinding //import com.base.appzxhy.databinding.ItemFolderBinding
import com.base.appzxhy.databinding.ItemFolderRecoveryBinding //import com.base.appzxhy.databinding.ItemFolderRecoveryBinding
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_PHOTOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_PHOTOS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_VIDEOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_VIDEOS
import com.bumptech.glide.Glide //import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop //import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners //import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions //import com.bumptech.glide.request.RequestOptions
//
class FileFolderAdapter( //class FileFolderAdapter(
private val scanType: Int, private val click: (bean: FolderBean) -> Unit // private val scanType: Int, private val click: (bean: FolderBean) -> Unit
) : RecyclerView.Adapter<FileFolderAdapter.FF>() { //) : RecyclerView.Adapter<FileFolderAdapter.FF>() {
//
private val TAG = "FileFolderAdapter" // private val TAG = "FileFolderAdapter"
private val beanList = arrayListOf<FolderBean>() // private val beanList = arrayListOf<FolderBean>()
//
class FF(view: View) : ViewHolder(view) // class FF(view: View) : ViewHolder(view)
//
fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View { // fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View {
return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot) // return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot)
} // }
//
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FF { // override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FF {
val layout = when (scanType) { // val layout = when (scanType) {
SCAN_PHOTOS, SCAN_VIDEOS -> R.layout.item_folder_recovery // SCAN_PHOTOS, SCAN_VIDEOS -> R.layout.item_folder_recovery
else -> R.layout.item_folder // else -> R.layout.item_folder
} // }
return FF(layout.inflate(parent)) // return FF(layout.inflate(parent))
} // }
//
override fun getItemCount(): Int { // override fun getItemCount(): Int {
return beanList.size // return beanList.size
} // }
//
fun Context.dpToPx(dps: Int): Int { // fun Context.dpToPx(dps: Int): Int {
return Math.round(resources.displayMetrics.density * dps) // return Math.round(resources.displayMetrics.density * dps)
} // }
//
@SuppressLint("SetTextI18n", "CheckResult") // @SuppressLint("SetTextI18n", "CheckResult")
override fun onBindViewHolder(holder: FF, position: Int) { // override fun onBindViewHolder(holder: FF, position: Int) {
//
val bean = beanList[position] // val bean = beanList[position]
val context = holder.itemView.context // val context = holder.itemView.context
//
when (scanType) { // when (scanType) {
SCAN_PHOTOS, SCAN_VIDEOS -> { // SCAN_PHOTOS, SCAN_VIDEOS -> {
val binding = ItemFolderRecoveryBinding.bind(holder.itemView) // val binding = ItemFolderRecoveryBinding.bind(holder.itemView)
runCatching { // runCatching {
val options = RequestOptions().transform(CenterCrop(), RoundedCorners(context.dpToPx(10))) // val options = RequestOptions().transform(CenterCrop(), RoundedCorners(context.dpToPx(10)))
val image1 = bean.recoveryList[0].path // val image1 = bean.recoveryList[0].path
val request1 = Glide.with(context).load(image1).apply(options) // val request1 = Glide.with(context).load(image1).apply(options)
if (scanType == SCAN_VIDEOS) { // if (scanType == SCAN_VIDEOS) {
request1.error(R.drawable.videotu) // request1.error(R.drawable.videotu)
} // }
request1.into(binding.iv1) // request1.into(binding.iv1)
//
val image2 = bean.recoveryList[1].path // val image2 = bean.recoveryList[1].path
val request2 = Glide.with(context).load(image2).apply(options) // val request2 = Glide.with(context).load(image2).apply(options)
if (scanType == SCAN_VIDEOS) { // if (scanType == SCAN_VIDEOS) {
request2.error(R.drawable.videotu) // request2.error(R.drawable.videotu)
} // }
request2.into(binding.iv2) // request2.into(binding.iv2)
//
val image3 = bean.recoveryList[2].path // val image3 = bean.recoveryList[2].path
val request3 = Glide.with(context).load(image3).apply(options) // val request3 = Glide.with(context).load(image3).apply(options)
if (scanType == SCAN_VIDEOS) { // if (scanType == SCAN_VIDEOS) {
request3.error(R.drawable.videotu) // request3.error(R.drawable.videotu)
} // }
request3.into(binding.iv3) // request3.into(binding.iv3)
} // }
//
binding.tvFolder.text = bean.folder // binding.tvFolder.text = bean.folder
binding.tvFolderNumber.text = "(${bean.recoveryList.size})" // binding.tvFolderNumber.text = "(${bean.recoveryList.size})"
binding.root.setOnClickListener { // binding.root.setOnClickListener {
click.invoke(bean) // click.invoke(bean)
} // }
} // }
//
else -> { // else -> {
// LogEx.logDebug(TAG, "scanType=$scanType") //// LogEx.logDebug(TAG, "scanType=$scanType")
val binding = ItemFolderBinding.bind(holder.itemView) // val binding = ItemFolderBinding.bind(holder.itemView)
binding.tvFolder.text = bean.folder // binding.tvFolder.text = bean.folder
binding.tvFileNumber.text = "${bean.recoveryList.size}" // binding.tvFileNumber.text = "${bean.recoveryList.size}"
binding.root.setOnClickListener { // binding.root.setOnClickListener {
click.invoke(bean) // click.invoke(bean)
} // }
} // }
} // }
//
//
} // }
//
@SuppressLint("NotifyDataSetChanged") // @SuppressLint("NotifyDataSetChanged")
fun setData(list: List<FolderBean>) { // fun setData(list: List<FolderBean>) {
beanList.clear() // beanList.clear()
beanList.addAll(list) // beanList.addAll(list)
notifyDataSetChanged() // notifyDataSetChanged()
} // }
//
@SuppressLint("NotifyDataSetChanged") // @SuppressLint("NotifyDataSetChanged")
fun addData(list: List<FolderBean>) { // fun addData(list: List<FolderBean>) {
beanList.addAll(list) // beanList.addAll(list)
notifyDataSetChanged() // notifyDataSetChanged()
} // }
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.recovery //package com.base.appzxhy.ui.recovery
//
import java.io.File //import java.io.File
import java.io.IOException //import java.io.IOException
import java.io.RandomAccessFile //import java.io.RandomAccessFile
//
object FileHexEx { //object FileHexEx {
//
private val TAG = "FileHexEx" // private val TAG = "FileHexEx"
private const val HEXES = "0123456789ABCDEF" // private const val HEXES = "0123456789ABCDEF"
//
//
fun readFileRange(filePath: String, start: Long, end: Long): ByteArray { // fun readFileRange(filePath: String, start: Long, end: Long): ByteArray {
var data = byteArrayOf() // var data = byteArrayOf()
try { // try {
val file = RandomAccessFile(filePath, "r") // val file = RandomAccessFile(filePath, "r")
file.seek(start) // file.seek(start)
val length = end - start // val length = end - start
data = ByteArray(length.toInt()) // data = ByteArray(length.toInt())
file.readFully(data) // file.readFully(data)
file.close() // file.close()
} catch (e: IOException) { // } catch (e: IOException) {
e.printStackTrace() // e.printStackTrace()
} // }
return data // return data
} // }
//
fun ByteArray.byteArrayToHexString(): String { // fun ByteArray.byteArrayToHexString(): String {
val hex = StringBuilder(2 * this.size) // val hex = StringBuilder(2 * this.size)
for (element in this) { // for (element in this) {
val high = element.toInt().and(0xFF).shr(4) // val high = element.toInt().and(0xFF).shr(4)
val low = element.toInt().and(0x0F) // val low = element.toInt().and(0x0F)
hex.append(HEXES[high]).append(HEXES[low]) // hex.append(HEXES[high]).append(HEXES[low])
} // }
return hex.toString() // return hex.toString()
} // }
//
fun isImage(file: File): Boolean { // fun isImage(file: File): Boolean {
return isWebp(file) || isPngOrJpg(file) // return isWebp(file) || isPngOrJpg(file)
} // }
//
fun isPngOrJpg(file: File): Boolean { // fun isPngOrJpg(file: File): Boolean {
val pngHex = "89504E47" // val pngHex = "89504E47"
val jpgHex1 = "FFD8FFE0" // val jpgHex1 = "FFD8FFE0"
val jpgHex2 = "FFD8FFE1" // val jpgHex2 = "FFD8FFE1"
val hex = readFileRange(file.absolutePath, 0, 4).byteArrayToHexString() // val hex = readFileRange(file.absolutePath, 0, 4).byteArrayToHexString()
return (hex == pngHex || hex == jpgHex1 || hex == jpgHex2) // return (hex == pngHex || hex == jpgHex1 || hex == jpgHex2)
} // }
//
fun isWebp(file: File): Boolean { // fun isWebp(file: File): Boolean {
val webpHex = "57454250" // val webpHex = "57454250"
val hex = readFileRange(file.absolutePath, 8, 11).byteArrayToHexString() // val hex = readFileRange(file.absolutePath, 8, 11).byteArrayToHexString()
return hex == webpHex // return hex == webpHex
} // }
//
fun isDocument(file: File): Boolean { // fun isDocument(file: File): Boolean {
return isPdf(file) || // return isPdf(file) ||
isDocx(file) || // isDocx(file) ||
isXlsx(file) || // isXlsx(file) ||
isPPTX(file) || // isPPTX(file) ||
isXls(file) || // isXls(file) ||
isPPT(file) || // isPPT(file) ||
isDoc(file) // isDoc(file)
} // }
//
fun isDoc(file: File): Boolean { // fun isDoc(file: File): Boolean {
val docHex = "57006F007200640044006F00630075006D0065006E007400" // val docHex = "57006F007200640044006F00630075006D0065006E007400"
val hex = readFileRange(file.absolutePath, 1408, 1432).byteArrayToHexString() // val hex = readFileRange(file.absolutePath, 1408, 1432).byteArrayToHexString()
val flag = hex == docHex // val flag = hex == docHex
// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}")
return flag // return flag
} // }
//
fun isPPT(file: File): Boolean { // fun isPPT(file: File): Boolean {
val pptHex = "50006F0077006500720050006F0069006E0074" // val pptHex = "50006F0077006500720050006F0069006E0074"
val hex = readFileRange(file.absolutePath, 1408, 1427).byteArrayToHexString() // val hex = readFileRange(file.absolutePath, 1408, 1427).byteArrayToHexString()
val flag = pptHex == hex // val flag = pptHex == hex
// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}")
return flag // return flag
} // }
//
fun isPdf(file: File): Boolean { // fun isPdf(file: File): Boolean {
val pdfHex = "25504446" // val pdfHex = "25504446"
val hex = readFileRange(file.absolutePath, 0, 4).byteArrayToHexString() // val hex = readFileRange(file.absolutePath, 0, 4).byteArrayToHexString()
return pdfHex == hex // return pdfHex == hex
} // }
//
fun isXls(file: File): Boolean { // fun isXls(file: File): Boolean {
val xlsHex = "4500540045007800740044006100740061" // val xlsHex = "4500540045007800740044006100740061"
val hex = readFileRange(file.absolutePath, 1280, 1297).byteArrayToHexString() // val hex = readFileRange(file.absolutePath, 1280, 1297).byteArrayToHexString()
val flag = hex == xlsHex // val flag = hex == xlsHex
// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}")
return flag // return flag
} // }
//
fun isDocx(file: File): Boolean { // fun isDocx(file: File): Boolean {
val docxHex = "6F6350726F70732F504B" // val docxHex = "6F6350726F70732F504B"
val hex = readFileRange(file.absolutePath, 31, 41).byteArrayToHexString() // val hex = readFileRange(file.absolutePath, 31, 41).byteArrayToHexString()
val flag = docxHex == hex // val flag = docxHex == hex
// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}")
return flag // return flag
} // }
//
//
fun isPPTX(file: File): Boolean { // fun isPPTX(file: File): Boolean {
val pptxHex = "6CCD97CB6EDB301045F705FA0F02B785" // val pptxHex = "6CCD97CB6EDB301045F705FA0F02B785"
val hex = readFileRange(file.absolutePath, 48, 64).byteArrayToHexString() // val hex = readFileRange(file.absolutePath, 48, 64).byteArrayToHexString()
val flag = hex == pptxHex // val flag = hex == pptxHex
// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}")
return flag // return flag
} // }
//
fun isXlsx(file: File): Boolean { // fun isXlsx(file: File): Boolean {
val xlsxHex = "6CCD94CD6A02311485F785BE43C8B6CC" // val xlsxHex = "6CCD94CD6A02311485F785BE43C8B6CC"
val hex = readFileRange(file.absolutePath, 48, 64).byteArrayToHexString() // val hex = readFileRange(file.absolutePath, 48, 64).byteArrayToHexString()
val flag = hex == xlsxHex // val flag = hex == xlsxHex
// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}")
return flag // return flag
} // }
//
fun isVideo(file: File): Boolean { // fun isVideo(file: File): Boolean {
return isMp4(file) || isAvi(file) || isMkv(file) // return isMp4(file) || isAvi(file) || isMkv(file)
} // }
//
fun isMp4(file: File): Boolean { // fun isMp4(file: File): Boolean {
val mp4Hex = "6D70343269736F6D000061316D6F6F76" // val mp4Hex = "6D70343269736F6D000061316D6F6F76"
val hex = readFileRange(file.absolutePath, 16, 32).byteArrayToHexString() // val hex = readFileRange(file.absolutePath, 16, 32).byteArrayToHexString()
val flag = hex == mp4Hex // val flag = hex == mp4Hex
// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}")
return flag // return flag
} // }
//
fun isAvi(file: File): Boolean { // fun isAvi(file: File): Boolean {
val aviHex = "524946461C1BA900415649204C495354" // val aviHex = "524946461C1BA900415649204C495354"
val hex = readFileRange(file.absolutePath, 0, 16).byteArrayToHexString() // val hex = readFileRange(file.absolutePath, 0, 16).byteArrayToHexString()
val flag = hex == aviHex // val flag = hex == aviHex
// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag=$flag hex=${hex} ${file.absolutePath}")
return flag // return flag
} // }
//
fun isMkv(file: File): Boolean { // fun isMkv(file: File): Boolean {
val mkvHex1 = "42F7810142F2810442F381084282886D" // val mkvHex1 = "42F7810142F2810442F381084282886D"
val hex1 = readFileRange(file.absolutePath, 16, 32).byteArrayToHexString() // val hex1 = readFileRange(file.absolutePath, 16, 32).byteArrayToHexString()
val flag1 = hex1 == mkvHex1 // val flag1 = hex1 == mkvHex1
// LogEx.logDebug(TAG, "flag1=$flag1 hex=${hex1} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag1=$flag1 hex=${hex1} ${file.absolutePath}")
return if (flag1) { // return if (flag1) {
true // true
} else { // } else {
val mkvHex2 = "42F7810142F2810442F381084282886D6174726F736B614287" // val mkvHex2 = "42F7810142F2810442F381084282886D6174726F736B614287"
val hex2 = readFileRange(file.absolutePath, 9, 34).byteArrayToHexString() // val hex2 = readFileRange(file.absolutePath, 9, 34).byteArrayToHexString()
val flag2 = hex2 == mkvHex2 // val flag2 = hex2 == mkvHex2
// LogEx.logDebug(TAG, "flag2=$flag2 hex=${hex2} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag2=$flag2 hex=${hex2} ${file.absolutePath}")
flag2 // flag2
} // }
//
} // }
//
fun isAudio(file: File): Boolean { // fun isAudio(file: File): Boolean {
return isMp3(file) || isFlac(file) || isWav(file) // return isMp3(file) || isFlac(file) || isWav(file)
} // }
//
fun isMp3(file: File): Boolean { // fun isMp3(file: File): Boolean {
val mp3Hex1 = "49443303" // val mp3Hex1 = "49443303"
val hex1 = readFileRange(file.absolutePath, 0, 4).byteArrayToHexString() // val hex1 = readFileRange(file.absolutePath, 0, 4).byteArrayToHexString()
val flag1 = hex1 == mp3Hex1 // val flag1 = hex1 == mp3Hex1
// LogEx.logDebug(TAG, "flag1=$flag1 hex1=${hex1} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag1=$flag1 hex1=${hex1} ${file.absolutePath}")
return flag1 // return flag1
} // }
//
fun isFlac(file: File): Boolean { // fun isFlac(file: File): Boolean {
val flacHex = "664C6143" // val flacHex = "664C6143"
val hex1 = readFileRange(file.absolutePath, 0, 4).byteArrayToHexString() // val hex1 = readFileRange(file.absolutePath, 0, 4).byteArrayToHexString()
val flag1 = hex1 == flacHex // val flag1 = hex1 == flacHex
// LogEx.logDebug(TAG, "flag1=$flag1 hex1=${hex1} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag1=$flag1 hex1=${hex1} ${file.absolutePath}")
return flag1 // return flag1
} // }
//
fun isWav(file: File): Boolean { // fun isWav(file: File): Boolean {
val wavHex = "5249464668E7820957415645666D74" // val wavHex = "5249464668E7820957415645666D74"
val hex1 = readFileRange(file.absolutePath, 0, 15).byteArrayToHexString() // val hex1 = readFileRange(file.absolutePath, 0, 15).byteArrayToHexString()
val flag1 = hex1 == wavHex // val flag1 = hex1 == wavHex
// LogEx.logDebug(TAG, "flag1=$flag1 hex1=${hex1} ${file.absolutePath}") //// LogEx.logDebug(TAG, "flag1=$flag1 hex1=${hex1} ${file.absolutePath}")
return flag1 // return flag1
} // }
//
//
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.recovery //package com.base.appzxhy.ui.recovery
//
import android.annotation.SuppressLint //import android.annotation.SuppressLint
import android.os.Bundle //import android.os.Bundle
import android.os.Environment //import android.os.Environment
import androidx.activity.addCallback //import androidx.activity.addCallback
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.base.BaseActivity //import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.business.ads.AdsMgr //import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.business.ads.AdsShowCallBack //import com.base.appzxhy.business.ads.AdsShowCallBack
import com.base.appzxhy.databinding.ActivityFileRecoveredBinding //import com.base.appzxhy.databinding.ActivityFileRecoveredBinding
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_AUDIOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_AUDIOS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_DOCUMENTS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_DOCUMENTS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_PHOTOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_PHOTOS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_VIDEOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_VIDEOS
import java.io.File //import java.io.File
//
class FileRecoveredActivity : BaseActivity<ActivityFileRecoveredBinding>(ActivityFileRecoveredBinding::inflate) { //class FileRecoveredActivity : BaseActivity<ActivityFileRecoveredBinding>(ActivityFileRecoveredBinding::inflate) {
//
//
override fun onCreate(savedInstanceState: Bundle?) { // override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) // super.onCreate(savedInstanceState)
initView() // initView()
initListener() // initListener()
} // }
//
@SuppressLint("SetTextI18n") // @SuppressLint("SetTextI18n")
override fun initView() { // override fun initView() {
super.initView() // super.initView()
//
val number = intent.extras?.getInt("Number") ?: 0 // val number = intent.extras?.getInt("Number") ?: 0
val scanType = intent.extras?.getInt("ScanType") // val scanType = intent.extras?.getInt("ScanType")
val path: String? = intent.extras?.getString("Path") // val path: String? = intent.extras?.getString("Path")
//
binding.tvNumber.text = number.toString() // binding.tvNumber.text = number.toString()
val type = when (scanType) { // val type = when (scanType) {
SCAN_PHOTOS -> if (number == 1) "Photo" else "Photos" // SCAN_PHOTOS -> if (number == 1) "Photo" else "Photos"
SCAN_VIDEOS -> if (number == 1) "Video" else "Videos" // SCAN_VIDEOS -> if (number == 1) "Video" else "Videos"
SCAN_DOCUMENTS -> if (number == 1) "Document" else "Documents" // SCAN_DOCUMENTS -> if (number == 1) "Document" else "Documents"
SCAN_AUDIOS -> if (number == 1) "Audio" else "Audios" // SCAN_AUDIOS -> if (number == 1) "Audio" else "Audios"
else -> "" // else -> ""
} // }
binding.tvType.text = type // binding.tvType.text = type
//
val appName = getString(R.string.app_name).replace("/", " ") // val appName = getString(R.string.app_name).replace("/", " ")
val appDir = File(Environment.getExternalStorageDirectory(), appName) // val appDir = File(Environment.getExternalStorageDirectory(), appName)
binding.tvDir.text = "Recovered in $appDir" // binding.tvDir.text = "Recovered in $appDir"
} // }
//
override fun initListener() { // override fun initListener() {
//
binding.ivBack.setOnClickListener { // binding.ivBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed() // onBackPressedDispatcher.onBackPressed()
} // }
onBackPressedDispatcher.addCallback { // onBackPressedDispatcher.addCallback {
AdsMgr.showInsert(this@FileRecoveredActivity, showCallBack = object : AdsShowCallBack() { // AdsMgr.showInsert(this@FileRecoveredActivity, showCallBack = object : AdsShowCallBack() {
override fun next() { // override fun next() {
finishToMainTop() // finishToMainTop()
} // }
}) // })
} // }
binding.tvContinue.setOnClickListener { // binding.tvContinue.setOnClickListener {
AdsMgr.showInsert(this@FileRecoveredActivity, showCallBack = object : AdsShowCallBack() { // AdsMgr.showInsert(this@FileRecoveredActivity, showCallBack = object : AdsShowCallBack() {
override fun next() { // override fun next() {
finish() // finish()
} // }
}) // })
} // }
binding.tvFinish.setOnClickListener { // binding.tvFinish.setOnClickListener {
onBackPressedDispatcher.onBackPressed() // onBackPressedDispatcher.onBackPressed()
} // }
} // }
//
//
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.recovery //package com.base.appzxhy.ui.recovery
//
import android.annotation.SuppressLint //import android.annotation.SuppressLint
import android.content.Intent //import android.content.Intent
import android.graphics.Bitmap //import android.graphics.Bitmap
import android.graphics.BitmapFactory //import android.graphics.BitmapFactory
import android.graphics.Color //import android.graphics.Color
import android.os.Bundle //import android.os.Bundle
import android.os.Environment //import android.os.Environment
import android.view.View //import android.view.View
import androidx.activity.SystemBarStyle //import androidx.activity.SystemBarStyle
import androidx.activity.addCallback //import androidx.activity.addCallback
import androidx.activity.enableEdgeToEdge //import androidx.activity.enableEdgeToEdge
import androidx.core.content.ContextCompat //import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat //import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat //import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible //import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope //import androidx.lifecycle.lifecycleScope
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.base.BaseActivity //import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.bean.recovery.FolderBean //import com.base.appzxhy.bean.recovery.FolderBean
import com.base.appzxhy.bean.recovery.RecoveryBean //import com.base.appzxhy.bean.recovery.RecoveryBean
import com.base.appzxhy.bean.recovery.RecoveryFilterBean //import com.base.appzxhy.bean.recovery.RecoveryFilterBean
import com.base.appzxhy.databinding.ActivityFileRecoveryBinding //import com.base.appzxhy.databinding.ActivityFileRecoveryBinding
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_AUDIOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_AUDIOS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_DOCUMENTS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_DOCUMENTS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_PHOTOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_PHOTOS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_VIDEOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_VIDEOS
import com.base.appzxhy.ui.recovery.RecoveringDialog.showRecoveringDialog //import com.base.appzxhy.ui.recovery.RecoveringDialog.showRecoveringDialog
import kotlinx.coroutines.Dispatchers //import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch //import kotlinx.coroutines.launch
import java.io.File //import java.io.File
import java.text.SimpleDateFormat //import java.text.SimpleDateFormat
import java.util.Calendar //import java.util.Calendar
import java.util.Locale //import java.util.Locale
//
class FileRecoveryActivity : BaseActivity<ActivityFileRecoveryBinding>(ActivityFileRecoveryBinding::inflate) { //class FileRecoveryActivity : BaseActivity<ActivityFileRecoveryBinding>(ActivityFileRecoveryBinding::inflate) {
//
private var scanType = 0 // private var scanType = 0
//
private lateinit var adapter: FileTimeColumnsAdapter // private lateinit var adapter: FileTimeColumnsAdapter
private lateinit var filterAdapter: RecoveryFilterAdapter // private lateinit var filterAdapter: RecoveryFilterAdapter
//
private val dateFilterList = arrayListOf( // private val dateFilterList = arrayListOf(
RecoveryFilterBean("All", "Size", true), // RecoveryFilterBean("All", "Size", true),
RecoveryFilterBean("With 1 month", "Date"), // RecoveryFilterBean("With 1 month", "Date"),
RecoveryFilterBean("With 6 months", "Date"), // RecoveryFilterBean("With 6 months", "Date"),
RecoveryFilterBean("With 24 months", "Date"), // RecoveryFilterBean("With 24 months", "Date"),
) // )
private var sizeFilterList = arrayListOf( // private var sizeFilterList = arrayListOf(
RecoveryFilterBean("All", "Size", true), // RecoveryFilterBean("All", "Size", true),
RecoveryFilterBean("0 - 1 M", "Size"), // RecoveryFilterBean("0 - 1 M", "Size"),
RecoveryFilterBean("1 - 5 M", "Size"), // RecoveryFilterBean("1 - 5 M", "Size"),
RecoveryFilterBean("> 5 M", "Size"), // RecoveryFilterBean("> 5 M", "Size"),
) // )
//
private val layoutFilterList = arrayListOf( // private val layoutFilterList = arrayListOf(
RecoveryFilterBean("2 columns", "Layout", true), // RecoveryFilterBean("2 columns", "Layout", true),
RecoveryFilterBean("3 columns", "Layout"), // RecoveryFilterBean("3 columns", "Layout"),
RecoveryFilterBean("4 columns", "Layout"), // RecoveryFilterBean("4 columns", "Layout"),
) // )
//
override fun onCreate(savedInstanceState: Bundle?) { // override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) // super.onCreate(savedInstanceState)
initView() // initView()
initListener() // initListener()
} // }
//
override fun useDefaultImmersive() { // override fun useDefaultImmersive() {
ViewCompat.setOnApplyWindowInsetsListener(binding.clTop) { v, insets -> // ViewCompat.setOnApplyWindowInsetsListener(binding.clTop) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) // val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) // v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets // insets
} // }
} // }
//
@SuppressLint("SetTextI18n") // @SuppressLint("SetTextI18n")
override fun initView() { // override fun initView() {
//
//
scanType = intent.extras?.getInt("ScanType") ?: 0 // scanType = intent.extras?.getInt("ScanType") ?: 0
//
when (scanType) { // when (scanType) {
SCAN_PHOTOS -> { // SCAN_PHOTOS -> {
setThumbnails() // setThumbnails()
} // }
//
SCAN_DOCUMENTS -> { // SCAN_DOCUMENTS -> {
binding.clThumbnails.visibility = View.GONE // binding.clThumbnails.visibility = View.GONE
binding.llLayout.visibility = View.GONE // binding.llLayout.visibility = View.GONE
} // }
//
SCAN_VIDEOS -> { // SCAN_VIDEOS -> {
binding.clThumbnails.visibility = View.GONE // binding.clThumbnails.visibility = View.GONE
} // }
//
SCAN_AUDIOS -> { // SCAN_AUDIOS -> {
binding.clThumbnails.visibility = View.GONE // binding.clThumbnails.visibility = View.GONE
binding.llLayout.visibility = View.GONE // binding.llLayout.visibility = View.GONE
} // }
//
} // }
adapter = FileTimeColumnsAdapter( // adapter = FileTimeColumnsAdapter(
scanType, // scanType,
select = { all, size -> // select = { all, size ->
binding.ivSelectAll.isSelected = all // binding.ivSelectAll.isSelected = all
binding.tvRecover.text = "Recover($size)" // binding.tvRecover.text = "Recover($size)"
binding.tvRecover.isEnabled = size > 0 // binding.tvRecover.isEnabled = size > 0
}) // })
binding.rv.adapter = adapter // binding.rv.adapter = adapter
//
filterAdapter = RecoveryFilterAdapter { bean -> // filterAdapter = RecoveryFilterAdapter { bean ->
filterDismiss(bean) // filterDismiss(bean)
} // }
binding.rvFilter.adapter = filterAdapter // binding.rvFilter.adapter = filterAdapter
//
initData() // initData()
} // }
//
@SuppressLint("SetTextI18n") // @SuppressLint("SetTextI18n")
private fun setThumbnails() = lifecycleScope.launch(Dispatchers.IO) { // private fun setThumbnails() = lifecycleScope.launch(Dispatchers.IO) {
//
var size = 0 // var size = 0
folderBean?.recoveryList?.forEach { bean -> // folderBean?.recoveryList?.forEach { bean ->
runCatching { // runCatching {
val bitmap: Bitmap? = BitmapFactory.decodeFile(bean.path) // val bitmap: Bitmap? = BitmapFactory.decodeFile(bean.path)
bitmap?.let { // bitmap?.let {
if (it.height < 256 || it.width < 256) { // if (it.height < 256 || it.width < 256) {
size++ // size++
bean.isThumbnails = true // bean.isThumbnails = true
} // }
} // }
} // }
} // }
launch(Dispatchers.Main) { // launch(Dispatchers.Main) {
binding.tvThumbnails.text = "Hide thumbnails (${size})" // binding.tvThumbnails.text = "Hide thumbnails (${size})"
} // }
} // }
//
override fun onResume() { // override fun onResume() {
super.onResume() // super.onResume()
} // }
//
override fun initListener() { // override fun initListener() {
binding.llFilter.setOnClickListener { // binding.llFilter.setOnClickListener {
filterDismiss() // filterDismiss()
} // }
binding.flFanhui.setOnClickListener { // binding.flFanhui.setOnClickListener {
onBackPressedDispatcher.onBackPressed() // onBackPressedDispatcher.onBackPressed()
} // }
onBackPressedDispatcher.addCallback { // onBackPressedDispatcher.addCallback {
finish() // finish()
} // }
binding.switchThumbnails.setOnCheckedChangeListener { buttonView, isChecked -> // binding.switchThumbnails.setOnCheckedChangeListener { buttonView, isChecked ->
adapter.toggleThumbnails(isChecked) // adapter.toggleThumbnails(isChecked)
} // }
binding.flSelectAll.setOnClickListener { // binding.flSelectAll.setOnClickListener {
binding.ivSelectAll.isSelected = !binding.ivSelectAll.isSelected // binding.ivSelectAll.isSelected = !binding.ivSelectAll.isSelected
adapter.toggleAllSelect(binding.ivSelectAll.isSelected) // adapter.toggleAllSelect(binding.ivSelectAll.isSelected)
} // }
binding.llDate.setOnClickListener { // binding.llDate.setOnClickListener {
showFilter(it.id) // showFilter(it.id)
} // }
binding.llSize.setOnClickListener { // binding.llSize.setOnClickListener {
showFilter(it.id) // showFilter(it.id)
} // }
binding.llLayout.setOnClickListener { // binding.llLayout.setOnClickListener {
showFilter(it.id) // showFilter(it.id)
} // }
binding.tvRecover.setOnClickListener { // binding.tvRecover.setOnClickListener {
var dirType = "" // var dirType = ""
when (scanType) { // when (scanType) {
SCAN_PHOTOS -> dirType = "Photo" // SCAN_PHOTOS -> dirType = "Photo"
SCAN_DOCUMENTS -> dirType = "Document" // SCAN_DOCUMENTS -> dirType = "Document"
SCAN_VIDEOS -> dirType = "Video" // SCAN_VIDEOS -> dirType = "Video"
SCAN_AUDIOS -> dirType = "Audio" // SCAN_AUDIOS -> dirType = "Audio"
} // }
val appName = getString(R.string.app_name).replace("/", " ") // val appName = getString(R.string.app_name).replace("/", " ")
val appDir = File(Environment.getExternalStorageDirectory(), appName) // val appDir = File(Environment.getExternalStorageDirectory(), appName)
val dir = File(appDir, dirType) // val dir = File(appDir, dirType)
if (!dir.exists()) { // if (!dir.exists()) {
dir.mkdirs() // dir.mkdirs()
} // }
beginRecover(dir) // beginRecover(dir)
} // }
} // }
//
private fun beginRecover(dir: File) { // private fun beginRecover(dir: File) {
val list = adapter.getSelectData().map { it.path } // val list = adapter.getSelectData().map { it.path }
showRecoveringDialog(lifecycleScope, list, dir, copyProgressAction = { // showRecoveringDialog(lifecycleScope, list, dir, copyProgressAction = {
//
}, finish = { // }, finish = {
startActivity(Intent(this, FileRecoveredActivity::class.java).apply { // startActivity(Intent(this, FileRecoveredActivity::class.java).apply {
putExtra("Number", list.size) // putExtra("Number", list.size)
putExtra("ScanType", scanType) // putExtra("ScanType", scanType)
}) // })
}) // })
} // }
//
private fun showFilter(filter: Int) { // private fun showFilter(filter: Int) {
//
if (!binding.llFilter.isVisible) { // if (!binding.llFilter.isVisible) {
binding.llFilter.isVisible = true // binding.llFilter.isVisible = true
binding.clTop.background = ContextCompat.getDrawable(this, R.drawable.bg_e7ecff_edf5ff_blr15) // binding.clTop.background = ContextCompat.getDrawable(this, R.drawable.bg_e7ecff_edf5ff_blr15)
} // }
//
if (filter == R.id.ll_date) { // if (filter == R.id.ll_date) {
binding.ivDate.setImageResource(R.drawable.zhankai) // binding.ivDate.setImageResource(R.drawable.zhankai)
filterAdapter.setData(dateFilterList) // filterAdapter.setData(dateFilterList)
} else { // } else {
binding.ivDate.setImageResource(R.drawable.shouqi) // binding.ivDate.setImageResource(R.drawable.shouqi)
} // }
if (filter == R.id.ll_size) { // if (filter == R.id.ll_size) {
binding.ivSize.setImageResource(R.drawable.zhankai) // binding.ivSize.setImageResource(R.drawable.zhankai)
filterAdapter.setData(sizeFilterList) // filterAdapter.setData(sizeFilterList)
} else { // } else {
binding.ivSize.setImageResource(R.drawable.shouqi) // binding.ivSize.setImageResource(R.drawable.shouqi)
} // }
if (filter == R.id.ll_layout) { // if (filter == R.id.ll_layout) {
binding.ivLayout.setImageResource(R.drawable.zhankai) // binding.ivLayout.setImageResource(R.drawable.zhankai)
filterAdapter.setData(layoutFilterList) // filterAdapter.setData(layoutFilterList)
} else { // } else {
binding.ivLayout.setImageResource(R.drawable.shouqi) // binding.ivLayout.setImageResource(R.drawable.shouqi)
} // }
} // }
//
private fun filterDismiss(recoveryFilterBean: RecoveryFilterBean? = null) { // private fun filterDismiss(recoveryFilterBean: RecoveryFilterBean? = null) {
binding.llFilter.isVisible = false // binding.llFilter.isVisible = false
binding.clTop.background = ContextCompat.getDrawable(this, R.drawable.bg_e7ecff_edf5ff_blr15) // binding.clTop.background = ContextCompat.getDrawable(this, R.drawable.bg_e7ecff_edf5ff_blr15)
binding.ivDate.setImageResource(R.drawable.shouqi) // binding.ivDate.setImageResource(R.drawable.shouqi)
binding.ivSize.setImageResource(R.drawable.shouqi) // binding.ivSize.setImageResource(R.drawable.shouqi)
binding.ivLayout.setImageResource(R.drawable.shouqi) // binding.ivLayout.setImageResource(R.drawable.shouqi)
//
recoveryFilterBean?.let { bean -> // recoveryFilterBean?.let { bean ->
if (bean.type == "Date") { // if (bean.type == "Date") {
dateFilterList.find { it.isSelect }?.isSelect = false // dateFilterList.find { it.isSelect }?.isSelect = false
dateFilterList.find { it == bean }?.isSelect = true // dateFilterList.find { it == bean }?.isSelect = true
initData() // initData()
return // return
} // }
if (bean.type == "Size") { // if (bean.type == "Size") {
sizeFilterList.find { it.isSelect }?.isSelect = false // sizeFilterList.find { it.isSelect }?.isSelect = false
sizeFilterList.find { it == bean }?.isSelect = true // sizeFilterList.find { it == bean }?.isSelect = true
initData() // initData()
return // return
} // }
if (bean.type == "Layout") { // if (bean.type == "Layout") {
layoutFilterList.find { it.isSelect }?.isSelect = false // layoutFilterList.find { it.isSelect }?.isSelect = false
layoutFilterList.find { it == bean }?.isSelect = true // layoutFilterList.find { it == bean }?.isSelect = true
//
val index = layoutFilterList.indexOf(bean) // val index = layoutFilterList.indexOf(bean)
val columns = when (index) { // val columns = when (index) {
0 -> 2 // 0 -> 2
1 -> 3 // 1 -> 3
2 -> 4 // 2 -> 4
else -> 2 // else -> 2
} // }
adapter.changeColumns(columns) // adapter.changeColumns(columns)
} // }
} // }
//
} // }
//
private fun Long.toFormatTime(): String { // private fun Long.toFormatTime(): String {
return SimpleDateFormat("MMM dd,yyyy", Locale.ENGLISH).format(this) // return SimpleDateFormat("MMM dd,yyyy", Locale.ENGLISH).format(this)
} // }
//
fun initData() { // fun initData() {
//
val hash = HashMap<String, ArrayList<RecoveryBean>>() // val hash = HashMap<String, ArrayList<RecoveryBean>>()
//
folderBean?.let { // folderBean?.let {
it.recoveryList.forEach { recoveryBean -> // it.recoveryList.forEach { recoveryBean ->
if (dateFilter(recoveryBean) && sizeFilter(recoveryBean)) { // if (dateFilter(recoveryBean) && sizeFilter(recoveryBean)) {
val file = File(recoveryBean.path) // val file = File(recoveryBean.path)
val time = file.lastModified().toFormatTime() // val time = file.lastModified().toFormatTime()
if (hash[time].isNullOrEmpty()) { // if (hash[time].isNullOrEmpty()) {
hash[time] = arrayListOf() // hash[time] = arrayListOf()
} // }
hash[time]?.add(recoveryBean) // hash[time]?.add(recoveryBean)
} // }
//
} // }
} // }
val list = arrayListOf<FolderBean>() // val list = arrayListOf<FolderBean>()
hash.forEach { (key, value) -> // hash.forEach { (key, value) ->
list.add(FolderBean(time = key, recoveryList = value)) // list.add(FolderBean(time = key, recoveryList = value))
} // }
adapter.setData(list) // adapter.setData(list)
} // }
//
private fun dateFilter(recoveryBean: RecoveryBean): Boolean { // private fun dateFilter(recoveryBean: RecoveryBean): Boolean {
val index = dateFilterList.indexOfFirst { it.isSelect } // val index = dateFilterList.indexOfFirst { it.isSelect }
return when (index) { // return when (index) {
1 -> isWithinOneMonth(File(recoveryBean.path).lastModified()) // 1 -> isWithinOneMonth(File(recoveryBean.path).lastModified())
2 -> isWithinSixMonths(File(recoveryBean.path).lastModified()) // 2 -> isWithinSixMonths(File(recoveryBean.path).lastModified())
3 -> isWithinTwentyFourMonths(File(recoveryBean.path).lastModified()) // 3 -> isWithinTwentyFourMonths(File(recoveryBean.path).lastModified())
else -> true // else -> true
} // }
} // }
//
private fun sizeFilter(recoveryBean: RecoveryBean): Boolean { // private fun sizeFilter(recoveryBean: RecoveryBean): Boolean {
val oneMegabyte = 1024 * 1024L // val oneMegabyte = 1024 * 1024L
val index = sizeFilterList.indexOfFirst { it.isSelect } // val index = sizeFilterList.indexOfFirst { it.isSelect }
//
return when (index) { // return when (index) {
1 -> File(recoveryBean.path).length() in 0L..oneMegabyte // 1 -> File(recoveryBean.path).length() in 0L..oneMegabyte
2 -> File(recoveryBean.path).length() in oneMegabyte..oneMegabyte * 5 // 2 -> File(recoveryBean.path).length() in oneMegabyte..oneMegabyte * 5
3 -> File(recoveryBean.path).length() > oneMegabyte * 5 // 3 -> File(recoveryBean.path).length() > oneMegabyte * 5
else -> true // else -> true
} // }
} // }
//
companion object { // companion object {
var folderBean: FolderBean? = FolderBean() // var folderBean: FolderBean? = FolderBean()
} // }
//
//
fun isWithinOneMonth(pastTimestamp: Long): Boolean { // fun isWithinOneMonth(pastTimestamp: Long): Boolean {
val calendar = Calendar.getInstance() // val calendar = Calendar.getInstance()
val currentTime = System.currentTimeMillis() // val currentTime = System.currentTimeMillis()
//
// 将当前时间减去一个月 // // 将当前时间减去一个月
calendar.timeInMillis = currentTime // calendar.timeInMillis = currentTime
calendar.add(Calendar.MONTH, -1) // calendar.add(Calendar.MONTH, -1)
val oneMonthAgo = calendar.timeInMillis // val oneMonthAgo = calendar.timeInMillis
//
// 检查过去的时间戳是否在当前时间与一个月前之间 // // 检查过去的时间戳是否在当前时间与一个月前之间
return pastTimestamp in oneMonthAgo..currentTime // return pastTimestamp in oneMonthAgo..currentTime
} // }
//
fun isWithinSixMonths(pastTimestamp: Long): Boolean { // fun isWithinSixMonths(pastTimestamp: Long): Boolean {
val calendar = Calendar.getInstance() // 获取当前时间的Calendar实例 // val calendar = Calendar.getInstance() // 获取当前时间的Calendar实例
val currentTime = System.currentTimeMillis() // 获取当前时间的时间戳 // val currentTime = System.currentTimeMillis() // 获取当前时间的时间戳
//
// 设置calendar到当前时间 // // 设置calendar到当前时间
calendar.timeInMillis = currentTime // calendar.timeInMillis = currentTime
// 减去6个月 // // 减去6个月
calendar.add(Calendar.MONTH, -6) // calendar.add(Calendar.MONTH, -6)
//
val sixMonthsAgo = calendar.timeInMillis // 计算6个月前的日期 // val sixMonthsAgo = calendar.timeInMillis // 计算6个月前的日期
//
// 检查过去的时间戳是否在6个月的范围内 // // 检查过去的时间戳是否在6个月的范围内
return pastTimestamp in sixMonthsAgo..currentTime // return pastTimestamp in sixMonthsAgo..currentTime
} // }
//
fun isWithinTwentyFourMonths(timestamp: Long): Boolean { // fun isWithinTwentyFourMonths(timestamp: Long): Boolean {
val calendar = Calendar.getInstance() // 获取当前时间的Calendar实例 // val calendar = Calendar.getInstance() // 获取当前时间的Calendar实例
val currentTime = System.currentTimeMillis() // 获取当前时间的时间戳 // val currentTime = System.currentTimeMillis() // 获取当前时间的时间戳
//
// 设置calendar到当前时间 // // 设置calendar到当前时间
calendar.timeInMillis = currentTime // calendar.timeInMillis = currentTime
// 减去24个月 // // 减去24个月
calendar.add(Calendar.MONTH, -24) // calendar.add(Calendar.MONTH, -24)
//
val twentyFourMonthsAgo = calendar.timeInMillis // 计算24个月前的日期 // val twentyFourMonthsAgo = calendar.timeInMillis // 计算24个月前的日期
//
// 检查时间戳是否在24个月的范围内 // // 检查时间戳是否在24个月的范围内
return timestamp in twentyFourMonthsAgo..currentTime // return timestamp in twentyFourMonthsAgo..currentTime
} // }
//
} //}
//
package com.base.appzxhy.ui.recovery //package com.base.appzxhy.ui.recovery
//
import android.animation.ValueAnimator //import android.animation.ValueAnimator
import android.annotation.SuppressLint //import android.annotation.SuppressLint
import android.app.AlertDialog //import android.app.AlertDialog
import android.view.LayoutInflater //import android.view.LayoutInflater
import android.view.View //import android.view.View
import android.view.animation.LinearInterpolator //import android.view.animation.LinearInterpolator
import androidx.appcompat.app.AppCompatActivity //import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope //import androidx.lifecycle.lifecycleScope
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.business.ads.AdsMgr //import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.databinding.DialogFileScanBinding //import com.base.appzxhy.databinding.DialogFileScanBinding
import kotlinx.coroutines.Dispatchers //import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharedFlow //import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.collectLatest //import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch //import kotlinx.coroutines.launch
//
class FileScanDialog( //class FileScanDialog(
val activity: AppCompatActivity, // val activity: AppCompatActivity,
) { //) {
private val TAG = "FileScanDialog" // private val TAG = "FileScanDialog"
private val a1 = ValueAnimator.ofFloat(0f, -360f) // private val a1 = ValueAnimator.ofFloat(0f, -360f)
private val dialog = AlertDialog.Builder(activity).create() // private val dialog = AlertDialog.Builder(activity).create()
private val binding = DialogFileScanBinding.inflate(LayoutInflater.from(activity)) // private val binding = DialogFileScanBinding.inflate(LayoutInflater.from(activity))
//
//
@SuppressLint("SetTextI18n") // @SuppressLint("SetTextI18n")
fun showFileScanDialog( // fun showFileScanDialog(
pathFlow: SharedFlow<String>, // pathFlow: SharedFlow<String>,
foundFlow: SharedFlow<Pair<Int, String>>, // foundFlow: SharedFlow<Pair<Int, String>>,
foundAction: ((path: String) -> Unit)? = null // foundAction: ((path: String) -> Unit)? = null
): AlertDialog { // ): AlertDialog {
dialog?.setView(binding.root) // dialog?.setView(binding.root)
dialog?.setCanceledOnTouchOutside(false) // dialog?.setCanceledOnTouchOutside(false)
dialog?.setCancelable(false) // dialog?.setCancelable(false)
dialog?.show() // dialog?.show()
//
dialog?.window?.setBackgroundDrawableResource(R.color.transparent) // dialog?.window?.setBackgroundDrawableResource(R.color.transparent)
val params = dialog?.window?.attributes // val params = dialog?.window?.attributes
params?.width = activity.resources.getDimensionPixelOffset(R.dimen.dp_300) // params?.width = activity.resources.getDimensionPixelOffset(R.dimen.dp_300)
dialog?.window?.attributes = params // dialog?.window?.attributes = params
//
a1.run { // a1.run {
duration = 1000 // duration = 1000
repeatMode = ValueAnimator.RESTART // repeatMode = ValueAnimator.RESTART
repeatCount = ValueAnimator.INFINITE // repeatCount = ValueAnimator.INFINITE
interpolator = LinearInterpolator() // interpolator = LinearInterpolator()
addUpdateListener { // addUpdateListener {
binding.iv.rotation = it.animatedValue as Float // binding.iv.rotation = it.animatedValue as Float
} // }
start() // start()
} // }
//
dialog?.setOnDismissListener { // dialog?.setOnDismissListener {
a1.cancel() // a1.cancel()
} // }
//
AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom) // AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom)
//
var pathShowed = false // var pathShowed = false
activity.lifecycleScope.launch(Dispatchers.Main) { // activity.lifecycleScope.launch(Dispatchers.Main) {
pathFlow.collectLatest { path -> // pathFlow.collectLatest { path ->
if (!pathShowed) { // if (!pathShowed) {
pathShowed = true // pathShowed = true
binding.tvPath.visibility = View.VISIBLE // binding.tvPath.visibility = View.VISIBLE
} // }
binding.tvPath.text = path // binding.tvPath.text = path
} // }
} // }
activity.lifecycleScope.launch { // activity.lifecycleScope.launch {
foundFlow.collectLatest { // foundFlow.collectLatest {
binding.tvFoundNumber.text = "Found ${it.first} files" // binding.tvFoundNumber.text = "Found ${it.first} files"
foundAction?.invoke(it.second) // foundAction?.invoke(it.second)
} // }
} // }
//
return dialog // return dialog
} // }
//
@SuppressLint("SetTextI18n") // @SuppressLint("SetTextI18n")
fun finishScan(clickAction: () -> Unit) { // fun finishScan(clickAction: () -> Unit) {
a1.cancel() // a1.cancel()
binding.tvBtn.visibility = View.VISIBLE // binding.tvBtn.visibility = View.VISIBLE
binding.iv.visibility = View.GONE // binding.iv.visibility = View.GONE
binding.tvPath.visibility = View.GONE // binding.tvPath.visibility = View.GONE
binding.tvTitle.text = "Scan Completed" // binding.tvTitle.text = "Scan Completed"
binding.tvBtn.setOnClickListener { // binding.tvBtn.setOnClickListener {
clickAction.invoke() // clickAction.invoke()
} // }
} // }
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.recovery //package com.base.appzxhy.ui.recovery
//
import android.Manifest //import android.Manifest
import android.annotation.SuppressLint //import android.annotation.SuppressLint
import android.app.Activity //import android.app.Activity
import android.app.Dialog //import android.app.Dialog
import android.content.Context //import android.content.Context
import android.content.Intent //import android.content.Intent
import android.content.pm.PackageManager //import android.content.pm.PackageManager
import android.graphics.Color //import android.graphics.Color
import android.graphics.drawable.ColorDrawable //import android.graphics.drawable.ColorDrawable
import android.net.Uri //import android.net.Uri
import android.os.Build //import android.os.Build
import android.os.Environment //import android.os.Environment
import android.provider.Settings //import android.provider.Settings
import android.view.LayoutInflater //import android.view.LayoutInflater
import android.view.View //import android.view.View
import androidx.activity.SystemBarStyle //import androidx.activity.SystemBarStyle
import androidx.activity.addCallback //import androidx.activity.addCallback
import androidx.activity.enableEdgeToEdge //import androidx.activity.enableEdgeToEdge
import androidx.core.app.ActivityCompat //import androidx.core.app.ActivityCompat
import androidx.core.view.ViewCompat //import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat //import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible //import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope //import androidx.lifecycle.lifecycleScope
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.base.BaseActivity //import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.bean.recovery.FolderBean //import com.base.appzxhy.bean.recovery.FolderBean
import com.base.appzxhy.bean.recovery.RecoveryBean //import com.base.appzxhy.bean.recovery.RecoveryBean
import com.base.appzxhy.bean.recovery.RecoveryBean.Companion.setAudioType //import com.base.appzxhy.bean.recovery.RecoveryBean.Companion.setAudioType
import com.base.appzxhy.bean.recovery.RecoveryBean.Companion.setDocumentType //import com.base.appzxhy.bean.recovery.RecoveryBean.Companion.setDocumentType
import com.base.appzxhy.business.ads.AdsMgr //import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.business.ads.AdsShowCallBack //import com.base.appzxhy.business.ads.AdsShowCallBack
import com.base.appzxhy.databinding.ActivityFileScanResultBinding //import com.base.appzxhy.databinding.ActivityFileScanResultBinding
import com.base.appzxhy.databinding.DialogExitFunctionBinding //import com.base.appzxhy.databinding.DialogExitFunctionBinding
import com.base.appzxhy.databinding.DialogPermissonOpenBinding //import com.base.appzxhy.databinding.DialogPermissonOpenBinding
import com.base.appzxhy.utils.ActivityLauncher //import com.base.appzxhy.utils.ActivityLauncher
import kotlinx.coroutines.CoroutineScope //import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers //import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.BufferOverflow //import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.delay //import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow //import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow //import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.launch //import kotlinx.coroutines.launch
import java.io.File //import java.io.File
import java.util.LinkedList //import java.util.LinkedList
import androidx.core.net.toUri //import androidx.core.net.toUri
import androidx.core.graphics.drawable.toDrawable //import androidx.core.graphics.drawable.toDrawable
//
class FileScanResultActivity : BaseActivity<ActivityFileScanResultBinding>(ActivityFileScanResultBinding::inflate) { //class FileScanResultActivity : BaseActivity<ActivityFileScanResultBinding>(ActivityFileScanResultBinding::inflate) {
//
private var scanOnce: Boolean = false // private var scanOnce: Boolean = false
private var scanType = 0 // private var scanType = 0
//
private lateinit var fileFolderAdapter: FileFolderAdapter // private lateinit var fileFolderAdapter: FileFolderAdapter
//
override fun useDefaultImmersive() { // override fun useDefaultImmersive() {
super.useDefaultImmersive() // super.useDefaultImmersive()
} // }
//
@SuppressLint("SetTextI18n") // @SuppressLint("SetTextI18n")
override fun initView() { // override fun initView() {
super.initView() // super.initView()
scanType = intent.extras?.getInt("ScanType") ?: 0 // scanType = intent.extras?.getInt("ScanType") ?: 0
//
// LogEx.logDebug(TAG, "scanType=$scanType") //// LogEx.logDebug(TAG, "scanType=$scanType")
when (scanType) { // when (scanType) {
SCAN_PHOTOS -> { // SCAN_PHOTOS -> {
binding.tvTittle.text = "Photo Recovery" // binding.tvTittle.text = "Photo Recovery"
binding.tvFileType.text = "Photos" // binding.tvFileType.text = "Photos"
} // }
//
SCAN_DOCUMENTS -> { // SCAN_DOCUMENTS -> {
binding.tvTittle.text = "Document Recovery" // binding.tvTittle.text = "Document Recovery"
binding.tvFileType.text = "Documents" // binding.tvFileType.text = "Documents"
} // }
//
SCAN_VIDEOS -> { // SCAN_VIDEOS -> {
binding.tvTittle.text = "Video Recovery" // binding.tvTittle.text = "Video Recovery"
binding.tvFileType.text = "Videos" // binding.tvFileType.text = "Videos"
} // }
//
SCAN_AUDIOS -> { // SCAN_AUDIOS -> {
binding.tvTittle.text = "Audio Recovery" // binding.tvTittle.text = "Audio Recovery"
binding.tvFileType.text = "Audios" // binding.tvFileType.text = "Audios"
} // }
} // }
fileFolderAdapter = FileFolderAdapter(scanType) { folderBean -> // fileFolderAdapter = FileFolderAdapter(scanType) { folderBean ->
FileRecoveryActivity.folderBean = null // FileRecoveryActivity.folderBean = null
FileRecoveryActivity.folderBean = folderBean // FileRecoveryActivity.folderBean = folderBean
startActivity(Intent(this, FileRecoveryActivity::class.java).apply { // startActivity(Intent(this, FileRecoveryActivity::class.java).apply {
putExtra("ScanType", scanType) // putExtra("ScanType", scanType)
}) // })
} // }
binding.rv.adapter = fileFolderAdapter // binding.rv.adapter = fileFolderAdapter
//
if (checkStorePermission()) { // if (checkStorePermission()) {
beginScan() // beginScan()
} else { // } else {
showGerPermission( // showGerPermission(
desc = "In order to scan and recover your lost photos, videos, and documents, we need to access your device storage. This permission is essential for our app to locate and restore your files.", // desc = "In order to scan and recover your lost photos, videos, and documents, we need to access your device storage. This permission is essential for our app to locate and restore your files.",
deny = { // deny = {
}, // },
allow = { // allow = {
requestStorePermission(launcher, result = { // requestStorePermission(launcher, result = {
if (it) beginScan() else finishToMainTop() // if (it) beginScan() else finishToMainTop()
}) // })
}) // })
} // }
} // }
//
override fun initListener() { // override fun initListener() {
binding.flFanhui.setOnClickListener { // binding.flFanhui.setOnClickListener {
onBackPressedDispatcher.onBackPressed() // onBackPressedDispatcher.onBackPressed()
} // }
onBackPressedDispatcher.addCallback { // onBackPressedDispatcher.addCallback {
showExitFunctionDialog(this@FileScanResultActivity) { // showExitFunctionDialog(this@FileScanResultActivity) {
if (it) { // if (it) {
AdsMgr.showInsert(this@FileScanResultActivity, showCallBack = object : AdsShowCallBack() { // AdsMgr.showInsert(this@FileScanResultActivity, showCallBack = object : AdsShowCallBack() {
override fun next() { // override fun next() {
finishToMainTop() // finishToMainTop()
} // }
}) // })
} // }
} // }
} // }
} // }
//
fun Context.checkStorePermission(): Boolean { // fun Context.checkStorePermission(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Environment.isExternalStorageManager() // Environment.isExternalStorageManager()
} else { // } else {
val readPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) // val readPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
val writePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) // val writePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
return readPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED; // return readPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED;
} // }
} // }
//
fun CoroutineScope.loadFileByFilter( // fun CoroutineScope.loadFileByFilter(
flow1: MutableSharedFlow<String>? = null, // flow1: MutableSharedFlow<String>? = null,
flow2: MutableSharedFlow<Pair<Int, String>>? = null, // flow2: MutableSharedFlow<Pair<Int, String>>? = null,
folder: File, // folder: File,
filter: (file: File) -> Boolean, // filter: (file: File) -> Boolean,
onDo: ((file: File) -> Unit)? = null, // onDo: ((file: File) -> Unit)? = null,
onFinish: (() -> Unit)? = null // onFinish: (() -> Unit)? = null
) = launch(Dispatchers.IO) { // ) = launch(Dispatchers.IO) {
delay(1000) // delay(1000)
var size = 0 // var size = 0
//
//添加第一层文件到链表 // //添加第一层文件到链表
val linkList = LinkedList<File>() // val linkList = LinkedList<File>()
val fileList = folder.listFiles() // val fileList = folder.listFiles()
fileList?.forEach { // fileList?.forEach {
if (it.isDirectory) { // if (it.isDirectory) {
linkList.add(it) // linkList.add(it)
} else { // } else {
val flag = filter(it) // val flag = filter(it)
if (flag) { // if (flag) {
onDo?.invoke(it) // onDo?.invoke(it)
size++ // size++
flow2?.emit(Pair(size, it.absolutePath)) // flow2?.emit(Pair(size, it.absolutePath))
} // }
flow1?.emit(it.absolutePath) // flow1?.emit(it.absolutePath)
} // }
} // }
//
//链表取文件 // //链表取文件
var tempFile: File // var tempFile: File
while (!linkList.isEmpty()) { // while (!linkList.isEmpty()) {
tempFile = linkList.removeFirst() // tempFile = linkList.removeFirst()
val tempFileList = tempFile.listFiles() // val tempFileList = tempFile.listFiles()
tempFileList?.forEach { // tempFileList?.forEach {
if (it.isDirectory) { // if (it.isDirectory) {
linkList.add(it) // linkList.add(it)
} else { // } else {
val flag = filter(it) // val flag = filter(it)
// LogEx.logDebug(TAG, "$it flag=$flag") //// LogEx.logDebug(TAG, "$it flag=$flag")
if (flag) { // if (flag) {
onDo?.invoke(it) // onDo?.invoke(it)
size++ // size++
flow2?.emit(Pair(size, it.absolutePath)) // flow2?.emit(Pair(size, it.absolutePath))
} // }
flow1?.emit(it.absolutePath) // flow1?.emit(it.absolutePath)
} // }
} // }
} // }
onFinish?.invoke() // onFinish?.invoke()
} // }
//
@SuppressLint("SetTextI18n") // @SuppressLint("SetTextI18n")
private fun beginScan() { // private fun beginScan() {
if (scanOnce) // if (scanOnce)
return // return
//
scanOnce = true // scanOnce = true
//变量路径 // //变量路径
val mPathFlow = MutableSharedFlow<String>( // val mPathFlow = MutableSharedFlow<String>(
replay = 5,//当新的订阅者Collect时,发送几个已经发送过的数据给它 // replay = 5,//当新的订阅者Collect时,发送几个已经发送过的数据给它
extraBufferCapacity = 5,//减去replay,MutableSharedFlow还缓存多少数据,缓冲池容量 = replay + extraBufferCapacity // extraBufferCapacity = 5,//减去replay,MutableSharedFlow还缓存多少数据,缓冲池容量 = replay + extraBufferCapacity
onBufferOverflow = BufferOverflow.DROP_OLDEST//缓存策略,三种 丢掉最新值、丢掉最旧值和挂起 // onBufferOverflow = BufferOverflow.DROP_OLDEST//缓存策略,三种 丢掉最新值、丢掉最旧值和挂起
) // )
val pathFlow: SharedFlow<String> = mPathFlow // val pathFlow: SharedFlow<String> = mPathFlow
//
//符合条件Flow // //符合条件Flow
val mFoundFlow = MutableSharedFlow<Pair<Int, String>>( // val mFoundFlow = MutableSharedFlow<Pair<Int, String>>(
replay = 5, // replay = 5,
extraBufferCapacity = 5, // extraBufferCapacity = 5,
onBufferOverflow = BufferOverflow.SUSPEND // onBufferOverflow = BufferOverflow.SUSPEND
) // )
val foundFlow: SharedFlow<Pair<Int, String>> = mFoundFlow // val foundFlow: SharedFlow<Pair<Int, String>> = mFoundFlow
//
//
val dialogClass = FileScanDialog(this) // val dialogClass = FileScanDialog(this)
val scanDialog = dialogClass.showFileScanDialog(pathFlow, foundFlow) { // val scanDialog = dialogClass.showFileScanDialog(pathFlow, foundFlow) {
//
pathList.add(it) // pathList.add(it)
binding.tvFileNumber.text = pathList.size.toString() // binding.tvFileNumber.text = pathList.size.toString()
setAdapterData(it) // setAdapterData(it)
} // }
//
val filter = when (scanType) { // val filter = when (scanType) {
SCAN_PHOTOS -> FileHexEx::isImage // SCAN_PHOTOS -> FileHexEx::isImage
SCAN_DOCUMENTS -> FileHexEx::isDocument // SCAN_DOCUMENTS -> FileHexEx::isDocument
SCAN_VIDEOS -> FileHexEx::isVideo // SCAN_VIDEOS -> FileHexEx::isVideo
SCAN_AUDIOS -> FileHexEx::isAudio // SCAN_AUDIOS -> FileHexEx::isAudio
else -> FileHexEx::isImage // else -> FileHexEx::isImage
} // }
val root = Environment.getExternalStorageDirectory() // val root = Environment.getExternalStorageDirectory()
lifecycleScope.loadFileByFilter( // lifecycleScope.loadFileByFilter(
mPathFlow, // mPathFlow,
mFoundFlow, // mFoundFlow,
root, filter = filter, // root, filter = filter,
onDo = { file -> // onDo = { file ->
// LogEx.logDebug(TAG, "file =${file.absolutePath}") //// LogEx.logDebug(TAG, "file =${file.absolutePath}")
}, // },
onFinish = { // onFinish = {
lifecycleScope.launch(Dispatchers.Main) { // lifecycleScope.launch(Dispatchers.Main) {
binding.ivWancheng.visibility = View.VISIBLE // binding.ivWancheng.visibility = View.VISIBLE
binding.tvScanning.text = "Completed" // binding.tvScanning.text = "Completed"
lifecycleScope.launchWhenResumed { // lifecycleScope.launchWhenResumed {
AdsMgr.showInsert(this@FileScanResultActivity) // AdsMgr.showInsert(this@FileScanResultActivity)
} // }
binding.flEmpty.isVisible = pathList.isEmpty() // binding.flEmpty.isVisible = pathList.isEmpty()
setAdapterData(null) // setAdapterData(null)
dialogClass.finishScan { // dialogClass.finishScan {
scanDialog.dismiss() // scanDialog.dismiss()
} // }
} // }
} // }
) // )
} // }
//
private val pathList = ArrayList<String>() // private val pathList = ArrayList<String>()
private val hashMap = HashMap<String, ArrayList<RecoveryBean>>() // private val hashMap = HashMap<String, ArrayList<RecoveryBean>>()
private fun setAdapterData(path: String? = null) { // private fun setAdapterData(path: String? = null) {
val flag = path?.let { addMapFolder(it) } ?: true // val flag = path?.let { addMapFolder(it) } ?: true
if (flag) { // if (flag) {
binding.tvFolderNumber.text = hashMap.keys.size.toString() // binding.tvFolderNumber.text = hashMap.keys.size.toString()
val mapList = hashMap.map { // val mapList = hashMap.map {
FolderBean(it.key, recoveryList = it.value) // FolderBean(it.key, recoveryList = it.value)
} // }
fileFolderAdapter.setData(mapList) // fileFolderAdapter.setData(mapList)
} // }
} // }
//
private fun addMapFolder(path: String): Boolean { // private fun addMapFolder(path: String): Boolean {
var isNewFolder = false // var isNewFolder = false
val folder = File(path).parent?.split("/")?.last() ?: "" // val folder = File(path).parent?.split("/")?.last() ?: ""
if (hashMap[folder] == null) { // if (hashMap[folder] == null) {
hashMap[folder] = arrayListOf() // hashMap[folder] = arrayListOf()
isNewFolder = true // isNewFolder = true
} // }
val recoveryBean = RecoveryBean(path) // val recoveryBean = RecoveryBean(path)
if (scanType == SCAN_DOCUMENTS) { // if (scanType == SCAN_DOCUMENTS) {
recoveryBean.setDocumentType() // recoveryBean.setDocumentType()
} // }
if (scanType == SCAN_AUDIOS) { // if (scanType == SCAN_AUDIOS) {
recoveryBean.setAudioType() // recoveryBean.setAudioType()
} // }
hashMap[folder]?.add(recoveryBean) // hashMap[folder]?.add(recoveryBean)
return isNewFolder // return isNewFolder
} // }
//
companion object { // companion object {
const val SCAN_PHOTOS = 1 // const val SCAN_PHOTOS = 1
const val SCAN_DOCUMENTS = 2 // const val SCAN_DOCUMENTS = 2
const val SCAN_VIDEOS = 3 // const val SCAN_VIDEOS = 3
const val SCAN_AUDIOS = 4 // const val SCAN_AUDIOS = 4
} // }
//
@SuppressLint("SetTextI18n") // @SuppressLint("SetTextI18n")
fun Context.showGerPermission( // fun Context.showGerPermission(
tittle: String? = null, // tittle: String? = null,
desc: String? = null, // desc: String? = null,
denyText: String? = null, // denyText: String? = null,
allowText: String? = null, // allowText: String? = null,
deny: ((view: Dialog) -> Unit)? = null, // deny: ((view: Dialog) -> Unit)? = null,
allow: ((view: Dialog) -> Unit)? = null // allow: ((view: Dialog) -> Unit)? = null
): Dialog { // ): Dialog {
val dialog = Dialog(this) // val dialog = Dialog(this)
val binding = DialogPermissonOpenBinding.inflate(LayoutInflater.from(this)) // val binding = DialogPermissonOpenBinding.inflate(LayoutInflater.from(this))
dialog.requestWindowFeature(1) // dialog.requestWindowFeature(1)
dialog.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) // dialog.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog.window!!.setLayout(-1, -1) // dialog.window!!.setLayout(-1, -1)
dialog.setCanceledOnTouchOutside(false) // dialog.setCanceledOnTouchOutside(false)
dialog.setCancelable(false) // dialog.setCancelable(false)
dialog.setContentView(binding.root) // dialog.setContentView(binding.root)
//
tittle?.let { binding.tvTitle.text = it } // tittle?.let { binding.tvTitle.text = it }
desc?.let { binding.tvDesc.text = it } // desc?.let { binding.tvDesc.text = it }
denyText?.let { binding.idDeny.text = it } // denyText?.let { binding.idDeny.text = it }
allowText?.let { binding.idTvAllow.text = it } // allowText?.let { binding.idTvAllow.text = it }
//
binding.idFullLottie.imageAssetsFolder = "recovery_permission_finger/images/" // binding.idFullLottie.imageAssetsFolder = "recovery_permission_finger/images/"
binding.idFullLottie.setAnimation("recovery_permission_finger/data.json") // binding.idFullLottie.setAnimation("recovery_permission_finger/data.json")
binding.idFullLottie.playAnimation() // binding.idFullLottie.playAnimation()
binding.idDeny.setOnClickListener { // binding.idDeny.setOnClickListener {
dialog.dismiss() // dialog.dismiss()
deny?.invoke(dialog) // deny?.invoke(dialog)
} // }
binding.idTvAllow.setOnClickListener { // binding.idTvAllow.setOnClickListener {
dialog.dismiss() // dialog.dismiss()
allow?.invoke(dialog) // allow?.invoke(dialog)
} // }
dialog.show() // dialog.show()
return dialog // return dialog
} // }
//
//
@SuppressLint("UseKtx") // @SuppressLint("UseKtx")
fun Context.requestStorePermission( // fun Context.requestStorePermission(
launcher: ActivityLauncher, // launcher: ActivityLauncher,
jumpAction: (() -> Unit)? = null, // jumpAction: (() -> Unit)? = null,
result: (flag: Boolean) -> Unit // result: (flag: Boolean) -> Unit
) { // ) {
//
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val intent = // val intent =
Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) // Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
intent.addCategory("android.intent.category.DEFAULT") // intent.addCategory("android.intent.category.DEFAULT")
intent.data = "package:${packageName}".toUri() // intent.data = "package:${packageName}".toUri()
jumpAction?.invoke() // jumpAction?.invoke()
launcher.launch(intent) { // launcher.launch(intent) {
result.invoke(checkStorePermission()) // result.invoke(checkStorePermission())
} // }
} else { // } else {
launcher.launch(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { map -> // launcher.launch(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { map ->
result(map.values.all { it }) // result(map.values.all { it })
} // }
} // }
//
} // }
//
fun Context.showExitFunctionDialog( // fun Context.showExitFunctionDialog(
activity: Activity, // activity: Activity,
exitAction: (showAd: Boolean) -> Unit // exitAction: (showAd: Boolean) -> Unit
) { // ) {
//
val dialog = Dialog(this) // val dialog = Dialog(this)
val binding = DialogExitFunctionBinding.inflate(LayoutInflater.from(this)) // val binding = DialogExitFunctionBinding.inflate(LayoutInflater.from(this))
dialog.requestWindowFeature(1) // dialog.requestWindowFeature(1)
dialog.window?.setBackgroundDrawable(Color.TRANSPARENT.toDrawable()) // dialog.window?.setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
dialog.window?.setLayout(-1, -1) // dialog.window?.setLayout(-1, -1)
dialog.setContentView(binding.root) // dialog.setContentView(binding.root)
dialog.show() // dialog.show()
//
// dialog.window?.setBackgroundDrawableResource(android.R.color.transparent) //// dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
// val params = dialog.window?.attributes //// val params = dialog.window?.attributes
// params?.width = resources.getDimensionPixelOffset(R.dimen.dp_345) //// params?.width = resources.getDimensionPixelOffset(R.dimen.dp_345)
// dialog.window?.attributes = params //// dialog.window?.attributes = params
AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom) // AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom)
binding.tvN.setOnClickListener { // binding.tvN.setOnClickListener {
dialog.dismiss() // dialog.dismiss()
exitAction.invoke(true) // exitAction.invoke(true)
} // }
binding.tvY.setOnClickListener { // binding.tvY.setOnClickListener {
dialog.dismiss() // dialog.dismiss()
} // }
} // }
//
//
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.recovery //package com.base.appzxhy.ui.recovery
//
import android.annotation.SuppressLint //import android.annotation.SuppressLint
import android.content.Context //import android.content.Context
import android.view.Gravity //import android.view.Gravity
import android.view.LayoutInflater //import android.view.LayoutInflater
import android.view.View //import android.view.View
import android.view.ViewGroup //import android.view.ViewGroup
import android.widget.ImageView //import android.widget.ImageView
import android.widget.LinearLayout //import android.widget.LinearLayout
import android.widget.TextView //import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager //import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager //import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView //import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder //import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.bean.recovery.FolderBean //import com.base.appzxhy.bean.recovery.FolderBean
import com.base.appzxhy.bean.recovery.RecoveryBean //import com.base.appzxhy.bean.recovery.RecoveryBean
import com.base.appzxhy.databinding.ItemDocumentBinding //import com.base.appzxhy.databinding.ItemDocumentBinding
import com.base.appzxhy.databinding.ItemTimeMediaBinding //import com.base.appzxhy.databinding.ItemTimeMediaBinding
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_AUDIOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_AUDIOS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_DOCUMENTS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_DOCUMENTS
import com.bumptech.glide.Glide //import com.bumptech.glide.Glide
import java.io.File //import java.io.File
import java.text.SimpleDateFormat //import java.text.SimpleDateFormat
import java.util.Locale //import java.util.Locale
//
class FileTimeColumnsAdapter( //class FileTimeColumnsAdapter(
val scanType: Int, // val scanType: Int,
val select: (all: Boolean, size: Int) -> Unit, // val select: (all: Boolean, size: Int) -> Unit,
) : RecyclerView.Adapter<FileTimeColumnsAdapter.MCV>() { //) : RecyclerView.Adapter<FileTimeColumnsAdapter.MCV>() {
//
private val beanList = arrayListOf<FolderBean>() // private val beanList = arrayListOf<FolderBean>()
private var hideThumbnails: Boolean = false // private var hideThumbnails: Boolean = false
private var columns: Int = 2 // private var columns: Int = 2
//
class MCV(view: View) : ViewHolder(view) // class MCV(view: View) : ViewHolder(view)
//
fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View { // fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View {
return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot) // return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot)
} // }
//
fun Context.dpToPx(dps: Int): Int { // fun Context.dpToPx(dps: Int): Int {
return Math.round(resources.displayMetrics.density * dps) // return Math.round(resources.displayMetrics.density * dps)
} // }
//
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MCV { // override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MCV {
return MCV(R.layout.item_time_media.inflate(parent)) // return MCV(R.layout.item_time_media.inflate(parent))
} // }
//
override fun getItemCount(): Int { // override fun getItemCount(): Int {
return beanList.size // return beanList.size
} // }
//
override fun onBindViewHolder(holder: MCV, position: Int) { // override fun onBindViewHolder(holder: MCV, position: Int) {
val binding = ItemTimeMediaBinding.bind(holder.itemView) // val binding = ItemTimeMediaBinding.bind(holder.itemView)
val context = holder.itemView.context // val context = holder.itemView.context
val bean = beanList[position] // val bean = beanList[position]
val file = File(bean.recoveryList.first().path) // val file = File(bean.recoveryList.first().path)
val time = SimpleDateFormat("yyyy-MMM-dd", Locale.getDefault()).format(file.lastModified()) // val time = SimpleDateFormat("yyyy-MMM-dd", Locale.getDefault()).format(file.lastModified())
binding.tvTime.text = time // binding.tvTime.text = time
binding.ivSelector.isSelected = bean.isSelect // binding.ivSelector.isSelected = bean.isSelect
//
//
val subAdapter = MediaColumnsAdapter() // val subAdapter = MediaColumnsAdapter()
//
if (scanType == SCAN_DOCUMENTS || scanType == SCAN_AUDIOS) { // if (scanType == SCAN_DOCUMENTS || scanType == SCAN_AUDIOS) {
binding.rvMediaColumns.layoutManager = LinearLayoutManager(context) // binding.rvMediaColumns.layoutManager = LinearLayoutManager(context)
} else { // } else {
binding.rvMediaColumns.layoutManager = GridLayoutManager(context, columns) // binding.rvMediaColumns.layoutManager = GridLayoutManager(context, columns)
binding.rvMediaColumns.layoutParams = // binding.rvMediaColumns.layoutParams =
LinearLayout.LayoutParams(RecyclerView.LayoutParams.WRAP_CONTENT, RecyclerView.LayoutParams.WRAP_CONTENT).apply { // LinearLayout.LayoutParams(RecyclerView.LayoutParams.WRAP_CONTENT, RecyclerView.LayoutParams.WRAP_CONTENT).apply {
topMargin = context.resources.getDimensionPixelOffset(R.dimen.dp_8) // topMargin = context.resources.getDimensionPixelOffset(R.dimen.dp_8)
gravity = Gravity.CENTER_HORIZONTAL // gravity = Gravity.CENTER_HORIZONTAL
} // }
} // }
binding.rvMediaColumns.adapter = subAdapter // binding.rvMediaColumns.adapter = subAdapter
val list = if (hideThumbnails) bean.recoveryList.filter { !it.isThumbnails } else bean.recoveryList // val list = if (hideThumbnails) bean.recoveryList.filter { !it.isThumbnails } else bean.recoveryList
if (list.isEmpty()) { // if (list.isEmpty()) {
binding.flTittle.visibility = View.GONE // binding.flTittle.visibility = View.GONE
} else { // } else {
binding.flTittle.visibility = View.VISIBLE // binding.flTittle.visibility = View.VISIBLE
subAdapter.setData(list) // subAdapter.setData(list)
} // }
//
binding.ivSelector.setOnClickListener { // binding.ivSelector.setOnClickListener {
bean.isSelect = !bean.isSelect // bean.isSelect = !bean.isSelect
binding.ivSelector.isSelected = bean.isSelect // binding.ivSelector.isSelected = bean.isSelect
notifyItemChanged(position) // notifyItemChanged(position)
itemClick(bean.isSelect, subAdapter) // itemClick(bean.isSelect, subAdapter)
} // }
} // }
//
@SuppressLint("NotifyDataSetChanged") // @SuppressLint("NotifyDataSetChanged")
fun setData(data: List<FolderBean>) { // fun setData(data: List<FolderBean>) {
beanList.clear() // beanList.clear()
beanList.addAll(data) // beanList.addAll(data)
notifyDataSetChanged() // notifyDataSetChanged()
} // }
//
inner class MediaColumnsAdapter : RecyclerView.Adapter<MediaColumnsAdapter.CS>() { // inner class MediaColumnsAdapter : RecyclerView.Adapter<MediaColumnsAdapter.CS>() {
private val list = arrayListOf<RecoveryBean>() // private val list = arrayListOf<RecoveryBean>()
//
inner class CS(view: View) : ViewHolder(view) { // inner class CS(view: View) : ViewHolder(view) {
val iv = view.findViewById<ImageView>(R.id.iv) // val iv = view.findViewById<ImageView>(R.id.iv)
val ivSelector = view.findViewById<ImageView>(R.id.iv_selector) // val ivSelector = view.findViewById<ImageView>(R.id.iv_selector)
val tvSize = view.findViewById<TextView>(R.id.tv_size) // val tvSize = view.findViewById<TextView>(R.id.tv_size)
} // }
//
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CS { // override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CS {
var layout = when (columns) { // var layout = when (columns) {
2 -> R.layout.item_media_columns2 // 2 -> R.layout.item_media_columns2
3 -> R.layout.item_media_columns3 // 3 -> R.layout.item_media_columns3
4 -> R.layout.item_media_columns4 // 4 -> R.layout.item_media_columns4
else -> R.layout.item_media_columns2 // else -> R.layout.item_media_columns2
} // }
if ((scanType == SCAN_DOCUMENTS) || (scanType == SCAN_AUDIOS)) { // if ((scanType == SCAN_DOCUMENTS) || (scanType == SCAN_AUDIOS)) {
layout = R.layout.item_document // layout = R.layout.item_document
} // }
return CS(layout.inflate(parent)) // return CS(layout.inflate(parent))
} // }
//
override fun getItemCount(): Int { // override fun getItemCount(): Int {
return list.size // return list.size
} // }
//
override fun onBindViewHolder(holder: CS, position: Int) { // override fun onBindViewHolder(holder: CS, position: Int) {
} // }
//
override fun onBindViewHolder(holder: CS, position: Int, payloads: MutableList<Any>) { // override fun onBindViewHolder(holder: CS, position: Int, payloads: MutableList<Any>) {
//
val context = holder.itemView.context // val context = holder.itemView.context
val data = list[position] // val data = list[position]
//
if ((scanType == SCAN_DOCUMENTS) or (scanType == SCAN_AUDIOS)) { // if ((scanType == SCAN_DOCUMENTS) or (scanType == SCAN_AUDIOS)) {
if (payloads.isEmpty()) { // if (payloads.isEmpty()) {
val binding = ItemDocumentBinding.bind(holder.itemView) // val binding = ItemDocumentBinding.bind(holder.itemView)
binding.ivSelector.isSelected = data.isSelect // binding.ivSelector.isSelected = data.isSelect
val icon = when (data.type) { // val icon = when (data.type) {
"PDF" -> R.drawable.pdf // "PDF" -> R.drawable.pdf
"DOC" -> R.drawable.doc // "DOC" -> R.drawable.doc
"XLS" -> R.drawable.xls // "XLS" -> R.drawable.xls
"PPT" -> R.drawable.ppt // "PPT" -> R.drawable.ppt
"MP3" -> R.drawable.mp3 // "MP3" -> R.drawable.mp3
"WAV" -> R.drawable.wav // "WAV" -> R.drawable.wav
"FLAC" -> R.drawable.flac // "FLAC" -> R.drawable.flac
else -> 0 // else -> 0
} // }
binding.ivType.setImageResource(icon) // binding.ivType.setImageResource(icon)
val file = File(data.path) // val file = File(data.path)
binding.tvName.text = file.name // binding.tvName.text = file.name
val time = SimpleDateFormat("MMM-dd-yyyy", Locale.getDefault()).format(file.lastModified()) // val time = SimpleDateFormat("MMM-dd-yyyy", Locale.getDefault()).format(file.lastModified())
val size = file.length().toFormatSize() // val size = file.length().toFormatSize()
val info = "$time $size" // val info = "$time $size"
binding.tvInfo.text = info // binding.tvInfo.text = info
binding.root.setOnClickListener { // binding.root.setOnClickListener {
data.isSelect = !data.isSelect // data.isSelect = !data.isSelect
holder.ivSelector.isSelected = data.isSelect // holder.ivSelector.isSelected = data.isSelect
notifyItemChanged(position, "asdada") // notifyItemChanged(position, "asdada")
subItemClick(data) // subItemClick(data)
} // }
} else { // } else {
holder.ivSelector.isSelected = data.isSelect // holder.ivSelector.isSelected = data.isSelect
super.onBindViewHolder(holder, position, payloads) // super.onBindViewHolder(holder, position, payloads)
} // }
//
} else { // } else {
if (payloads.isEmpty()) { // if (payloads.isEmpty()) {
Glide.with(context).asBitmap().load(data.path).centerCrop().into(holder.iv) // Glide.with(context).asBitmap().load(data.path).centerCrop().into(holder.iv)
holder.ivSelector.isSelected = data.isSelect // holder.ivSelector.isSelected = data.isSelect
holder.itemView.setOnClickListener { // holder.itemView.setOnClickListener {
data.isSelect = !data.isSelect // data.isSelect = !data.isSelect
holder.ivSelector.isSelected = data.isSelect // holder.ivSelector.isSelected = data.isSelect
notifyItemChanged(position, "changeIv") // notifyItemChanged(position, "changeIv")
//
subItemClick(data) // subItemClick(data)
} // }
val file = File(data.path) // val file = File(data.path)
holder.tvSize.text = file.length().toFormatSize() // holder.tvSize.text = file.length().toFormatSize()
} else { // } else {
holder.ivSelector.isSelected = data.isSelect // holder.ivSelector.isSelected = data.isSelect
super.onBindViewHolder(holder, position, payloads) // super.onBindViewHolder(holder, position, payloads)
} // }
} // }
//
} // }
//
@SuppressLint("NotifyDataSetChanged") // @SuppressLint("NotifyDataSetChanged")
fun setData(bean: List<RecoveryBean>) { // fun setData(bean: List<RecoveryBean>) {
list.clear() // list.clear()
list.addAll(bean) // list.addAll(bean)
notifyDataSetChanged() // notifyDataSetChanged()
} // }
//
@SuppressLint("NotifyDataSetChanged") // @SuppressLint("NotifyDataSetChanged")
fun toggleSelect(select: Boolean) { // fun toggleSelect(select: Boolean) {
list.forEach { // list.forEach {
it.isSelect = select // it.isSelect = select
} // }
notifyDataSetChanged() // notifyDataSetChanged()
} // }
//
//
} // }
//
@SuppressLint("NotifyDataSetChanged") // @SuppressLint("NotifyDataSetChanged")
fun subItemClick(data: RecoveryBean) { // fun subItemClick(data: RecoveryBean) {
val folderBean = beanList.find { it.recoveryList.contains(data) } // val folderBean = beanList.find { it.recoveryList.contains(data) }
//
folderBean?.let { folder -> // folderBean?.let { folder ->
val select = folder.recoveryList.all { it.isSelect } // val select = folder.recoveryList.all { it.isSelect }
if (folder.isSelect != select) { // if (folder.isSelect != select) {
folder.isSelect = select // folder.isSelect = select
notifyDataSetChanged() // notifyDataSetChanged()
} // }
} // }
val all = beanList.all { it.isSelect } // val all = beanList.all { it.isSelect }
val size = beanList.sumOf { it.recoveryList.filter { bean -> bean.isSelect }.size } // val size = beanList.sumOf { it.recoveryList.filter { bean -> bean.isSelect }.size }
select.invoke(all, size) // select.invoke(all, size)
} // }
//
private fun itemClick(isSelect: Boolean, subAdapter: MediaColumnsAdapter) { // private fun itemClick(isSelect: Boolean, subAdapter: MediaColumnsAdapter) {
subAdapter.toggleSelect(isSelect) // subAdapter.toggleSelect(isSelect)
//
val all = beanList.all { it.isSelect } // val all = beanList.all { it.isSelect }
val size = beanList.sumOf { it.recoveryList.filter { bean -> bean.isSelect }.size } // val size = beanList.sumOf { it.recoveryList.filter { bean -> bean.isSelect }.size }
select.invoke(all, size) // select.invoke(all, size)
} // }
//
@SuppressLint("NotifyDataSetChanged") // @SuppressLint("NotifyDataSetChanged")
fun toggleThumbnails(hideThumbnails: Boolean) { // fun toggleThumbnails(hideThumbnails: Boolean) {
this.hideThumbnails = hideThumbnails // this.hideThumbnails = hideThumbnails
notifyDataSetChanged() // notifyDataSetChanged()
} // }
//
@SuppressLint("NotifyDataSetChanged") // @SuppressLint("NotifyDataSetChanged")
fun toggleAllSelect(selected: Boolean) { // fun toggleAllSelect(selected: Boolean) {
beanList.forEach { // beanList.forEach {
it.isSelect = selected // it.isSelect = selected
it.recoveryList.forEach { bean -> bean.isSelect = selected } // it.recoveryList.forEach { bean -> bean.isSelect = selected }
} // }
notifyDataSetChanged() // notifyDataSetChanged()
val all = beanList.all { it.isSelect } // val all = beanList.all { it.isSelect }
val size = beanList.sumOf { it.recoveryList.filter { bean -> bean.isSelect }.size } // val size = beanList.sumOf { it.recoveryList.filter { bean -> bean.isSelect }.size }
select.invoke(all, size) // select.invoke(all, size)
} // }
//
@SuppressLint("NotifyDataSetChanged") // @SuppressLint("NotifyDataSetChanged")
fun changeColumns(columns: Int) { // fun changeColumns(columns: Int) {
this.columns = columns // this.columns = columns
notifyDataSetChanged() // notifyDataSetChanged()
} // }
//
fun getSelectData(): List<RecoveryBean> { // fun getSelectData(): List<RecoveryBean> {
return beanList.flatMap { it.recoveryList }.filter { it.isSelect } // return beanList.flatMap { it.recoveryList }.filter { it.isSelect }
} // }
//
fun Number.toFormatSize(count: Int = 1): String { // fun Number.toFormatSize(count: Int = 1): String {
var suffix = "B" // var suffix = "B"
var fSize = this.toDouble() // var fSize = this.toDouble()
if (fSize > 1024) { // if (fSize > 1024) {
suffix = "KB" // suffix = "KB"
fSize /= 1024.0 // fSize /= 1024.0
} // }
if (fSize > 1024) { // if (fSize > 1024) {
suffix = "MB" // suffix = "MB"
fSize /= 1024.0 // fSize /= 1024.0
} // }
if (fSize > 1024) { // if (fSize > 1024) {
suffix = "GB" // suffix = "GB"
fSize /= 1024.0 // fSize /= 1024.0
} // }
return String.format("%.${count}f %s", fSize, suffix) // return String.format("%.${count}f %s", fSize, suffix)
} // }
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.recovery //package com.base.appzxhy.ui.recovery
//
import android.annotation.SuppressLint //import android.annotation.SuppressLint
import android.content.Context //import android.content.Context
import android.view.LayoutInflater //import android.view.LayoutInflater
import android.view.View //import android.view.View
import androidx.lifecycle.LifecycleCoroutineScope //import androidx.lifecycle.LifecycleCoroutineScope
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.databinding.DialogRecoveringBinding //import com.base.appzxhy.databinding.DialogRecoveringBinding
import com.google.android.material.bottomsheet.BottomSheetBehavior //import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog //import com.google.android.material.bottomsheet.BottomSheetDialog
import kotlinx.coroutines.Dispatchers //import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel //import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.BufferOverflow //import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.delay //import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow //import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow //import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.collectLatest //import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch //import kotlinx.coroutines.launch
import java.io.File //import java.io.File
import kotlin.random.Random //import kotlin.random.Random
//
object RecoveringDialog { //object RecoveringDialog {
//
@SuppressLint("SetTextI18n") // @SuppressLint("SetTextI18n")
fun Context.showRecoveringDialog( // fun Context.showRecoveringDialog(
lifecycleScope: LifecycleCoroutineScope, // lifecycleScope: LifecycleCoroutineScope,
list: List<String>, // list: List<String>,
dir: File, // dir: File,
copyProgressAction: () -> Unit, // copyProgressAction: () -> Unit,
finish: () -> Unit // finish: () -> Unit
) { // ) {
val dialog = BottomSheetDialog(this, R.style.BottomSheetDialog) // val dialog = BottomSheetDialog(this, R.style.BottomSheetDialog)
val binding = DialogRecoveringBinding.inflate(LayoutInflater.from(this)) // val binding = DialogRecoveringBinding.inflate(LayoutInflater.from(this))
dialog.setContentView(binding.root) // dialog.setContentView(binding.root)
dialog.setCanceledOnTouchOutside(false) // dialog.setCanceledOnTouchOutside(false)
//
val mutableSharedFlow = MutableSharedFlow<Int>( // val mutableSharedFlow = MutableSharedFlow<Int>(
replay = 5,//当新的订阅者Collect时,发送几个已经发送过的数据给它 // replay = 5,//当新的订阅者Collect时,发送几个已经发送过的数据给它
extraBufferCapacity = 5,//减去replay,MutableSharedFlow还缓存多少数据,缓冲池容量 = replay + extraBufferCapacity // extraBufferCapacity = 5,//减去replay,MutableSharedFlow还缓存多少数据,缓冲池容量 = replay + extraBufferCapacity
onBufferOverflow = BufferOverflow.SUSPEND//缓存策略,三种 丢掉最新值、丢掉最旧值和挂起 // onBufferOverflow = BufferOverflow.SUSPEND//缓存策略,三种 丢掉最新值、丢掉最旧值和挂起
) // )
val sharedFlow: SharedFlow<Int> = mutableSharedFlow // val sharedFlow: SharedFlow<Int> = mutableSharedFlow
//
val parentView = binding.root.parent as View // val parentView = binding.root.parent as View
val behavior = BottomSheetBehavior.from(parentView) // val behavior = BottomSheetBehavior.from(parentView)
//展开 // //展开
behavior.state = BottomSheetBehavior.STATE_EXPANDED // behavior.state = BottomSheetBehavior.STATE_EXPANDED
// 设置禁止通过拖动来隐藏 // // 设置禁止通过拖动来隐藏
behavior.isHideable = false // behavior.isHideable = false
//
// 禁止点击外部区域关闭 // // 禁止点击外部区域关闭
dialog.setOnCancelListener { dialogInterface -> // dialog.setOnCancelListener { dialogInterface ->
dialogInterface.cancel() // 这里可以处理点击外部区域的逻辑 // dialogInterface.cancel() // 这里可以处理点击外部区域的逻辑
} // }
//
lifecycleScope.launch(Dispatchers.IO) { // lifecycleScope.launch(Dispatchers.IO) {
//
val arrayList = arrayListOf<String>().apply { // val arrayList = arrayListOf<String>().apply {
addAll(list) // addAll(list)
} // }
var index = 0 // var index = 0
while (arrayList.isNotEmpty()) { // while (arrayList.isNotEmpty()) {
val path = arrayList[0] // val path = arrayList[0]
arrayList.removeAt(0) // arrayList.removeAt(0)
val file = File(path) // val file = File(path)
runCatching { // runCatching {
val recoveryFile = File(dir, file.name) // val recoveryFile = File(dir, file.name)
file.copyTo(recoveryFile, true) // file.copyTo(recoveryFile, true)
} // }
mutableSharedFlow.emit(index) // mutableSharedFlow.emit(index)
delay(Random.nextLong(500, 1500)) // delay(Random.nextLong(500, 1500))
index++ // index++
} // }
mutableSharedFlow.emit(-1) // mutableSharedFlow.emit(-1)
} // }
//
lifecycleScope.launch(Dispatchers.Main) { // lifecycleScope.launch(Dispatchers.Main) {
sharedFlow.collectLatest { // sharedFlow.collectLatest {
// LogEx.logDebug(TAG, "Flow $it") //// LogEx.logDebug(TAG, "Flow $it")
if (it == -1) { // if (it == -1) {
finish.invoke() // finish.invoke()
dialog.dismiss() // dialog.dismiss()
cancel() // cancel()
} else { // } else {
val process = it.toFloat() / list.size.toFloat() // val process = it.toFloat() / list.size.toFloat()
if (process > 0.3) { // if (process > 0.3) {
copyProgressAction.invoke() // copyProgressAction.invoke()
} // }
binding.tvNumber.text = "${it + 1}/${list.size}" // binding.tvNumber.text = "${it + 1}/${list.size}"
} // }
} // }
} // }
//
dialog.show() // dialog.show()
} // }
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.recovery //package com.base.appzxhy.ui.recovery
//
import android.annotation.SuppressLint //import android.annotation.SuppressLint
import android.graphics.Color //import android.graphics.Color
import android.view.LayoutInflater //import android.view.LayoutInflater
import android.view.View //import android.view.View
import android.view.ViewGroup //import android.view.ViewGroup
import androidx.annotation.Dimension //import androidx.annotation.Dimension
import androidx.core.view.isVisible //import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView //import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder //import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.bean.recovery.RecoveryFilterBean //import com.base.appzxhy.bean.recovery.RecoveryFilterBean
import com.base.appzxhy.databinding.ItemRecoveryFilterBinding //import com.base.appzxhy.databinding.ItemRecoveryFilterBinding
import androidx.core.graphics.toColorInt //import androidx.core.graphics.toColorInt
//
class RecoveryFilterAdapter( //class RecoveryFilterAdapter(
val click: (bean: RecoveryFilterBean) -> Unit // val click: (bean: RecoveryFilterBean) -> Unit
) : RecyclerView.Adapter<RecoveryFilterAdapter.YYDS>() { //) : RecyclerView.Adapter<RecoveryFilterAdapter.YYDS>() {
//
private val beanList = arrayListOf<RecoveryFilterBean>() // private val beanList = arrayListOf<RecoveryFilterBean>()
//
inner class YYDS(view: View) : ViewHolder(view) // inner class YYDS(view: View) : ViewHolder(view)
//
fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View { // fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View {
return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot) // return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot)
} // }
//
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): YYDS { // override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): YYDS {
return YYDS(R.layout.item_recovery_filter.inflate(parent)) // return YYDS(R.layout.item_recovery_filter.inflate(parent))
} // }
//
override fun getItemCount(): Int { // override fun getItemCount(): Int {
return beanList.size // return beanList.size
} // }
//
override fun onBindViewHolder(holder: YYDS, position: Int) { // override fun onBindViewHolder(holder: YYDS, position: Int) {
val binding = ItemRecoveryFilterBinding.bind(holder.itemView) // val binding = ItemRecoveryFilterBinding.bind(holder.itemView)
val bean = beanList[position] // val bean = beanList[position]
val context = holder.itemView.context // val context = holder.itemView.context
binding.tv.text = bean.tittle // binding.tv.text = bean.tittle
binding.iv.isVisible = bean.isSelect // binding.iv.isVisible = bean.isSelect
if (bean.isSelect) { // if (bean.isSelect) {
binding.tv.setTextColor(Color.BLACK) // binding.tv.setTextColor(Color.BLACK)
binding.tv.setTextSize(Dimension.SP, 18f) // binding.tv.setTextSize(Dimension.SP, 18f)
} else { // } else {
binding.tv.setTextColor("#747474".toColorInt()) // binding.tv.setTextColor("#747474".toColorInt())
binding.tv.setTextSize(Dimension.SP, 16f) // binding.tv.setTextSize(Dimension.SP, 16f)
} // }
binding.root.setOnClickListener { // binding.root.setOnClickListener {
click.invoke(bean) // click.invoke(bean)
} // }
} // }
//
@SuppressLint("NotifyDataSetChanged") // @SuppressLint("NotifyDataSetChanged")
fun setData(list: List<RecoveryFilterBean>) { // fun setData(list: List<RecoveryFilterBean>) {
beanList.clear() // beanList.clear()
beanList.addAll(list) // beanList.addAll(list)
notifyDataSetChanged() // notifyDataSetChanged()
} // }
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.recyclebin //package com.base.appzxhy.ui.recyclebin
//
import android.content.Context //import android.content.Context
import android.view.ViewGroup //import android.view.ViewGroup
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.databinding.ItemRecoveryBinBinding //import com.base.appzxhy.databinding.ItemRecoveryBinBinding
import com.base.appzxhy.ui.adapter.CommonViewHolder //import com.base.appzxhy.ui.adapter.CommonViewHolder
import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.getImgRes //import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.getImgRes
import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.mImageStr //import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.mImageStr
import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.mVideoStr //import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.mVideoStr
import com.base.appzxhy.utils.KotlinExt.toFormatSize //import com.base.appzxhy.utils.KotlinExt.toFormatSize
import com.base.appzxhy.utils.XmlEx.inflate //import com.base.appzxhy.utils.XmlEx.inflate
import com.bumptech.glide.Glide //import com.bumptech.glide.Glide
import com.chad.library.adapter4.BaseQuickAdapter //import com.chad.library.adapter4.BaseQuickAdapter
import java.io.File //import java.io.File
//
class RecycleBinAdapter : BaseQuickAdapter<File, CommonViewHolder>() { //class RecycleBinAdapter : BaseQuickAdapter<File, CommonViewHolder>() {
//
var clickAction: ((file: File) -> Unit)? = null // var clickAction: ((file: File) -> Unit)? = null
//
override fun onBindViewHolder(holder: CommonViewHolder, position: Int, item: File?) { // override fun onBindViewHolder(holder: CommonViewHolder, position: Int, item: File?) {
item ?: return // item ?: return
val binding = ItemRecoveryBinBinding.bind(holder.itemView) // val binding = ItemRecoveryBinBinding.bind(holder.itemView)
val context = holder.itemView.context // val context = holder.itemView.context
//
if (mImageStr.contains("." + item.extension) || mVideoStr.contains("." + item.extension)) { // if (mImageStr.contains("." + item.extension) || mVideoStr.contains("." + item.extension)) {
Glide.with(context).load(item.absoluteFile).into(binding.icon) // Glide.with(context).load(item.absoluteFile).into(binding.icon)
} else { // } else {
binding.icon.setImageResource(item.getImgRes()) // binding.icon.setImageResource(item.getImgRes())
} // }
binding.tvName.text = item.name // binding.tvName.text = item.name
binding.tvSize.text = item.length().toFormatSize() // binding.tvSize.text = item.length().toFormatSize()
binding.root.setOnClickListener { // binding.root.setOnClickListener {
clickAction?.invoke(item) // clickAction?.invoke(item)
} // }
} // }
//
override fun onCreateViewHolder( // override fun onCreateViewHolder(
context: Context, // context: Context,
parent: ViewGroup, // parent: ViewGroup,
viewType: Int // viewType: Int
): CommonViewHolder { // ): CommonViewHolder {
return CommonViewHolder(R.layout.item_recovery_bin.inflate(parent)) // return CommonViewHolder(R.layout.item_recovery_bin.inflate(parent))
} // }
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.recyclebin //package com.base.appzxhy.ui.recyclebin
//
import android.os.Environment //import android.os.Environment
import android.view.View //import android.view.View
import androidx.lifecycle.lifecycleScope //import androidx.lifecycle.lifecycleScope
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.base.BaseActivity //import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.business.ads.AdsMgr //import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.business.ads.AdsShowCallBack //import com.base.appzxhy.business.ads.AdsShowCallBack
import com.base.appzxhy.databinding.ActivityRecycleBinDetailBinding //import com.base.appzxhy.databinding.ActivityRecycleBinDetailBinding
import com.base.appzxhy.ui.recovery.FileRecoveredActivity //import com.base.appzxhy.ui.recovery.FileRecoveredActivity
import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.getImgRes //import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.getImgRes
import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.getType //import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.getType
import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.mImageStr //import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.mImageStr
import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.mVideoStr //import com.base.appzxhy.ui.recyclebin.RecycleBinUtils.mVideoStr
import com.base.appzxhy.utils.FileUtils.deleteIfExists //import com.base.appzxhy.utils.FileUtils.deleteIfExists
import com.base.appzxhy.utils.KotlinExt.toFormatSize //import com.base.appzxhy.utils.KotlinExt.toFormatSize
import com.base.appzxhy.utils.KotlinExt.toFormatTime //import com.base.appzxhy.utils.KotlinExt.toFormatTime
import com.bumptech.glide.Glide //import com.bumptech.glide.Glide
import kotlinx.coroutines.launch //import kotlinx.coroutines.launch
import java.io.File //import java.io.File
//
class RecycleBinDetailActivity : BaseActivity<ActivityRecycleBinDetailBinding>(ActivityRecycleBinDetailBinding::inflate) { //class RecycleBinDetailActivity : BaseActivity<ActivityRecycleBinDetailBinding>(ActivityRecycleBinDetailBinding::inflate) {
//
companion object { // companion object {
lateinit var recycleBinFile: File // lateinit var recycleBinFile: File
} // }
//
override fun initView() { // override fun initView() {
super.initView() // super.initView()
if (mImageStr.contains("." + recycleBinFile.extension) || mVideoStr.contains("." + recycleBinFile.extension)) { // if (mImageStr.contains("." + recycleBinFile.extension) || mVideoStr.contains("." + recycleBinFile.extension)) {
Glide.with(this).load(recycleBinFile.absoluteFile).placeholder(R.drawable.icon_file).into(binding.iv) // Glide.with(this).load(recycleBinFile.absoluteFile).placeholder(R.drawable.icon_file).into(binding.iv)
} else { // } else {
binding.iv.setImageResource(recycleBinFile.getImgRes()) // binding.iv.setImageResource(recycleBinFile.getImgRes())
} // }
binding.tvPath.text = recycleBinFile.absolutePath // binding.tvPath.text = recycleBinFile.absolutePath
binding.tvSize.text = recycleBinFile.length().toFormatSize() // binding.tvSize.text = recycleBinFile.length().toFormatSize()
binding.tvTime.text = recycleBinFile.lastModified().toFormatTime() // binding.tvTime.text = recycleBinFile.lastModified().toFormatTime()
//
functionInAd { // functionInAd {
binding.v.visibility = View.GONE // binding.v.visibility = View.GONE
} // }
} // }
//
override fun initListener() { // override fun initListener() {
super.initListener() // super.initListener()
//
//
binding.ivBack.setOnClickListener { // binding.ivBack.setOnClickListener {
binding.v.visibility = View.VISIBLE // binding.v.visibility = View.VISIBLE
onBackPressedDispatcher.onBackPressed() // onBackPressedDispatcher.onBackPressed()
finish() // finish()
} // }
binding.ivDelete.setOnClickListener { // binding.ivDelete.setOnClickListener {
lifecycleScope.launch { // lifecycleScope.launch {
recycleBinFile.deleteIfExists() // recycleBinFile.deleteIfExists()
} // }
onBackPressedDispatcher.onBackPressed() // onBackPressedDispatcher.onBackPressed()
finish() // finish()
} // }
binding.tvRestore.setOnClickListener { // binding.tvRestore.setOnClickListener {
lifecycleScope.launch { // lifecycleScope.launch {
restore() // restore()
} // }
AdsMgr.showInsert(this, showCallBack = object : AdsShowCallBack() { // AdsMgr.showInsert(this, showCallBack = object : AdsShowCallBack() {
override fun show() { // override fun show() {
super.show() // super.show()
binding.v.visibility = View.VISIBLE // binding.v.visibility = View.VISIBLE
} // }
//
override fun next() { // override fun next() {
goToAc(FileRecoveredActivity::class.java, exb = { // goToAc(FileRecoveredActivity::class.java, exb = {
putExtra("Number", 1) // putExtra("Number", 1)
putExtra("ScanType", recycleBinFile.getType()) // putExtra("ScanType", recycleBinFile.getType())
}) // })
finish() // finish()
} // }
}) // })
//
} // }
} // }
//
fun restore() { // fun restore() {
val appName = getString(R.string.app_name).replace("/", " ") // val appName = getString(R.string.app_name).replace("/", " ")
val appDir = File(Environment.getExternalStorageDirectory(), appName) // val appDir = File(Environment.getExternalStorageDirectory(), appName)
val dir = File(appDir, "Restore") // val dir = File(appDir, "Restore")
if (!dir.exists()) { // if (!dir.exists()) {
dir.mkdirs() // dir.mkdirs()
} // }
val recoveryFile = File(dir, recycleBinFile.name) // val recoveryFile = File(dir, recycleBinFile.name)
recycleBinFile.copyTo(recoveryFile, true) // recycleBinFile.copyTo(recoveryFile, true)
recycleBinFile.deleteIfExists() // recycleBinFile.deleteIfExists()
//
} // }
//
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.recyclebin //package com.base.appzxhy.ui.recyclebin
//
import androidx.core.view.isVisible //import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope //import androidx.lifecycle.lifecycleScope
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.base.BaseFragment //import com.base.appzxhy.base.BaseFragment
import com.base.appzxhy.base.goToAc //import com.base.appzxhy.base.goToAc
import com.base.appzxhy.business.ads.AdsMgr //import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.databinding.FragmentRecycleBinBinding //import com.base.appzxhy.databinding.FragmentRecycleBinBinding
import com.base.appzxhy.ui.main.MainActivity //import com.base.appzxhy.ui.main.MainActivity
import kotlinx.coroutines.flow.collectLatest //import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch //import kotlinx.coroutines.launch
//
class RecycleBinFragment : BaseFragment<FragmentRecycleBinBinding>(FragmentRecycleBinBinding::inflate) { //class RecycleBinFragment : BaseFragment<FragmentRecycleBinBinding>(FragmentRecycleBinBinding::inflate) {
//
private val adapter = RecycleBinAdapter() // private val adapter = RecycleBinAdapter()
override fun initView() { // override fun initView() {
super.initView() // super.initView()
AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom) // AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom)
binding.rv.adapter = adapter // binding.rv.adapter = adapter
//
lifecycleScope.launch { // lifecycleScope.launch {
(requireActivity() as MainActivity).viewModel.recycleBinFileFlow.collectLatest { // (requireActivity() as MainActivity).viewModel.recycleBinFileFlow.collectLatest {
binding.llEmpty.isVisible = it.isEmpty() // binding.llEmpty.isVisible = it.isEmpty()
adapter.submitList(it) // adapter.submitList(it)
} // }
} // }
} // }
//
override fun initListener() { // override fun initListener() {
super.initListener() // super.initListener()
adapter.clickAction = { // adapter.clickAction = {
RecycleBinDetailActivity.recycleBinFile = it // RecycleBinDetailActivity.recycleBinFile = it
goToAc(RecycleBinDetailActivity::class.java) // goToAc(RecycleBinDetailActivity::class.java)
} // }
} // }
//
} //}
\ No newline at end of file \ No newline at end of file
package com.base.appzxhy.ui.recyclebin //package com.base.appzxhy.ui.recyclebin
//
import com.base.appzxhy.MyApplication //import com.base.appzxhy.MyApplication
import com.base.appzxhy.R //import com.base.appzxhy.R
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_AUDIOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_AUDIOS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_DOCUMENTS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_DOCUMENTS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_PHOTOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_PHOTOS
import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_VIDEOS //import com.base.appzxhy.ui.recovery.FileScanResultActivity.Companion.SCAN_VIDEOS
import java.io.File //import java.io.File
//
object RecycleBinUtils { //object RecycleBinUtils {
//
val mImageStr: Set<String> = HashSet( // val mImageStr: Set<String> = HashSet(
mutableListOf(".jpg", ".jpeg", ".png", ".gif", ".bmp") // mutableListOf(".jpg", ".jpeg", ".png", ".gif", ".bmp")
) // )
val mVideoStr: Set<String> = HashSet( // val mVideoStr: Set<String> = HashSet(
mutableListOf(".mp4", ".avi", ".mov", ".mkv") // mutableListOf(".mp4", ".avi", ".mov", ".mkv")
) // )
val mAudioStr: Set<String> = HashSet( // val mAudioStr: Set<String> = HashSet(
mutableListOf(".mp3", ".flac", ".wav") // mutableListOf(".mp3", ".flac", ".wav")
) // )
//
val mDocumentStr: Set<String> = HashSet(mutableListOf(".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf")) // val mDocumentStr: Set<String> = HashSet(mutableListOf(".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf"))
//
fun File.getType(): Int { // fun File.getType(): Int {
if (mImageStr.contains("." + extension)) { // if (mImageStr.contains("." + extension)) {
return SCAN_PHOTOS // return SCAN_PHOTOS
} // }
if (mVideoStr.contains("." + extension)) { // if (mVideoStr.contains("." + extension)) {
return SCAN_VIDEOS // return SCAN_VIDEOS
} // }
if (mAudioStr.contains("." + extension)) { // if (mAudioStr.contains("." + extension)) {
return SCAN_AUDIOS // return SCAN_AUDIOS
} // }
if (mDocumentStr.contains("." + extension)) { // if (mDocumentStr.contains("." + extension)) {
return SCAN_DOCUMENTS // return SCAN_DOCUMENTS
} // }
//
return -1 // return -1
} // }
//
fun File.getImgRes(): Int { // fun File.getImgRes(): Int {
return when (extension) { // return when (extension) {
"mp3" -> R.drawable.mp3 // "mp3" -> R.drawable.mp3
"flac" -> R.drawable.flac // "flac" -> R.drawable.flac
"doc", "docx" -> R.drawable.doc // "doc", "docx" -> R.drawable.doc
"xls", "xlsx" -> R.drawable.xls // "xls", "xlsx" -> R.drawable.xls
"ppt", "pptx" -> R.drawable.ppt // "ppt", "pptx" -> R.drawable.ppt
else -> R.drawable.icon_file // else -> R.drawable.icon_file
} // }
} // }
//
fun getRecycleBinData(): List<File> { // fun getRecycleBinData(): List<File> {
val recycleBinDir = File(MyApplication.Companion.appContext.filesDir, "recycleBin") // val recycleBinDir = File(MyApplication.Companion.appContext.filesDir, "recycleBin")
if (recycleBinDir.exists()) { // if (recycleBinDir.exists()) {
return recycleBinDir.listFiles()?.toList() ?: listOf() // return recycleBinDir.listFiles()?.toList() ?: listOf()
} else { // } else {
return listOf() // return listOf()
} // }
} // }
//
fun addRecycleBinFile(file: File) { // fun addRecycleBinFile(file: File) {
val recycleBinDir = File(MyApplication.Companion.appContext.filesDir, "recycleBin") // val recycleBinDir = File(MyApplication.Companion.appContext.filesDir, "recycleBin")
if (!recycleBinDir.exists()) { // if (!recycleBinDir.exists()) {
recycleBinDir.mkdirs() // recycleBinDir.mkdirs()
} // }
//
val recycleBinFile = File(recycleBinDir, file.name) // val recycleBinFile = File(recycleBinDir, file.name)
//
file.copyTo(recycleBinFile, true) // file.copyTo(recycleBinFile, true)
} // }
//
//
} //}
\ No newline at end of file \ No newline at end of file
...@@ -28,8 +28,6 @@ import com.base.appzxhy.databinding.ItemSimilarPhotosBinding ...@@ -28,8 +28,6 @@ import com.base.appzxhy.databinding.ItemSimilarPhotosBinding
import com.base.appzxhy.databinding.ItemSimilarPhotosChildBinding import com.base.appzxhy.databinding.ItemSimilarPhotosChildBinding
import com.base.appzxhy.ui.cleanresult.CleanResultActivity import com.base.appzxhy.ui.cleanresult.CleanResultActivity
import com.base.appzxhy.ui.dialog.ConfirmDialog import com.base.appzxhy.ui.dialog.ConfirmDialog
import com.base.appzxhy.ui.recyclebin.RecycleBinUtils
import com.base.appzxhy.ui.similar.SimilarPhotosActivity
import com.base.appzxhy.utils.FileUtils import com.base.appzxhy.utils.FileUtils
import com.base.appzxhy.utils.MediaUtils import com.base.appzxhy.utils.MediaUtils
import com.base.appzxhy.utils.Utils import com.base.appzxhy.utils.Utils
...@@ -293,7 +291,6 @@ class SimilarPhotosActivity : BaseActivity<ActivitySimilarPhotosBinding>(Activit ...@@ -293,7 +291,6 @@ class SimilarPhotosActivity : BaseActivity<ActivitySimilarPhotosBinding>(Activit
paths.forEach { paths.forEach {
val file = File(it) val file = File(it)
cleanedSize = cleanedSize + file.length() cleanedSize = cleanedSize + file.length()
RecycleBinUtils.addRecycleBinFile(file)
FileUtils.deleteFile(it) FileUtils.deleteFile(it)
} }
launch(Dispatchers.Main) { MediaUtils.updateMedia(applicationContext, paths) } launch(Dispatchers.Main) { MediaUtils.updateMedia(applicationContext, paths) }
......
...@@ -39,11 +39,9 @@ import com.base.appzxhy.ui.guide.GuideCleanActivity ...@@ -39,11 +39,9 @@ import com.base.appzxhy.ui.guide.GuideCleanActivity
import com.base.appzxhy.ui.main.MainActivity import com.base.appzxhy.ui.main.MainActivity
import com.base.appzxhy.utils.PermissionUtils.checkStorePermission import com.base.appzxhy.utils.PermissionUtils.checkStorePermission
import com.base.appzxhy.utils.PermissionUtils.requestStoragePermission import com.base.appzxhy.utils.PermissionUtils.requestStoragePermission
import com.base.appzxhy.utils.ToastUtils.toast
import com.base.appzxhy.utils.UmpUtils import com.base.appzxhy.utils.UmpUtils
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient <gradient
android:endColor="#328EF6" android:endColor="@color/colorPrimary"
android:startColor="#328EF6" /> android:startColor="@color/colorPrimary" />
<corners android:radius="@dimen/dp_10" /> <corners android:radius="@dimen/dp_10" />
</shape> </shape>
\ No newline at end of file
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.language.LanguageActivity">
<FrameLayout
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
...@@ -5,49 +5,16 @@ ...@@ -5,49 +5,16 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<FrameLayout <fragment
android:id="@+id/fl_container" android:id="@+id/fragment"
android:name="com.base.appzxhy.ui.main.HomeFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/flBottom"
app:layout_constraintTop_toTopOf="parent">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:scrollbars="none" />
</FrameLayout>
<FrameLayout
android:id="@+id/flBottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dp_60" android:layout_marginBottom="@dimen/dp_60"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/fl_container"> app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@color/white"
app:tabIndicatorHeight="0dp"
app:tabMinWidth="100dp"
app:tabMode="fixed"
app:tabRippleColor="@android:color/transparent"
tools:ignore="SpeakableTextPresentCheck" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="bottom"
android:background="#F5F5F5" />
</FrameLayout> </fragment>
<FrameLayout <FrameLayout
android:id="@+id/flBanner" android:id="@+id/flBanner"
......
...@@ -6,86 +6,6 @@ ...@@ -6,86 +6,6 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/white"> android:background="@color/white">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:paddingVertical="15dp"
android:text="@string/file_recovery"
android:textColor="#000000"
android:textSize="19sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivVips"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="8dp"
android:src="@drawable/h_vip_s"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/tv_app_name"
app:layout_constraintStart_toEndOf="@id/tv_app_name"
app:layout_constraintTop_toTopOf="@id/tv_app_name" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivVip"
android:layout_width="@dimen/dp_30"
android:layout_height="@dimen/dp_30"
android:layout_marginEnd="14dp"
android:src="@drawable/h_vip"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/tv_app_name"
app:layout_constraintEnd_toStartOf="@id/ll_weather"
app:layout_constraintTop_toTopOf="@id/tv_app_name" />
<LinearLayout
android:id="@+id/ll_weather"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_marginEnd="20dp"
android:background="@drawable/bg_f3f5f7_61"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="@id/tv_app_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_app_name">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:layout_marginEnd="2dp"
android:includeFontPadding="false"
android:text="20"
android:textColor="#000000"
android:textSize="14sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="4dp"
android:includeFontPadding="false"
android:text="℃"
android:textColor="#000000"
android:textSize="14sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<ImageView
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="9dp"
android:src="@drawable/tianqi"
tools:ignore="ContentDescription" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv" android:id="@+id/rv"
...@@ -94,7 +14,6 @@ ...@@ -94,7 +14,6 @@
android:overScrollMode="never" android:overScrollMode="never"
android:paddingHorizontal="8dp" android:paddingHorizontal="8dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent" />
app:layout_constraintTop_toBottomOf="@+id/tv_app_name" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.Home3Fragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
\ No newline at end of file
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<color name="black">#FF000000</color> <color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color> <color name="white">#FFFFFFFF</color>
<color name="transparent">#00000000</color> <color name="transparent">#00000000</color>
<color name="colorPrimary">#328EF6</color> <color name="colorPrimary">#2DD29E</color>
<color name="colorDisEnable">#FF7DB9FF</color> <color name="colorDisEnable">#FF7DB9FF</color>
<color name="color_66000000">#66000000</color> <color name="color_66000000">#66000000</color>
......
<resources> <resources>
<string name="app_name">Dumpster Cleaner</string> <string name="app_name">Master Malware Clean</string>
<string name="hello_blank_fragment">Hello blank fragment</string> <string name="hello_blank_fragment">Hello blank fragment</string>
<string name="facebook_app_id">4512448902756291</string> <string name="facebook_app_id">4512448902756291</string>
......
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