简体   繁体   English

使应用服务在后台不可见

[英]Making app service work invisible in background

i have an app that runs a background service infinitely while also hiding the app icon and hiding it from the backstack so it wont be visible to the user while running using:我有一个无限运行后台服务的应用程序,同时还隐藏了应用程序图标并将其隐藏在后台堆栈中,因此在运行时用户不会看到它:

       val componentName = ComponentName(this, FullscreenActivity::class.java)
       p.setComponentEnabledSetting(
           componentName,
           PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
           PackageManager.DONT_KILL_APP
       )

this is how i launch the service from my fragment:这就是我从片段启动服务的方式:

parentFragment?.activity?.startService(
                    Intent(
                        requireParentFragment().requireActivity().applicationContext,
                        RescueService::class.java
                    ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                )

which successfully hides the icon and the app from backstack and the service keep running, also when i press the square button on my phone to show the backstack apps running i dont see the app there which is what i want, but if i click the "X" button to clear all backstack apps it also kills my app and my service dies even though the app does not appear there as i mentioned.它成功地从后台隐藏图标和应用程序并且服务继续运行,当我按下手机上的方形按钮以显示后台应用程序正在运行时,我没有看到我想要的应用程序,但是如果我点击“ X”按钮清除所有后台应用程序它也会杀死我的应用程序并且我的服务会死掉,即使应用程序没有像我提到的那样出现在那里。

Any ideas what makes the service die after doing it?任何想法是什么让服务在完成后死亡? because it did not happen to couple of days ago before i did some changes in my app..因为几天前我对我的应用程序进行了一些更改之前并没有发生这种情况..

One of the changes i made is turnning my Service into LifecycleService because i needed my service to observe a livedata which needs a LifecycleOwner .Can it be the cause of my service to die when clearing the backstack?我所做的更改之一是将我的Service变成LifecycleService因为我需要我的服务来观察需要LifecycleOwner的 livedata。这可能是我的服务在清除后台堆栈时死亡的原因吗?

All suggestions will be welcomed !欢迎所有建议!

EDIT1 - here is my TestService that performs voice recording uses WorkManager .I call hideApp() to hide the icon from the phone and make the app invisible from the backstack: EDIT1 - 这是我使用WorkManager执行语音录制的TestService 。我调用hideApp()从手机中隐藏图标并使应用程序在后台不可见:

class RecordingWork(
    context: Context,
    params: WorkerParameters
) : CoroutineWorker(context, params) {

    override val coroutineContext = Dispatchers.Main
    override suspend fun doWork(): Result {

        mSpeechRecognizer.startListening(mSpeechRecognizerIntent)
        return Result.success()
    }
}

private lateinit var mSpeechRecognizer: SpeechRecognizer
private val mSpeechRecognizerIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)

class TestService : Service() {

    private lateinit var workManager: WorkManager

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.d("TestService", "onStartCommand called")
        hideApp()
        prepareVoiceRecording()
        workManager = WorkManager.getInstance(applicationContext)
        workManager.enqueue(OneTimeWorkRequestBuilder<RecordingWork>().build())

        return START_REDELIVER_INTENT
    }

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

    fun prepareVoiceRecording() {
        mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(applicationContext)
        mSpeechRecognizerIntent.putExtra(
            RecognizerIntent.EXTRA_LANGUAGE_MODEL,
            RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
        )
        mSpeechRecognizerIntent.putExtra(
            RecognizerIntent.EXTRA_LANGUAGE,
            Locale.getDefault()
        )
        mSpeechRecognizer.setRecognitionListener(
            object : RecognitionListener {

                @RequiresApi(Build.VERSION_CODES.M)
                override fun onError(i: Int) {
                    Log.d(TAG, "onErrorCalled error is $i")
                    if (i == SpeechRecognizer.ERROR_NETWORK || i == SpeechRecognizer.ERROR_SPEECH_TIMEOUT || i == SpeechRecognizer.ERROR_NO_MATCH) {
                        Log.d(TAG, "error triggered")
                        mSpeechRecognizer.destroy()
                        prepareVoiceRecording()
                        workManager.enqueue(OneTimeWorkRequestBuilder<RecordingWork>().build())

                    }
                }

                @RequiresApi(Build.VERSION_CODES.M)
                override fun onResults(bundle: Bundle) {
                    Log.d(TAG, "onResults Called")
                    //getting all the matches
                    val matches = bundle
                        .getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)!!
                    workManager.enqueue(OneTimeWorkRequestBuilder<RecordingWork>().build())
                }

 private fun hideApp() {
        val componentName = ComponentName(
            this,
            WelcomeScreenActivity::class.java
        )
        packageManager.setComponentEnabledSetting(
            componentName,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP
        )
    }

this service does work to repeatedly record voice by rescheduling the Worker every time.该服务确实可以通过每次重新安排 Worker 来重复录制语音。 but this service also dies when clearing backstack (even though the app does not appear there because of hideApp() )但是在清除 backstack 时这个服务也会死掉(即使应用程序因为hideApp()没有出现在那里)

Use workManager for long running background task (some device like Mi phone you need to white list the app for battery saver if you don't do that the OS will kill your app) and hiding of app icon not work in android X (only system apps can hide their icon)使用 workManager 进行长时间运行的后台任务(某些设备,如小米手机,如果您不这样做,操作系统会杀死您的应用程序,您需要将应用程序列入白名单以节省电量)和隐藏应用程序图标在 android X 中不起作用(仅限系统应用程序可以隐藏他们的图标)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM