Android:后台服务中的计时器

Android:后台服务中的计时器,android,timer,gps,Android,Timer,Gps,您好 我试图实现一个计时器,每10秒向我的服务器发送GPS坐标 以下是我正在实现的服务的代码片段: @Override public int onStartCommand(Intent intent, int flags, int startId) { Timer timer=new Timer(); TimerTask tt=new TimerTask(){ @Override public void ru

您好

我试图实现一个计时器,每10秒向我的服务器发送GPS坐标

以下是我正在实现的服务的代码片段:

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Timer timer=new Timer();
        TimerTask tt=new TimerTask(){
            @Override
            public void run() {
                Location loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                sendCoords(String.valueOf(loc.getLatitude()), String.valueOf(loc.getLongitude()));
                Toast.LENGTH_SHORT).show();
                Log.i("EOH",String.valueOf(loc.getLatitude()));
            }
        };
        timer.schedule(tt,0,10000);

        return START_STICKY;
    }
现在的问题是run()中的任何内容都会导致我的应用程序强制关闭

以下是LogCat转储:

12-2818:44:18.284: 错误/AndroidRuntime(6537):致命 例外:计时器-0 12-28 18:44:18.284: 错误/AndroidRuntime(6537): java.lang.RuntimeException:无法 在具有 未调用Looper.prepare()12-28 18:44:18.284: 错误/AndroidRuntime(6537):在 android.os.Handler.(Handler.java:121) 12-28 18:44:18.284: 错误/AndroidRuntime(6537):在 .driver.Background$2.(Background.java:83) 12-28 18:44:18.284: 错误/AndroidRuntime(6537):在 prestecab.driver.Background.sendCoords(Background.java:83) 12-28 18:44:18.284: 错误/AndroidRuntime(6537):在 prestecab.driver.Background$3.run(Background.java:114) 12-28 18:44:18.284: 错误/AndroidRuntime(6537):在 Timer$TimerImpl.run(Timer.java:289) 12-28 18:44:18.554: 错误/WindowManager(1310):返回 移除已锁定的窗口

有人能建议解决这个问题吗

我尝试使用locationManager onLocationChanged()函数,但无法将间隔设置为10秒。显然,指定的时间只是一个指导,操作系统决定什么是最好的。即使我将间隔设置为100秒,它也会每隔一秒左右给出一个位置。这就是我使用计时器的原因

我希望有人能提出一些建议

提前感谢,

我试图实现一个计时器,每10秒向我的服务器发送GPS坐标

这是不现实的。您可能根本得不到任何修复。你可能要过10秒才能得到修复。例如,我正在测试一项服务,该服务旨在帮助开发人员以更低的频率(例如,每小时一次)对位置更新进行投票,而且很容易就需要一分钟才能得到修复,即使是坐在窗口的电话

以下是我正在实现的服务的代码片段:

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Timer timer=new Timer();
        TimerTask tt=new TimerTask(){
            @Override
            public void run() {
                Location loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                sendCoords(String.valueOf(loc.getLatitude()), String.valueOf(loc.getLongitude()));
                Toast.LENGTH_SHORT).show();
                Log.i("EOH",String.valueOf(loc.getLatitude()));
            }
        };
        timer.schedule(tt,0,10000);

        return START_STICKY;
    }
这是有缺陷的
getLastKnownLocation()
通常会返回
null
,对于初学者来说,超出了
计时器的问题

我希望有人能提出一些建议

首先,我会重新设计你的应用程序,以摆脱10秒这个硬要求

然后,使用
requestLocationUpdates()
。如果获得的读数太多,请忽略不需要的读数,不要将其发送到服务器。当然,请仅在短时间内运行此功能,并且仅基于积极的用户请求(例如,明确运行您的应用程序),考虑到保持GPS收音机打开所需的电池消耗


requestLocationUpdates()
的文档在计时方面确实令人困惑——我最近才意识到不一定遵守最短时间。

我在堆栈跟踪中注意到关于“无法在未调用Looper.prepare()的线程内创建处理程序…”的语句这让我想起了一个交叉线程类型的错误,或者一个对象尚未完成内部状态设置的情况


几周前我看了一段视频,其中主持人做了类似的事情。。。根据计时器从GPS发送数据,但我现在似乎找不到。试着搜索一下。。。这是一个大约一小时长的视频,但值得花时间。

当您使用外部线程调用主UI元素时,MainUI线程将使异常在调用Toast或任何其他UI组件时使用它:-

使处理程序如下所示:-

Handler progressHandler = new Handler() {
    public void handleMessage(Message msg) {
        // display UI , Update UI
        /* To do your UI updation here */
    }
};
Thread background = new Thread (new Runnable() {
    @Override
    public void run() {
        // this will be done in the Pipeline Thread
        /* Do your GPS task here */
        // active the update handler
        progressHandler.sendMessage(progressHandler.obtainMessage());
    }
});

// start the background thread
background.start();
现在,让您的线程如下所示:-

Handler progressHandler = new Handler() {
    public void handleMessage(Message msg) {
        // display UI , Update UI
        /* To do your UI updation here */
    }
};
Thread background = new Thread (new Runnable() {
    @Override
    public void run() {
        // this will be done in the Pipeline Thread
        /* Do your GPS task here */
        // active the update handler
        progressHandler.sendMessage(progressHandler.obtainMessage());
    }
});

// start the background thread
background.start();

希望这对您有所帮助。

您确定“lm.RequestLocationUpdate(LocationManager.GPS_PROVIDER,5000,1,lr);”没有帮助吗?第三个参数是触发另一个位置更新的最小距离,而第二个参数是您正在使用的参数-位置更新之间的最短时间。无论先满足哪种条件,您都会得到位置更新。@kellogs显然,从这篇文章中,参数只是指示符,每个设备都会决定什么是最好的……嘿,很抱歉,回复太晚了。我接受了你的建议,只是忽略了那些太频繁出现的阅读资料。比这个计时器容易多了@Commonware礼貌地表示不同意。虽然最初的用户认为他不需要定时事件,但问题所指的应用程序本身并不是无用的。假设你需要每隔XX秒知道用户在哪里(我同意可以用10来表示)。如果需要每10秒启动一次位置查询,则可能没有位置修复,但在调用位置查询之前,应该先缓存位置。请查看Reto Meier的《潜水地点》。retoMeier知道他的东西,他是谷歌的技术领导者。