2011-04-24 88 views
1

我正在编写一个应用程序,它不断地侦听并检查传感器(几乎全部可用)并将该数据保存到设备中的数据库中。在实时应用程序中在后台运行重复任务

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

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

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

我想听听不同的意见。 在此先感谢!吉列尔莫。

+2

杰夫阿特伍德已经关闭了这个问题的原始副本,所以我想我们应该保持这一个开放。 – 2011-04-25 22:11:26

回答

3

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

关于唤醒锁(从AlarmManager参考):

警报管理器,只要该报警接收机的 的onReceive()方法被执行保持CPU唤醒 锁。这 保证,手机将不会 睡眠,直到您处理完 广播。一旦onReceive() 返回,警报管理器将释放 此唤醒锁定。这意味着在您的onReceive()方法完成后,某些情况下 手机会在一段时间内尽快睡眠 。 如果您的报警接收器名为 Context.startService(),则有可能 电话将在启动 请求的服务之前休眠。为了防止这种情况发生,您的BroadcastReceiver 和Service将需要实施 单独的唤醒锁定策略,以确保 电话继续运行,直到 服务变为可用。

+0

对不起,你能解释一下吗?我应该从哪里开始服务和警报?警报和服务之间有什么关系? 我在考虑使用BroadcastReceiver并进行计算,为什么“要使计算使用服务”? – polonskyg 2011-04-25 03:04:39

+0

您首先通过AlarmManager设置您的警报,然后在您的警报接收器中启动服务。你不需要一个UI,所以你不会使用一个活动,你应该考虑一个服务这种情况。 – aromero 2011-04-25 03:43:53

+0

我明白了,谢谢!我会给它一个镜头。 – polonskyg 2011-04-25 17:43:09

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