在一个服务中使用AlarmManager进行Android定期GPS位置更新

4
我看到很多问题,但无法找出问题所在。
我正在为Android编写现场服务应用程序。 在一个活动(MyActivity.java)中,我有两个按钮:开始和停止。
当现场工人按下开始按钮时,我需要使用GPS获取他的当前位置,并及时将其发送到服务器(默认为5分钟,这里设置为20秒进行测试)。 客户希望这样做以查看工人在交通中花费的时间,我的城市(伊斯坦布尔)的交通情况非常糟糕。
我在我的活动中有一个AlarmManager,当按下开始按钮时,通过 AlarmManager.setRepeating()设置闹钟来启动服务(ServiceClass.java)。
Intent intent = new Intent (MyActivity.this, ServiceClass.class);
mPendingIntent = PendingIntent.getService(MyActivity.this, 0, intent,
                                              PendingIntent.FLAG_CANCEL_CURRENT);
mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mAlarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 20*1000,
                                                                  mPendingIntent);

我使用停止按钮取消闹钟。
在这里它运行得非常完美,服务已经启动。它的 onCreate()onStart()onDestroy() 方法都已执行。但是我无法获取位置信息。由于我没有实际设备,所以我正在使用 DDMS 来发送位置信息。但是应用程序会跳过此步骤,并将我的位置的经度和纬度打印为 Lon:0 Lat:0。
以下是服务内部的代码:
public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
    Log.d("Testing", "Service got started, calling location updates:");
    mLocationManager.requestSingleUpdate(mCriteria, mLocationListener,
                                                                getMainLooper());
    Log.i("TESTING LOCATION UPDATE: LOCATION:", "\nLat:"   + mLatitude +
                                                          "  Lon:" + mLongitude);
    stopSelf(startId);
    Log.d("Testing", "Service Stopped!");

最后,这是我的LocationListener:

 mLocationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {

            if(location != null){
                mLatitude = location.getLatitude();
                mLongitude = location.getLongitude();
                Log.i("onLocationChanged(Location location)", "Lat:"+mLatitude + "
                                                            Lon:" + mLongitude);
}

还有一件事引起了我的注意,当我运行代码时:

mLocationProvider = mLocationManager.getBestProvider(mCriteria, true);
Log.i("BEST PROVIDER IS:", mLocationProvider);

它说最佳提供者是:gps。但是在onProviderEnabled()中的日志从未显示在logcat中。

@Override
public void onProviderEnabled(String s) {
    Log.v("onProviderEnabled", "ENABLED");
}

有两点需要补充说明,如果我使用:

mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
                                                              mLocationListener);

它也不起作用。

但是这个可以工作,我可以获取LastKnownLocation:

Location lastKnown = mLocationManager.getLastKnownLocation(
                                                   LocationManager.GPS_PROVIDER);

首先,这是一个进行此操作的好方法吗?如果是,请检查我是否遗漏了什么。如果不是,请告诉我如何更好地实施这个方法。
谢谢 :)

1
这是关于Android定位的较好的文章之一;http://android-developers.blogspot.com/2011/06/deep-dive-into-location.html - 它回答了你大部分的问题。 - tonys
@tonys 谢谢你,我会第一时间阅读的。 - Lev
这个非常完美:输入链接描述 - Rohan Ashik
2个回答

8
首先,您不能在注册位置更新后关闭服务。最好的情况是会泄漏线程。最糟糕的情况是Android将终止您的进程(认为其中没有任何运行内容),您将无法获得更新。此外,GPS需要一段时间才能启动,因此在城市环境中可能在20秒内无法获得修复。还要确保设备在尝试收集修复时保持唤醒状态。
因此,在后台获取定期位置修复是一个相当复杂的问题。
我编写了一个现在已停用的LocationPoller来尝试解决这个问题,另一位开发人员对其进行了分支和扩展。您可以尝试该分支或仅将其用作想法来源。

requestLocationUpdates(String provider, long minTime, float minDistance, PendingIntent intent)与已在清单文件中注册的接收器一样,会遇到相同的问题吗?也就是说,AlarmManager用于传递PendingIntent(在此情况下将唤醒接收器)吗? - Mr_and_Mrs_D
@Mr_and_Mrs_D:抱歉,我不理解你的问题。 - CommonsWare
如果我使用requestLocationUpdates(... PendingIntent pi)代替requestLocationUpdates (...LocationListener listener),并且使用一些pi = PendinIntent.getBroadcast()和已注册的接收器来接收广播,那么这个pi会被AlarmManager传递吗?这样它就会唤醒接收器(而不需要唤醒锁)了吗?如果我表达不清楚,请见谅。 - Mr_and_Mrs_D
1
@ValkyrieSavage:好的,尽管 fork 仍然存在。我已经更新了回答。谢谢! - CommonsWare
我能在哪里找到已编译的JAR文件呢?我查看了GitHub存储库,但没有看到它。克隆存储库并尝试构建会让我感到非常痛苦 :-/ - Ted
显示剩余6条评论

1
尝试这个:

AlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,,,);

我正在使用GPS获取当前位置,但我的项目每10秒钟才能工作一次。现在我不知道该怎么办了。以下是我的代码:

AlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),6000000,pi);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接