Android定期GPS轮询服务,最大限度延长电池寿命

Android定期GPS轮询服务,最大限度延长电池寿命,android,service,background,gps,Android,Service,Background,Gps,我正在尝试编写一项服务,它将每X分钟尝试获取设备的GPS位置,并在后台运行和录制,即使应用程序不在焦点位置 所以,是时候创建一个服务了 我创建了一个服务,设置了locationListener,获得了LocationManager和RequestLocationUpdate。。。世界上一切都好。。基本骨架工作 现在,我不希望GPS持续运行,因为这会耗尽电池,我希望发生的是服务,启动GPS,请求更新,然后关机(至少它对GPS位置感兴趣),然后5或10分钟后再这样做 很简单,在侦听器的onLocat

我正在尝试编写一项服务,它将每X分钟尝试获取设备的GPS位置,并在后台运行和录制,即使应用程序不在焦点位置

所以,是时候创建一个服务了

我创建了一个服务,设置了locationListener,获得了LocationManager和RequestLocationUpdate。。。世界上一切都好。。基本骨架工作

现在,我不希望GPS持续运行,因为这会耗尽电池,我希望发生的是服务,启动GPS,请求更新,然后关机(至少它对GPS位置感兴趣),然后5或10分钟后再这样做

很简单,在侦听器的onLocationChanged()方法上,我添加了行LocationManager(removeUpdates(locationListener))。。因此,当我的服务要求更新时,它只得到一个,然后关闭

我决定添加一个小while循环,有效地注册我的位置侦听器,并睡眠X分钟。所以从逻辑上讲,它应该注册它需要信息,然后再睡觉。。一个更新进来了,我在onLocationChange中得到了更新,它注销了它在事件中的权益,关闭GPS直到下一次执行循环

现在,我有两个问题1)从逻辑上看,这似乎可以吗?还是有更优雅的方式?请记住,我希望它记录启动应用程序是否处于焦点的信息,老实说,即使启动应用程序被终止,我也希望服务继续潜在运行,但这是我尚未完全做出的设计决策

第二个问题是,我需要将这个循环放在一个线程中,因为在oncreate中使用它会导致服务最终被终止,因为从oncreate返回要花很长时间,那么什么是最好的方法呢?AsyncTask是一个选项,但这是一个理论上永远无法完成的任务。。处理程序似乎也有点傻,因为没有真正的回调,它只是注册GPS更新,而不感兴趣的代码在LocationListener onLocationChange()中

一旦实例化,这个线程就不会产生真正的通信,尽管当服务将被某些用户交互关闭时,需要向其发出死亡/结束的信号


所以我应该只使用一个基本线程吗?即使任务永远不会回来,也要执行它?还是使用处理程序是更好的选择?还是我的模型只是一种完全不好的形式?

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

首先,我在服务中使用了一个
Ibinder
,并通过与的活动绑定到它

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

解除绑定服务(mServconn)

我在活动中注册了使用
sendBroadcast()
BroadcastReceivers
的服务。位置数据通过广播目的中的附加程序传递

我在服务中使用了一个状态机,它有三种状态:空闲状态、查找状态和正在睡眠状态。睡眠时间通过服务的公共方法中公开的“changeGPSParameters”方法传入。另一个参数是所需的准确度,即在得到比所需准确度更好的修正之前,不要广播消息,然后才能睡觉。睡眠意味着关闭GPS,直到时间过去

计时由Runnable管理,处理程序使用类似于

mHandler.postDelayed(this, mSleepTime );
我发现这很有效。当没有任何活动绑定到服务时,
onUnbind()
将在服务中运行。在这种方法中,您只需确保使用
mHandler.removeCallbacks停止位置侦听器并停止计时器

更新

下面是一个简单的Runnable示例,您可以通过main.xml中的两个按钮启动/停止Runnable,该按钮应有一个文本视图来显示计时器状态:

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

您可以对此进行调整,以便将其用于您的服务。

Nick,谢谢您的输入。虽然我猜我的问题是服务中的实际可运行性,以及如何按照我的要求工作。一般的开始循环注册事件,在运行中睡眠,我准备一个循环器,创建监听器,然后我启动一个while(true)循环,为位置管理器设置条件,和请求更新;Looper.loop()和循环结束。依靠onLocationChange回调来注销我的兴趣,所有内容都将休眠,直到下一次触发。但我的代码似乎永远不会离开Looper.Loop()代码,直到我最终得到更新。内部while True循环在第一次回调之前按预期循环,但是在那之后,代码在while(True)循环结束时从未离开looper.Loop()调用,而while(True)循环正在驱动所有事情。老实说,我不完全确定为什么我甚至需要looper,因为我没有尝试或希望向循环发送消息,但是显然Android需要编译它,并且在我的while(true)循环结束时没有looper.loop(),对onLocationChanged的回调永远不会发生。。所以我需要它们。显然地但是现在我陷入了如何调用Looper.quit()的困境,当我的线程卡在Looper中时。loop()调用我认为我做错了什么。我将用一个基本的Runnable/handler示例编辑我的答案,您可以对其进行调整