2012-03-01 22 views
4

我正在尝试编写一项服务,即每X分钟尝试获取设备的GPS位置,并在后台运行并记录,即使应用程序不在focuse。Android常规GPS轮询服务,最大限度延长电池使用时间

所以,创建一个服务的时间。

我创建了一个服务,设置了locationListener,得到了位置管理器和requestLocationUpdates ...所有的东西都很好..基本的骨架工作。

现在,我不希望GPS不断运行,因为这会导致电池无法使用,我希望发生的是服务,启动GPS,请求更新,然后关闭(至少它的兴趣在GPS位置),然后5或10分钟后再次做这个。

足够简单,我的侦听器的onLocationChanged服务要求更新,它只有一个,并关闭。

我决定添加一个while循环,这有效地注册我的位置监听器,并休眠X分钟。所以在逻辑上,它应该注册它需要的信息,然后睡觉..更新进来后,我在onLocationChange中获得更新,并在事件中取消注册它的intereste,关闭GPS直到下一次执行循环。

现在,我有2个问题1)这在逻辑上看起来好吗?还是有更优雅的方式?请记住,我希望这记录信息是否启动应用程序是关注的,并且诚实地即使启动应用程序被杀也希望服务继续运行,但这是我尚未完全做出的设计决定。

第二个问题是,我需要把这个LOOP放在一个线程里面,因为它在创建时,导致服务最终被杀死,因为它耗时太长,所以最好是什么这样做的方式? AsyncTask是一个选项,但这是一个从未在理论上完成的任务。处理程序似乎也很愚蠢,因为没有真正的回调,它只是注册GPS更新,而不感兴趣的代码位于LocationListener onLocationChange()。

这个线程实例化后没有真正的通信,尽管当服务将被某些用户交互关闭时,它将需要发信号通知来终止/结束...

所以我应该只是使用基线程?使用AsyncTask即使它永远不会真的回来?或者正在使用Handler更好的选项?或者,我的模型是否完全脱离了大门?

回答

3

我认为有一个管理GPS的服务是明智的方法,特别是如果您有多个活动可能需要位置信息。我在我的应用程序中采用了这种方法。

首先我在服务中使用的Ibinder和每个活动的结合,将其从活动与

bindService (new Intent(....), mServconn, Context.BIND_AUTO_CREATE); 
在调用onStart()

unbindService(mServconn);在的onStop()

我服务使用sendBroadcast()BroadcastReceivers注册的活动。位置数据通过广播意图中的附加内容传递。

我在服务中使用了状态机,状态为3,IDLE,SEEKING和GOT_A_FIX_NOW_SLEEPING。睡眠时间通过暴露在服务的公共方法中的'changeGPSParameters'方法传入。另一个参数是所要求的准确度,即在你的修复比所需的准确度更好之前不要广播消息,那么你可以睡觉。睡眠意味着关闭GPS,直到时间流逝。

的定时由一个Runnable和处理程序将消息发布到它的代码管理像

mHandler.postDelayed(this, mSleepTime); 

我觉得这是行之有效的。当没有活动绑定到该服务时,则onUnbind()将在该服务中运行。在这种方法中,你只需要确保你停止位置监听器,并与mHandler.removeCallbacks

UPDATE

下面停止计时器是一个Runnable的一个简单的例子,你可以通过在两个按钮来启动/停止你的main.xml应该有一个textview来显示定时器的状态:

import android.app.Activity; 
import android.os.Bundle; 
import android.os.Handler; 
import android.view.View; 
import android.widget.TextView; 

public class TimerLoopActivity extends Activity { 

    private Handler mHandler = new Handler(); 
    private int mSleepTime = 2; //seconds 
    private int mLoopCount = 0; 
    private Runnable mUpdateTimeTask = new Runnable() { 
     public void run() { 
      // Code here for when timer completes 
      mLoopCount++; 
      setTextBoxMsg("Running - count = " + mLoopCount); 
      mHandler.removeCallbacks(this); 
      mHandler.postDelayed(this, mSleepTime * 1000); // keep looping 
     } 
    }; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     setTextBoxMsg("Timer Idle"); 
    } 

    private void setTextBoxMsg(String string) { 
     TextView tv = (TextView) findViewById(R.id.textView1); 
     tv.setText(string); 
    } 

    public void myClickHandler(View target) { 
     switch (target.getId()) { 
      case R.id.startbutton: 
       setTextBoxMsg("Starting timer"); 
       startTimer(); 
       break; 
      case R.id.stopbutton: 
       setTextBoxMsg("Stopping timer"); 
       mLoopCount = 0; 
       stopTimer(); 
       break; 
     } 
    } 

    private void stopTimer() { mHandler.removeCallbacks(mUpdateTimeTask); } 
    private void startTimer() { mHandler.postDelayed(mUpdateTimeTask, mSleepTime * 1000);} 
} 

你可以调整它,把它放在你的服务。

+0

尼克,感谢您的意见。我有点关注你,尽管我猜测我的问题是服务中的实际可运行情况,以及如何按照我的意愿使其工作。 – user282172 2012-03-02 16:04:02

+0

一般 开始循环注册事件,睡眠 – user282172 2012-03-02 16:05:07

+0

在运行中,我准备一个循环,创建侦听器,然后我启动一个while(true)循环,只需设置位置管理器的criteia和requestsLocationUpdates; Looper.loop()然后循环结束。 依靠onLocationChange回调取消注册我的兴趣,所有事情都会休眠直到下一次触发。 但我的代码似乎永远不会离开Looper.Loop()代码,一旦我终于得到更新。 True Loop循环与预期的一样循环,直到第一次回调,但在此之后,代码从不离开looper.loop()调用,在while(true)循环结束时驱动所有内容 – user282172 2012-03-02 16:09:47