@ -10,6 +10,7 @@
package com.timesafari.dailynotification ;
import android.util.Log ;
import java.util.UUID ;
/ * *
@ -30,7 +31,39 @@ public class NotificationContent {
private String body ;
private long scheduledTime ;
private String mediaUrl ;
private long fetchTime ;
private final long fetchedAt ; // When content was fetched (immutable)
private long scheduledAt ; // When this instance was scheduled
// Gson will try to deserialize this field, but we ignore it to keep fetchedAt immutable
@SuppressWarnings ( "unused" )
private transient long fetchTime ; // Legacy field for Gson compatibility (ignored)
// Custom deserializer to handle fetchedAt field
public static class NotificationContentDeserializer implements com . google . gson . JsonDeserializer < NotificationContent > {
@Override
public NotificationContent deserialize ( com . google . gson . JsonElement json , java . lang . reflect . Type typeOfT , com . google . gson . JsonDeserializationContext context ) throws com . google . gson . JsonParseException {
com . google . gson . JsonObject jsonObject = json . getAsJsonObject ( ) ;
// Create new instance (constructor sets fresh fetchedAt)
NotificationContent content = new NotificationContent ( ) ;
// Deserialize other fields
if ( jsonObject . has ( "id" ) ) content . id = jsonObject . get ( "id" ) . getAsString ( ) ;
if ( jsonObject . has ( "title" ) ) content . title = jsonObject . get ( "title" ) . getAsString ( ) ;
if ( jsonObject . has ( "body" ) ) content . body = jsonObject . get ( "body" ) . getAsString ( ) ;
if ( jsonObject . has ( "scheduledTime" ) ) content . scheduledTime = jsonObject . get ( "scheduledTime" ) . getAsLong ( ) ;
if ( jsonObject . has ( "mediaUrl" ) ) content . mediaUrl = jsonObject . get ( "mediaUrl" ) . getAsString ( ) ;
if ( jsonObject . has ( "scheduledAt" ) ) content . scheduledAt = jsonObject . get ( "scheduledAt" ) . getAsLong ( ) ;
if ( jsonObject . has ( "sound" ) ) content . sound = jsonObject . get ( "sound" ) . getAsBoolean ( ) ;
if ( jsonObject . has ( "priority" ) ) content . priority = jsonObject . get ( "priority" ) . getAsString ( ) ;
if ( jsonObject . has ( "url" ) ) content . url = jsonObject . get ( "url" ) . getAsString ( ) ;
// fetchedAt is set by constructor and not overwritten
Log . d ( "NotificationContent" , "Deserialized content with fetchedAt=" + content . fetchedAt + " (from constructor)" ) ;
return content ;
}
}
private boolean sound ;
private String priority ;
private String url ;
@ -40,9 +73,11 @@ public class NotificationContent {
* /
public NotificationContent ( ) {
this . id = UUID . randomUUID ( ) . toString ( ) ;
this . fetchTime = System . currentTimeMillis ( ) ;
this . fetchedAt = System . currentTimeMillis ( ) ;
this . scheduledAt = System . currentTimeMillis ( ) ;
this . sound = true ;
this . priority = "default" ;
Log . d ( "NotificationContent" , "Constructor: created with fetchedAt=" + this . fetchedAt + ", scheduledAt=" + this . scheduledAt ) ;
}
/ * *
@ -152,21 +187,30 @@ public class NotificationContent {
}
/ * *
* Get the fetch time when content was retrieved
* Get the fetch time when content was retrieved ( immutable )
*
* @return Timestamp in milliseconds
* /
public long getFetchedAt ( ) {
return fetchedAt ;
}
/ * *
* Get when this notification instance was scheduled
*
* @return Timestamp in milliseconds
* /
public long getFetchTime ( ) {
return fetchTime ;
public long getScheduledAt ( ) {
return scheduledAt ;
}
/ * *
* Set the fetch time when content was retrieved
* Set when this notification instance was schedul ed
*
* @param fetchTime Timestamp in milliseconds
* @param scheduledAt Timestamp in milliseconds
* /
public void setFetchTime ( long fetchTime ) {
this . fetchTime = fetchTime ;
public void setScheduledAt ( long scheduledAt ) {
this . scheduledAt = scheduledAt ;
}
/ * *
@ -224,23 +268,32 @@ public class NotificationContent {
}
/ * *
* Check if this notification is stale ( older than 24 hours )
* Check if this notification content is stale ( older than 24 hours )
*
* @return true if notification is stale
* @return true if notification content is stale
* /
public boolean isStale ( ) {
long currentTime = System . currentTimeMillis ( ) ;
long age = currentTime - fetchTim e ;
long age = currentTime - fetchedAt ;
return age > 24 * 60 * 60 * 1000 ; // 24 hours in milliseconds
}
/ * *
* Get the age of this notification in milliseconds
* Get the age of this notification content in milliseconds
*
* @return Age in milliseconds
* /
public long getAge ( ) {
return System . currentTimeMillis ( ) - fetchTime ;
return System . currentTimeMillis ( ) - fetchedAt ;
}
/ * *
* Get the age since this notification was scheduled
*
* @return Age in milliseconds
* /
public long getScheduledAge ( ) {
return System . currentTimeMillis ( ) - scheduledAt ;
}
/ * *
@ -292,7 +345,8 @@ public class NotificationContent {
", body='" + body + '\'' +
", scheduledTime=" + scheduledTime +
", mediaUrl='" + mediaUrl + '\'' +
", fetchTime=" + fetchTime +
", fetchedAt=" + fetchedAt +
", scheduledAt=" + scheduledAt +
", sound=" + sound +
", priority='" + priority + '\'' +
", url='" + url + '\'' +