Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package net.activitywatch.android.workers

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.jakewharton.threetenabp.AndroidThreeTen
import net.activitywatch.android.MainActivity
import net.activitywatch.android.R
import net.activitywatch.android.RustInterface
import org.json.JSONArray
Expand All @@ -23,6 +26,12 @@ private const val CHANNEL_ID = "aw_notify_channel"
private const val PREFS_NAME = "aw_notify_prefs"
private const val DEFAULT_START_OF_DAY_HOUR = 4

// PendingIntent identity ignores extras and Intent launch flags, so a request code
// shared with another MainActivity PendingIntent resolves to that existing instance
// and silently drops our FLAG_ACTIVITY_CLEAR_TOP. Request codes already taken:
// 0 = BackgroundService foreground notification, 2 = CategoryTimeWidget open button.
private const val PENDING_INTENT_REQUEST_CODE = 1

// Mirrors desktop aw-notify CategoryAlert semantics.
// positive=true → "Goal reached!" title; false → "Time spent"
internal data class CategoryAlert(
Expand Down Expand Up @@ -179,12 +188,24 @@ class NotifyWorker(context: Context, params: WorkerParameters) : Worker(context,
val body = "${alert.label}: $thresholdStr" +
if (thresholdStr != actualStr) " ($actualStr)" else ""

// Open the activity/timeline view in MainActivity when the notification is tapped.
val openIntent = Intent(applicationContext, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
}
val pendingIntent = PendingIntent.getActivity(
applicationContext,
PENDING_INTENT_REQUEST_CODE,
openIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
)
Comment thread
TimeToBuildBob marked this conversation as resolved.

val notification = NotificationCompat.Builder(applicationContext, CHANNEL_ID)
.setContentTitle(if (alert.positive) "Goal reached!" else "Time spent")
.setContentText(body)
.setSmallIcon(R.mipmap.aw_launcher_round)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.build()

// Stable ID per alert so notifications update in-place rather than stacking
Expand Down
Loading