简体   繁体   中英

Locations updates stay active when Android app is not longer active

I have the following problem: I send in regular interval GPS data from the mobile to a server. In fact I want this background service only running as long the user is willing to submit data. There should be some sort of confirmation dialog that from now on data are submitted and then these submissions should be active - event if the App is shutdown meanwhile - until the user again confirms that data should be no longer sended:

Here is my current entry in the AndroidManifest.xml:

   ....
   <receiver
        android:name="ch.bbcag.jumpin.app.receiver.gps.ConnectivityReceiver"
        android:process=":gps_process" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.USER_PRESENT" />
        </intent-filter>
    </receiver>
    <receiver
        android:name="ch.bbcag.jumpin.app.service.LocationUpdaterService"
        android:process=":gps_process" />

    <service
        android:name="ch.bbcag.jumpin.app.service.LocationUpdaterService"
        android:process=":gps_process" />

    ....

GcmIntentService.java:

public class ConnectivityReceiver extends BroadcastReceiver {
   private static final int EXEC_INTERVAL = AppConstants.GPS_REPEAT_SECONDS * 1000;
   private final static String TAG =  "ch.bbcag.jumpin.app.receiver.gps.ConnectivityReceiver";

   @Override
   public void onReceive(Context context, Intent intent) {  
      Log.d(TAG, "Received event"); 
      final AlarmManager alarmManager = (AlarmManager) context
            .getSystemService(Context.ALARM_SERVICE);
      final PendingIntent wakeupIntent = PendingIntent.getService(context, 0,
            new Intent(context, LocationUpdaterService.class),
            PendingIntent.FLAG_UPDATE_CURRENT);
      final boolean hasNetwork = !intent.getBooleanExtra(
            ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
      if (hasNetwork) {
          context.startService(new Intent(context,LocationUpdaterService.class));
          Calendar now = Calendar.getInstance();
          now.add(Calendar.SECOND, AppConstants.GPS_REPEAT_SECONDS);
          alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,            now.getTimeInMillis(), EXEC_INTERVAL, wakeupIntent);
      } else {
          alarmManager.cancel(wakeupIntent);
      }
  }
}

The problem with this approach is that event the user is not using the App events are sent to the server. A simple solution would be in the class LocationUpdaterService to check in preferences if app should really send events. But the fact stays that LocationsUpdaterService is called regularly even if I don't use it (and Android wastes time to call this service).

How I can figure this out? Articles? Code examples are welcome!

How I can figure this out?

Only schedule your alarms when you need them. If you no longer need them, cancel the alarms.

Also, if you are going to use RTC_WAKEUP , either use WakefulBroadcastReceiver or my WakefulIntentService , otherwise your alarms will not be reliable.

Also also, your manifest is malformed. Either ch.bbcag.jumpin.app.service.LocationUpdaterService is a <receiver> or it is a <service> , but it cannot be both.

And also also also, dump the android:process=":gps_process" unless you have a clear understanding of why you are using it and its costs to you and the users.

I just have to read the documentation from Google to get aware how things are really working:

1) I don't want to start the Alarm when the device boots:

Solution: (AndroidManifest.xml)

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver android:name=".SampleBootReceiver"
    android:enabled="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"></action>
    </intent-filter>
</receiver>

Notice that in the manifest, the boot receiver is set to android:enabled="false"

This means that the receiver will not be called unless the application explicitly enables it. This prevents the boot receiver from being called unnecessarily. Once you have started the your App you can:

ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
PackageManager pm = context.getPackageManager();

pm.setComponentEnabledSetting(receiver,
    PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
    PackageManager.DONT_KILL_APP);

From this point on the GPS locations are send in regular intervals to the server. Once you have done this, the next time the receiver will start on boot up. This is what i want to prevent.

2) Prevent automatically starting BootReceiver from boot:

For this purpose I'm looking for a possibility to get the shutdown event of the Android system:

<uses-permission android:name="android.permission.DEVICE_POWER" />

<receiver android:name=".ShutdownReceiver">
   <intent-filter>
      <action android:name="android.intent.action.ACTION_SHUTDOWN" />
   </intent-filter>
</receiver>

public class ShutdownReceiver extends BroadcastReceiver {

   @Override
   public void onReceive(Context context, Intent intent) {
     ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
     PackageManager pm = context.getPackageManager();

     pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP);
   }

}

This has the effect that next time the mobile boots it will not start automatically the SampleBootReceiver until you explicitly specify this with the code:

pm.setComponentEnabledSetting(receiver,
    PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
    PackageManager.DONT_KILL_APP);

3) Conclusions:

a) Once your App is started the Receiver is activated: GPS coordinates go in regular intervals to the server

b) In your App you can make a setting to terminated the receiver or to enable it.

c) Finally if the handy shut down it's time to remove the receiver.

d) The next time you can restart with a)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM