在 GPS 芯片长时间处于活动状态后,Android 设备需要重启/重启才能获取 GPS 位置

Posted

技术标签:

【中文标题】在 GPS 芯片长时间处于活动状态后,Android 设备需要重启/重启才能获取 GPS 位置【英文标题】:Android device needs restart/reboot to get GPS locations after having GPS chip active a long time 【发布时间】:2015-04-09 18:05:51 【问题描述】:

我正在为 android 开发另一个 GPS 跟踪应用程序,我正在使用 Android 4.3 在 Sony Xperia SP c5302 中测试我的代码。

我创建了一个后台服务,它使用 Google Play Services 的 GoogleApiClient 来获取融合位置。我能够很好地获取位置,但几个小时后,我意识到我的 GPS 芯片停止返回位置,因为它们的精度从 10 提高到 30 或 50(这意味着除了 GPS 之外的其他提供商正在返回新位置)。

考虑到我在室内,我认为 API 决定只听网络提供商的声音,然后我走到街上(关闭了 wifi 和数据连接)并完全停止获取融合位置(我没有得到网络修复正如预期的那样,GPS芯片已经死了)。甚至谷歌地图也无法追踪到我。然后我决定在那一刻重新启动我的手机,我的应用程序和谷歌地图上的 GPS 芯片更新都很好(wifi 和数据连接仍然关闭)。

我对使用 LocationManager 的原始 Location API 尝试了相同的方法,结果相同......我必须重新启动手机才能让 GPS 芯片再次工作。

这是我使用 GoogleApiClient 的基本代码:

public class MyService extends Service 

private final static String TAG = MyService.class.getSimpleName();

//GPS
private GoogleApiClient miGoogleApiClient = null;
private LocationRequest miLocationRequest = null;
private LocationRequest currLocation = null;

@Override  
public void onCreate()      
    super.onCreate();     
    Log.i(TAG, "onCreate MY SERVICE");

    startGPS();


@Override
public void onDestroy()
    super.onDestroy();
    Log.d(TAG, "onDestroy");
    stopGPS();



public boolean startGPS()
    Log.d(TAG, "startGPS");
    try
        miGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(miConnectionCallbacks)
            .addOnConnectionFailedListener(miOnConnectionFailedListener)
            .build();
        miGoogleApiClient.connect();

        return true;
    catch(Exception e)
        Log.d(TAG, "can't start GPS:"+e);
        return false;
    finallyreturn false;


public void stopGPS()
    Log.d(TAG, "stopGPS");
    miGoogleApiClient.disconnect();


private LocationListener miLocationListener = new LocationListener()
    @Override public void onLocationChanged(Location location)
        Log.d(TAG, "onLocationChanged:"+new Date(location.getTime())+", "+ location);
        //...more work
        currLocation = location;
    
;

private GoogleApiClient.ConnectionCallbacks miConnectionCallbacks = new GoogleApiClient.ConnectionCallbacks()
    @Override public void onConnected(Bundle bundle)
        Log.d(TAG, "onConnected:"+bundle);
        currLocation = LocationServices.FusedLocationApi.getLastLocation(miGoogleApiClient); //may be old
        miLocationRequest = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            //.setSmallestDisplacement(10) //Won't use this for now
            .setInterval(30000)
            .setFastestInterval(30000);
        LocationServices.FusedLocationApi.requestLocationUpdates(
            miGoogleApiClient, miLocationRequest, miLocationListener);
    
    @Override public void onConnectionSuspended(int i)
        Log.d(TAG, "onConnectionSuspended:"+i);
    
;

private GoogleApiClient.OnConnectionFailedListener miOnConnectionFailedListener = new GoogleApiClient.OnConnectionFailedListener()
    @Override public void onConnectionFailed(ConnectionResult connectionResult)
        Log.d(TAG, "onConnectionFailed:"+connectionResult);
    
;


我知道这种方法会更快地消耗电池电量,但此应用程序是针对特定客户而非普通公众的,所以没关系。

¿这种行为是应该发生的还是我的手机有问题或我的代码有问题?我觉得特别奇怪的是,即使是 Google 地图也无法获取位置,所以我想知道我的应用程序是不是在弄乱手机本身。

编辑。

我必须重新启动手机,因为从 Android 设置菜单中关闭和打开 GPS 没有任何区别。 (我的服务日志显示,如果我停止并重新启动 GPS,它会正常启动)

【问题讨论】:

虽然它应该做同样的事情,但你可以尝试使用github.com/mcharmas/Android-ReactiveLocation,无论如何它可以为你节省很多代码行 @cYrixmorten 谢谢。这是一个有趣的图书馆。正如您所说,它使用相同的代码来处理 GoogleApiClient 但样板代码可能是一个因素。我想知道在服务上下文中使用 GoogleApi 的注意事项。我会尝试根据您的建议制作一个测试项目。 记得在我知道的onDestroy() 中退订。我自己在服务中使用它。只是为了加入另一个库,然后我使用 EventBus github.com/greenrobot/EventBus 来广播,只要有新的位置可用于更新 UI。这几乎像常规广播一样工作,但不限于可序列化的数据,而是适用于任何复杂的对象,而且它比设置广播接收器等需要更少的代码。 @cYrixmorten 事件 EventBus 似乎很棒。我以前读过它,但忘记了它的名字,从未使用过它。很高兴看到该项目仍在进行中。 @cYrixmorten 我不知道该怎么想。我只是在用 ReactiveLocation 做几个测试。我修改了示例项目并添加了与此问题中的服务类似的服务。我离开了原始设置(500 毫秒的更新时间)并工作了一个小时(时间不多,但工作)。然后我只是将设置更改为 30 秒 = 30000 毫秒,它在半小时内就被杀死了,但由于 START_STICKY 再次开始,但没有更多的位置。我将项目重新构建回 500 毫秒并重新启动手机。 5 小时后,它仍然提供 GPS 芯片位置。 【参考方案1】:

经过长时间的测试,我可以看出“问题”与设备有关。我的应用在朋友的 Nexus 4 上运行良好很长时间。

我还通过更改更新间隔让它在我的 Xperia SP 中工作

miLocationRequest = LocationRequest.create()
        .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
        .setInterval(5000)

也许我可以将它设置为更高的间隔。我只是确定 30 秒太多了。

为了覆盖我客户的设备,我最好的猜测是设置一些共享偏好,以便在 GPS 芯片停止提供位置的情况下设置此间隔。

【讨论】:

以上是关于在 GPS 芯片长时间处于活动状态后,Android 设备需要重启/重启才能获取 GPS 位置的主要内容,如果未能解决你的问题,请参考以下文章

许多长时间运行的 Apache 进程处于 READ 状态,一段时间后没有请求

如果 Android 设备长时间处于空闲状态,则不会收到推送通知

MySQL 查询:长时间处于“init”状态

如何让 Appium 会话长时间保持活动状态

MySQL进阶垫脚石:线程长时间处于killed状态怎么破?

Android服务在其仍处于活动状态时停止后台处理