Iraklis Eleftheriadis
Iraklis Eleftheriadis

Reputation: 109

How to run a foreground service for 10 seconds, every 5 minutes?

I want to run a Foreground Service whether the app is closed or open for, lets say, 10 seconds. After those 10 seconds have passed, the Foreground Service should be destroyed and be called again after 5 minutes. The Foreground Service I have finds the user's location and then saves it to an SQLite database. So basically I want to store new coordinates once, every 5 minutes, so that I can improve battery consumption.

My Service Class:

public class LocationService extends Service{

private final static int UPDATE_TIME = 10000;
private final static int UPDATE_DISTANCE = 0;

private LocationListener locationListener;
private LocationManager locationManager;

private PowerManager.WakeLock mWakeLock;

private String latitude, longitude;

private DatabaseHelper myDb;

@Override
public void onCreate() {
    super.onCreate();

    myDb = new DatabaseHelper(this);
    locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);

    createWakeLock(); //Creates a wakelock
    createNotification(); //Creates a notification if SDK version is > 26

}

@SuppressLint("MissingPermission")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    mWakeLock.acquire(10*60*500L /*5 minutes*/);

    locationListener = new LocationListener() {

        @Override
        public void onLocationChanged(Location location) {

            Log.d("Location", "Updated");

            getCoordinates(location); //Gets coordinates
            insertCoordinates(latitude, longitude); //Sends coordinates to SQLite database
            sendDataToMainActivity(latitude, longitude); //Sends coordinates to MainActivity

        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

            Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(i);

        }

    };

    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, UPDATE_TIME, UPDATE_DISTANCE, locationListener);

    return START_NOT_STICKY;

}

@Override
public void onDestroy() {

    super.onDestroy();

    Log.d("Service", "Destroyed");

    if(locationManager != null)
        locationManager.removeUpdates(locationListener);

    mWakeLock.release();

}

private void createWakeLock() {

    PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);

    if(pm != null)
        mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "myApp:myWakeLock");

}

private void createNotification() {

    Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this,0, notificationIntent, 0);

    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Service")
            .setContentText("Coordinates Location Running")
            .setContentIntent(pendingIntent)
            .build();

    startForeground(1, notification);

}

private void getCoordinates(Location location) {

    this.latitude = String.valueOf(location.getLatitude());
    this.longitude = String.valueOf(location.getLongitude());

}

private void insertCoordinates(String latitude, String longitude) {

    boolean inserted = myDb.insertData(latitude, longitude); //Insert coordinates

    //Check if insertion is completed
    if(inserted)
        Toast.makeText(LocationService.this, "Coordinates Inserted", Toast.LENGTH_SHORT).show();
    else
        Toast.makeText(LocationService.this, "Coordinates Not Inserted", Toast.LENGTH_SHORT).show();

}

private void sendDataToMainActivity(String latitude, String longitude) {

    Intent i = new Intent("location_update");
    i.putExtra("latitude", latitude);
    i.putExtra("longitude",longitude);

    sendBroadcast(i);

}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

Upvotes: 2

Views: 3636

Answers (3)

Denis Korotenko
Denis Korotenko

Reputation: 1

"Fused Location Api" may not work in background due to power management restrictions. You should use Alarm Manager, but there are some limitations in latest android versions. More about DOZE here

    AlarmManager alarm =
            (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    if (alarm == null) return;  // for instant apps

    Intent intent = new Intent(this, MyBroadcastReceiver.class)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerInMillis,
                PendingIntent.getBroadcast(this, intent, PendingIntent.FLAG_UPDATE_CURRENT));

    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        AlarmManager.AlarmClockInfo ac=
                new AlarmManager.AlarmClockInfo(triggerInMillis, null);
        alarm.setAlarmClock(ac, PendingIntent.getBroadcast(this, intent, PendingIntent.FLAG_UPDATE_CURRENT));

    } else {
        alarm.setExact(AlarmManager.RTC_WAKEUP, triggerInMillis,
                PendingIntent.getBroadcast(this, intent, PendingIntent.FLAG_UPDATE_CURRENT));
    }

Upvotes: 0

Eren Tüfekçi
Eren Tüfekçi

Reputation: 2511

You can use Alarm Manager to set an exact alarm, start service in Alarm's on receive function run the foreground service for 5 minutes than set next alarm

Upvotes: 0

Jinesh Francis
Jinesh Francis

Reputation: 3665

Use Fused Location Api to request location updates,which will trigger a pending intent(Let's say starts an intent service) in the specified repeat interval(Give 5 minutes).So Fused Location Api reads the location every 5 minutes and send it to a intent service,from where you can do your processing.

Please refere this for more details.

Upvotes: 2

Related Questions