【问题标题】:Can't receive LocationClient's location updates after screen gone off屏幕关闭后无法接收 LocationClient 的位置更新
【发布时间】:2013-07-17 15:25:03
【问题描述】:

我正在尝试编写一个简单的 Android 服务,该服务在后台运行并从 LocationClient(Google Map API Android V2)接收位置更新。问题是当屏幕关闭时,我的服务不再接收位置更新。我试图检查服务是否处于活动状态,即使屏幕关闭也是如此(我有一个 TimerTask 调度日志)。当屏幕打开时,我可以接收位置更新,但是当屏幕关闭时,我只看到 TimerTask 的日志并且我没有收到任何位置更新。唤醒屏幕再次打开位置更新。怎么解决?

这是我的简单服务:

public class LocationService extends Service implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener{

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

private LocationClient mLocationClient;

private Timer timer;
private static final LocationRequest REQUEST = LocationRequest.create()
          .setInterval(5*1000)      // 5 seconds
          .setFastestInterval(3*1000) // 3 seconds
          .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);


@Override
public void onCreate() {
    Log.d(TAG, "Creating..");
    mLocationClient = new LocationClient(this, this, this);
    timer = new Timer();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "Starting..");
    if(!mLocationClient.isConnected() || !mLocationClient.isConnecting()) {
        Log.d(TAG, "Connecting location client..");
        mLocationClient.connect();
    }
    timer.scheduleAtFixedRate(new TimerTask(){
        @Override
        public void run() {
            Log.d(TAG, "TimerTask executing");
        }}, 0, 3*1000);
    return START_STICKY;
}

@Override
public void onConnectionFailed(ConnectionResult result) {
    Log.d(TAG, "Connection failed..");
    stopSelf();
}

@Override
public void onConnected(Bundle bundle) {
    System.out.println("Connected ...");
    mLocationClient.requestLocationUpdates(REQUEST, this);
}

@Override
public void onDisconnected() {
    Log.d(TAG, "Disconnected..");
    stopSelf();
}

@Override
public IBinder onBind(Intent arg0) {
    throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public void onLocationChanged(Location location) {
    Log.d(TAG, "Received location update");
}

@Override
public void onDestroy() {
    Log.d(TAG, "Destroying..");
    timer.cancel();
    mLocationClient.removeLocationUpdates(this);
}
}

【问题讨论】:

  • 我也有同样的问题。我解决不了。任何新闻?这是一个错误吗?
  • 给你加个赏金,给题主多加点奖励...
  • 您能接受编辑吗?你能开始赏金吗? @user1781028
  • @User1781028,你能告诉我为什么在这个服务中创建了一个单独的线程(定时器)。谢谢你
  • 我也有同样的问题,使用 LocationManager 并没有解决问题。我正在考虑使用wakeLock,但它会太快耗尽电池..

标签: android android-service android-maps-v2


【解决方案1】:

使用WakeLock

在 onStartCommand 中

wl = ((PowerManager)getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, yourTAG);
wl.acquire();

在 onDestroy 中

if (wl != null && wl.isHeld()) {
    wl.release();
}

【讨论】:

    【解决方案2】:

    更新:--

    首先,您需要在 OnCreate() 中定义 LocationClient,它将调用您的 onConnected() ...

    像这样定义你的 locationClient ..

    locationClient = new LocationClient(this, this, this);
            locationClient.connect();
    

    现在在你的 onConnected() 中.. 只需像这样请求位置更新..

    @Override
        public void onConnectionFailed(ConnectionResult arg0) {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void onConnected(Bundle arg0) {
            src = locationClient.getLastLocation();
            System.out.println("======================location 1==" + src);
    
    
            LocationRequest lrequest = new LocationRequest();
            lrequest.setInterval(0);
            lrequest.setSmallestDisplacement(0);
            lrequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    
            locationClient.requestLocationUpdates(lrequest, new LocationListener() {
    
                @Override
                public void onLocationChanged(Location arg0) {
                     System.out.println("======================location 1233==" +
                     arg0);
                    /*Toast.makeText(getApplicationContext(),
                            "Location is 12" + arg0.getLatitude(),
                            Toast.LENGTH_SHORT).show();*/
    
    
                }
            });
    
    
        }
    
        @Override
        public void onDisconnected() {
            // TODO Auto-generated method stub
    
        }
    

    *************** 之前 ************

    如果您主要关心的是不断发现您的位置更新......那么您可以使用下面提到的。

    使用这个 ::(这将根据 GPS 定期更新用户的位置)

    For OnCreate()::
    ----------------------
    
    @Override
            protected void onCreate(Bundle savedInstanceState) {
                // TODO Auto-generated method stub
                super.onCreate(savedInstanceState);
                requestWindowFeature(Window.FEATURE_NO_TITLE);
                setContentView(R.layout.speed);
    
    
                initui();
    
                lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
                location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                provider = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
    
                if(!provider){
                    String text = "ENABLE GPS TO ACCESS SPEEDO METER!";
                    Toast.makeText(Speedometer.this, text, Toast.LENGTH_LONG).show();
                    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    startActivity(intent);
    
                }
    
                if (location != null) {
    
                    /*lat = (int) (location.getLatitude() * 1E6);
                    longi = (int)(location.getLongitude() * 1E6);*/
                    String text = "Got Coordinates";
                    Toast.makeText(Speedometer.this, text, Toast.LENGTH_SHORT).show();
    
                }
                //lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 2, this);
            }
    
    
    Now use onLocationChanged()
    ---------------------------
    
    
    @Override
            public void onLocationChanged(Location loc) {
                // TODO Auto-generated method stub
    
                float distance = 0;
                //float prevDis = 0;
    
                try{
                if(prevLoc==null)
                {
                    prevLoc = loc;
                    //Toast.makeText(MainActivity.this, "PrevLOC" + prevLoc, Toast.LENGTH_SHORT).show();
                    Log.i("Main Activity", "Prev LOC" + prevLoc);
                }
                else {
                    try{
                    Runtime r = Runtime.getRuntime();
                    r.gc();
                    }catch(Exception e){
                        e.printStackTrace();
                    }
                    // When prevLoc is not null
                    Log.i("Main Activity", "Prev LOC in new LOC BLAH BLAH BLAH" + prevLoc);
                    newLoc = loc;
                    //Toast.makeText(MainActivity.this, "NewLoc" + newLoc, Toast.LENGTH_SHORT).show();
                    Log.i("Main Activity", "New LOC" + newLoc);
                    distance = prevLoc.distanceTo(newLoc);
                    Log.i("Main Activity", "New DISTANCE DISTANCE DISTANCE DISTANCE DISTANCE DISTANCE " + distance);
    
                    distance = (float) (3.6*distance); 
                    speed = distance;
                    prevLoc = newLoc;
                    Log.i("Main Activity", "New Coordinates set to PrevLoc" + prevLoc);
                }
    
                }catch(Exception e){
                    e.printStackTrace();
                }
    
    
                if(speed <= 160){
    
                    try
                    {
                    mView.calculateAngleOfDeviation(speed);
                    }
                    catch (Exception e) {
                        // TODO: handle exception
                        e.printStackTrace();
                    }
                }else
                {
                    Toast.makeText(Speedometer.this, "CONTROL SPEED", Toast.LENGTH_SHORT).show();
                }
    
            }
    
    You can also utilize same in your activity ::
    -----------------------------------------------
    
    @Override
            public void onProviderDisabled(String provider) {
                // TODO Auto-generated method stub
            }
            @Override
            public void onProviderEnabled(String provider) {
                // TODO Auto-generated method stub
            }
            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
                // TODO Auto-generated method stub
            }
            @Override
            protected void onPause() {
                // TODO Auto-generated method stub
                stopListening();
                super.onPause();
            }
            private void stopListening() {
                // TODO Auto-generated method stub
                try{
                if(lm != null){
                    lm.removeUpdates(this);
                }else{
                    lm.removeUpdates(this);
                     }
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
    
    
    
            @Override
            protected void onResume() {
                // TODO Auto-generated method stub
                super.onResume();
                startListening();
            }
    
            private void startListening() {
                // TODO Auto-generated method stub
                try{
                lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
    
            @Override
            protected void onDestroy() {
                // TODO Auto-generated method stub
                super.onDestroy();
                lm.removeUpdates(Speedometer.this);
                //System.exit(0);
                finish();
            } 
    
    
    
    Finally there's always a lot of way to do single thing.
    Hope it helps... 
    Cheers!
    

    【讨论】:

    • 问题是关于 LocationClient 而不是 LocationManager。您的解决方案,可能是一种解决方法。如果您很好地解释了 Location Client 未按预期工作的原因,则可以接受。
    • 我上面所说的显然是一种解决方法.. 对于您自己的具体问题,您尝试过“PARTIAL_WAKE_LOCK”,它可以帮助您的应用不进入睡眠模式。试试这个。
    • 以下线程上的最后一个 cmets 是我的。唤醒锁不能解决问题:stackoverflow.com/questions/17613888/…
    【解决方案3】:

    我不确定您的问题出在哪里。我用你的代码做了一个项目,它似乎在这里按要求工作。即使屏幕关闭,我也会收到更新。无论如何,这是我采取的步骤,也许您的问题不在于服务,而在于您如何启动它,或者其他地方:

    1. 我创建了一个默认的 android 项目,其中包含一个主要活动。
    2. 我将您的代码包含在名为“LocationService”的单独文件中
    3. 我在项目中添加了 google play 服务库。
    4. 我在清单中添加了以下权限:

    在应用程序标签中我声明了服务:

       <service
            android:name=".LocationService"
            android:process=":Location_Service_Test" />
    

    最后我在主要活动的 onCreate 中添加了以下内容:

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        //Start the service
        Intent service = new Intent(this, LocationService.class);
        startService(service);
    } 
    

    如果这不能解决您的问题:请包含您的其余代码。

    【讨论】:

    • 我编辑了问题,让我们等待作者审核。无论如何,我发布了整个代码。我做了你所做的。
    • 在logcat上我可以看到“timertask”在持续执行,但是“Received location update”只有在屏幕打开时才会显示。我的智能手机是安卓 4.2.1。你的呢?
    • 你模拟位置变化了吗?
    • 我在屏幕关闭时收到“已接收位置更新”日志。我在 android 4.3 上运行,我没有模拟位置变化。这是android项目,看看你是否遗漏了什么:s000.tinyupload.com/?file_id=81195373734373847745
    • 我在我的桌面上解压了你的文件夹,我在安卓中导入并启动了。同样的效果。当我锁定屏幕时,我没有收到更新。你能把你的代码生成的apk发给我吗?如果不是编译问题,可能与android版本有关
    猜你喜欢
    • 2014-04-05
    • 2018-07-08
    • 2017-01-13
    • 1970-01-01
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多