В моем фрагменте есть кнопка, которая при нажатии запускает сервис, который опросает датчики, и использует службу-исполнитель для хранения данных датчика в базе данных. onClick
фрагмента выглядит следующим образом:Откроется диалоговое окно закрытия Android от службы
public void onClick(View v) {
if (!recordingStarted){
try{
recordingStarted = true;
mainActivity.startService(new Intent(mainActivity, SensorService.class));
startButton.setText(getResources().getString(R.string.start_button_label_stop));
Snackbar.make(coordinatorLayout, "Recording...", Snackbar.LENGTH_SHORT).show();
} catch (SQLException e){
mainActivity.logger.e(getActivity(),TAG, "SQL error insertSubject()", e);
}
} else {
dialog = new ProgressDialog(mainActivity);
dialog.setTitle("Stop recording");
dialog.setMessage("Please wait...");
dialog.show();
mainActivity.stopService(new Intent(mainActivity, SensorService.class));
startButton.setEnabled(false);
Snackbar.make(coordinatorLayout, "Recording stopped.", Snackbar.LENGTH_SHORT).show();
}
}
SensorService
класс создан для хранения данных датчиков в базу данных каждые 10 мс с использованием ExecutorService
.
Соответствующие части этого класса являются:
public class SensorService extends Service implements SensorEventListener {
public void onSensorChanged(SensorEvent event) {
//get sensor values here
//insert into database
try{
executor.execute(insertHandler);
} catch (SQLException e) {
Log.e(TAG, "insertData: " + e.getMessage(), e);
}
}
}
@Override
public void onCreate() {
super.onCreate();
dbHelper = new DBHelper(getApplicationContext());
PowerManager manager =
(PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
registerReceiver(receiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
//Executor service and runnable for DB inserts
executor = Executors.newSingleThreadExecutor();
insertHandler = new InsertHandler();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startForeground(Process.myPid(), new Notification());
registerListener();
wakeLock.acquire();
return START_STICKY;
}
@Override
public void onDestroy() {
//Prevent new tasks from being added to thread
executor.shutdown();
try {
//Wait for all tasks to finish before we proceed
while (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
Log.i(TAG, "Waiting for current tasks to finish");
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
//Stop everything else once the task queue is clear
unregisterReceiver(receiver);
unregisterListener();
wakeLock.release();
dbHelper.close();
stopForeground(true);
}
class InsertHandler implements Runnable {
public void run() {
dbHelper.insertData(Short.parseShort(MainActivity.subInfo.get("subNum")), System.currentTimeMillis(),
accelerometerMatrix[0], accelerometerMatrix[1], accelerometerMatrix[2],
accelerometerWorldMatrix[0], accelerometerWorldMatrix[1], accelerometerWorldMatrix[2],
gyroscopeMatrix[0], gyroscopeMatrix[1], gyroscopeMatrix[2]);
}
}
}
Так что, когда попадает пользователь кнопка SensorService
проходит через его onCreate
и onStartCommand
методами. Всякий раз, когда данные датчика меняются, служба-исполнитель вставляет его в базу данных
Когда пользователь снова нажимает кнопку, чтобы остановить, я говорю исполнителю выключиться, но сначала закончить обработку всех текущих задач. После того как очередь исполнителя очищается, мы закрываем базу данных, отменяем регистрацию слушателей и т. Д.
На этом этапе, когда исполнитель ожидает завершения работы и очистки своей очереди, я хочу показать пользователю диалог прогресса, чтобы сказать, что он проходит через процесс закрытия вещей.
Таким образом, я показываю прогрессдиалог в самом фрагменте, когда нажата кнопка остановки. Но как я могу отменить диалог только после того, как служба-исполнитель закончила обработку очереди и закрыта правильно?
я могу легко сделать это с асинхронными задачами, но я решил использовать исполнителю услуги для этого вместо того, чтобы, так что это не вариант
диалогпрогресс принадлежит к фрагменту, так что я не могу сделать что-то вроде MainActivity.dialog.dismiss()
от внутри службы. Я не чувствую, что это очень чистый способ обработки вещей в любом случае
Так что, я думаю, я остался с обработчиками, но не совсем уверен, как его настроить в этом случае, потому что служба-исполнитель работает в другой службе (SensorService
). Как выглядел бы код, если бы использовал обработчик для решения этой проблемы?