Как лучше обрабатывать местоположение GPS и Android

У меня есть фрагмент со списком, который извлекает местоположение пользователей, а затем обновляет представление списка на основе местоположения пользователей.

Проблема с моим кодом заключается в том, что он, кажется, захватывает обновление списка местоположения, а затем продолжает обновлять. И перезагрузка списка, почти до раздражения. Вот мой код:

public class FindBrewery extends Fragment implements LocationListener {

    private TextView latituteField;
    private TextView longitudeField;
    LocationManager locationManager;
    private String provider;


    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        Context c = getActivity().getApplicationContext();
        locationManager =(LocationManager)activity.getSystemService(Context.LOCATION_SERVICE);

    }



    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //todo change view
        View rootView = inflater.inflate(R.layout.beer_location_list,container, false);

        // Get the location manager
        // Define the criteria how to select the locatioin provider -> use
        // default
        Criteria criteria = new Criteria();
        provider = locationManager.getBestProvider(criteria, false);
        Location location = locationManager.getLastKnownLocation(provider);

        // Initialize the location fields
        if (location != null) {
            System.out.println("Provider " + provider + " has been selected.");
            onLocationChanged(location);
        } else {

        }


        return rootView;
    }




    /* Request updates at startup */
    @Override
    public void onResume() {
        super.onResume();
        locationManager.requestLocationUpdates(provider, 400, 1, this);
    }

    /* Remove the locationlistener updates when Activity is paused */
    @Override
    public void onPause() {
        super.onPause();
        locationManager.removeUpdates(this);
    }

    @Override
    public void onLocationChanged(Location location) {
        int lat = (int) (location.getLatitude());
        int lng = (int) (location.getLongitude());
        //latituteField.setText(String.valueOf(lat));
        //longitudeField.setText(String.valueOf(lng));

        //Toast.makeText(this, "Finding your loaction",Toast.LENGTH_SHORT).show();

        //call asycn task for location
        String url = "myURL";

        Log.d("urlTest", url);

        //async task goes here
        new GetNearbyBreweries(this.getActivity()).execute(url);



    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onProviderEnabled(String provider) {
        //Toast.makeText(this, "Enabled new provider " + provider,Toast.LENGTH_SHORT).show();

    }

    @Override
    public void onProviderDisabled(String provider) {
        //Toast.makeText(this, "Disabled provider " + provider,Toast.LENGTH_SHORT).show();
    }



}

person Mike    schedule 11.03.2014    source источник


Ответы (5)


Возможно, вы захотите попробовать этот подход:

LocationClient mLocationClient;
LocationRequest mLocationRequest;

@Override
public void onAttach(Activity activity) {
  if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(activity)) {
    mLocationClient = new LocationClient(activity, activity, activity);

    mLocationRequest = LocationRequest.create();
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setInterval(5000);
    mLocationRequest.setNumUpdates(1);
    mLocationRequest.setFastestInterval(1000);
  }
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
  if (mLocationClient != null) {
    mLocationClient.connect();
  }
}

@Override
protected void onStop() {
  if (mLocationClient != null) {
    if (mLocationClient.isConnected()) {
      mLocationClient.removeLocationUpdates(this);
    }

    mLocationClient.disconnect();
  }
  super.onStop();
}

@Override
public void onConnected(Bundle dataBundle) {
  LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
  mLocationClient.requestLocationUpdates(mLocationRequest, this);
}

@Override
public void onLocationChanged(Location location) {
  int lat = (int) (location.getLatitude());
  int lng = (int) (location.getLongitude());

  // post to a handler to update the list items
}

Хитрость заключается в следующем:

  • вы не используете getLastKnownLocation, так как он использует кеш и чаще всего возвращает неправильные данные,
  • вы установили setNumUpdates(1), поэтому вам не нужно звонить removeLocationUpdates()

Не забудьте разрешения AndroidManifest:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
person Saran    schedule 11.03.2014
comment
где в приведенном выше коде я вызываю свою асинхронную задачу, когда у нее есть местоположение? - person Mike; 12.03.2014
comment
Как вы уже поняли: прокрутите поле кода, чтобы увидеть :) Дайте мне знать, сработало ли это для вас. - person Saran; 12.03.2014

Вот большой пост о местоположении GPS и о том, как проверять его время от времени. (30 минут в этом примере)

Вы также можете взглянуть на Timer, чтобы установить повторный вызов метода, который получает местоположение с нужным вам интервалом.

person JayD    schedule 11.03.2014

Хотя это может быть немного надежным для ваших нужд, проверьте Fused Location Provider. Это довольно революционно в том, что касается диспетчера местоположений в Android. Это позволяет вам делать определенные вещи, такие как установка максимального и минимального времени интервала, а также довольно простая реализация выключения. Я сделал свой первый запуск из этого примера, и он работал очень хорошо (я пытался сделать наоборот, мне нужны были обновления каждые 5 секунд, тогда как Android делал обновления каждые 30-45 секунд):

http://www.kpbird.com/2013/06/fused-location-provider-example.html

person zgc7009    schedule 11.03.2014

Вы должны удалить обновления из gps где-то в своем коде (предположим, что в вашем случае вы можете сделать это, когда у вас есть текущая локализация от пользователя), поэтому вызовите locationManager.removeUpdates(this); внутри метода onLocationChanged(), когда у вас есть подходящее местоположение для ваших нужд.

person Carlos Morera    schedule 11.03.2014

Для этой цели я использовал отдельный сервис и внедрил в него функции, связанные с GPS. Этот сервис делает запросы о местоположении и передает их обратно. Таким образом, вы можете просто зарегистрировать приемник, чтобы получить полученные координаты.

LocationService.java

package com.my.package.services;

import android.app.Service;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;


public class LocationService extends Service implements LocationListener, ConnectionCallbacks, OnConnectionFailedListener {
    private static final String TAG = LocationService.class.getSimpleName();

    public static final String BROADCAST_ACTION = "com.my.package.LOCATION_UPDATE";

    // Milliseconds per second
    private static final int MILLISECONDS_PER_SECOND = 1000;

    // Update frequency in seconds
    public static final int UPDATE_INTERVAL_IN_SECONDS = 60;

    // Update frequency in milliseconds
    private static final long UPDATE_INTERVAL = MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;

    // The fastest update frequency, in seconds
    private static final int FASTEST_INTERVAL_IN_SECONDS = 40;

    // A fast frequency ceiling in milliseconds
    private static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;

    private LocationClient locationClient;

    @Override
    public void onCreate() {
        super.onCreate();

        Log.d(TAG, "Location service created…");

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

    // Unregister location listeners
    private void clearLocationData() {
        locationClient.disconnect();

        if (locationClient.isConnected()) {
            locationClient.removeLocationUpdates(this);
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    // When service destroyed we need to unbind location listeners
    @Override
    public void onDestroy() {
        super.onDestroy();

        Log.d(TAG, "Location service destroyed…");

        clearLocationData();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "Calling command…");

        return START_STICKY;
    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.d(TAG, "Location Callback. onConnected");

        Location currentLocation = locationClient.getLastLocation();

        // Create the LocationRequest object
        LocationRequest locationRequest = LocationRequest.create();

        // Use power balanced mode
        locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

        // Set the update interval to 5 seconds
        locationRequest.setInterval(UPDATE_INTERVAL);

        // Set the fastest update interval to 1 second
        locationRequest.setFastestInterval(FASTEST_INTERVAL);

        locationClient.requestLocationUpdates(locationRequest, this);

        onLocationChanged(currentLocation);
    }

    @Override
    public void onLocationChanged(Location location) {
        Log.d(TAG, "onLocationChanged");
        Log.d(TAG, "LOCATION: " + location.getLatitude() + ":" + location.getLongitude());

        // Since location information updated, broadcast it
        Intent broadcast = new Intent();

        // Set action so other parts of application can distinguish and use this information if needed
        broadcast.setAction(BROADCAST_ACTION);
        broadcast.putExtra("latitude", location.getLatitude());
        broadcast.putExtra("longitude", location.getLongitude());

        sendBroadcast(broadcast);
    }

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

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d(TAG, "Location Callback. onConnectionFailed");
    }
}
person sultan    schedule 12.03.2014