From 7cf780c30ee4be47660ad3701d0d576ec10799d2 Mon Sep 17 00:00:00 2001 From: Raymond Lai Date: Tue, 23 Apr 2024 23:27:34 +0800 Subject: [PATCH] Use ContextCompat.startForegroundService() to better handle intents to start FTP service Fixes #4161. --- .../asynchronous/services/ftp/FtpReceiver.kt | 3 +- .../services/ftp/FtpReceiverTest.kt | 117 ++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 app/src/test/java/com/amaze/filemanager/asynchronous/services/ftp/FtpReceiverTest.kt diff --git a/app/src/main/java/com/amaze/filemanager/asynchronous/services/ftp/FtpReceiver.kt b/app/src/main/java/com/amaze/filemanager/asynchronous/services/ftp/FtpReceiver.kt index 0903585dd1..9d71e405a9 100644 --- a/app/src/main/java/com/amaze/filemanager/asynchronous/services/ftp/FtpReceiver.kt +++ b/app/src/main/java/com/amaze/filemanager/asynchronous/services/ftp/FtpReceiver.kt @@ -24,6 +24,7 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.util.Log +import androidx.core.content.ContextCompat import com.amaze.filemanager.BuildConfig.DEBUG import com.amaze.filemanager.asynchronous.services.ftp.FtpService.Companion.isRunning @@ -42,7 +43,7 @@ class FtpReceiver : BroadcastReceiver() { service.putExtras(intent) runCatching { if (intent.action == FtpService.ACTION_START_FTPSERVER && !isRunning()) { - context.startService(service) + ContextCompat.startForegroundService(context, service) } else if (intent.action == FtpService.ACTION_STOP_FTPSERVER) { context.stopService(service) } else { diff --git a/app/src/test/java/com/amaze/filemanager/asynchronous/services/ftp/FtpReceiverTest.kt b/app/src/test/java/com/amaze/filemanager/asynchronous/services/ftp/FtpReceiverTest.kt new file mode 100644 index 0000000000..7fe0fc513e --- /dev/null +++ b/app/src/test/java/com/amaze/filemanager/asynchronous/services/ftp/FtpReceiverTest.kt @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2014-2023 Arpit Khurana , Vishal Nehra , + * Emmanuel Messulam, Raymond Lai and Contributors. + * + * This file is part of Amaze File Manager. + * + * Amaze File Manager is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.amaze.filemanager.asynchronous.services.ftp + +import android.content.Intent +import android.os.Build +import android.os.Build.VERSION_CODES.KITKAT +import android.os.Build.VERSION_CODES.N +import android.os.Build.VERSION_CODES.O +import android.os.Build.VERSION_CODES.P +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.amaze.filemanager.application.AppConfig +import com.amaze.filemanager.shadows.ShadowMultiDex +import io.mockk.Called +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.slot +import io.mockk.spyk +import io.mockk.unmockkObject +import io.mockk.verify +import org.junit.After +import org.junit.Assert.assertFalse +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config + +@RunWith(AndroidJUnit4::class) +@Config(shadows = [ShadowMultiDex::class], sdk = [KITKAT, P, Build.VERSION_CODES.R]) +@Suppress("StringLiteralDuplication") +class FtpReceiverTest { + private lateinit var receiver: FtpReceiver + + /** + * Pre-test setup. + */ + @Before + fun setUp() { + mockkObject(FtpService) + receiver = FtpReceiver() + } + + /** + * Post test teardown. + */ + @After + fun tearDown() { + unmockkObject(FtpService) + } + + /** + * Test when an invalid Intent is passed into the [FtpReceiver]. + */ + @Test + fun testWhenNoActionSpecified() { + every { FtpService.isRunning() } returns false + assertFalse(FtpService.isRunning()) + receiver.onReceive(AppConfig.getInstance(), Intent()) + assertFalse(FtpService.isRunning()) + } + + /** + * Test [Context.startService()] called for pre-Oreo Androids. + */ + @Test + @Config(minSdk = KITKAT, maxSdk = N) + fun testStartServiceCalled() { + val ctx = AppConfig.getInstance() + val spy = spyk(ctx) + val capturedIntent = slot() + every { spy.startService(capture(capturedIntent)) } answers { callOriginal() } + val intent = Intent(FtpService.ACTION_START_FTPSERVER) + receiver.onReceive(spy, intent) + + verify { + spy.startService(capturedIntent.captured) + } + } + + /** + * Test [Context.startForegroundService()] called for post-Nougat Androids. + */ + @Test + @Config(minSdk = O) + fun testStartForegroundServiceCalled() { + val ctx = AppConfig.getInstance() + val spy = spyk(ctx) + val capturedIntent = slot() + every { spy.startService(capture(capturedIntent)) } answers { callOriginal() } + every { spy.startForegroundService(capture(capturedIntent)) } answers { callOriginal() } + val intent = Intent(FtpService.ACTION_START_FTPSERVER) + receiver.onReceive(spy, intent) + + verify { + spy.startService(capturedIntent.captured)?.wasNot(Called) + spy.startForegroundService(capturedIntent.captured) + } + } +}