Commit f32cb609 authored by wanglei's avatar wanglei

[新功能]app卸载

parent 76413497
......@@ -40,9 +40,7 @@
android:supportsRtl="true"
android:theme="@style/Theme.AppTheme"
tools:targetApi="31">
<activity
android:name=".ui.appuninstall.AppUninstallActivity"
android:exported="false" />
<activity
android:name=".ui.splash.SplashActivity"
android:exported="true"
......@@ -127,6 +125,11 @@
android:exported="false"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.appuninstall.AppUninstallActivity"
android:exported="false"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<provider
android:name="androidx.core.content.FileProvider"
......
......@@ -3,11 +3,9 @@ package com.base.appzxhy.bean
import android.graphics.drawable.Drawable
data class AppInfoBean(
val packageName: String,
val appName: String,
val icon: Drawable,
val packageName: String,
var isSelected: Boolean = false,
val isInstall:Boolean?=null,
val score:Int?=null,
val apkPath:String?=null
val installTime: Long,
val storageSize: Long
)
......@@ -21,6 +21,7 @@ class FeatureBean(
const val PHOTO_COMPRESSION = "photo_compression"
const val SIMILAR_PHOTOS = "similar_photos"
const val VIDEO_CLEAN = "video_clean"
const val UNINSTALL_APP = "uninstall_app"
const val RECOVERY_PHOTOS = "recovery_photos"
const val RECOVERY_VIDEOS = "recovery_videos"
......
package com.base.appzxhy.ui.appuninstall
import android.annotation.SuppressLint
import android.content.Context
import android.view.ViewGroup
import com.base.appzxhy.R
import com.base.appzxhy.bean.AppInfoBean
import com.base.appzxhy.databinding.ItemAppUninstallBinding
import com.base.appzxhy.ui.adapter.CommonViewHolder
import com.base.appzxhy.utils.KotlinExt.toFormatSize
import com.base.appzxhy.utils.KotlinExt.toFormatTime4
import com.base.appzxhy.utils.XmlEx.inflate
import com.chad.library.adapter4.BaseQuickAdapter
class AppAdapter : BaseQuickAdapter<AppInfoBean, CommonViewHolder>() {
var uninstallAction: ((item: AppInfoBean) -> Unit)? = null
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(
holder: CommonViewHolder,
position: Int,
item: AppInfoBean?
) {
item ?: return
val binding = ItemAppUninstallBinding.bind(holder.itemView)
binding.ivIcon.setImageDrawable(item.icon)
binding.tvName.text = item.appName
binding.tvInfo.text = "${item.storageSize.toFormatSize()} ${item.installTime.toFormatTime4()}"
binding.tvBtn.setOnClickListener {
uninstallAction?.invoke(item)
}
}
override fun onCreateViewHolder(
context: Context,
parent: ViewGroup,
viewType: Int
): CommonViewHolder {
return CommonViewHolder(R.layout.item_app_uninstall.inflate(parent))
}
}
\ No newline at end of file
package com.base.appzxhy.ui.appuninstall
import android.annotation.SuppressLint
import android.app.ActivityManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.os.StatFs
import com.base.appzxhy.bean.AppInfoBean
import com.base.appzxhy.utils.LogEx
import java.io.File
object AppInfoUtils {
private val TAG = "AppInfoUtils"
@SuppressLint("QueryPermissionsNeeded")
fun getAppInfo(context: Context): ArrayList<AppInfoBean> {
val packageManager: PackageManager = context.packageManager
val apps = packageManager.getInstalledApplications(PackageManager.GET_META_DATA)
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val memoryInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memoryInfo)
val list = arrayListOf<AppInfoBean>()
for (app in apps) {
// 过滤掉系统应用和自身应用
if ((app.flags and ApplicationInfo.FLAG_SYSTEM) == 0 && app.packageName != context.packageName) {
try {
val packageName = app.packageName
//app名称
val appName = packageManager.getApplicationLabel(app).toString()
// 获取app图标
val appIcon = packageManager.getApplicationIcon(app)
// 获取安装时间
val installTime = packageManager.getPackageInfo(packageName, 0).firstInstallTime
// 获取储存大小
val storageSize = getStorageSize(context, packageName)
list.add(AppInfoBean(packageName, appName, appIcon, installTime, storageSize))
LogEx.logDebug(TAG, "appName=$appName appIcon=$appIcon installTime=$installTime storageSize=$storageSize")
} catch (e: Exception) {
e.printStackTrace()
}
}
}
return list
}
private fun getStorageSize(context: Context, packageName: String): Long {
val pm = context.packageManager
val appInfo = pm.getApplicationInfo(packageName, 0)
val appDir = File(appInfo.dataDir) // 获取应用的数据目录
val apkFile = File(appInfo.sourceDir) // 获取APK文件路径
val appDirSize = getDirectorySize(appDir)
val apkFileSize = apkFile.length()
return appDirSize + apkFileSize
}
private fun getDirectorySize(directory: File): Long {
var totalSize = 0L
val files = directory.listFiles() ?: return 0L
for (file in files) {
if (file.isDirectory) {
totalSize += getDirectorySize(file)
} else {
totalSize += file.length()
}
}
return totalSize
}
}
\ No newline at end of file
package com.base.appzxhy.ui.appuninstall
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import androidx.activity.viewModels
import androidx.core.net.toUri
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.base.appzxhy.R
import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.base.LottieEnum
import com.base.appzxhy.bean.FeatureBean.Companion.UNINSTALL_APP
import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.business.ads.AdsShowCallBack
import com.base.appzxhy.databinding.ActivityAppUninstallBinding
import com.base.appzxhy.ui.cleanresult.CleanResultActivity
import com.base.appzxhy.utils.ToastUtils.toast
class AppUninstallActivity : BaseActivity<ActivityAppUninstallBinding>(ActivityAppUninstallBinding::inflate) {
private val viewModel: AppUninstallViewModel by viewModels()
private val adapter = AppAdapter()
override fun initView() {
super.initView()
binding.rv.adapter = adapter
showAdAnimation(LottieEnum.SCREENSHOT_LOTTIE) {
}
AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom)
}
override fun initListener() {
super.initListener()
binding.ivBack.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
binding.tvOk.setOnClickListener {
CleanResultActivity.functionKey = UNINSTALL_APP
CleanResultActivity.titleName = this.getString(R.string.app_uninstall)
goToAc(CleanResultActivity::class.java)
finish()
}
binding.llSize.setOnClickListener {
binding.ivInstallTime.setImageResource(R.drawable.icon_paixu_normal)
when (viewModel.sortMode) {
0 -> {
viewModel.sortMode = 1
binding.ivSize.setImageResource(R.drawable.icon_paixu_up)
}
else -> {
viewModel.sortMode = 0
binding.ivSize.setImageResource(R.drawable.icon_paixu_down)
}
}
viewModel.changeSort {
adapter.submitList(viewModel.appList)
}
}
binding.llInstallTime.setOnClickListener {
binding.ivSize.setImageResource(R.drawable.icon_paixu_normal)
when (viewModel.sortMode) {
2 -> {
viewModel.sortMode = 3
binding.ivInstallTime.setImageResource(R.drawable.icon_paixu_up)
}
else -> {
viewModel.sortMode = 2
binding.ivInstallTime.setImageResource(R.drawable.icon_paixu_down)
}
}
viewModel.changeSort {
adapter.submitList(viewModel.appList)
}
}
adapter.uninstallAction = { bean ->
val uninstall = {
try {
val deleteIntent = Intent(Intent.ACTION_DELETE).apply {
data = "package:${bean.packageName}".toUri()
}
launcher.launch(deleteIntent) {
if (!isAppInstalled(this, bean.packageName)) {
toast("uninstall success", true)
viewModel.appList.removeIf { it.packageName == bean.packageName }
viewModel.changeSort {
adapter.submitList(viewModel.appList)
}
}
}
} catch (e: Exception) {
toast("uninstall error", true)
}
}
AdsMgr.showInsert(this, showCallBack = object : AdsShowCallBack() {
override fun next() {
uninstall.invoke()
}
})
}
viewModel.initData(this) {
binding.llSize.callOnClick()
}
}
override fun useDefaultImmersive() {
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, 0, systemBars.right, systemBars.bottom)
binding.flTop.setPadding(0, systemBars.top, 0, 0)
insets
}
}
fun isAppInstalled(context: Context, packageName: String): Boolean {
val packageManager = context.packageManager
return try {
// 尝试获取应用信息
packageManager.getPackageInfo(packageName, PackageManager.GET_META_DATA)
true // 如果没有抛出异常,说明应用已安装
} catch (e: PackageManager.NameNotFoundException) {
false // 如果抛出异常,说明应用未安装
}
}
}
\ No newline at end of file
package com.base.appzxhy.ui.appuninstall
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.base.appzxhy.bean.AppInfoBean
import com.base.appzxhy.ui.appuninstall.AppInfoUtils.getAppInfo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class AppUninstallViewModel : ViewModel() {
val appList = arrayListOf<AppInfoBean>()
fun initData(context: Context, callBack: () -> Unit) = viewModelScope.launch(Dispatchers.IO) {
val list = getAppInfo(context)
appList.addAll(list)
launch(Dispatchers.Main) {
callBack.invoke()
}
}
var sortMode = -1
//下从大到小,下从新-旧
private fun sortList() {
when (this.sortMode) {
0 -> {
appList.sortByDescending { it.storageSize }
}
1 -> {
appList.sortBy { it.storageSize }
}
2 -> {
appList.sortByDescending { it.installTime }
}
3 -> {
appList.sortBy { it.installTime }
}
}
}
fun changeSort(callBack: () -> Unit) = viewModelScope.launch(Dispatchers.IO) {
sortList()
launch(Dispatchers.Main) {
callBack.invoke()
}
}
}
\ No newline at end of file
......@@ -15,13 +15,13 @@ import com.base.appzxhy.R
import com.base.appzxhy.base.BaseActivity
import com.base.appzxhy.base.jumpAction
import com.base.appzxhy.bean.FeatureBean
import com.base.appzxhy.bean.FeatureBean.Companion.ANTIVIRUS
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.bean.FeatureBean.Companion.UNINSTALL_APP
import com.base.appzxhy.business.ads.AdsMgr
import com.base.appzxhy.business.ads.AdsShowCallBack
import com.base.appzxhy.databinding.ActivityCleanResultBinding
......@@ -96,10 +96,10 @@ class CleanResultActivity : BaseActivity<ActivityCleanResultBinding>(ActivityCle
binding.tvCleanedUp.text = "${getString(R.string.cleaned_up)} ${Utils.getSizeFormat(total)}"
total = 0L
}
if (functionKey == ANTIVIRUS) {
if (functionKey == UNINSTALL_APP) {
binding.tvCleanedUp.updatePadding(bottom = resources.getDimensionPixelSize(R.dimen.dp_20))
binding.tvTip.visibility = View.GONE
binding.tvCleanedUp.text = getString(R.string.no_threats_found)
// binding.tvCleanedUp.text = getString(R.string.no_threats_found)
}
list = getData()
......
......@@ -12,9 +12,9 @@ import androidx.recyclerview.widget.GridLayoutManager
import com.airbnb.lottie.LottieDrawable
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
import com.base.appzxhy.bean.FeatureBean.Companion.ANTIVIRUS
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
......@@ -24,6 +24,7 @@ import com.base.appzxhy.bean.FeatureBean.Companion.SETTINGS
import com.base.appzxhy.bean.FeatureBean.Companion.SIMILAR_PHOTOS
import com.base.appzxhy.bean.FeatureBean.Companion.VIDEO_CLEAN
import com.base.appzxhy.databinding.FragmentHome3Binding
import com.base.appzxhy.ui.appuninstall.AppUninstallActivity
import com.base.appzxhy.ui.dialog.permissionStorageJump
import com.base.appzxhy.ui.set.SettingActivity
import com.base.appzxhy.utils.BarUtils
......@@ -108,7 +109,7 @@ class HomeFragment : BaseFragment<FragmentHome3Binding>(FragmentHome3Binding::in
binding.lottie.setMinFrame(0)
binding.lottie.setMaxFrame(55)
binding.lottie.speed = 1f
binding.lottie.speed = 0.75f
binding.lottie.setRepeatCount(LottieDrawable.INFINITE) // 设置无限循环播放
binding.lottie.setRepeatMode(LottieDrawable.REVERSE) // 设置每次播放结束后重新开始
binding.lottie.playAnimation() // 开始播放动画
......@@ -123,24 +124,32 @@ class HomeFragment : BaseFragment<FragmentHome3Binding>(FragmentHome3Binding::in
}
adapter.itemClick = {
when (it.key) {
JUNK_CLEAN,
SCREENSHOT_CLEAN,
LARGE_FILE_CLEAN,
PHOTO_COMPRESSION, SIMILAR_PHOTOS -> {
(requireActivity() as MainActivity).permissionStorageJump(it.key)
}
BATTERY_INFO -> {
(requireActivity() as MainActivity).jumpAction(it.key)
}
if (it.key == VIDEO_CLEAN) {
goToAc(AppUninstallActivity::class.java)
} else {
when (it.key) {
JUNK_CLEAN,
SCREENSHOT_CLEAN,
LARGE_FILE_CLEAN,
PHOTO_COMPRESSION, SIMILAR_PHOTOS -> {
(requireActivity() as MainActivity).permissionStorageJump(it.key)
}
SETTINGS -> {
(requireActivity() as MainActivity).goToAc(SettingActivity::class.java)
}
BATTERY_INFO -> {
(requireActivity() as MainActivity).jumpAction(it.key)
}
SETTINGS -> {
(requireActivity() as MainActivity).goToAc(SettingActivity::class.java)
}
}
}
}
}
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners android:radius="@dimen/dp_12" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners android:radius="@dimen/dp_4" />
</shape>
\ No newline at end of file
......@@ -5,6 +5,153 @@
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F5F6F7"
tools:context=".ui.appuninstall.AppUninstallActivity">
<FrameLayout
android:id="@+id/flTop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="@dimen/dp_8"
android:layout_marginStart="@dimen/dp_8"
android:padding="@dimen/dp_8"
app:srcCompat="@drawable/icon_back" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/dp_60"
android:text="@string/app_uninstall"
android:textColor="#1A1A1A"
android:textSize="@dimen/sp_20"
android:textStyle="bold" />
</FrameLayout>
<LinearLayout
android:id="@+id/llSort"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_16"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@id/flTop">
<LinearLayout
android:id="@+id/llSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:background="@drawable/bg_ffffff_4"
android:foreground="?attr/selectableItemBackground"
android:gravity="center"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/dp_20"
android:paddingVertical="@dimen/dp_5">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/size"
android:textColor="#1A1A1A"
android:textSize="@dimen/sp_16" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivSize"
android:layout_width="@dimen/dp_15"
android:layout_height="@dimen/dp_15"
android:layout_marginStart="@dimen/dp_4"
app:srcCompat="@drawable/icon_paixu_normal" />
</LinearLayout>
<LinearLayout
android:id="@+id/llInstallTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:background="@drawable/bg_ffffff_4"
android:foreground="?attr/selectableItemBackground"
android:gravity="center"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/dp_20"
android:paddingVertical="@dimen/dp_5">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/install_time"
android:textColor="#1A1A1A"
android:textSize="@dimen/sp_16" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivInstallTime"
android:layout_width="@dimen/dp_15"
android:layout_height="@dimen/dp_15"
android:layout_marginStart="@dimen/dp_4"
app:srcCompat="@drawable/icon_paixu_normal" />
</LinearLayout>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingTop="@dimen/dp_8"
android:paddingBottom="@dimen/dp_88"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@id/flAd"
app:layout_constraintTop_toBottomOf="@id/llSort" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F5F6F7"
app:layout_constraintBottom_toBottomOf="@id/rv">
<TextView
android:id="@+id/tvOk"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_54"
android:layout_gravity="center"
android:layout_marginHorizontal="@dimen/dp_28"
android:layout_marginTop="@dimen/dp_10"
android:layout_marginBottom="@dimen/dp_16"
android:background="@drawable/bg_btn_50"
android:foreground="?attr/selectableItemBackground"
android:gravity="center"
android:text="@string/ok"
android:textColor="@color/white"
android:textSize="@dimen/sp_20" />
</FrameLayout>
<com.base.appzxhy.business.ads.NativeParentView
android:id="@+id/flAd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/zhanwei1"
tools:ignore="ImageContrastCheck" />
</com.base.appzxhy.business.ads.NativeParentView>
<include
android:id="@+id/layout_animation"
layout="@layout/layout_animation"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -24,7 +24,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.45"
app:lottie_fileName="clean_home.json" />
app:lottie_fileName="qiling_dongxiao.json" />
<FrameLayout
android:id="@+id/flTop"
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_66"
android:layout_marginHorizontal="@dimen/dp_16"
android:layout_marginVertical="@dimen/dp_6"
android:background="@drawable/bg_ffffff_12"
android:gravity="center_vertical"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ivIcon"
android:layout_width="@dimen/dp_42"
android:layout_height="@dimen/dp_42"
android:layout_marginStart="@dimen/dp_20" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/dp_15"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/tvName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#1A1A1A"
android:textSize="@dimen/sp_16"
tools:text="@string/app_name" />
<TextView
android:id="@+id/tvInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_8"
android:singleLine="true"
android:textColor="#999999"
android:textSize="@dimen/sp_12"
tools:text="26.30 MB 2008-12-31" />
</LinearLayout>
<TextView
android:id="@+id/tvBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_20"
android:background="@drawable/bg_btn_50"
android:foreground="?attr/selectableItemBackground"
android:paddingHorizontal="@dimen/dp_12"
android:paddingVertical="@dimen/dp_8"
android:text="@string/uninstall"
android:textColor="@color/white"
android:textSize="@dimen/sp_14" />
</LinearLayout>
\ No newline at end of file
......@@ -237,6 +237,10 @@ Please rest assured that we will handle your information in strict accordance wi
<string name="thank_you_very_much">Thank you very much for taking the time to rate us.</string>
<string name="view">View</string>
<string name="content_not_found">Content not found</string>
<string name="app_uninstall">App Uninstall</string>
<string name="ok">OK</string>
<string name="size">Size</string>
<string name="install_time">Install Time</string>
</resources>
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