Android 6.0.0中onStartCommand的START_STICKY [英] START_STICKY of onStartCommand in Android 6.0.0
问题描述
我正在使用一些启动服务的应用程序.
I am working with some application which starts a service.
当我在 Android 7.0.0下关闭应用程序时,其服务可以继续正常运行.
但是在Android 6.0.0中却没有.
我使用此代码段来保持服务正常
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;
}
我在这里想念什么?
服务类别的代码
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;
}
}
推荐答案
在清单中使用属性 android:stopWithTask ="false" (如果为true)(如果您不使用此属性,则默认为false在清单中).
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"/>
在onTaskRemoved()上重新启动服务.
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);
}
如文档所述
如果服务当前正在运行并且用户已删除来自服务应用程序的任务,则将调用onTaskRemoved.如果已设置ServiceInfo.FLAG_STOP_WITH_TASK,则将不会收到此回调.相反,该服务只会停止.
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.
这篇关于Android 6.0.0中onStartCommand的START_STICKY的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!