安卓前台服务无法停止

3

我终于设置好了我的应用程序(跟踪实时GPS)以使用前台服务进行跟踪。然而,我现在遇到的问题是,即使我告诉它停止,服务也永远不会停止。每当我从位置客户端获取新位置时,我都会收到日志。我似乎找不到任何解释这个问题的东西,所以希望能得到帮助。

服务的前几个相关方法如下...

@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 是一个 com.google.android.gms.location.LocationRequest

mLocationClient 是一个 com.google.android.gms.common.api.GoogleApiClient

Activity 这样启动它:ContextCompat.startForegroundService(this, buildLocationServiceIntent(true));

并尝试这样停止它:ContextCompat.startForegroundService(this, buildLocationServiceIntent(false)); 这行代码在 activity 的 onDestroy 方法中,如果有影响的话。

你看到的 Log.i 出现在 app 日志中的时间与预期相同。但是在 '停止' 服务后,我的 onLocationChanged 方法中的日志仍然一直出现。我确定我错过了一些简单的东西,只是没有看到它。

Edit

服务代码 -> https://codeshare.io/5D7LvZ 活动代码 -> https://codeshare.io/5g4nO8

Edit v2

这是我的 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'
}

为什么不使用Context.stopService(),并在服务的onDestroy()中处理所有销毁等操作呢? - TheWanderer
@TheWanderer 我没有 Context.stopService(),但是在活动中我可以访问到 stopService(Intent)。这是你的意思吗?如果是的话,我已经尝试过了,但为了确保,我会再试一次。 - Nieminen
@TheWanderer 是的,结果一样。 - Nieminen
你要将带有停止前台操作的 intent 发送到哪里?你试过在 stopSelf() 行设置调试断点吗?检查一下应用是否到达了那一行。 - Aaditya Brahmbhatt
@AadityaBrahmbhatt 我会尽快尝试一下,但我认为我已经做过了。肯定没有抛出任何异常,就是这样。 - Nieminen
1个回答

0

如果有绑定的组件,显式停止服务不会终止服务,而且只有在显式停止服务(如果曾经启动过)之后,解除所有组件的绑定过程才会终止它。此外,请注意,无论您调用startService()方法多少次,只要调用一次stopService()或stopSelf()方法就可以停止它。我认为这个概念将帮助您解决问题。

编辑: 由于我没有足够的声望,因此无法发表评论。因此,我正在编辑我的答案。

如果允许您的服务启动并绑定,则当服务已启动时,系统不会在所有客户端取消绑定时销毁该服务。相反,您必须通过调用stopSelf()或stopService()方法来显式停止服务。然后服务将停止。

这个链接可能会对您有所帮助,

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


如果存在绑定的组件并且我调用stopService()或stopService(),那会发生什么? - navylover
@Sana 我明确调用了 stopServicestopSelf。如果你查看我问题中的 onStartCommand,你会发现在 stop 条件下我有一个 stopSelf()。我还尝试在 onDestroy() 中调用 stopSelf(),它被执行了,但事件仍然继续触发。今天晚些时候我会编辑我的问题,包括整个活动和服务,希望这能提供更有用的上下文。 - Nieminen
我会查看您编辑后的答案,并在Android Studio中尝试。 - Sana
请也发送 app.gradle 文件。这样可以节省我的时间 :) - Sana
@Sana,我已经根据你的要求更新了问题,并附上了app.gradle文件。 - Nieminen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接