Commit d00f1ecb authored by wanglei's avatar wanglei

...

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