Android前台服务不会停止

Posted

技术标签:

【中文标题】Android前台服务不会停止【英文标题】:Android foreground service won't stop 【发布时间】:2019-02-12 06:28:26 【问题描述】:

我终于设置了我的应用程序(跟踪实时 GPS)以使用前台服务进行跟踪。但是,我现在遇到的问题是服务永远不会停止,即使在我告诉它之后也是如此。每当我从位置客户端获得新位置时,我都会不断获取日志。我似乎在任何地方都找不到任何解释这一点的东西,因此我们将不胜感激。

Service的前几个相关方法是这样的……

@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;

mLocationRequestcom.google.android.gms.location.LocationRequest

mLocationClientcom.google.android.gms.common.api.GoogleApiClient

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

并且 尝试 像这样阻止它: ContextCompat.startForegroundService(this, buildLocationServiceIntent(false)); 如果重要的话,这一行在活动的onDestroy 方法中。

您看到的Log.i 完全按照您的预期出现在我的应用日志中。但是我的onLocationChanged 方法的日志在“停止”服务后会无限期地出现。我确定我错过了一些简单的东西,我只是没有看到它。

编辑

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

编辑 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 我没有Context.stopService(),但我可以在活动中访问stopService(Intent)。你是这个意思吗?如果是这样,我已经尝试过了,但我会再试一次,以防万一。 @TheWanderer 是的,同样的结果。 你在哪里发送意图以停止前台的操作?您是否尝试将调试点放在stopSelf() 行。检查应用程序是否甚至进入该行。 @AadityaBrahmbhatt 我会尽快尝试,但我想我已经做到了。肯定不会抛出异常,所以就是这样。 【参考方案1】:

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

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

如果您确实允许启动和绑定您的服务,那么当服务已启动时,系统不会在所有客户端解除绑定时销毁该服务。相反,您必须通过调用 stopSelf() 或 stopService() 显式停止服务。然后服务将停止。

此链接可能对您有所帮助,

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

【讨论】:

如果有绑定的组件,我调用了stopService()或stopService(),那么发生了什么? @Sana 我明确地打电话给stopServicestopSelf。如果您查看我的问题中的onStartCommand,我在stop 条件下有stopSelf()。我也尝试在onDestroy() 中调用stopSelf() 并被击中,但事件不断触发。今天晚些时候,我将使用整个活动和服务来编辑我的问题,因此希望这会提供一些更有用的上下文。 我会寻找你编辑的答案。我会在 android studio 中尝试。 请同时发送 app.gradle 文件。它将节省我的时间:) @Sana 我再次使用您请求的 app.gradle 文件更新了问题。

以上是关于Android前台服务不会停止的主要内容,如果未能解决你的问题,请参考以下文章

当我在 Android 设置中手动禁用位置时,为啥 Android 前台服务会停止?

为啥在 Android Oreo 上关闭屏幕时前台服务停止?

Android 服务的限制

Android:更改联系人时,带有广播接收器的前台服务停止工作

如果我按下“全部清除”按钮,为啥我的前台服务会停止

Android 使用前台服务