START_STICKY of onStartCommand in Android 6.0.0

2019-08-02 01:32发布

I am working with some application which starts a service.

When I close app under Android 7.0.0 its service is continue working fine.

But under Android 6.0.0 it does not.

I use this snippet to keep working service

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
 // We want this service to continue running until it is explicitly
 // stopped, so return sticky.

 return START_STICKY;
}

What do I missing here?

Code of the service class

import android.Manifest;
//import android.app.LoaderManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
//import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
//import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
//import android.support.v4.content.ContextCompat;
//import android.telephony.TelephonyManager;
import android.text.format.DateFormat;
import android.util.Log;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.gson.Gson;

import java.util.Date;
import java.util.Timer;
//import java.util.TimerTask;
import java.io.*;
import java.net.*;
//import java.util.Timer;
//import java.util.TimerTask;

import static com.google.android.gms.location.LocationServices.getFusedLocationProviderClient;


public class gps_service extends Service {

    private static final String TAG = "MyService";
    private LocationListener listener;
    private LocationManager locationManager;
    private Timer timer = new Timer();
    // private DLocation dLocation;
    private final Object lock = new Object();
    Context context;

    private LocationRequest mLocationRequest;
    private long UPDATE_INTERVAL = 60 * 1000;  /* 60 secs */
    private long FASTEST_INTERVAL = 10000; /* 10 sec */

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // We want this service to continue running until it is explicitly
        // stopped, so return sticky.

        startLocationUpdates();

        return START_STICKY;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        context = this;

    }

    // Trigger new location updates at interval
    protected void startLocationUpdates() {

        // Create the location request to start receiving updates
        mLocationRequest = new LocationRequest();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(UPDATE_INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);

        // Create LocationSettingsRequest object using location request
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        builder.addLocationRequest(mLocationRequest);
        LocationSettingsRequest locationSettingsRequest = builder.build();

        // Check whether location settings are satisfied
        // https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
        SettingsClient settingsClient = LocationServices.getSettingsClient(this);
        settingsClient.checkLocationSettings(locationSettingsRequest);

        // new Google API SDK v11 uses getFusedLocationProviderClient(this)
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }


        getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, new LocationCallback() {
                    @Override
                    public void onLocationResult(LocationResult locationResult) {
                        // do work here
                        onLocationChanged(locationResult.getLastLocation());
                    }
                }, Looper.myLooper());
    }

    public void getLastLocation() {
        // Get last known recent location using new Google Play Services SDK (v11+)
        FusedLocationProviderClient locationClient = getFusedLocationProviderClient(this);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }

        locationClient.getLastLocation()
                .addOnSuccessListener(new OnSuccessListener<Location>() {
                    @Override
                    public void onSuccess(Location location) {
                        // GPS location can be null if GPS is switched off
                        if (location != null) {
                            onLocationChanged(location);
                        }
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.d(TAG, "Ошибка получения последнего GPS позиции");
                        e.printStackTrace();
                    }
                });
    }

    public void onLocationChanged(Location location) {
        // New location has now been determined
        try
        {
            ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(context, "App_Settings", 0);
            AppSettings appSettings = complexPreferences.getObject("App_Settings", AppSettings.class);
            if (appSettings != null) {

                LocationItem locationItem = new LocationItem();
                locationItem.DeviceID = appSettings.getDeviceID();
                locationItem.Latitude =  Double.toString(location.getLatitude());
                locationItem.Longitude = Double.toString(location.getLongitude());
                Date d = new Date();
                CharSequence timeOfRequest = DateFormat.format("yyyy-MM-dd HH:mm:ss", d.getTime()); // YYYY-MM-DD HH:mm:ss
                locationItem.TimeOfRequest = timeOfRequest.toString();
                locationItem.SerialNumber = appSettings.getSerialNumber();

                //**************** Отправка сообщения в окно *********************
                Intent i = new Intent("location_update");
                Log.d(TAG, "Рассылка по слушателям в окнах");
                DLocation dLocation = new  DLocation();
                dLocation.Latitude = locationItem.Latitude;
                dLocation.Longitude = locationItem.Longitude;
                dLocation.TimeOfRequest = locationItem.TimeOfRequest;
                dLocation.Errors = "Данные передаются...";
                i.putExtra("coordinates", dLocation);
                sendBroadcast(i);
                //**************** Отправка сообщения в окно *********************

                Gson gson = new Gson();
                String requestObject = gson.toJson(locationItem);
                Log.d(TAG, "Формирование URL API сервера");
                String url = appSettings.getIpAddress() + "/api/staff/savedata";
                makeRequest(url, requestObject, dLocation);
            }
        }
        catch (Exception ex)
        {
            Log.d(TAG, "Ошибка: " + ex.getMessage());
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (locationManager != null) {
            locationManager.removeUpdates(listener);
        }
    }

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


    public void makeRequest(String uri, String json, DLocation dLocation) {

        HandlerThread handlerThread = new HandlerThread("URLConnection");
        handlerThread.start();
        Handler mainHandler = new Handler(handlerThread.getLooper());

        Runnable myRunnable = createRunnable(uri, json, dLocation);

        mainHandler.post(myRunnable);
    }

    private Runnable createRunnable(final String uri, final String data,final DLocation dLocation){

        Runnable aRunnable = new Runnable(){
            public void run(){
                try {
                    Log.d(TAG, "Перед запросом HTTP");

                    //Connect
                    HttpURLConnection urlConnection;
                    urlConnection = (HttpURLConnection) ((new URL(uri).openConnection()));
                    urlConnection.setDoOutput(true);
                    urlConnection.setRequestProperty("Content-Type", "application/json");
                    urlConnection.setRequestProperty("Accept", "application/json");
                    urlConnection.setRequestMethod("POST");
                    urlConnection.connect();

                    //Write
                    OutputStream outputStream = urlConnection.getOutputStream();
                    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
                    try {
                        writer.write(data);
                    } catch (IOException e) {
                        e.printStackTrace();
                        Log.d(TAG,"Ошибка записи в буфер для пережачи по HTTP");
                    }
                    writer.close();
                    outputStream.close();

                    //Read
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));

                    String line = null;
                    StringBuilder sb = new StringBuilder();

                    while ((line = bufferedReader.readLine()) != null) {
                        sb.append(line);
                    }

                    bufferedReader.close();
                    String result = sb.toString();

                    Log.d(TAG, "После запроса HTTP");
                    Log.d(TAG, result);

                    // Log.d(TAG, "Результат передачи: " + result);
                    //**************** Отправка сообщения в окно *********************
                    Intent iResult = new Intent("location_update");
                    Log.d(TAG, "Рассылка по слушателям в окнах");
                    DLocation dLocation = new DLocation();
                    if(result.equals("true"))
                    {
                        dLocation.Errors = "Данные успешно переданы.";
                    }
                    else
                    {
                        dLocation.Errors = "Ошибка передачи данных.";
                    }
                    iResult.putExtra("result", dLocation);
                    sendBroadcast(iResult);
                    //**************** Отправка сообщения в окно *********************

                }catch( Exception err){
                    err.printStackTrace();
                    Log.d(TAG, "Ошибка HTTP " + err.getMessage());
                }
            }
        };

        return aRunnable;

    } 
}

1条回答
祖国的老花朵
2楼-- · 2019-08-02 01:33

Use attribute android:stopWithTask="false" in manifest, if its true (By default its false if you are not using this in manifest).

<service
        android:name=".gps_service"
        android:enabled="true"
        android:stopWithTask="false"/>

restart the service on onTaskRemoved().

 @Override
public void onTaskRemoved(Intent rootIntent) {
        Intent restartService = new Intent(getApplicationContext(),
                this.getClass());
        restartService.setPackage(getPackageName());
        PendingIntent restartServicePI = PendingIntent.getService(
                getApplicationContext(), 1, restartService,
                PendingIntent.FLAG_ONE_SHOT);
        AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
        alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000, restartServicePI);
}

As documentation says

onTaskRemoved will called if the service is currently running and the user has removed a task that comes from the service's application. If you have set ServiceInfo.FLAG_STOP_WITH_TASK then you will not receive this callback; instead, the service will simply be stopped.

查看更多
登录 后发表回答