Skip to content

Android service not working when app is closed

I’m having trouble with an android service that I’m doing. The service is about to get the location of the user every 5 minutes. All seems to go well except when i kill the app, the service won’t do nothing. In the code you will ses its checking every 60 seconds I think, but this will change to 5 minutes.

Minimum Target Version: API 23

Target Version: API 29

Android Manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.venomapps.meets">

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

<application
    android:name=".Utils.App"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".Activities.RegisterActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".Activities.MainActivity" />
    <activity android:name=".Activities.LoginActivity">
    </activity>

    <service android:name=".Services.LocationService"
        android:enabled="true"
        android:exported="true"/>
</application>

Code that executes the service:

AlarmManager am=(AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getApplicationContext(), LocationService.class);                            intent.setAction(Constants.ACTION_START_LOCATION_SERVICE);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), Constants.LOCATION_SERVICE_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), 60000, pendingIntent);

Service:

public class LocationService extends Service {
private LocationCallback locationCallback = new LocationCallback() {
    @Override
    public void onLocationResult(LocationResult locationResult) {
        super.onLocationResult(locationResult);
        if (locationResult != null && locationResult.getLastLocation() != null) {
            double latitude = locationResult.getLastLocation().getLatitude();
            double longitude = locationResult.getLastLocation().getLongitude();
            Log.d("LOCATION_UPDATE", latitude + ", " + longitude);
            stopLocationService();
        }
    }
};

@Nullable
@Override
public IBinder onBind(Intent intent) {
    throw new UnsupportedOperationException("Not yet implemented");
}

public void startLocationService() {
    String channelId = "location_notification_channel";
    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    Intent resultIntent = new Intent();
    PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    NotificationCompat.Builder builder = new NotificationCompat.Builder(
            getApplicationContext(),
            channelId
    );
    builder.setSmallIcon(R.drawable.ic_app);
    builder.setContentTitle("Location Service");
    builder.setDefaults(NotificationCompat.DEFAULT_ALL);
    builder.setContentText("Running");
    builder.setContentIntent(pendingIntent);
    builder.setAutoCancel(false);
    builder.setPriority(NotificationCompat.PRIORITY_MAX);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        if (notificationManager != null && notificationManager.getNotificationChannel(channelId) == null) {
            NotificationChannel notificationChannel = new NotificationChannel(
                    channelId, "Location Service", NotificationManager.IMPORTANCE_HIGH
            );
            notificationChannel.setDescription("This channel is used by location service");
            notificationManager.createNotificationChannel(notificationChannel);
        }
    }

    LocationRequest locationRequest = new LocationRequest();
    locationRequest.setInterval(8000);
    locationRequest.setFastestInterval(5000);
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    LocationServices.getFusedLocationProviderClient(this)
            .requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper());
    startForeground(Constants.LOCATION_SERVICE_ID, builder.build());
}

private void stopLocationService(){
    LocationServices.getFusedLocationProviderClient(this)
            .removeLocationUpdates(locationCallback);
    stopForeground(true);
    stopSelf();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if(intent != null){
        String action = intent.getAction();
        if(action != null){
            if(action.equals(Constants.ACTION_START_LOCATION_SERVICE)){
                startLocationService();
            }
        }
    }
    return super.onStartCommand(intent, flags, startId);
}

}

Answer

AlarmManager is deprecated if used for that purpose. Have a look at WorkManager.