Browse Source

Merge pull request #13065 from nextcloud/bugfix/start-foreground-service-in-background

Bugfix Start Foreground Service When App In Foreground
Alper Öztürk 11 tháng trước cách đây
mục cha
commit
0580f93889

+ 2 - 1
app/build.gradle

@@ -291,7 +291,8 @@ dependencies {
     implementation 'androidx.webkit:webkit:1.11.0'
     implementation 'androidx.cardview:cardview:1.0.0'
     implementation 'androidx.exifinterface:exifinterface:1.3.7'
-    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0"
+    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.1"
+    implementation "androidx.lifecycle:lifecycle-service:2.8.1"
     implementation "androidx.work:work-runtime:$workRuntime"
     implementation "androidx.work:work-runtime-ktx:$workRuntime"
     implementation "androidx.fragment:fragment-ktx:1.7.1"

+ 16 - 10
app/src/main/java/com/nextcloud/client/jobs/transfer/FileTransferService.kt

@@ -7,10 +7,11 @@
  */
 package com.nextcloud.client.jobs.transfer
 
-import android.app.Service
 import android.content.Context
 import android.content.Intent
 import android.os.IBinder
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleService
 import com.nextcloud.client.account.User
 import com.nextcloud.client.core.AsyncRunner
 import com.nextcloud.client.core.LocalBinder
@@ -32,7 +33,7 @@ import dagger.android.AndroidInjection
 import javax.inject.Inject
 import javax.inject.Named
 
-class FileTransferService : Service() {
+class FileTransferService : LifecycleService() {
 
     companion object {
         const val TAG = "DownloaderService"
@@ -94,14 +95,16 @@ class FileTransferService : Service() {
 
     override fun onCreate() {
         AndroidInjection.inject(this)
+        super.onCreate()
     }
 
-    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
-        if (intent.action != ACTION_TRANSFER) {
+    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+        super.onStartCommand(intent, flags, startId)
+        if (intent == null || intent.action != ACTION_TRANSFER) {
             return START_NOT_STICKY
         }
 
-        if (!isRunning) {
+        if (!isRunning && lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
             ForegroundServiceHelper.startService(
                 this,
                 AppNotificationManager.TRANSFER_NOTIFICATION_ID,
@@ -111,16 +114,19 @@ class FileTransferService : Service() {
         }
 
         val request: Request = intent.getParcelableArgument(EXTRA_REQUEST, Request::class.java)!!
-        val transferManager = getTransferManager(request.user)
-        transferManager.enqueue(request)
+
+        getTransferManager(request.user).run {
+            enqueue(request)
+        }
 
         logger.d(TAG, "Enqueued new transfer: ${request.uuid} ${request.file.remotePath}")
 
         return START_NOT_STICKY
     }
 
-    override fun onBind(intent: Intent?): IBinder? {
-        val user = intent?.getParcelableArgument(EXTRA_USER, User::class.java) ?: return null
+    override fun onBind(intent: Intent): IBinder? {
+        super.onBind(intent)
+        val user = intent.getParcelableArgument(EXTRA_USER, User::class.java) ?: return null
         return Binder(getTransferManager(user), this)
     }
 
@@ -128,7 +134,7 @@ class FileTransferService : Service() {
         if (!isRunning) {
             logger.d(TAG, "All downloads completed")
             notificationsManager.cancelTransferNotification()
-            stopForeground(true)
+            stopForeground(STOP_FOREGROUND_DETACH)
             stopSelf()
         } else if (transfer.direction == Direction.DOWNLOAD) {
             notificationsManager.postDownloadTransferProgress(

+ 17 - 8
app/src/main/java/com/nextcloud/utils/ForegroundServiceHelper.kt

@@ -10,24 +10,33 @@ package com.nextcloud.utils
 import android.app.Notification
 import android.app.Service
 import android.os.Build
+import android.util.Log
 import androidx.core.app.ServiceCompat
 import androidx.work.ForegroundInfo
 import com.owncloud.android.datamodel.ForegroundServiceType
 
 object ForegroundServiceHelper {
+    private const val TAG = "ForegroundServiceHelper"
+    private val isAboveOrEqualAndroid10 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
+
+    @Suppress("TooGenericExceptionCaught")
     fun startService(
         service: Service,
         id: Int,
         notification: Notification,
         foregroundServiceType: ForegroundServiceType
     ) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-            ServiceCompat.startForeground(
-                service,
-                id,
-                notification,
-                foregroundServiceType.getId()
-            )
+        if (isAboveOrEqualAndroid10) {
+            try {
+                ServiceCompat.startForeground(
+                    service,
+                    id,
+                    notification,
+                    foregroundServiceType.getId()
+                )
+            } catch (e: Exception) {
+                Log.d(TAG, "Exception caught at ForegroundServiceHelper.startService: $e")
+            }
         } else {
             service.startForeground(id, notification)
         }
@@ -38,7 +47,7 @@ object ForegroundServiceHelper {
         notification: Notification,
         foregroundServiceType: ForegroundServiceType
     ): ForegroundInfo {
-        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+        return if (isAboveOrEqualAndroid10) {
             ForegroundInfo(id, notification, foregroundServiceType.getId())
         } else {
             ForegroundInfo(id, notification)

+ 12 - 0
gradle/verification-metadata.xml

@@ -235,7 +235,9 @@
          <trusted-key id="A42FEF087AF29AE864684EAEE6039456D5BBD4F8" group="io.fabric8" name="kubernetes-client-bom" version="5.12.4"/>
          <trusted-key id="A5BD02B93E7A40482EB1D66A5F69AD087600B22C" group="org.ow2.asm"/>
          <trusted-key id="A5F483CD733A4EBAEA378B2AE88979FB9B30ACF2">
+            <trusting group="androidx.annotation"/>
             <trusting group="androidx.fragment"/>
+            <trusting group="androidx.lifecycle"/>
             <trusting group="androidx.webkit" name="webkit" version="1.11.0"/>
             <trusting group="^androidx[.]compose($|([.].*))" regex="true"/>
          </trusted-key>
@@ -1808,6 +1810,11 @@
             <sha256 value="9affa24c6160dc8cadaac9422d4f714e5009537d0243afc4bc74b5b7cf0de4ad" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="androidx.lifecycle" name="lifecycle-livedata" version="2.8.1">
+         <artifact name="lifecycle-livedata-2.8.1.aar">
+            <sha256 value="1a280b5d6351515907aaa19d3179ec8076095985e979e323a5972bdc5d6b7945" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="androidx.lifecycle" name="lifecycle-livedata-core" version="2.0.0">
          <artifact name="lifecycle-livedata-core-2.0.0.aar">
             <sha256 value="fde334ec7e22744c0f5bfe7caf1a84c9d717327044400577bdf9bd921ec4f7bc" origin="Generated by Gradle" reason="Artifact is not signed"/>
@@ -6579,6 +6586,11 @@
             <sha256 value="3edce6b711ba368efe16b9b7aacb0214fbd648414cb9b965953a2e7ed89a819a" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="com.google.errorprone" name="error_prone_annotations" version="2.3.4">
+         <artifact name="error_prone_annotations-2.3.4.pom">
+            <sha256 value="1326738a4b4f7ccacf607b866a11fb85193ef60f6a59461187ce7265f9be5bed" origin="Generated by Gradle"/>
+         </artifact>
+      </component>
       <component group="com.google.errorprone" name="error_prone_annotations" version="2.5.1">
          <artifact name="error_prone_annotations-2.5.1.pom">
             <sha256 value="983ad7fe0fa6f6f91e2d20477f5089eccc3f4d8ec6c51d6eb45583970e279d3c" origin="Generated by Gradle"/>