3

I want to store a boolean in the Preferences when the user changes the android system time. Therefore I added the broadcast action ACTION_TIME_CHANGED to the manifest:

<receiver android:name="test.TimeChangedReceiver">
   <intent-filter>
      <action android:name="android.intent.action.TIME_SET" />
      <action android:name="android.intent.action.TIMEZONE_CHANGED" />
   </intent-filter>
</receiver>

The TimeChangedReceiver extends the BroadcastReceiver and overrides onReceive(). In this class the boolean will be stored and a notification will be shown.

public class TimeChangedReceiver extends BroadcastReceiver {

private static final String TAG = "TimeChangedReceiver";

public TimeChangedReceiver() {
    super();
}

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

    // store boolean to SharedPreferences
    PreferenceUtils.getInstance().storeBoolean(true, PreferenceUtils.CHECK_LICENSE);

    // build notification 
    int icon = android.R.drawable.ic_dialog_alert;
    String title = "changed time";
    String text = "user changed time";

    long when = System.currentTimeMillis();
    String timezone = intent.getStringExtra("time-zone");
    Notification notification = new Notification(icon, title, when);
    NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    int notification_id = (int) System.currentTimeMillis();
    Intent notificationIntent = new Intent(context, MainView.class);
    notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    notificationIntent.putExtra("time-zone", timezone);
    PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_ONE_SHOT );
    notification.setLatestEventInfo(context, title, text, contentIntent);
    mgr.notify(notification_id, notification);
}

}

Everything is working fine until the app is closed - not runnning in the background anymore.

Here it says:


How can I receive the broadcast anyway and store the boolean?

I don't need to see the notification.

Community
  • 1
  • 1
maryBlaa
  • 115
  • 10
  • Try to add `android:enabled="true"` to your receiver inside of `` after or before the `android:name="..."` attribute – Marat Oct 10 '16 at 09:47
  • It is enabled by default ^ – Tim Oct 10 '16 at 09:53
  • @Marat [link](https://developer.android.com/guide/topics/manifest/receiver-element.html) The default value is "true". It changes nothing. :( – maryBlaa Oct 10 '16 at 09:57
  • Could you test your app with `Log` to make sure that it is not running `onReceive` when app is not active? – Marat Oct 10 '16 at 10:17
  • @Marat I tested it on a Samsung with Android 6.0.1. There are logs when the app is in the background. There are no logs when I "force stop" the application and changing the date afterwards. – maryBlaa Oct 10 '16 at 14:54
  • I need to clarify, what do you mean by "force stopping" app? Do you mean just closing the app from recently opened apps? Or you mean the disabling the app from the Settings - > Apps -> Your app -> Stop App? – Marat Oct 10 '16 at 15:00
  • @Marat, going to Settings - Application Manager - Choose app - click on Force Stop (for a Samsung phone) or going to Settings - Manage apps - Choose app - click on Force Stop (for Huawei phones) For clarification: On Samsung the broadcast will receive when the app is in the background or swiped away, but will not receive when the app will be "forced stopped". On Huawei the broadcast will receive only when the app is in the background. It will not receive when it's swiped away or "forced stopped". – maryBlaa Oct 10 '16 at 15:08

2 Answers2

3

Everything is working fine until the app is closed - not runnning in the background anymore.

There are no logs when I "force stop" the application and changing the date afterwards.

Your observation is correct and considered to be the normal behaviour. After you did a "force stop" via the system settings, your BroadcastReceiver will no longer receive the messages, even when you declared them in your AndroidManifest.xml. By executing a "force stop" you basically instruct the system: "stop this app now and don't let it run again". It is an administrative action, hence it is only accessible from the system settings. This makes sense doesn't it? The same is true for a freshly installed app. It will not receive any broadcast intents until it got started at least once.

That's how the Android system is designed. You can't do anything against it.

How can I receive the broadcast anyway and store the boolean?

After a "force stop", your app (or one of it's components) has to be manually (re)started by the user at least once again. In that case the receiver declared in your AndroidManifest.xml will receive the broadcast intents as expected even after a full system reboot.

You should not confuse a "force stop" with the situation where the system destroys your app (e.g. because of lacking memory). These are not the same, as the "force stop" sets a permanent flag for your app which prevents it from running again.

reflective_mind
  • 1,407
  • 3
  • 14
  • 26
0

From the docs:

A process that is currently executing a BroadcastReceiver (that is, currently running the code in its onReceive(Context, Intent) method) is considered to be a foreground process and will be kept running by the system except under cases of extreme memory pressure.

Then

This means that for longer-running operations you will often use a Service in conjunction with a BroadcastReceiver to keep the containing process active for the entire time of your operation.

So I guess you need to implement a service that registers the receiver to make sure that the receiver's process has a high priority and thus keeps running.

Mina Samy
  • 10,466
  • 13
  • 86
  • 149
  • How could I start a never ending service that listen to the ACTION_TIME_CHANGED broadcast from android? @Mina Samy – maryBlaa Oct 10 '16 at 14:42
  • When you "Force stop" the app, the process is terminated, so the receiver cannot receive events unless the application's process is live again. That's a normal behavior because the user wants to force stop your app intentionally. A workaround is described here http://stackoverflow.com/a/21551045/235123 where you can keep your process alive even if the application was Force Stopped – Mina Samy Oct 10 '16 at 15:07