Playhi/FreezeYou

View on GitHub
app/src/main/java/cf/playhi/freezeyou/fuf/FreezeYouFUFSinglePackage.kt

Summary

Maintainability
B
4 hrs
Test Coverage
package cf.playhi.freezeyou.fuf

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import androidx.annotation.UiThread
import cf.playhi.freezeyou.MainApplication
import cf.playhi.freezeyou.R
import cf.playhi.freezeyou.storage.key.DefaultMultiProcessMMKVStorageBooleanKeys.avoidFreezeForegroundApplications
import cf.playhi.freezeyou.storage.key.DefaultMultiProcessMMKVStorageBooleanKeys.openImmediately
import cf.playhi.freezeyou.storage.key.DefaultMultiProcessMMKVStorageStringKeys.selectFUFMode
import cf.playhi.freezeyou.ui.AskRunActivity
import cf.playhi.freezeyou.utils.FUFUtils.checkAndCreateFUFQuickNotification
import cf.playhi.freezeyou.utils.FUFUtils.isAvoidFreezeNotifyingApplicationsEnabledAndAppStillNotifying
import cf.playhi.freezeyou.utils.FUFUtils.realGetFrozenStatus
import cf.playhi.freezeyou.utils.FUFUtils.sendStatusChangedBroadcast
import cf.playhi.freezeyou.utils.NotificationUtils.deleteNotification
import cf.playhi.freezeyou.utils.TasksUtils.*
import cf.playhi.freezeyou.utils.ToastUtils.showToast
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class FreezeYouFUFSinglePackage(
    override val context: Context,
    override val singlePackageName: String,
    override val actionMode: Int = if (
        realGetFrozenStatus(
            context,
            singlePackageName
        )
    ) ACTION_MODE_UNFREEZE else ACTION_MODE_FREEZE,
    override val apiMode: Int = selectFUFMode.getValue()!!.toInt(),
    val needAskRun: Boolean = false,
    /**
     * Only takes effect when [needAskRun] is true
     */
    val runImmediately: Boolean = false,
    val tasks: String? = null,
    val target: String? = null
) : FUFSinglePackage(context, singlePackageName, actionMode, apiMode) {

    /**
     * In most cases, we should call [checkAndStartTaskAndTargetAndActivity] after the method returns.
     */
    override suspend fun commit(): Int {
        if (actionMode == ACTION_MODE_FREEZE) {
            if (avoidFreezeForegroundApplications.getValue()
                && MainApplication.currentPackage.equals(singlePackageName)
            ) {
                return ERROR_USER_SET_NOT_ALLOWED_TO_FREEZE_FOREGROUND_APPLICATION
            }
            if (isAvoidFreezeNotifyingApplicationsEnabledAndAppStillNotifying(singlePackageName)) {
                return ERROR_USER_SET_NOT_ALLOWED_TO_FREEZE_NOTIFYING_APPLICATION
            }
        }
        val result = super.commit()
        when (result) {
            ERROR_NO_ERROR_SUCCESS, ERROR_NO_ERROR_CAUGHT_UNKNOWN_RESULT -> {
                sendStatusChangedBroadcast(context)
                when (actionMode) {
                    ACTION_MODE_FREEZE -> {
                        withContext(Dispatchers.Main) {
                            onFApplications(context, singlePackageName)
                        }
                        deleteNotification(context, singlePackageName)
                    }
                    ACTION_MODE_UNFREEZE -> {
                        withContext(Dispatchers.Main) {
                            onUFApplications(context, singlePackageName)
                        }
                        checkAndCreateFUFQuickNotification(context, singlePackageName)
                    }
                }
            }
        }
        return result
    }

    /**
     * As [runTask] contains [showToast] related function,
     * this method should run on UI thread.
     */
    @UiThread
    fun checkAndStartTaskAndTargetAndActivity(originResult: Int): Int {
        if (originResult != ERROR_NO_ERROR_SUCCESS
            && originResult != ERROR_NO_ERROR_CAUGHT_UNKNOWN_RESULT
        ) {
            return originResult
        }

        if (tasks != null) {
            runTask(tasks, context, null)
        }

        if (needAskRun && context.getString(R.string.onlyUnfreeze) != target) {
            if (runImmediately || openImmediately.getValue()) {
                checkAndStartTaskAndTargetAndActivityOfUnfrozenApp(
                    context,
                    singlePackageName,
                    target,
                    null, // Already executed
                    originResult
                ).let { if (it != originResult) return it }
            } else {
                context.startActivity(
                    Intent(context, AskRunActivity::class.java)
                        .putExtra("pkgName", singlePackageName)
                        .putExtra("target", target)
                        .putExtra("tasks", tasks)
                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                )
            }
        }
        return originResult
    }

    companion object {

        /**
         * As [runTask] contains [showToast] related function,
         * this method should run on UI thread.
         */
        @UiThread
        fun checkAndStartTaskAndTargetAndActivityOfUnfrozenApp(
            context: Context,
            pkgName: String,
            target: String?,
            tasks: String?,
            originResult: Int = ERROR_NO_ERROR_SUCCESS
        ): Int {

            if (tasks != null) {
                runTask(tasks, context, null)
            }

            if (target != null) {
                if (context.getString(R.string.onlyUnfreeze) != target) {
                    try {
                        val component = ComponentName(pkgName, target)
                        val intent = Intent()
                        intent.component = component
                        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
                        intent.action = Intent.ACTION_MAIN
                        context.startActivity(intent)
                    } catch (e: SecurityException) {
                        e.printStackTrace()
                        return ERROR_NO_SUFFICIENT_PERMISSION_TO_START_THIS_ACTIVITY
                    }
                }
            } else if (
                context.packageManager.getLaunchIntentForPackage(pkgName) != null
            ) {
                val intent = Intent(
                    context.packageManager.getLaunchIntentForPackage(
                        pkgName
                    )
                )
                context.startActivity(intent)
            } else {
                return ERROR_CANNOT_FIND_THE_LAUNCH_INTENT_OR_UNFREEZE_FAILED
            }
            return originResult
        }

    }

}