You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Android应用在被杀死/后台时通知7天未活跃用户?

Solution for Notifying Inactive Users (7 Days of Inactivity)

Hey there! Let's break down a better approach to solve your problem—since your previous attempts with AlarmManager and BroadcastReceiver hit roadblocks (like not working when the app is killed, or causing infinite loops), WorkManager is the way to go here. It's Jetpack's dedicated component for reliable background tasks, and it handles all the edge cases you're struggling with.

Why Your Previous Approaches Failed

  • AlarmManager can get canceled when the app is force-stopped or the device reboots (unless you handle boot broadcasts, which adds unnecessary complexity).
  • Calling your TimerRestarterBroadcastReceiver from onDestroy() is risky: first, onDestroy() isn't guaranteed to run (the system can kill your app without invoking it), and second, restarting the service every time it destroys creates that infinite loop you're seeing.

Step-by-Step Implementation with WorkManager

1. Add WorkManager Dependency

First, make sure you have the WorkManager runtime dependency in your app-level build.gradle:

dependencies {
    def work_version = "2.8.1"
    implementation "androidx.work:work-runtime:$work_version"
}

2. Create a Worker Class for Inactivity Checks

This class will handle checking if the user has been inactive for 7 days and sending the reminder notification:

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import android.preference.PreferenceManager;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

public class InactiveUserCheckerWorker extends Worker {
    private static final String CHANNEL_ID = "INACTIVE_USER_REMINDER";
    private static final long SEVEN_DAYS_IN_MILLIS = 7 * 24 * 60 * 60 * 1000;

    public InactiveUserCheckerWorker(@NonNull Context context, @NonNull WorkerParameters params) {
        super(context, params);
    }

    @NonNull
    @Override
    public Result doWork() {
        // Fetch the last time the user opened the app
        long lastActiveTime = getLastActiveTime();
        long currentTime = System.currentTimeMillis();

        // Check if 7 full days have passed since the user's last activity
        if (currentTime - lastActiveTime >= SEVEN_DAYS_IN_MILLIS) {
            sendInactiveUserNotification();
        }

        // Return success to let WorkManager know the task completed properly
        return Result.success();
    }

    private long getLastActiveTime() {
        return PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
                .getLong("last_app_open_time", System.currentTimeMillis());
    }

    private void sendInactiveUserNotification() {
        NotificationManager notificationManager = 
                (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);

        // Create a notification channel for Android O and above (required for notifications)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID,
                    "Inactive User Reminder",
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            notificationManager.createNotificationChannel(channel);
        }

        // Build and show the reminder notification
        Notification notification = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_app_icon) // Replace with your app's actual icon
                .setContentTitle("We Miss You!")
                .setContentText("It's been 7 days since you used our app—come back and explore what's new!")
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setAutoCancel(true)
                .build();

        notificationManager.notify(1001, notification);
    }
}

3. Track User Activity & Schedule the Work

You need to update the user's last active time every time they open the app (e.g., in your main activity's onResume() or your Application class's onCreate()). Then schedule a periodic WorkManager task to check for inactivity every 7 days.

Example in Your Application Class:

import android.app.Application;
import android.content.Context;
import androidx.preference.PreferenceManager;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import java.util.concurrent.TimeUnit;

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // Update last active time when the app starts
        updateLastActiveTime(this);

        // Schedule a recurring task to check for inactivity every 7 days
        PeriodicWorkRequest inactivityCheckRequest = new PeriodicWorkRequest.Builder(
                InactiveUserCheckerWorker.class,
                7,
                TimeUnit.DAYS
        ).build();

        // Enqueue the task with a unique name to avoid duplicate tasks
        WorkManager.getInstance(this).enqueueUniquePeriodicWork(
                "InactiveUserCheck",
                ExistingPeriodicWorkPolicy.KEEP, // Keep existing task if it already exists
                inactivityCheckRequest
        );
    }

    public static void updateLastActiveTime(Context context) {
        PreferenceManager.getDefaultSharedPreferences(context)
                .edit()
                .putLong("last_app_open_time", System.currentTimeMillis())
                .apply();
    }
}

Update Activity Time in Your Main Activity:

Make sure to refresh the last active time every time the user brings the app to the foreground:

@Override
protected void onResume() {
    super.onResume();
    MyApp.updateLastActiveTime(this);
}

Key Benefits of This Approach

  • Reliability: WorkManager automatically handles device reboots, app force-stops, and doze mode. It uses the best available background task mechanism for the Android version (JobScheduler for API 23+, AlarmManager for older versions).
  • No Infinite Loops: Unlike your previous BroadcastReceiver setup, WorkManager manages task lifecycle—no need to trigger restarts from onDestroy().
  • Simplicity: You don't have to handle complex broadcast registrations or AlarmManager edge cases. WorkManager abstracts all that away.
  • Flexibility: You can add constraints (e.g., only run when the device is charging or has network access) to save battery:
    Constraints constraints = new Constraints.Builder()
            .setRequiredNetworkType(NetworkType.NOT_REQUIRED) // Adjust based on your needs
            .setRequiresCharging(false) // Adjust based on your needs
            .build();
    
    // Add constraints to your PeriodicWorkRequest
    PeriodicWorkRequest inactivityCheckRequest = new PeriodicWorkRequest.Builder(...)
            .setConstraints(constraints)
            .build();
    

内容的提问来源于stack exchange,提问作者segfault404

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:12:49