2015-09-11 2 views
1

Когда возникает onPerformSync, мне нужно текущее местоположение, но я не хочу настраивать отдельную службу, которая постоянно активно запрашивает местоположение, потому что мой период SyncAdapter экспоненциально отступает, так что периоды между синхронизациями могут быть много часов Кроме. Было бы расточительно иметь запросы местоположения, выполняемые между каждой синхронизацией.SyncAdapter onPerformSync получает текущее местоположение

Я планирую использовать GoogleApiClient и LocationServices.FusedLocationApi.requestLocationUpdates, затем Thread.sleep(###)onPerformSync нить до тех пор, пока не будет найдено местоположение.

Тем не менее, я прочитал, что requestLocationUpdates должен быть вызван на main looper and that it makes callbacks on that thread, и в этом случае я ожидаю, что он не сможет вернуть результаты местоположения, потому что я спал по потоку, который его назвал.

Нужно ли мне начинать собственный поток петлителя?

Есть ли другой/лучший способ получить текущее местоположение от onPerformSync?

ответ

1

Оказывается, мои страхи не оправдались, мой метод работает без ошибок. Я поставил вместе удобный пример класс ниже в случае, если кто-то хочет сделать это:

public class cSyncLocation implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener 
{ 

    // ======================================================= 
    // private vars 
    // ======================================================= 
    private GoogleApiClient moGoogleApiClient; 
    private LocationRequest moLocationRequest; 
    private Location moCurrentLocation; 
    private static final int kTIMEOUT_MILLISECONDS = 2500; 

    // ======================================================= 
    // public static vars 
    // ======================================================= 

    // ======================================================= 
    // public methods 
    // ======================================================= 

    public void Start(Context oContext) 
    { 
     if (moGoogleApiClient == null) 
     { 
      moGoogleApiClient = new GoogleApiClient.Builder(oContext) 
           .addApi(LocationServices.API) 
           .addConnectionCallbacks(this) 
           .addOnConnectionFailedListener(this) 
           .build(); 
     } 
     if (moLocationRequest == null) 
     { 
      moLocationRequest = new LocationRequest(); 

      moLocationRequest.setInterval(1); 
      moLocationRequest.setFastestInterval(1); 
      moLocationRequest.setInterval(1); 
      moLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 
     } 
     // Start the connection 
     if (moGoogleApiClient != null) 
     { 
      if (!moGoogleApiClient.isConnecting() && !moGoogleApiClient.isConnected()) 
       moGoogleApiClient.connect(); 
      else if (moCurrentLocation == null) 
       LocationServices.FusedLocationApi.requestLocationUpdates(moGoogleApiClient, moLocationRequest, this); 

     } 
    } 

    public void Stop() 
    { 
     if (moGoogleApiClient != null && moGoogleApiClient.isConnected()) 
      LocationServices.FusedLocationApi.removeLocationUpdates(moGoogleApiClient, this); 
     if (moGoogleApiClient != null) 
      moGoogleApiClient.disconnect();  
    } 

    public Location GetLocationBlocking(Context oContext) 
    { 
     if (moCurrentLocation == null) 
     { 
      intTimeout = kTIMEOUT_MILLISECONDS; 
      Start(oContext); 
      while(intTimeout > 0 && aFrmLocationActivity.IsLastLocationExpired(oContext)) 
      { 
       Thread.sleep(100); 
       intTimeout -= 100; 
      } 
      Stop(); 
     } 
     return moCurrentLocation; 
    } 

    // ======================================================= 
    // Location API Events 
    // ======================================================= 

    @Override 
    public void onLocationChanged(Location oLocation) 
    { 
     if (oLocation != null) 
     { 
      moCurrentLocation = oLocation; 
     } 
    } 

    // ======================================================= 
    // Google API Connection Events 
    // ======================================================= 


    @Override 
    public void onConnected(Bundle connectionHint) 
    { 
     // Connected to Google Play services! The good stuff goes here. 
     if (moGoogleApiClient != null) 
     { 
      Location oLocation = LocationServices.FusedLocationApi.getLastLocation(moGoogleApiClient); 
      if (oLocation != null) 
       moCurrentLocation = oLocation; 
      else 
       LocationServices.FusedLocationApi.requestLocationUpdates(moGoogleApiClient, moLocationRequest, this); 
     } 
    } 

    @Override 
    public void onConnectionSuspended(int cause) 
    { 
     //... 
    } 

    @Override 
    public void onConnectionFailed(ConnectionResult result) 
    { 
     //... 
    }  


} 

Как использовать его, в вашем методе onPerformSync называют его, как этот

cSyncLocation oSyncLocation = new cSyncLocation(); 
Location oLocation = oSyncLocation.GetLocationBlocking(getContext()); 

Очевидно, что вы хотите добавьте обработку исключений и обработайте нулевой результат.

+0

Это не работает для меня, 'onLocationChanged' никогда не вызывался. –

+0

Проверьте, что у вас есть использование - разрешение ACCESS_FINE_LOCATION в манифесте. Если вы настроите таргетинг и работаете на Android 6.0 (уровень API 23) или выше, вам нужно будет попросить у пользователя разрешения на доступ к местоположению в части пользовательского интерфейса вашего приложения, после того как оно предоставлено, оно должно работать и с синхронизатором. Но, возможно, это просто время, прежде чем найти место. –

+0

Я попытался получить местоположение с разрешением ACCESS_COARSE_LOCATION. Когда я изменил его на ACCESS_FINE_LOCATION, проблема была исправлена. –

Смежные вопросы