1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.work.integration.testapp
18 
19 import android.app.Notification
20 import android.app.NotificationChannel
21 import android.app.NotificationManager
22 import android.content.Context
23 import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
24 import android.os.Build
25 import androidx.annotation.RequiresApi
26 import androidx.core.app.NotificationCompat
27 import androidx.work.CoroutineWorker
28 import androidx.work.Data
29 import androidx.work.ForegroundInfo
30 import androidx.work.WorkerParameters
31 import androidx.work.workDataOf
32 import kotlinx.coroutines.delay
33 
34 class ForegroundWorker(context: Context, parameters: WorkerParameters) :
35     CoroutineWorker(context, parameters) {
36 
37     private val notificationManager =
38         context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
39 
40     private var progress: Data = Data.EMPTY
41 
doWorknull42     override suspend fun doWork(): Result {
43         val notificationId = inputData.getInt(InputNotificationId, NotificationId)
44         val delayTime = inputData.getLong(InputDelayTime, Delay)
45         val range = 20
46         for (i in 1..range) {
47             delay(delayTime)
48             progress = workDataOf(Progress to i * (100 / range))
49             setProgress(progress)
50             if (Build.VERSION.SDK_INT < 31) {
51                 // No need for notifications starting S.
52                 notificationManager.notify(
53                     notificationId,
54                     getForegroundInfo(notificationId).notification
55                 )
56             }
57         }
58         return Result.success()
59     }
60 
getForegroundInfonull61     override suspend fun getForegroundInfo(): ForegroundInfo {
62         val notificationId = inputData.getInt(InputNotificationId, NotificationId)
63         return getForegroundInfo(notificationId)
64     }
65 
getForegroundInfonull66     private fun getForegroundInfo(notificationId: Int): ForegroundInfo {
67         val percent = progress.getInt(Progress, 0)
68         val id = applicationContext.getString(R.string.channel_id)
69         val title = applicationContext.getString(R.string.notification_title)
70         val content = "Progress ($percent) %"
71         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
72             createChannel()
73         }
74 
75         val notification =
76             NotificationCompat.Builder(applicationContext, id)
77                 .setContentTitle(title)
78                 .setTicker(title)
79                 .setContentText(content)
80                 .setSmallIcon(R.drawable.ic_work_notification)
81                 .setOngoing(true)
82                 .build()
83 
84         return ForegroundInfo(notificationId, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC)
85     }
86 
87     @RequiresApi(Build.VERSION_CODES.O)
createChannelnull88     private fun createChannel() {
89         val id = applicationContext.getString(R.string.channel_id)
90         val name = applicationContext.getString(R.string.channel_name)
91         val description = applicationContext.getString(R.string.channel_description)
92         val channel = NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW)
93         channel.description = description
94         channel.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
95         notificationManager.createNotificationChannel(channel)
96     }
97 
98     companion object {
99         private const val NotificationId = 10
100         private const val Delay = 1000L
101         private const val Progress = "Progress"
102         const val InputNotificationId = "NotificationId"
103         const val InputDelayTime = "DelayTime"
104     }
105 }
106