Skip to content

Commit

Permalink
步入第一个alphaRelease阶段
Browse files Browse the repository at this point in the history
  • Loading branch information
ElisaMin committed Feb 11, 2021
1 parent 13d929e commit 9a20b2d
Show file tree
Hide file tree
Showing 16 changed files with 184 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import me.heizi.box.package_manager.utils.dialog
class StopForegroundService : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent) {
Log.i(TAG, "onReceive: got it")
try {
CleaningAndroidService.intent(context).let {
context.stopService(it)
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/me/heizi/box/package_manager/dao/DB.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ abstract class DB: RoomDatabase() {

fun CoroutineScope.updateDB(
dispatcher: CoroutineDispatcher = IO,
block:suspend DB.()->Unit
block: DB.()->Unit
) = launch(dispatcher) { block(INSTANCE) }
}
abstract fun getDefaultMapper():DBMapper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ interface UninstallInfo{
val packageName:String
val sourceDirectory:String
val dataDirectory:String?

data class DefaultUninstallInfo(
override val applicationName:String,
override val packageName:String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class CleaningAndroidService : Service() {
* 显示停止按钮和帮助文字提示正在耗电和点击后的后果。
*/
private suspend fun notifyDone() = coroutineScope { launch(Main) {
val pIntent = PendingIntent.getBroadcast(this@CleaningAndroidService,0, Intent(this@CleaningAndroidService,StopForegroundService::class.java),0)
val pIntent = PendingIntent.getBroadcast(this@CleaningAndroidService,0, Intent(this@CleaningAndroidService,StopForegroundService::class.java),PendingIntent.FLAG_IMMUTABLE)
val n = NotificationCompat.Builder(this@CleaningAndroidService, DONE_NOTIFY_CHANNEL_ID)
.setContentTitle("卸载完成")
.setContentText("关闭前台服务时可能通知会随之消失,请根据耗电情况自行关闭本服务。")
Expand All @@ -118,10 +118,22 @@ class CleaningAndroidService : Service() {
.build()
notificationManager.notify(DONE_NOTIFY_ID,n)
} }

/**
* 通知开始
*
*/
private suspend fun notifyStart() = coroutineScope { launch(Main) {
val n = NotificationCompat.Builder(this@CleaningAndroidService, DONE_NOTIFY_CHANNEL_ID)
.setContentTitle("卸载开始")
.setSmallIcon(R.drawable.ic_outline_done_24)
.build()
notificationManager.notify(DONE_NOTIFY_ID,n)
} }
private fun buildChannel() {
NotificationChannel(PROCESS_NOTIFY_CHANNEL_ID,"正在卸载",NotificationManager.IMPORTANCE_MIN).let(notificationManager::createNotificationChannel)
NotificationChannel(FAILED_NOTIFY_CHANNEL_ID,"卸载失败",NotificationManager.IMPORTANCE_DEFAULT).let(notificationManager::createNotificationChannel)
NotificationChannel(DONE_NOTIFY_CHANNEL_ID,"卸载完成",NotificationManager.IMPORTANCE_HIGH).let(notificationManager::createNotificationChannel)
NotificationChannel(DONE_NOTIFY_CHANNEL_ID,"卸载通知",NotificationManager.IMPORTANCE_MAX).let(notificationManager::createNotificationChannel)
}

private suspend fun collectResults(pair: Pair <UninstallInfo,CommandResult>): Unit = coroutineScope {
Expand Down
19 changes: 17 additions & 2 deletions app/src/main/java/me/heizi/box/package_manager/ui/clean/Adapter.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package me.heizi.box.package_manager.ui.clean

import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import me.heizi.box.package_manager.Application.Companion.TAG
import me.heizi.box.package_manager.R
import me.heizi.box.package_manager.models.UninstallInfo
import me.heizi.box.package_manager.utils.bindText
import java.util.*

class Adapter:ListAdapter<UninstallInfo,Adapter.ViewHolder>(differ){

Expand All @@ -21,11 +24,13 @@ class Adapter:ListAdapter<UninstallInfo,Adapter.ViewHolder>(differ){
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
Log.i(TAG, "onCreateViewHolder: called")
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_uninstall_info_input,parent,false)
return ViewHolder(view)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
Log.i(TAG, "onBindViewHolder: called $position")
with(getItem(position)){ with(holder) {
title =
""" ${applicationName.takeIf { it!=packageName }?.plus(":")?:""} $applicationName """
Expand All @@ -38,17 +43,27 @@ class Adapter:ListAdapter<UninstallInfo,Adapter.ViewHolder>(differ){
}
} }
}

private var finalList:ArrayList<UninstallInfo> = ArrayList()

override fun submitList(list: MutableList<UninstallInfo>?) {
val arrayList = ArrayList<UninstallInfo>()
list?.let { arrayList.addAll(it) }
finalList = arrayList
super.submitList(list)
}
private fun removeItem(position: Int) {
currentList.removeAt(position)
finalList.removeAt(position)
notifyItemRemoved(position)
submitList(finalList)
notifyItemRangeChanged(position-1,3)
}
companion object {
private val differ = object : DiffUtil.ItemCallback<UninstallInfo>(){
override fun areItemsTheSame(oldItem: UninstallInfo, newItem: UninstallInfo): Boolean =
oldItem.packageName == newItem.packageName
override fun areContentsTheSame(oldItem: UninstallInfo, newItem: UninstallInfo): Boolean =
oldItem==newItem
oldItem.equals(newItem)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package me.heizi.box.package_manager.ui.clean
import android.content.Context
import android.content.ServiceConnection
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import androidx.fragment.app.Fragment
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import me.heizi.box.package_manager.Application.Companion.DEFAULT_MOUNT_STRING
import me.heizi.box.package_manager.R
import me.heizi.box.package_manager.SingletonActivity.Companion.parent
Expand All @@ -17,7 +19,7 @@ import me.heizi.box.package_manager.repositories.CleaningAndroidService
import me.heizi.box.package_manager.utils.dialogBuilder
import me.heizi.box.package_manager.utils.longToast

class CleanFragment : Fragment(R.layout.clean_fragment) {
class CleanFragment : BottomSheetDialogFragment() {
private val binding by lazy { CleanFragmentBinding.bind(requireView()) }
private val viewModel:CleanViewModel by viewModels(factoryProducer = { object :ViewModelProvider.Factory{
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
Expand All @@ -26,7 +28,7 @@ class CleanFragment : Fragment(R.layout.clean_fragment) {
} })

private val defaultViewModelService = object : CleanViewModel.Service {
override fun getBackupType() = callDialogGetBackupType()
override fun withBackupTypeAwait(block: (BackupType) -> Unit) { callDialogGetBackupType(block) }
override fun longToast(string: String) { context?.longToast(string) }
override fun getMountString(): String = parent.viewModel.preferences.mountString ?: DEFAULT_MOUNT_STRING
override fun startAndBindService(connection: ServiceConnection) {
Expand All @@ -37,27 +39,31 @@ class CleanFragment : Fragment(R.layout.clean_fragment) {
}
}
}

override fun startedCallback() {
dismiss()
}
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return layoutInflater.inflate(R.layout.clean_fragment,container) }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.lifecycleOwner = viewLifecycleOwner
binding.viewModel = viewModel
viewModel.stopProcessing()
}

private fun callDialogGetBackupType():BackupType {
var type:BackupType? = null
private fun callDialogGetBackupType(block:(BackupType)->Unit) {
requireContext().dialogBuilder(
title = "请选择备份模式",
).apply {
setItems(arrayOf("不备份","把apk改名为apk.bak","把APK移动到内部存储空间")) {_,i ->
type = when(i) {
when(i) {
0 -> BackupType.JustRemove
1 -> BackupType.BackupWithOutPath
else -> BackupType.BackupWithPath.Default
}
}.let(block)
}
}.show()
return type!!
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.Default
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import me.heizi.box.package_manager.Application.Companion.TAG
import me.heizi.box.package_manager.models.BackupType
Expand All @@ -28,10 +26,11 @@ private val service:Service
) : ViewModel() {

interface Service {
fun getBackupType():BackupType
fun withBackupTypeAwait(block:(BackupType)->Unit)
fun longToast(string: String)
fun getMountString():String
fun startAndBindService(connection: ServiceConnection)
fun startedCallback()
}

val processing get() = _processing.asStateFlow()
Expand All @@ -40,46 +39,56 @@ private val service:Service

val helpText get() = _helpText.asStateFlow()

val isUninstallable get() = _isUninstallable.asStateFlow()
private val _isUninstallable = msf(false)
private val _processing = msf(true)

/**
* Uninstall info
* 变动时扔到adapter里面展示给用户
*/
private val _uninstallsInfo:MutableSharedFlow<JsonContent> = MutableSharedFlow()
private val _uninstallsInfo:MutableSharedFlow<JsonContent?> = MutableSharedFlow()
private val _helpText:msf<String?> = msf(null)
fun startProcessing() {
_processing set true
}
fun stopProcessing() {
_processing set false
}
var isUsing = false
init {
viewModelScope.launch(Dispatchers.Default) {
textInput.filter {
it.length>6
}.collectLatest {
viewModelScope.launch(Default) {
textInput.collectLatest {
if (it.length <= 6) {
_helpText set null

return@collectLatest
}
startProcessing()
try {
val jsonContent = Compressor.buildJson(it)
launch(Default) {
_uninstallsInfo.emit(jsonContent)
}
Log.i(TAG, "workingwill")
isUsing = true
_isUninstallable set true
_helpText set null
}catch (e:Exception) {
Log.i(TAG, "wrongWithDecoding ",e)
isUsing = false
_isUninstallable set false
_helpText set e.message
_uninstallsInfo.emit(null)
} finally {
stopProcessing()
}
}
}
viewModelScope.launch(Dispatchers.Unconfined) {
_uninstallsInfo.collectLatest {
launch(Main) { adapter.submitList(it.apps.toMutableList()) }
_uninstallsInfo
.collectLatest {
launch(Main) {
Log.i(TAG, "list: changed on cleaning")
adapter.submitList(it?.apps?.toMutableList())
}
}
}

Expand All @@ -91,24 +100,23 @@ private val service:Service
* 当点击时弹出窗口让用户选择备份模式
*/
fun onDoneBtnClicked() {
Log.i(TAG, "onDoneBtnClicked: $isUsing")
if (isUsing) {
val task = viewModelScope.async(Main){ service.getBackupType() }
val list = adapter.currentList
val mountString = service.getMountString()
val connect = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
if (service is CleaningAndroidService.Binder) {
viewModelScope.launch {
task.await().let {
service.startUninstall(viewModelScope,list,it,mountString)
if (_isUninstallable.value) {
service.withBackupTypeAwait {
val list = adapter.currentList
val mountString = service.getMountString()
val connect = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
if (binder is CleaningAndroidService.Binder) {
viewModelScope.launch {
binder.startUninstall(viewModelScope,list,it,mountString)
service.startedCallback()
}
}
}
override fun onServiceDisconnected(name: ComponentName?) {}
}
override fun onServiceDisconnected(name: ComponentName?) {}
service.startAndBindService(connect)
}
service.startAndBindService(connect)
} else {
service.longToast("似乎列表还没有就绪")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
package me.heizi.box.package_manager.ui.export

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import androidx.fragment.app.Fragment
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import me.heizi.box.package_manager.R
import me.heizi.box.package_manager.databinding.ExportFragmentBinding

class ExportFragment : Fragment(R.layout.export_fragment) {
class ExportFragment : BottomSheetDialogFragment() {
private val binding by lazy { ExportFragmentBinding.bind(requireView()) }
private val viewModel:ExportViewModel by viewModels()

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return layoutInflater.inflate(R.layout.export_fragment,container)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.lifecycleOwner = this
Expand Down
Loading

0 comments on commit 9a20b2d

Please sign in to comment.