即使我已显着移动,也会在后台更新相同的位置

Posted

技术标签:

【中文标题】即使我已显着移动,也会在后台更新相同的位置【英文标题】:Same Location updates in the background even though I have moved Significantly 【发布时间】:2013-03-10 13:22:39 【问题描述】:

我有一项服务,它在 onCreateMethod 中请求网络位置更新。我已经使用 LocationListener 来接收新的位置、提供者的状态和提供者中的 statusChange。

当设备处于低电量状态(手机屏幕关闭)时,我获得了与手机屏幕处于活动状态(屏幕打开)时网络提供商相同的位置修复。

public class LocationRegisterService extends Service implements LocationListener

private String TAG = LocationRegisterService.class.getName();

private LocationManager lm;

public void onCreate()

    Log.d(TAG,"Entering LocationRegisterService::onCreate()");
    //Register for network location updates
    lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
    Log.i(TAG,"Regsitering for Network Location Updates");
    Log.i(TAG,"minTime = 0,minDistance = 0");
    lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
            Log.d(TAG,"Exiting LocationRegisterSerivce::onCreate()");


public int onStartCommand(Intent intent, int flags, int startId)

    Log.d(TAG,"Entering LocationRegisterService::onStartCommand()");
    Log.d(TAG,"Exiting LocationRegisterService::onStartCommand()");
    return Service.START_STICKY;



@Override
public IBinder onBind(Intent arg0) 
    // TODO Auto-generated method stub
    return null;


public void onDestroy() 

    super.onDestroy();
    Log.d(TAG,"Entering LocationRegisterService::onDestroy()");
    lm.removeUpdates(this);
    Log.d(TAG,"Exiting LocationRegisterService::onDestroy()");


@Override
public void onLocationChanged(Location location) 
    Helpers.logScreenStatus(this);
    double latitude = location.getLatitude();
    double longitude = location.getLongitude();
    double accuracy = location.getAccuracy();
    String location_timestamp = formatTime(location.getTime());
    String log = latitude + "," + longitude +","+accuracy+","+location_timestamp;
    Log.i(TAG,log);


@Override
public void onProviderDisabled(String provider) 
    String log = "Network Provider Disabled";


@Override
public void onProviderEnabled(String provider) 
    String log = "Network Provider Enabled";


@Override
public void onStatusChanged(String provider, int status, Bundle extras) 
    String log = "";
    switch(status)
        case LocationProvider.AVAILABLE:
            log = "Network Available";
            break;
        case LocationProvider.OUT_OF_SERVICE:
            log = "Network Out Of Service";
            break;
        case LocationProvider.TEMPORARILY_UNAVAILABLE:
            log = "Network Temporarily Unavailable";
            break;
    
    setServiceWakeUpTime();
    stopSelf();


private void setServiceWakeUpTime()

    AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(this,AlarmReceiver.class);
    PendingIntent operation = PendingIntent.getBroadcast(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
    long wakeAt = System.currentTimeMillis() + (60 * 1000);
    am.set(AlarmManager.RTC_WAKEUP, wakeAt , operation);
    FileLogger.log(this, "Service will wake up after one minute");


private String formatTime(long epoch)

    Date date = new Date(epoch);
    String pattern = "y/M/d H:m:s.S";
    SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
    return dateFormat.format(date);



我从一项活动开始这项服务,并在关闭设备屏幕的情况下行驶了近 50 公里。我正在附上旅行的日志。

2013/3/21 0:29:58.743  Entering Broadcast Receiver
2013/3/21 0:29:58.756  Screen is off
2013/3/21 0:29:58.778  Exiting Broadcast Receiver
2013/3/21 0:29:58.783  Registering for network location updates
2013/3/21 0:30:53.571  Screen is off
2013/3/21 0:30:53.587  13.07383585,80.22151335000001,50.0,2013/3/21 0:30:8.551
2013/3/21 0:30:53.593  Screen is off
2013/3/21 0:30:53.595  Network Temporarily Unavailable
2013/3/21 0:30:53.613  Service will wake up after one minute
2013/3/21 0:30:53.619  UnRegistering listener for location updates
2013/3/21 0:31:53.676  Entering Broadcast Receiver
2013/3/21 0:31:53.689  Screen is off
2013/3/21 0:31:53.710  Exiting Broadcast Receiver
2013/3/21 0:31:58.516  Registering for network location updates
2013/3/21 0:32:17.583  Screen is off
2013/3/21 0:32:17.594  13.07383585,80.22151335000001,50.0,2013/3/21 0:32:3.544

相同的日志重复了将近一个小时。此代码在 HTC Explorer 中运行 android 2.3.3。有人对此行为有答案吗?

【问题讨论】:

我将尝试使用部分唤醒锁定并分享我的结果。 如果您在onStatusChange() 中评论setServiceWakeUpTime();stopSelf(); 会发生什么?根据日志,您的提供商刚刚进入临时不可用状态。它可以在几秒钟内从中恢复。看看它恢复后是否会为您提供正确的更新。 @AshishGupta 我上面提到的问题只发生在HTC。一旦设备处于非活动状态超过 15 分钟,它就会关闭 wifi 和任何活动的移动数据连接。因此,即使我已经大幅移动,它也会返回相同的位置。 @DavidOlsson 使用 WakeLocks 在这里没有任何区别。我通过专门接收 PARTIAL_WAKE_LOCK 尝试了上面的代码,但结果相同(即使我移动了很多,但在后台更新了相同的位置)。 【参考方案1】:

获取相同位置更新的问题仅发生在 HTC 手机中。我不知道这是否发生在所有 HTC Android 手机上。但它肯定会出现在我的 HTC Explorer 上。

在后台获取相同位置更新的原因是,一旦手机处于非活动状态超过 15 分钟,HTC 将禁用添加活动的互联网连接(WIFI 或移动数据连接)。为了交叉检查,我编写了以下代码。

安排一分钟后调用 AlarmReceiver 的活动。 警报接收器检查是否有任何连接可以建立互联网连接。 警报接收器会在一分钟后注册警报以调用自身

我编写的代码可以通宵运行。

public class AlarmReceiver extends BroadcastReceiver 

private static String TAG = AlarmReceiver.class.getName();

@Override
public void onReceive(Context context, Intent intent) 

    Log.i(TAG, "Entering Broadcast Receiver onReceive");
    FileLogger.log(context, "Entering Broadcast Receiver");
    logActiveNetworkInfo(context);
    setAlarm(context);
    FileLogger.log(context, "Exiting Broadcast Receiver");
    Log.i(TAG, "Exiting Broadcast Receiver onReceive");


private void logActiveNetworkInfo(Context context)

    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    if(networkInfo == null)
    
        FileLogger.log(context, "No network connectivity");
        return;
    
    String networkTypeName = networkInfo.getTypeName();
    boolean isConnected = networkInfo.isConnected();
    String log = "";
    if(isConnected == true)
    
        log = "Internet available through " + networkTypeName;
    
    else
        log = "Internet not available through "+ networkTypeName;
    FileLogger.log(context, log);
    Log.i(TAG,log);
    return;


private void setAlarm(Context context)

    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    long wakeUpAt = System.currentTimeMillis() + (60 * 1000);
    Intent intent = new Intent(context, AlarmReceiver.class);
    PendingIntent operation = PendingIntent.getBroadcast(context,
                                                         0,
                                                         intent,
                                                         PendingIntent.FLAG_UPDATE_CURRENT);
    alarmManager.set(AlarmManager.RTC_WAKEUP, wakeUpAt , operation);
    Log.i(TAG,"Alarm set to ring after "+wakeUpAt + " milliseconds");

所以应用开发者要小心,如果你想在 HTC 手机的后台进行 HTTP 调用,如果手机处于非活动状态超过 15 分钟就会失败。

此问题已报告HTC Deep Sleep

【讨论】:

这与HTC设备中的SmartSync功能有关。

以上是关于即使我已显着移动,也会在后台更新相同的位置的主要内容,如果未能解决你的问题,请参考以下文章

为啥即使我在后台请求位置更新,我的 iOS 应用程序也会被杀死?

即使设备没有移动,位置也会不断变化

即使鼠标不移动,D3 'Drag' 事件也会触发

即使手机放在桌子上,位置也会发生变化

即使浏览器关闭,服务人员也会在后台运行吗?

即使父节点在移动,如何在屏幕上给每个节点相同的起始位置?