如何防止Service被销毁

5

我有一个Service,用于跟踪用户的位置,在某个时间点上,我通过GoogleApiClient获取用户的位置。

有时候会发生Service停止的情况,这取决于互联网或手机型号,Service停止向Web服务发送位置信息。看起来像是被销毁了。

我该如何防止这种情况发生?

public class LocationService extends Service implements
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener {

    private static final String TAG = "LocationService";
    public long UPDATE_MILLISECONDS_DEFAULT = 180000;

    private boolean currentlyProcessingLocation = false;
    private LocationRequest locationRequest;
    private GoogleApiClient googleApiClient;

    @Override
    public void onCreate() {
        Log.d(TAG,"Location service create");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // if we are currently trying to get a location and the alarm manager has called this again,
        // no need to start processing a new location.
        if (!currentlyProcessingLocation) {
            currentlyProcessingLocation = true;
            startTracking();
        }

        return START_NOT_STICKY;
    }

    private void startTracking() {
        Log.d(TAG, "startTracking");

        if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
            googleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();

            if (!googleApiClient.isConnected() || !googleApiClient.isConnecting()) {
                googleApiClient.connect();
            }
        } else {
            Log.e(TAG, "unable to connect to google play services.");
        }
    }

    protected void sendLocationToServer(Location location) {
            // here I call my webservice and send location
            Log.d(TAG, "Update to Server location");
    }

    @Override
    public void onDestroy() {
        Log.d(TAG,"Destroy service");
        stopLocationUpdates();
        super.onDestroy();

    }


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

    @Override
    public void onLocationChanged(Location location) {
       sendLocationToServer(location);
    }

    public void stopLocationUpdates() {
        if (googleApiClient != null && googleApiClient.isConnected()) {
            googleApiClient.disconnect();
        }
    }

    /**
     * Called by Location Services when the request to connect the
     * client finishes successfully. At this point, you can
     * request the current location or start periodic updates
     */
    @Override
    public void onConnected(Bundle bundle) {
        Log.d(TAG, "onConnected");

        locationRequest = LocationRequest.create();
            locationRequest.setInterval(UPDATE_MILLISECONDS_DEFAULT); // milliseconds for default
            locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);


        //locationRequest.setFastestInterval(1000); // the fastest rate in milliseconds at which your app can handle location updates

        LocationServices.FusedLocationApi.requestLocationUpdates(
                googleApiClient, locationRequest, this);
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.e(TAG, "onConnectionFailed");

        stopLocationUpdates();
        stopSelf();
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.e(TAG, "GoogleApiClient connection has been suspend");
    }


}
2个回答

6

你正在从onStartCommand()返回START_NOT_STICKY

因此,每当操作系统杀死您的Service(例如为了回收内存)时,它将不会重新创建。

请更改以下行:

return START_NOT_STICKY;

转换为这样:

return START_STICKY;

START_STICKY 的文档中可以得知:START_STICKY 是在 onStartCommand(Intent, int, int) 中返回的常量。如果该服务的进程在启动后被杀死(在从 onStartCommand(Intent, int, int) 返回后),则保持其处于已启动状态,但不保留此传递的 Intent。稍后系统将尝试重新创建该服务。因为它处于已启动状态,所以它将保证在创建新服务实例后调用 onStartCommand(Intent, int, int);如果没有任何待处理的启动命令要传递到服务,则会使用空 intent 对象调用它,因此您必须注意检查此情况。
注意: START_STICKY 不能防止您的 Service 被杀死。它只是告诉操作系统尽快重新启动它(取决于可用资源)。如果您想让您的 Service 更不容易被杀死,您可以通过调用 startForeground() 方法使其在前台运行。

0

你只需要更改这行代码

 @Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // if we are currently trying to get a location and the alarm manager has called this again,
    // no need to start processing a new location.
    if (!currentlyProcessingLocation) {
        currentlyProcessingLocation = true;
        startTracking();
    }

    return START_STICKY;
}

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