来自服务

时间:2016-03-31 03:28:25

标签: android android-fragments android-service android-dialog android-handler

在我的片段中是一个按钮,单击该按钮将启动一个服务,该服务轮询传感器,并使用执行程序服务将传感器数据存储到数据库。片段的onClick如下所示:

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类设置为使用ExecutorService每10毫秒将传感器数据存储到数据库。

该课程的相关部分是:

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时,会通过其onCreateonStartCommand方法。每当传感器数据发生变化时,执行程序服务就会将其插入数据库

当用户再次点击按钮停止时,我告诉执行者关闭,但是要先完成所有当前任务的处理。清除执行程序队列后,我们关闭数据库,取消注册侦听器等。

在此阶段,当执行程序正在等待关闭并清除其队列时,我想向用户显示一个进度对话框,说明它正在完成关闭过程。

因此,一旦按下停止按钮,我就会在片段中显示progressdialog。但是,只有在执行程序服务完成处理队列并正确关闭后,如何才解除对话框?

我可以使用异步任务轻松完成此操作,但我已选择使用执行程序服务,因此这不是一个选项

进度对话框属于片段,因此我无法从服务中执行MainActivity.dialog.dismiss()之类的操作。我不觉得那是一种非常干净的处理方式

所以我想我已经离开了处理程序,但在这种情况下并不完全确定如何设置它,因为执行程序服务在另一个服务(SensorService)内运行。如果使用处理程序来解决这个问题,代码会是什么样的?

1 个答案:

答案 0 :(得分:0)

您需要一些服务机制才能向活动组件发送信号。最简单和最常见的方法是使用事件总线。正确实现这一点完全取决于您,但您可以使用现有的事件总线库来帮助您。您可以通过简单的谷歌搜索找到这些。