应用从后台划走后Service数据重置:亮屏计数功能异常求助
Hey there! I’ve run into this exact issue before, so let’s break down what’s going wrong and how to fix it.
The Root Problem
When you swipe your app away from the recent apps list, Android often kills the entire app process to free up memory. The onDestroy() method of your Service isn’t guaranteed to run in this scenario—Android can terminate the process abruptly without calling cleanup methods. That’s why your saved count never gets persisted when the app is closed this way.
Step-by-Step Solutions
1. Persist Counts Immediately (Don’t Wait for onDestroy)
Instead of relying on onDestroy() to save your counter, save the value every time it increments. Use SharedPreferences (perfect for small data like this) or a local database like Room to store the count in real time.
Here’s how to implement this in your broadcast receiver:
public class ScreenOnReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) { // Load current count from SharedPreferences SharedPreferences prefs = context.getSharedPreferences("ScreenTracker", Context.MODE_PRIVATE); int currentCount = prefs.getInt("screen_on_count", 0); // Increment and save immediately currentCount++; prefs.edit() .putInt("screen_on_count", currentCount) .apply(); // Use apply() for async, commit() for sync if needed // Update your UI here (use ViewModel, LiveData, or LocalBroadcast to notify the activity) } } }
2. Initialize Counter from Persistence on App Launch
When your app starts up (e.g., in your main Activity’s onCreate()), load the saved count to restore the previous value:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView countTextView = findViewById(R.id.count_text); SharedPreferences prefs = getSharedPreferences("ScreenTracker", Context.MODE_PRIVATE); int savedCount = prefs.getInt("screen_on_count", 0); // Update UI with the saved count countTextView.setText(String.format("Screen On Count: %d", savedCount)); }
3. Keep Your Broadcast Receiver Active (Use Foreground Service)
Android 8.0+ restricts background services and dynamic broadcast receivers. To ensure your receiver keeps listening for ACTION_SCREEN_ON even when the app is in the background, run a Foreground Service (which shows a persistent notification to let the user know your app is running).
Here’s how to set up the Foreground Service:
public class ScreenTrackingService extends Service { private ScreenOnReceiver screenOnReceiver; @Override public void onCreate() { super.onCreate(); // Register the broadcast receiver IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); screenOnReceiver = new ScreenOnReceiver(); registerReceiver(screenOnReceiver, filter); // Create a notification channel (required for Android 8.0+) createNotificationChannel(); // Start the service in foreground mode Notification notification = new NotificationCompat.Builder(this, "SCREEN_TRACKER_CHANNEL") .setContentTitle("Screen Count Tracker") .setContentText("Tracking screen on events") .setSmallIcon(R.drawable.ic_notification) .setPriority(NotificationCompat.PRIORITY_LOW) .build(); startForeground(1, notification); } @Override public void onDestroy() { super.onDestroy(); // Clean up the receiver when service stops unregisterReceiver(screenOnReceiver); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( "SCREEN_TRACKER_CHANNEL", "Screen Tracker", NotificationManager.IMPORTANCE_LOW ); NotificationManager manager = getSystemService(NotificationManager.class); manager.createNotificationChannel(channel); } } }
Don’t forget to declare the service in your AndroidManifest.xml:
<service android:name=".ScreenTrackingService" android:foregroundServiceType="dataSync" />
Key Takeaways
- Never rely on
onDestroy()for critical data persistence—Android doesn’t guarantee it will run when the process is killed. - Save data incrementally every time the counter changes to avoid losing progress.
- Use Foreground Service to maintain your broadcast receiver’s activity in the background (compliant with Android 8.0+ restrictions).
内容的提问来源于stack exchange,提问作者Omar El banna

