3

I've finally set up my app (tracking live GPS) to track using a foreground service. However the issue I'm running into now, is the service never stops, even after I tell it to. I keep getting logs whenever I get a new location from the location client. I can't seem to find anything that explains this anywhere, so any help would be appreciated.

Service's first few relevant methods look like this...

@Override
public void onCreate() {
    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? createNotificationChannel(notificationManager) : "";
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId);
    Notification notification = notificationBuilder.setOngoing(true)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setPriority(PRIORITY_MIN)
            .setCategory(NotificationCompat.CATEGORY_SERVICE)
            .build();

    startForeground(ID_SERVICE, notification);
}

@RequiresApi(Build.VERSION_CODES.O)
private String createNotificationChannel(NotificationManager notificationManager){
    String channelId = "my_service_channelid";
    String channelName = "My Foreground Service";
    NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
    // omitted the LED color
    channel.setImportance(NotificationManager.IMPORTANCE_NONE);
    channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
    notificationManager.createNotificationChannel(channel);
    return channelId;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    if (intent.getAction().equals(Constants.STARTFOREGROUND_ACTION)) {
        Log.i(TAG, "Received Start Foreground Intent");
        mLocationClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

        mLocationRequest.setInterval(LOCATION_INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_LOCATION_INTERVAL);

        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationClient.connect();
    } else if (intent.getAction().equals(Constants.STOPFOREGROUND_ACTION)) {
        Log.i(TAG, "Received Stop Foreground Intent");
        mLocationClient.disconnect();
        mLocationClient.unregisterConnectionCallbacks(this);
        stopForeground(true);
        stopSelf();
    }
    //Make it stick to the notification panel so it is less prone to get cancelled by the Operating System.
    return START_STICKY;
}

mLocationRequest is a com.google.android.gms.location.LocationRequest

mLocationClient is a com.google.android.gms.common.api.GoogleApiClient

Activity starts it like so: ContextCompat.startForegroundService(this, buildLocationServiceIntent(true));

And attempts to stop it like this: ContextCompat.startForegroundService(this, buildLocationServiceIntent(false)); This line is in the onDestroy method on the activity if that matters.

The Log.i's you see appear in my app log exactly when you'd expect them to. But the logs from my onLocationChanged method keep coming indefinitely after 'stopping' the service. I'm sure I'm missing something simple, I'm just not seeing it.

Edit

Service code -> https://codeshare.io/5D7LvZ Activity code -> https://codeshare.io/5g4nO8

Edit v2

Here's my app.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "[[appid]]"
        minSdkVersion 18
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

ext {
    androidSupportVersion = "27.1.1"
    playServicesVersion = "15.0.1"
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "com.android.support:appcompat-v7:${androidSupportVersion}"
    implementation "com.android.support:design:${androidSupportVersion}"
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    implementation 'com.android.support:support-v4:27.1.1'
    implementation 'com.android.support:recyclerview-v7:27.1.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation('com.mikepenz:materialdrawer:6.0.7') {
        transitive = true
    }
    //required support lib modules
    implementation "com.android.support:appcompat-v7:${androidSupportVersion}"
    implementation "com.android.support:recyclerview-v7:${androidSupportVersion}"
    implementation "com.android.support:support-annotations:${androidSupportVersion}"
    implementation "com.android.support:design:${androidSupportVersion}"

    implementation "com.google.android.gms:play-services-maps:${playServicesVersion}"
    implementation "com.google.android.gms:play-services-location:${playServicesVersion}"

    implementation 'javax.annotation:jsr250-api:1.0'
    implementation 'com.google.dagger:dagger:2.0.1'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.0.1'

    implementation "com.mikepenz:iconics-core:3.0.4@aar"
    implementation "com.mikepenz:iconics-views:3.0.4@aar"
    implementation 'com.mikepenz:google-material-typeface:3.0.1.2.original@aar'
    implementation 'com.mikepenz:material-design-iconic-typeface:2.2.0.4@aar'
    implementation 'com.mikepenz:fontawesome-typeface:5.0.13.0@aar'
    implementation 'com.google.android.gms:play-services-maps:15.0.1'
    implementation 'com.google.code.gson:gson:2.8.5'
}
Nieminen
  • 1,284
  • 2
  • 13
  • 31
  • Why don't you use `Context.stopService()` and just handle all your destroys and such in the Service's `onDestroy()`? – TheWanderer Sep 07 '18 at 00:01
  • @TheWanderer I don't have a `Context.stopService()`, but there's a `stopService(Intent)` I have access to in the activity. Is that what you mean? If so, I've already tried that, But I'll give it another go, just in case. – Nieminen Sep 07 '18 at 02:37
  • @TheWanderer Yep, same result. – Nieminen Sep 07 '18 at 02:44
  • Where do you send intent with action to stop foreground? Have you tried placing debug point at `stopSelf()` line. Check if app even goes to that line. – Aaditya Brahmbhatt Sep 07 '18 at 03:07
  • @AadityaBrahmbhatt I'll give that a go as soon as I have opportunity to, but I think I've already done that. There's certainly no exceptions being thrown, so there's that. – Nieminen Sep 08 '18 at 13:40

1 Answers1

0

Stopping a service explicitly wouldn't terminate the service as long as there are bound components, and te unbinding all components process wouldn't terminate it until it’s explicitly stopped (if it was ever started). Also note that no matter how many times you call te metod startService(), a single call to stopService() or stopSelf() will stop it.I think this concept will help you to solve your issue.

Edit: As I do not have enough reputation I am unable to comment.Therefor I am editing my answer.

If you do allow your service to be started and bound, then when the service has been started, the system does not destroy the service when all clients unbind. Instead, you must explicitly stop the service by calling stopSelf() or stopService().Then the service will stop.

This link may help you,

https://developer.android.com/guide/components/bound-services

Sana
  • 456
  • 3
  • 9
  • If there are bound components and I call stopService() or stopService(), then what happed? – navylover Sep 07 '18 at 12:19
  • @Sana I am explicitly calling `stopService` and `stopSelf`. If you check out the `onStartCommand` in my question, I've got `stopSelf()` in there on the `stop` condition. I've also tried calling `stopSelf()` in `onDestroy()` and it gets hit, but the events keep firing. Later today I'll edit my question with the entire activity, and service, so hopefully that'll provide a little more useful context. – Nieminen Sep 07 '18 at 16:31
  • I will look for your edited answer.I will try on that in android studio. – Sana Sep 07 '18 at 16:58
  • Please also send the app.gradle file.It will save my time :) – Sana Sep 08 '18 at 13:53
  • @Sana I've once again updated the question with your requested app.gradle file. – Nieminen Sep 15 '18 at 00:19