【问题标题】:Running a repeating task in background on a real time application在实时应用程序的后台运行重复任务
【发布时间】:2011-04-24 23:42:25
【问题描述】:

我正在编写一个应用程序,它不断地监听和检查传感器(几乎所有可用的)并将该数据保存到设备的数据库中。

我需要每隔 X 秒使用该数据进行一些计算,如果计算检查显示如此,则抛出一个新事件。 我正在考虑在使用应用程序时请求插入设备(关于电池消耗)。

对于需要进行计算和引发事件的任务,最好的方法是什么?计时器?线程?异步任务?报警管理器?另一种方法?

我想继续获取传感器数据并将它们保存到数据库中,即使应用程序不在前台...只要用户没有停止应用程序,它就应该保存这些值。 一种选择是唤醒锁(PARTIAL_WAKE_LOCK,保持 CPU 运行)。

我想听听不同的意见。 提前致谢!吉列尔莫。

【问题讨论】:

  • 杰夫阿特伍德已经关闭了这个问题的原始副本,所以我想我们应该保持这个开放。

标签: android real-time alarmmanager


【解决方案1】:

您可以使用AlarmManager 设置重复任务(这是 Android 设置未来/重复任务的首选方式)。要进行计算,请使用Service(如果您认为计算会很昂贵,请考虑将它们移至单独的工作线程或使用IntentService)。

关于唤醒锁(来自 AlarmManager 参考):

警报管理器保持 CPU 唤醒 只要报警接收器的锁定 onReceive() 方法正在执行。这 保证手机不会 睡觉直到你完成处理 广播。一旦 onReceive() 返回,警报管理器释放 这个唤醒锁。这意味着 手机在某些情况下会尽快入睡 当您的 onReceive() 方法完成时。 如果您的报警接收器呼叫 Context.startService(),有可能 手机会在 启动请求的服务。到 防止这种情况,你的 BroadcastReceiver 和服务将需要实施 单独的唤醒锁定策略以确保 手机继续运行直到 服务可用。

【讨论】:

  • 对不起,你能再解释一下吗?我应该从哪里触发服务和警报?报警和服务有什么关系?我考虑使用 BroadcastReceiver 并在那里进行计算,为什么“使用服务进行计算”?
  • 您首先通过 AlarmManager 设置您的警报,然后在您的警报接收器中启动一个服务。您不需要 UI,因此您不会使用 Activity,您应该为这种情况考虑 Service。
  • 我明白了,谢谢!我试试看。
【解决方案2】:

这是我不久前编写的用于记录 CPU 频率的服务的修改后的 sn-p。它缺少ApplicationActivity 部分,但说明了我如何编写Service 以保持每十秒记录一次。当手机进入深度睡眠时它不会记录,所以如果你想不间断地记录,那么你需要获取PARTIAL_WAKE_LOCKs,但考虑到这样会严重降低电池寿命。

public class YOURCLASS_Service extends Service {
    private long mStartTime = 0L;
    private final Handler mHandler = new Handler();
    private Runnable mUpdateTimeTask;
    private YOURAPP app;

    @Override
    public void onCreate() {
        super.onCreate();
        app = (YOURAPP) getApplicationContext();
    }

    @Override
    public void onDestroy() {
        Toast.makeText(this, "Service finished.", Toast.LENGTH_SHORT).show();
        stopLog ();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (app.isRunning())
            return START_STICKY;
        try {
            File file = new File(Environment.getExternalStorageDirectory(), "yourlog.csv");
            OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file, false));
            out.write("Log title");
            out.close();
        } catch (java.io.IOException e) {
              stopLog ();
              Toast.makeText(this, "Error creating log file. Aborting.", Toast.LENGTH_SHORT).show();
        }

        mUpdateTimeTask = new Runnable() {
            public void run() {
                long millis = SystemClock.uptimeMillis() - mStartTime;
                int seconds = (int) (millis / 1000);
                int minutes = seconds / 60;
                seconds     = seconds % 60;

                readYourSensors ();
                   if (!writeLog (str)) stopLog();
                   mHandler.postAtTime(this, mStartTime + (((minutes * 60) + seconds + 10) * 1000));
                   mHandler.postDelayed (mUpdateTimeTask, 10000);
        }};
        mStartTime = SystemClock.uptimeMillis();
        mHandler.removeCallbacks(mUpdateTimeTask);
        mHandler.postDelayed(mUpdateTimeTask, 100);

        Notification notification = new Notification(R.drawable.notification_icon, "App title", System.currentTimeMillis());
        Intent notificationIntent = new Intent(this, YOURCLASS.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
        notification.setLatestEventInfo(getApplicationContext(), "App title", "Please see /sdcard/yourlog.csv", contentIntent);
        startForeground(startId, notification);

        app.isRunning(true);
        return START_STICKY;
    }

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

    public void stopLog () {
            mHandler.removeCallbacks(mUpdateTimeTask);
    }
}    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多