Мне нужно выполнять несколько задач параллельно в пользовательской службе, чтобы заставить их работать:
- Служба определения местоположения и API распознавания действий.
- API Geofence и вызовы REST API.
Я новичок в потоках в Java и Android, и я обнаружил, что лучший способ реализовать это — использовать ThreadPoolExecutor вместо того, чтобы создавать свои собственные классы потоков и иметь дело со всеми вещами Handler Looper.
Когда я запускаю свое приложение, служба запускается, обновления местоположения и обновления активности работают нормально внутри потока. но когда я закрываю приложение, служба перезапускается (когда return START_STICKY;
), и поток больше не работает. Когда (return START_NOT_STICKY;
), служба исчезает. (В моем случае я не могу использовать startforeground())
Я использую эту библиотеку(smart-location-lib) для получения обновлений о местоположении и действиях.
– Вот код моей специальной службы:
public class LocationService extends Service {
private ThreadPoolExecutor mDecodeThreadPool;
private BlockingQueue<Runnable> mDecodeWorkQueue;
private int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
private final int KEEP_ALIVE_TIME = 1;
private final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
public LocationService () {
}
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Location services created", Toast.LENGTH_SHORT).show();
mDecodeWorkQueue = new LinkedBlockingQueue<Runnable>();
mDecodeThreadPool = new ThreadPoolExecutor(
NUMBER_OF_CORES * 2, // Initial pool size
NUMBER_OF_CORES * 2, // Max pool size
KEEP_ALIVE_TIME,
KEEP_ALIVE_TIME_UNIT,
mDecodeWorkQueue);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Location services started", Toast.LENGTH_SHORT).show();
mDecodeThreadPool.execute(new LocationRunnable(getApplicationContext()));
return START_STICKY;
}
@Override
public void onLowMemory() {
super.onLowMemory();
Log.v("LOW MEMORY", "|||||||||||||||||||||||||||||||||||||");
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onDestroy() {
Toast.makeText(this, "Location services stopped", Toast.LENGTH_LONG).show();
mDecodeThreadPool.shutdown();
mDecodeThreadPool.shutdownNow();
super.onDestroy();
}
}
- Вот мой код класса Runnable:
public class LocationRunnable implements Runnable, OnLocationUpdatedListener, OnActivityUpdatedListener {
SmartLocation smartLocation;
public LocationRunnable(Context ctx) {
smartLocation = new SmartLocation.Builder(ctx).logging(true).build();
}
@Override
public void run() {
Log.v("THREAD", "THREAD STARTED");
startLocation();
}
private void startLocation() {
smartLocation.location().start(this);
smartLocation.activity().start(this);
}
@Override
public void onActivityUpdated(DetectedActivity detectedActivity) {
if (detectedActivity != null) {
Log.v("ACTIVITY", "ACTIVITY UPDATED");
} else {
Log.v("ACTIVITY", "NULL");
}
}
int i = 0;
@Override
public void onLocationUpdated(Location location) {
Log.v("LOCATION", "LOCATION UPDATED" + i++);
}
private String getNameFromType(DetectedActivity activityType) {
switch (activityType.getType()) {
case DetectedActivity.IN_VEHICLE:
return "in_vehicle";
case DetectedActivity.ON_BICYCLE:
return "on_bicycle";
case DetectedActivity.ON_FOOT:
return "on_foot";
case DetectedActivity.STILL:
return "still";
case DetectedActivity.TILTING:
return "tilting";
default:
return "unknown";
}
}
}
Я не совсем уверен, что это правильный или лучший способ получить то, что мне нужно.
Любая помощь очень ценится!