首页 > 解决方案 > 除了 TimerTask 之外,还有其他方法可以在另一个应用程序上显示覆盖吗?

问题描述

我正在构建一个应用程序,该应用程序显示覆盖另一个应用程序,例如应用程序储物柜。但它不喜欢它。每次打开应用程序时,我都想在数据库中存在的应用程序上显示一个对话框。我提供了一项服务,该服务使用设置为延迟和 1 秒周期的计时器任务连续检查哪个应用程序处于前台。

问题在于,由于计时器任务运行函数中的一条语句,它在每个应用程序上只显示一次对话框。我怎样才能使它工作,以便它始终在应用程序上显示对话框。任何替代或优化?

import android.app.ActivityManager
import android.app.Dialog
import android.app.Service
import android.app.usage.UsageStats
import android.app.usage.UsageStatsManager
import android.content.Context
import android.content.Intent
import android.graphics.PixelFormat
import android.os.Build
import android.os.IBinder
import android.util.Log
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import android.widget.ImageView
import androidx.annotation.RequiresApi
import app.privvio.android.policysplash.PolicyDialog
import app.privvio.android.preference.GetFirebaseAllApps
import java.util.*
import kotlin.collections.ArrayList


class AppCheckServices : Service() {
private var context: Context? = null
var imageView: ImageView? = null
private var windowManager: WindowManager? = null
private var dialog: Dialog? = null
var dbPackageName: ArrayList<String> = GetFirebaseAllApps().getAppsUploaded()


override fun onCreate() {
    super.onCreate()
    context = applicationContext

    /** Timer started for long time **/
    timer = Timer("AppCheckServices")
    timer!!.scheduleAtFixedRate(updateTask, 1000L, 1000L)


    /** Window Manager posts a Blank Image
     * view with transparent background which blocks the view
     * and the policy dialog is shown over it
     * **/
    windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
    imageView = ImageView(this)
    imageView!!.visibility = View.GONE

    val LAYOUT_FLAG: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
    } else {
        WindowManager.LayoutParams.TYPE_PHONE
    }
    val params = WindowManager.LayoutParams(
            WindowManager.LayoutParams.MATCH_PARENT,
            WindowManager.LayoutParams.MATCH_PARENT,
            LAYOUT_FLAG,
            WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSPARENT)
    params.gravity = Gravity.TOP or Gravity.CENTER
    params.x = applicationContext.resources.displayMetrics.widthPixels / 2
    params.y = applicationContext.resources.displayMetrics.heightPixels / 2
    windowManager!!.addView(imageView, params)
}


private val updateTask: TimerTask = object : TimerTask() {
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
    override fun run() {
        currentApp = ForegroundApps
        if (dbPackageName.contains(ForegroundApps)) {
            Log.d("DBAppFRGRND", "true : The application is in foreground.")
            if (imageView != null) {
                imageView!!.post {
                    if (currentApp != previousApp) {
                        showPolicyDialog()
                        previousApp = currentApp
                    } else {
                        Log.d("AppCheckService", "currentApp matches previous App")
                    }
                }
            }
        } else {
            Log.d("DBAppFRGRND", "false : The application is not uploaded to the server. ")
            if (imageView != null) {
                imageView!!.post {
                    hidePolicyDialog();
                }
            }
        }
    }
}


/** This section tells whether an application is in foreground or background */
val ForegroundApps: String?
    @RequiresApi(Build.VERSION_CODES.LOLLIPOP_MR1)
    get() {
        var mpackageName: String? = null
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
            val usm = this.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
            val time = System.currentTimeMillis()
            val appList: List<UsageStats>? = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, 0, time)
            if (appList != null && appList.isNotEmpty()) {
                val sortedMap = TreeMap<Long, UsageStats>()
                for (usageStats in appList) {
                    sortedMap[usageStats.lastTimeUsed] = usageStats
                }
                mpackageName = sortedMap.takeIf { it.isNotEmpty() }?.lastEntry()?.value?.packageName
                Log.d(TAG, "isEmpty No : $mpackageName")
            } else {
                Log.d(TAG, "isEmpty Yes")
                mpackageName = ""
            }
        } else {
            val am = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
            @Suppress("DEPRECATION") //The deprecated method is used for devices running an API lower than LOLLIPOP
            mpackageName = am.getRunningTasks(5)[0].topActivity?.packageName
            Log.d(TAG, "isEmpty No : $mpackageName")
        }
        return mpackageName
    }

fun showPolicyDialog() {
    if (context == null) context = applicationContext
    PolicyDialog(context!!).showDialog(context!!)
}

fun hidePolicyDialog() {
    previousApp = ""
    try {
        if (dialog != null) {
            if (dialog!!.isShowing) {
                dialog!!.dismiss()
            }
        }
    } catch (e: java.lang.Exception) {
        e.printStackTrace()
    }
}

override fun onBind(intent: Intent): IBinder? {
    return null
}

override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
    /** We want this service to continue running until it is explicitly
     * stopped, so return sticky.
     */
    return START_STICKY
}


 override fun onDestroy() {
    super.onDestroy()
  //        timer!!.cancel()
  //        timer = null
    if (imageView != null) {
        windowManager!!.removeView(imageView)
    }
    try {
        if (dialog != null) {
            if (dialog!!.isShowing) {
                dialog!!.dismiss()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}


companion object {
    const val TAG = "AppCheckServices"
    var currentApp: String? = ""
    var previousApp: String? = ""
    var timer: Timer? = null
}

}

标签: javaandroidkotlin

解决方案


推荐阅读