Alarm Manager -Verhalten stimmt nicht überprotokolle übereinJava

Java-Forum
Anonymous
 Alarm Manager -Verhalten stimmt nicht überprotokolle überein

Post by Anonymous »

Ich versuche eine App zu schreiben, die mehrere Listen verderblicher Waren aus dem internen Lager verfolgt. Ich speichere und lese serialisierte .json -Dateien, um Listen usw. zu bearbeiten und zu speichern, aber ich bin extrem festgefahren, wenn es darum geht, ein gutes Benachrichtigungsschema zu implementieren. Aus irgendeinem Grund, egal was ich tue, feuern die meisten Benachrichtigungen sofort.

Code: Select all

private void scheduleAlarms(Context context, JSONArray inventory, String listName)
{

int DAYS_BEFORE_EXPIRY = 7; // Notify 7 days before expiration
long MILLIS_IN_A_DAY = 24 * 60 * 60 * 1000; // 1 day in milliseconds

// Set up the date formatter (force UTC if needed)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
//sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

for (int i = 0; i < inventory.length(); i++) {
try {
JSONObject item = inventory.getJSONObject(i);
String name = item.getString("name");
String expDateString = item.getString("expDate");

Date expDate = sdf.parse(expDateString); // Set to end of day (23:59:59)

long expDateMillis = expDate.getTime();

long daysNoticeMillis = item.getInt("daysNotice") * MILLIS_IN_A_DAY;
long expirationThreshold = expDateMillis - daysNoticeMillis;

Log.d("EXP DATE MILLIS:", String.valueOf(expDateMillis));
Log.d("DAYS NOTICE MILLIS:", String.valueOf(daysNoticeMillis));

long notifyTimeMillis = expDateMillis - (DAYS_BEFORE_EXPIRY * MILLIS_IN_A_DAY);
Log.d("NOTIFY TIME MILLIS:", String.valueOf(notifyTimeMillis));

long currentTimeMillis = System.currentTimeMillis();

// Only schedule alarms if we're within the notice window
if (currentTimeMillis >= expirationThreshold)
{
Intent intent = new Intent(context, NotificationReceiver.class);

String expiredOrGoing = "";
String title = "";

if (currentTimeMillis > expDateMillis)
{
expiredOrGoing = name + " has expired!";
title = "\uD83D\uDD34 Expiration notice for " + listName + " list!";
}

else if (currentTimeMillis >= expirationThreshold)
{
expiredOrGoing = name + " will expire soon!";
title = "\uD83D\uDFE0 Going notice for " + listName + " list!";
}
else if (currentTimeMillis < expirationThreshold)
{expiredOrGoing = name + " is safe for now!";}

Log.d("Debug", name + ": " + expiredOrGoing);

intent.putExtra("itemData", item.toString());
intent.putExtra("titleExtra", title);
intent.putExtra("messageExtra", expiredOrGoing);

// Use a composite unique identifier
String uniqueKey = listName + "_" + name; // Combine list and item name
int uniqueID = uniqueKey.hashCode();

// Create a new PendingIntent
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, uniqueID, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);

Log.d("Debug", "Attempting to schedule notification for " + name + " at: " + notifyTimeMillis);

//Log.d("Debug", name + " - Expiration Date: " + expDateMillis);
//Log.d("Debug", name + " - daysNoticeMillis: " + daysNoticeMillis);
//Log.d("Debug", name + " - Notify time: " + notifyTimeMillis);

/*if (notifyTimeMillis < System.currentTimeMillis()) {
Log.e("AlarmError", "⛔ Not scheduling alarm for past date: " + name + ", "  + notifyTimeMillis);
continue;
}*/

// Parsing the expiration date string into a Date object

Log.d("NOTIFY TIME MILLIS:", String.valueOf(notifyTimeMillis));

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

// Schedule the alarm
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
long bdate = new Long("1898978269000");

//alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, bdate, pendingIntent);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, notifyTimeMillis, pendingIntent);

} else
{
alarmManager.setExact(AlarmManager.RTC_WAKEUP, notifyTimeMillis, pendingIntent);
}

Log.d("Alarm", "Scheduled notification for " + name + " at " + notifyTimeMillis);
}
else {Log.d("Debug", name + " - Notify time (" + notifyTimeMillis + ") has already passed. (Optionally trigger immediately or skip.)");}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Dies ist die Berechnungslogik i will , aber wenn ich diese Zeile verwende, feuern nicht nur die Benachrichtigungen sofort, sondern auch nicht alle Benachrichtigungen, insbesondere die Benachrichtigung für "Koks":

Code: Select all

"long expirationThreshold = expDateMillis - (DAYS_BEFORE_EXPIRY * MILLIS_IN_A_DAY);"
< /code>
Die Differenz zwischen dieser Berechnung, die ich möchte, und diesen, die ich verwende, ist das Cola -Element, der die einzige ist, die in ersteren gegenüber tatsächlich korrekt geplant wird.long notifyTimeMillis = expDateMillis - expirationThreshold;
< /code>
Ich bin jetzt seit drei Tagen festgefahren. Wenn Sie also helfen können: Vielen Dank im Voraus! Periodische Anfrage anstelle eines Onetimerequest, damit die Alarme alle 24 Stunden geplant werden, wenn der Artikel noch verläuft, aber noch nicht abgelaufen ist. Sie hätten also 14 Tage zuvor einen Alarm, dann 7, dann 3, dann 1.  2 Woche, 1 Woche, 3 Tage und 1 -Tage -Erinnerung.2025-02-27 23:13:15.392 10185-10185 WM-WorkerWrapper        sma...tory.smartinventorywithsearch  D  Starting work for smart.inventory.smartinventorywithsearch.ExpirationCheckWorker
2025-02-27 23:13:15.393 10185-10340 Worker                  sma...tory.smartinventorywithsearch  D  Directories found: [/data/user/0/smart.inventory.smartinventorywithsearch/files/Smart Inventory/All Lists/misc, /data/user/0/smart.inventory.smartinventorywithsearch/files/Smart Inventory/All Lists/games]
2025-02-27 23:13:15.394 10185-10340 EXP DATE MILLIS:        sma...tory.smartinventorywithsearch  D  1741237200000
2025-02-27 23:13:15.394 10185-10340 DAYS NOTICE MILLIS:     sma...tory.smartinventorywithsearch  D  8640000000
2025-02-27 23:13:15.394 10185-10340 NOTIFY TIME MILLIS:     sma...tory.smartinventorywithsearch  D  1740632400000
2025-02-27 23:13:15.394 10185-10340 Debug                   sma...tory.smartinventorywithsearch  D  Elder Scrolls V: Skyrim (Xbox 360 / PS3 / PC): Elder Scrolls V: Skyrim (Xbox 360 / PS3 / PC) will expire soon!
2025-02-27 23:13:15.395 10185-10340 Debug                   sma...tory.smartinventorywithsearch  D  Attempting to schedule notification for Elder Scrolls V: Skyrim (Xbox 360 / PS3 / PC) at: 1740632400000
2025-02-27 23:13:15.395 10185-10340 NOTIFY TIME MILLIS:     sma...tory.smartinventorywithsearch  D  1740632400000
2025-02-27 23:13:15.395 10185-10340 Alarm                   sma...tory.smartinventorywithsearch  D  Scheduled notification for Elder Scrolls V: Skyrim (Xbox 360 / PS3 / PC) at 1740632400000
2025-02-27 23:13:15.395 10185-10340 EXP DATE MILLIS:        sma...tory.smartinventorywithsearch  D  1740546000000
2025-02-27 23:13:15.395 10185-10340 DAYS NOTICE MILLIS:     sma...tory.smartinventorywithsearch  D  6912000000
2025-02-27 23:13:15.395 10185-10340 NOTIFY TIME MILLIS:     sma...tory.smartinventorywithsearch  D  1739941200000
2025-02-27 23:13:15.396 10185-10340 Debug                   sma...tory.smartinventorywithsearch  D  Irish Penny Whistle - Key Of D | Book | Condition Good: Irish Penny Whistle - Key Of D | Book | Condition Good has expired!
2025-02-27 23:13:15.396 10185-10340 Debug                   sma...tory.smartinventorywithsearch  D  Attempting to schedule notification for Irish Penny Whistle - Key Of D | Book | Condition Good at: 1739941200000
2025-02-27 23:13:15.396 10185-10340 NOTIFY TIME MILLIS:     sma...tory.smartinventorywithsearch  D  1739941200000
2025-02-27 23:13:15.396 10185-10340 Alarm                   sma...tory.smartinventorywithsearch  D  Scheduled notification for Irish Penny Whistle - Key Of D | Book | Condition Good at 1739941200000
2025-02-27 23:13:15.396 10185-10340 EXP DATE MILLIS:        sma...tory.smartinventorywithsearch  D  1747713600000
2025-02-27 23:13:15.396 10185-10340 DAYS NOTICE MILLIS:     sma...tory.smartinventorywithsearch  D  7776000000
2025-02-27 23:13:15.396 10185-10340 NOTIFY TIME MILLIS:     sma...tory.smartinventorywithsearch  D  1747108800000
2025-02-27 23:13:15.396 10185-10340 Debug                   sma...tory.smartinventorywithsearch  D  coke: coke will expire soon!
2025-02-27 23:13:15.396 10185-10340 Debug                   sma...tory.smartinventorywithsearch  D  Attempting to schedule notification for coke at: 1747108800000
2025-02-27 23:13:15.396 10185-10340 NOTIFY TIME MILLIS:     sma...tory.smartinventorywithsearch  D  1747108800000
2025-02-27 23:13:15.397 10185-10340 Alarm                   sma...tory.smartinventorywithsearch  D  Scheduled notification for coke at 1747108800000
2025-02-27 23:13:15.397 10185-10340 EXP DATE MILLIS:        sma...tory.smartinventorywithsearch  D  1741064400000
2025-02-27 23:13:15.397 10185-10340 DAYS NOTICE MILLIS:     sma...tory.smartinventorywithsearch  D  21600000000
2025-02-27 23:13:15.397 10185-10340 NOTIFY TIME MILLIS:     sma...tory.smartinventorywithsearch  D  1740459600000
2025-02-27 23:13:15.397 10185-10340 Debug                   sma...tory.smartinventorywithsearch  D  Ratchet & Clank 2 for PlayStation 2: Ratchet & Clank 2 for PlayStation 2 will expire soon!
2025-02-27 23:13:15.397 10185-10340 Debug                   sma...tory.smartinventorywithsearch  D  Attempting to schedule notification for Ratchet & Clank 2 for PlayStation 2 at: 1740459600000
2025-02-27 23:13:15.397 10185-10340 NOTIFY TIME MILLIS:     sma...tory.smartinventorywithsearch  D  1740459600000
2025-02-27 23:13:15.398 10185-10340 Alarm                   sma...tory.smartinventorywithsearch  D  Scheduled notification for Ratchet &  Clank 2 for PlayStation 2 at 1740459600000
2025-02-27 23:13:15.408 10185-10185 WM-SystemJobService     sma...tory.smartinventorywithsearch  D  onStartJob for WorkGenerationalId(workSpecId=1b7fecec-6d33-4f51-b7d3-60c416f9d8a1, generation=0)
2025-02-27 23:13:15.412 10185-10226 WM-Processor            sma...tory.smartinventorywithsearch  D  Work WorkGenerationalId(workSpecId=1b7fecec-6d33-4f51-b7d3-60c416f9d8a1, generation=0) is already enqueued for processing
2025-02-27 23:13:15.413 10185-10225 WM-WorkerWrapper        sma...tory.smartinventorywithsearch  I  Worker result SUCCESS for Work [ id=1b7fecec-6d33-4f51-b7d3-60c416f9d8a1, tags={ smart.inventory.smartinventorywithsearch.ExpirationCheckWorker } ]
2025-02-27 23:13:15.413 10185-10185 WM-Processor            sma...tory.smartinventorywithsearch  D  Processor 1b7fecec-6d33-4f51-b7d3-60c416f9d8a1 executed; reschedule = false
2025-02-27 23:13:15.413 10185-10185 WM-SystemJobService     sma...tory.smartinventorywithsearch  D  1b7fecec-6d33-4f51-b7d3-60c416f9d8a1 executed on JobScheduler
2025-02-27 23:13:15.415 10185-10225 WM-GreedyScheduler      sma...tory.smartinventorywithsearch  D  Cancelling work ID 1b7fecec-6d33-4f51-b7d3-60c416f9d8a1
2025-02-27 23:13:15.420 10185-10225 WM-PackageManagerHelper sma...tory.smartinventorywithsearch  D  androidx.work.impl.background.systemalarm.RescheduleReceiver disabled
2025-02-27 23:13:15.903 10185-10185 VRI[EditActivity]       sma...tory.smartinventorywithsearch  D  visibilityChanged oldVisibility=true newVisibility=false
2025-02-27 23:13:15.915 10185-10215 HWUI                    sma...tory.smartinventorywithsearch  D  endAllActiveAnimators on 0xb4000071a6fe0980 (RippleDrawable) with handle 0xb4000071d6ea0980
2025-02-27 23:13:20.423 10185-10185 Notification            sma...tory.smartinventorywithsearch  D  Notification received!
2025-02-27 23:13:20.440 10185-10185 Notification            sma...tory.smartinventorywithsearch  D  Notification received!
2025-02-27 23:13:20.450 10185-10185 Notification            sma...tory.smartinventorywithsearch  D  Notification received!
From the logs, you see "daysNoticeMillis" is definitely correct as I have them set to 100 for Elder Scrolls (8640000000 millis), 80 for Irish Penny whistle (6912000000 millis), 90 for "coke" (7776000000 millis), and 250 for Ratchet and Clank 2 (21600000000 millis). Konverter) < /p>
Das Problem ist also auf "benachrichtigen Timemillis" eingeschränkt. Aus irgendeinem Grund kehrt es vergangene Werte zurück:
27. Februar 2025 (Elder Scrolls), 19. Februar 2025 (Irish Whistle), 13. Mai 2025 (zufällig ein ordentlicher Wert für Koks? Daher, dass die Benachrichtigung vielleicht genau das Richtige für die Auslösche ist. Und dann wieder ein poopy -vergangener Wert für Ratchet und Clank 2! (25. Februar 2025).

Code: Select all

private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
String channelId = "expiration_channel"; // Must match the ID in NotificationCompat.Builder
String channelName = "Expiration Notifications";
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);

NotificationManager notificationManager = getSystemService(NotificationManager.class);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
}
}
}

public void scheduleExpirationWorker() {
OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(ExpirationCheckWorker.class)
.build();

WorkManager.getInstance(this).enqueueUniqueWork(
"ExpirationCheckWorker",
ExistingWorkPolicy.REPLACE,
workRequest
);
}

@Override
protected void onCreate(Bundle savedInstanceState)
{
Context context = this;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

...

createNotificationChannel();
scheduleExpirationWorker();
...
}

...

// ----- Then I call that scheduleExpirationWorker() method whenever I save the lists
// ----- (which can be done with a button to save a new list, or by clicking a listview item to overwrite a list):

saveButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
String fileNameInput = saveEditText.getText().toString().trim();
File listDirectory = new File(subDirectory, fileNameInput);

if (!fileNameInput.isEmpty())
{
if (!itemsList.isEmpty())
{
// ----------------- CREATE NEW LIST FOLDER ----------------- //

if (!listDirectory.exists())
{
listDirectory.mkdirs();     // Make the directory first since it doesn't exist yet

saveInventory(listDirectory);
makeToast("'" + listDirectory.getName() + "' saved!");
}
else
{
// -------- YES or NO warning dialog for overwriting lists -------- //

DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which){
case DialogInterface.BUTTON_POSITIVE:
//Yes button clicked

// ----------------- SAVE INVENTORY TO SELECTED DIRECTORY ----------------- //
saveInventory(listDirectory);                   // Save the data to existing directory

makeToast("'" + listDirectory.getName() + "' overwritten!");
//makeToast(listDirectory.getAbsolutePath());

saveDialog.dismiss();         // Close save list" dialog after selecting a list to load

break;

case DialogInterface.BUTTON_NEGATIVE:
//No button clicked
break;
}
}
};

AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("This list already exists! Do you want to overwrite '"  + fileNameInput + "'?").setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener).show();
}

sdFilesArray = subDirectory.listFiles();         // Refresh File array of Sub Directory Folders

importFolders.clear();  // Clear the list for the loop...

// ---------- LOOP FOR POPULATING IMPORT LIST ---------- //
for (File f : sdFilesArray)
{
String filename = f.getName();
importFolders.add(filename);      // Add the folder name to the ArrayList
}

saveEditText.setText("");     // Reset the edit text to blank.

saveDialog.dismiss();

// Schedule notifications for expiring goods at the end of saving a list!
scheduleExpirationWorker();
}
else
{
makeToast("You can't save an empty list!");
}
}
else
{
makeToast("You must give the list a name!");
}
}
});
...
saveListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
@Override
public void onItemClick(AdapterView parent, View view, int position, long id)
{
// ----- 2.9.4 FIX ----- //
// Get folder name by looping through sdFilesArray
// and checking for a match to the clicked item:

String folderName = sdFilesArray[position].toString();

for (File f : sdFilesArray)
{
String listDir = folderName.substring(folderName.lastIndexOf("/") + 1);
if (folderName.equals(f.toString()))
{
// -------- YES or NO warning dialog for overwriting lists -------- //

DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which){
case DialogInterface.BUTTON_POSITIVE:
//Yes button clicked

if (!itemsList.isEmpty())
{
// ----------------- SAVE INVENTORY TO SELECTED DIRECTORY ----------------- //
File saveExistingList = new File(subDirectory, listDir);

saveInventory(saveExistingList);

makeToast("'" + listDir + "' overwritten!");

saveDialog.dismiss();         // Close save list" dialog after selecting a list to load
}
else
{
makeToast("You can't save an empty list!");
}

break;

case DialogInterface.BUTTON_NEGATIVE:
//No button clicked
break;
}
}
};

AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("Are you sure you want to overwrite '"  + listDir + "'?").setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener).show();
}
}

// Schedule notifications for expiring goods at the end of saving a list!
scheduleExpirationWorker();
}
});

< /code>
Und hier ist die Benachrichtigungsempfängerklasse: < /p>
public class NotificationReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

Log.d("Notification", "Notification received!");
String itemDataString = intent.getStringExtra("itemData");

if (itemDataString == null) {
Log.e("NotificationReceiver", "No valid item data received!");
return;
}

try {
JSONObject item = new JSONObject(itemDataString);
String name = item.getString("name");

String title = intent.getStringExtra("titleExtra");
String message = intent.getStringExtra("messageExtra");

// Build and send the notification
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = "EXPIRATION_CHANNEL"; // Ensure this matches your NotificationChannel ID

NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.use_now_status) // Replace with your actual icon
.setContentTitle(title)
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true);

if (notificationManager != null) {
notificationManager.notify((int) System.currentTimeMillis(), builder.build());
}

} catch (JSONException e) {
Log.e("NotificationReceiver", "Error parsing item data: " + e.getMessage());
}
}

}

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post