I have an app with a Switch
that has to fire my JobService
. I called two methods in setOnCheckedChangeListener
of the Switch, one for register and one for unregister the job.
It seems to work, like debug shows, but the the background work inside the onStartJob
. What am I missing?
MemoNotificationService.kt
class MemoNotificationService : JobService() {
companion object {
const val TAG = "MemoPush"
const val serviceId = 4242
}
override fun onStartJob(params: JobParameters?): Boolean {
doBackgroundWork(params)
return true
}
private fun doBackgroundWork(params: JobParameters?) {
CoroutineScope(Dispatchers.IO).launch {
Log.d(TAG, "Push sending...")
sendNotification("body push 1", "title push 1", "", 1)
Log.d(TAG, "Push sent")
jobFinished(params, false)
}
}
override fun onStopJob(params: JobParameters?): Boolean {
Log.d(TAG, "<Job interrupt>")
return true
}
fun sendNotification(
messageBody: String,
messageTitle: String,
largeIconPath: String,
pushId: Int
) {
val channelId = getString(R.string.consumer_notification_channel_id)
val channelName = getString(R.string.consumer_notification_channel_name)
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.logo_anim1)
.setColor(ContextCompat.getColor(this, R.color.colorAccent))
.setColorized(true)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setLights(Color.YELLOW, 1000, 1000)
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_DEFAULT
)
channel.enableLights(true)
channel.lightColor = Color.YELLOW
notificationManager.createNotificationChannel(channel)
}
notificationManager.notify(pushId, notificationBuilder.build())
}
}
SettingsFragment.kt
private fun registerNotification() {
//TODO("Not yet implemented")
val componentService = ComponentName(requireContext(), MemoNotificationService::class.java)
val info = JobInfo.Builder(MemoNotificationService.serviceId, componentService)
.setPersisted(true) /*persist on boot*/ /*not sure if needed*/
.setPeriodic(30 * 1000) /*once a day = 24 * 60 * 60 * 1000 */
.build()
val scheduler = requireContext().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
val resultCode = scheduler.schedule(info)
if(resultCode == JobScheduler.RESULT_SUCCESS)
Log.d(MemoNotificationService.TAG, "<Job scheduled>")
else
Log.d(MemoNotificationService.TAG, "<Job scheduling failed>")
}
private fun unregisterNotification() {
//TODO("Not yet implemented")
val scheduler = requireContext().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
Log.d(MemoNotificationService.TAG, "<Job scheduling cancelling> :: ${scheduler.allPendingJobs}")
scheduler.cancel(MemoNotificationService.serviceId)
Log.d(MemoNotificationService.TAG, "<Job scheduling cancelled> :: ${scheduler.allPendingJobs}")
}
AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
<service
android:name=".MemoNotificationService"
android:permission="android.permission.BIND_JOB_SERVICE" />
Logcat
D/MemoPush: <Job scheduled>
D/MemoPush: <Job scheduling cancelling> :: [(job:4242/com.example.testjobservice/.MemoNotificationService)]
D/MemoPush: <Job scheduling cancelled> :: []
Actually I need to send push notifications with an offline service (no Internet in the entire application), once a day for example, with the same notification, or a list of... Is it the right way to achieve this?
Documentation says that minimum scheduler time is 15 minutes, so it would probably be the problem. Changing the code to:
SettingsFragment.kt
private fun registerNotification() {
val componentService = ComponentName(requireContext(), MemoNotificationService::class.java)
val info = JobInfo.Builder(MemoNotificationService.serviceId, componentService)
.setPersisted(true)
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
//info.setPeriodic(24 * 60 * 60 * 1000,12 * 60 * 60 * 1000)
info.setPeriodic(30 * 60 * 1000,15 * 60 * 1000) //for testing purpose
}
else {
//info.setPeriodic(24 * 60 * 60 * 1000)
info.setPeriodic(15 * 60 * 1000) //for testing purpose
}
val scheduler = requireContext().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
val resultCode = scheduler.schedule(info.build())
if(resultCode == JobScheduler.RESULT_SUCCESS)
Log.d(MemoNotificationService.TAG, "<Job scheduled>")
else
Log.d(MemoNotificationService.TAG, "<Job scheduling failed>")
}
it works like a charm, I guess.
Anyway, for further solutions, it's better to use WorkManager
that is built upon AlarmManager
(API < 21) and JobScheduler
(API >= 21).
Official codelab: https://developer.android.com/codelabs/android-workmanager?index=..%2F..index#0