在实时应用程序中在后台运行重复任务

时间:2011-04-24 23:42:25

标签: android real-time alarmmanager

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

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

需要进行计算并抛出事件的任务的最佳方法是什么?计时器?主题? AsynkTask? AlarmManager?另一种方法?

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

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

2 个答案:

答案 0 :(得分:3)

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

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

  

警报管理器保持CPU唤醒   锁定只要报警接收器的   onReceive()方法正在执行。这个   保证手机不会   睡觉直到你完成处理   广播。一旦onReceive()   返回,Alarm Manager发布   这个唤醒锁。这意味着   在某些情况下,手机会尽快睡觉   因为你的onReceive()方法完成了。   如果你的报警接收器叫   Context.startService(),它是可能的   电话会在之前睡觉   请求的服务已启动。至   阻止这个,你的BroadcastReceiver   和服务将需要实施一个   单独的唤醒锁定策略以确保   手机继续运行直到   服务变得可用。

答案 1 :(得分:0)

这是我之前写的用于记录CPU频率的服务的修改片段。它缺少ApplicationActivity部分,但说明了我如何编写Service以保持每十秒记录一次。手机进入深度睡眠状态时不会记录,因此如果您想在不中断的情况下进行记录,则需要获取PARTIAL_WAKE_LOCK s,但请注意电池寿命会因此而严重降低。

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);
    }
}