Android的常规GPS轮询的服务,最大限度地延长电池寿命限度、寿命、常规、电池

2023-09-05 08:15:32 作者:Despair 绝望

我试图写一个服务,即会每隔X分钟尝试获取设备的GPS位置,并在后台运行并记录,即使当应用程序不处于focuse

I am attempting to write a service, that will every X minutes attempt to get the GPS location of the device, and run and record in the background even when the app is not in focuse.

所以,时间创建服务。

我创建了一个服务,成立了LocationListener的,得到了​​位置管理和requestLocationUpdates ......一切都很好与世界..基本的框架工作。

I created a service, set up the locationListener, got the location Manager and requestLocationUpdates... all is good with the world.. rudimentary skeleton working.

现在,我不希望GPS持续运行,因为这会杀了电池,我想发生的是服务,火了GPS,要求一个更新,然后关闭(其至少在兴趣GPS位置),然后5或10分钟后再次做到这一点。

Now, I don't want the GPS running constantly as this will kill the battery, what I would like to happen is the service, fire up the GPS, ask for an update, then shut down (at least its interest in the gps location) and then 5 or 10 minutes later do this again..

很简单,我的听众的onLocationChanged()方法中,我添加了一行LocationManager(removeUpdates(LocationListener的))。所以,当我的服务要求的更新,它只有一个,关闭。

Simple enough, on the onLocationChanged() method of my listener, I add the line LocationManager (removeUpdates(locationListener)).. so when my service asks for an update, it gets only one, and shuts down.

我决定加入少许while循环,能有效注册我的位置监听器,以及休眠X分钟。所以从逻辑上讲,它应该注册它想要的信息,然后睡..更新到来时,我得到了onLocationChange的更新并将其unregisteres其intereste事件,关闭GPS,直至循环的下一次执行。

I decide to add a little while loop, that effectively registers my location listener, and sleeps for X minutes. So logically, it should register that it wants information, then sleep.. an update comes in, I get that update in the onLocationChange and it unregisteres its intereste in the event, shutting down the GPS until the next execution of the loop.

现在,我有2个问题,1)这个在逻辑上似乎还好吗?还是有更优雅的方式?还记得我希望这个记录信息启动应用程序是否清晰对焦,老老实实即使启动的应用程序被打死希望继续服役潜在的运行,但这是一个设计决策,我还没有完全尚未作出。

Now, I have 2 questions 1) Does this logically seem okay? or is there a more elegant way? Remember I want this to record information whether or not the launching application is in focus, and honestly even if the launching app was killed would like the service to continue running potentially but that's a design decision I haven't fully made yet.

的第二个问题是,我需要把这个循环中的线程内,因为有它在OnCreate,会导致服务最终被杀死,因为它的时间太长来自OnCreate中回来,所以这将是最好的方法去这样做呢? AsyncTask的是一种选择,但这是一个任务,那就是从来没有在理论上要完成..处理程序也似乎几分傻了,因为没有真正的回调,它只是登记了全球定位系统的更新和uninterest code是在LocationListener的onLocationChange()。

The 2nd question is, I will need to put this LOOP inside a thread since having it in the oncreate, causes the service to eventually be killed because its taking too long to come back from oncreate, so what would be the best way to go about doing this? AsyncTask is an option, but this is a task that is never in theory going to finish.. Handler also seems sort of silly, as there are no real callbacks, its just registering for the GPS updates, and the uninterest code is in the LocationListener onLocationChange().

有没有真正的交流,将来到这个线程过一次实例化,尽管它需要被通知到死时,该服务会被一些用户交互关闭/结束的话...

There is no real communication that would come out of this thread once instantiated, though it would need to be signaled to die/end when the service is going to be shut down by some user interaction to do so...

所以,我应该只是只使用一个线程的基础?去与AsyncTask的,即使它从来没有真正回来了吗?或者是使用处理器更好的选择?或者是我的模型只是完成不好的形式出了大门?

So should I just just use a base thread? Go with an AsyncTask even though its never really coming back? or is using the Handler the better option? Or is my model just complete bad form out of the gate?

推荐答案

我觉得有一个服务管理的全球定位系统是明智的路要走,特别是如果你有可能需要的位置信息多于一个的活动。我在我的应用程序采用了这样的方法。

I think having a service to manage the GPS is the sensible way to go, especially if you have more than one activity which might want location information. I adopted such an approach in my app.

首先我用了一个的IBinder 在服务并绑定到它的活动

Firstly I used an Ibinder in the service and bound to it from the activities with

bindService (new Intent(....),   mServconn, Context.BIND_AUTO_CREATE);

在ONSTART()

unbindService(mServconn); 中的每个活动的onStop()

and unbindService(mServconn); in onStop() of each activity

我的服务使用 sendBroadcast() BroadcastReceivers 的活动注册。位置的数据通过在广播意图额外传递

I had the service use sendBroadcast() to BroadcastReceivers registered in the activities. The location data is passed via extras in the broadcast intent.

我用了一个状态机在服务与3种状态,IDLE,寻求和GOT_A_FIX_NOW_SLEEPING。睡眠时间是通过在通过changeGPSParameters的方法,在服务的公共方法暴露。另一个参数是必需的精确度,即不播出一条消息,直到你有一个固定比所要求的精度更好,那么你就可以睡觉。睡眠表示关闭GPS,直到时间结束。

I used a state machine in the service with 3 states, IDLE, SEEKING and GOT_A_FIX_NOW_SLEEPING. The sleep time is passed in through a 'changeGPSParameters' method exposed in a public method of the service. Another parameter is the required accuracy, i.e. don't broadcast a message until you've had a fix better than the the required accuracy, then you can sleep. Sleep means turn off the GPS until the time has elapsed.

的时序是由一个Runnable和处理程序将消息发布到它与code像

The timing is managed by a Runnable and a Handler posts messages to it with code like

mHandler.postDelayed(this, mSleepTime );

我觉得这个效果很好。如果没有活动被绑定到服务,则 onUnbind()将在服务运行。在该方法中,你只需要确保你停止位置监听器,并停止与 mHandler.removeCallbacks

I find this works well. When no activities are bound to the service then onUnbind() will run in the service. In that method you just have to make sure that you stop the location listener and stop the timer with mHandler.removeCallbacks

更新

下面是一个可运行的一个简单的例子,而可以通过在main.xml中两个按钮装置,它应该有一个单一的TextView显示定时器的状态启动/停止:

Below is a simple example of a Runnable which you can start/stop by means of two buttons in your main.xml which should have a single textview to show the timer state:

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

您可以适应这把它放在你的服务。

You can adapt this to put it in your service.

 
精彩推荐
图片推荐