1

Работаю над приложением, которое часто требует обновления местоположения, даже когда оно находится в фоновом режиме. Следуя документации here, я работаю с ожидающим намерения, а не идентификатором местоположения. Мой код нижеFusedLocationApi с PendingIntent запускается только один раз и его нуль

/** 
* Created by philip on 7/30/16. 
*/ 
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener{ 
    private GoogleApiClient mGoogleApiClient; 
    private LocationRequest mLocationRequest; 

    public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000 * 30; //1 minute; 
    /** 
    * The fastest rate for active location updates. Exact. Updates will never be more frequent 
    * than this value. 
    */ 
    public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 
      UPDATE_INTERVAL_IN_MILLISECONDS/2; 

    private String mLastUpdateTime; 
    private Location mCurrentLocation; 

    private GeoFire mGeoFire = null; 
    private String uuid = null; 
    private Intent intentService; 
    private PendingIntent mPendingIntent; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     Firebase.setAndroidContext(this); 
     buildGoogleApiClient(); 
    } 

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

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     if (!mGoogleApiClient.isConnected()) { 
      mGoogleApiClient.connect(); 
     } 
     createLocationRequest(); 
     if(intent != null){ 
      intentService = new Intent(this, LocationBroadcastReceiver.class); 
      intentService.putExtra("UUID", intent.getStringExtra("UUID")); 
      intentService.setAction("foo.LOCATION_UPDATE_INTENT"); 
      mPendingIntent = PendingIntent.getBroadcast(this, 0, intentService, PendingIntent.FLAG_UPDATE_CURRENT); 
     } 
     return START_REDELIVER_INTENT; 
    } 

    /********************************************** Google api connection callback below **************************************/ 

    /*** 
    * callback fired once connection has been established 
    * @param bundle 
    */ 
    @Override 
    public void onConnected(Bundle bundle) { 
     startLocationUpdates(); 
     Log.i(this.getClass().getSimpleName(), "Location Service api has been connected"); 
    } 


    /*** 
    * callback fired when connection fails 
    * @param connectionResult 
    */ 
    @Override 
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { 
     Log.i(this.getClass().getSimpleName(), "Location Service disconnected"); 
    } 


    /** 
    * callback fired when connection is temporary suspended 
    * @param i 
    */ 
    @Override 
    public void onConnectionSuspended(int i) { 
     if (mGoogleApiClient != null) { 
      mGoogleApiClient.connect(); 
     } 
    } 

    /************************************** Ease methods ************************************************/ 

    /** 
    * Builds a GoogleApiClient. Uses the {@code #addApi} method to request the 
    * LocationServices API. 
    */ 
    protected synchronized void buildGoogleApiClient() { 
     mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(API) 
       .build(); 
    } 

    /** 
    * Requests location updates from the FusedLocationApi. 
    */ 
    protected void startLocationUpdates() { 
     if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
      // TODO: Consider calling 
      return; 
     } 
     FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mPendingIntent); 
    } 

    protected void createLocationRequest() { 
     mLocationRequest = new LocationRequest(); 

     // Sets the desired interval for active location updates. This interval is 
     // inexact. You may not receive updates at all if no location sources are available, or 
     // you may receive them slower than requested. You may also receive updates faster than 
     // requested if other applications are requesting location at a faster interval. 
     mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS); 

     // Sets the fastest rate for active location updates. This interval is exact, and your 
     // application will never receive updates faster than this value. 
     mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS); 

     mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 
    } 


} 

и мой BroadcastReceiver

@Override 
    public void onReceive(Context context, Intent intent) { 
     Firebase.setAndroidContext(context); 
     Log.i(getClass().getSimpleName(), "broadcast has been called"); 

     if (intent != null) { 
      String uuid = intent.getStringExtra("UUID"); 
      mGeoFire = new GeoFire(new Firebase("https://foo.firebaseio.com/users/" + uuid)); 

      LocationResult locationResult = LocationResult.extractResult(intent); 

      if(locationResult == null){// check for null pointer 
       Log.i(getClass().getSimpleName(), "location result is null <<<<<<<<<<<<<<<<<<"); 
       return; 
      } 

      Log.i(getClass().getSimpleName(), "location result found >>>>>>>>>>>>>>>>>>>>====>>>>>>>>>>>>>>>>>>>"); 

      location = locationResult.getLastLocation(); 
     } 

     if(isBetterLocation(location, currentBestLocation)){ 
      currentBestLocation = location; 
     }else { 
      return; 
     } 

     if (mGeoFire != null) { 
      mGeoFire.setLocation("location", new GeoLocation(location.getLatitude(), location.getLongitude())); 
     } 
    } 

вопрос я столкнуться в том, что

  1. Моя широковещательный только когда вызывается один раз,
  2. Когда я действительно получают намерение , LocationResult locationResult = LocationResult.extractResult(intent);null

и последний я слышал от моего эфира Reveiver

+1

У меня этот вопрос - вы когда-нибудь решить эту проблему? –

+0

Я был. Я положу свое решение в суть и отправлю ответ немного. –

+0

Я только что разместил свое рабочее решение ниже –

ответ

0

Я в основном переместил слушатель onConnected и проверен на null. После этого он отлично справился.

package com.github.robophil.location_service; 

import android.Manifest; 
import android.app.PendingIntent; 
import android.app.Service; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.content.pm.PackageManager; 
import android.location.Location; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.support.annotation.NonNull; 
import android.support.annotation.Nullable; 
import android.support.v4.app.ActivityCompat; 
import android.util.Log; 
import android.widget.Toast; 

import com.firebase.client.Firebase; 
import com.firebase.geofire.GeoFire; 
import com.google.android.gms.common.ConnectionResult; 
import com.google.android.gms.common.api.GoogleApiClient; 
import com.google.android.gms.location.LocationRequest; 
import com.google.android.gms.location.LocationResult; 

import static com.google.android.gms.location.LocationServices.API; 
import static com.google.android.gms.location.LocationServices.FusedLocationApi; 

/** 
* Created by philip on 7/30/16. 
*/ 
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { 
    private GoogleApiClient mGoogleApiClient; 
    private LocationRequest mLocationRequest; 

    public static final String prefName = "com.github.robophil.pref"; 

    public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000 * 60; //1 minute; 
    /** 
    * The fastest rate for active location updates. Exact. Updates will never be more frequent 
    * than this value. 
    */ 
    public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 
      UPDATE_INTERVAL_IN_MILLISECONDS/2; 

    private String mLastUpdateTime; 
    private Location mCurrentLocation; 

    private GeoFire mGeoFire = null; 
    private String uuid = null; 
    private Intent intentService; 
    private PendingIntent mPendingIntent; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     Firebase.setAndroidContext(this); 
     buildGoogleApiClient(); 
    } 

    @Override 
    public void onDestroy() { 
     if(mGoogleApiClient != null){ 
      if(mGoogleApiClient.isConnected()){ 
       mGoogleApiClient.disconnect(); 
       FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mPendingIntent); 
      } 
     } 
     super.onDestroy(); 
    } 

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

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     if (intent != null) { 
      if(!intent.hasExtra("UUID") || !intent.hasExtra("URL")){ 
       Log.i(getClass().getSimpleName(), "Service has stopped itself"); 
       Toast.makeText(this, "stopself called", Toast.LENGTH_SHORT).show(); 
       stopSelf(); 
      } 

      SharedPreferences.Editor editor = getSharedPreferences(LocationService.prefName, getApplicationContext().MODE_PRIVATE).edit(); 
      editor.putString("UUID", intent.getStringExtra("UUID")); 
      editor.putString("URL", intent.getStringExtra("URL")); 
      editor.apply(); 

      intentService = new Intent(this, LocationIntentService.class); 
      intentService.setExtrasClassLoader(LocationResult.class.getClassLoader()); 
      mPendingIntent = PendingIntent.getService(getApplicationContext(), 0, intentService, PendingIntent.FLAG_UPDATE_CURRENT); 
     } 

     if (!mGoogleApiClient.isConnected()) { 
      mGoogleApiClient.connect(); 
     } 

     return START_REDELIVER_INTENT; 
    } 

    /********************************************** Google api connection callback below **************************************/ 

    /*** 
    * callback fired once connection has been established 
    * @param bundle 
    */ 
    @Override 
    public void onConnected(Bundle bundle) { 
     createLocationRequest(); 
     startLocationUpdates(); 
     Log.i(this.getClass().getSimpleName(), "Location Service api has been connected"); 
     if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
      // TODO: Consider calling 
      return; 
     } 
     Location location = FusedLocationApi.getLastLocation(mGoogleApiClient); 
     if (location == null){ 
      Log.i(getClass().getSimpleName(), "init location is null"); 
      return; 
     } 
     Log.i(getClass().getSimpleName(), "init location ==> "+location.getAccuracy()+" "+location.getProvider()); 
    } 


    /*** 
    * callback fired when connection fails 
    * @param connectionResult 
    */ 
    @Override 
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { 
     Log.i(this.getClass().getSimpleName(), "Location Service disconnected"); 
    } 


    /** 
    * callback fired when connection is temporary suspended 
    * @param i 
    */ 
    @Override 
    public void onConnectionSuspended(int i) { 
     if (mGoogleApiClient != null) { 
      mGoogleApiClient.connect(); 
     } 
    } 

    /************************************** Ease methods ************************************************/ 

    /** 
    * Builds a GoogleApiClient. Uses the {@code #addApi} method to request the 
    * LocationServices API. 
    */ 
    protected synchronized void buildGoogleApiClient() { 
     mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(API) 
       .build(); 
    } 

    /** 
    * Requests location updates from the FusedLocationApi. 
    */ 
    protected void startLocationUpdates() { 
     if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
      // TODO: Consider calling 
      return; 
     } 
//  FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); 
     FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mPendingIntent); 
    } 

    protected void createLocationRequest() { 
     mLocationRequest = new LocationRequest(); 

     // Sets the desired interval for active location updates. This interval is 
     // inexact. You may not receive updates at all if no location sources are available, or 
     // you may receive them slower than requested. You may also receive updates faster than 
     // requested if other applications are requesting location at a faster interval. 
     mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS); 

     // Sets the fastest rate for active location updates. This interval is exact, and your 
     // application will never receive updates faster than this value. 
     mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS); 

     mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 
    } 


} 

LocationsIntentService используется для моего отложенного намерения остается прежним, просто проверяя нуль, прежде чем делать что-нибудь

package com.github.robophil.location_service; 

import android.app.IntentService; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.location.Location; 
import android.os.Bundle; 
import android.util.Log; 

import com.firebase.client.Firebase; 
import com.firebase.geofire.GeoFire; 
import com.firebase.geofire.GeoLocation; 
import com.google.android.gms.location.LocationResult; 

import java.util.Set; 

/** 
* Created by philip on 8/7/16. 
*/ 
public class LocationIntentService extends IntentService { 
    private GeoFire mGeoFire; 
    private Location location, currentBestLocation; 

    /** 
    * Creates an IntentService. Invoked by your subclass's constructor. 
    * 
    * @param name Used to name the worker thread, important only for debugging. 
    */ 
    public LocationIntentService(String name) { 
     super("i am a value"); 
    } 

    public LocationIntentService(){ 
     super("i am a value"); 
    } 



    @Override 
    protected void onHandleIntent(Intent intent) { 
     Firebase.setAndroidContext(this); 
     Log.i(getClass().getSimpleName(), "intent service has been called"); 

     SharedPreferences pref = getSharedPreferences(LocationService.prefName, getApplicationContext().MODE_PRIVATE); 
     String uuid = pref.getString("UUID", null); 
     String url = pref.getString("URL", null); 

     if(uuid == null || url==null){ 
      stopSelf(); 
      return; 
     } 

     if (intent != null) { 

      mGeoFire = new GeoFire(new Firebase(url +"/"+ uuid)); 
      Log.i(getClass().getSimpleName(), "user id found ==> "+uuid+", "+url); 

      Bundle extra = intent.getExtras(); 
      Set<String> extraKeySet = extra.keySet(); 
      for(String key: extraKeySet){ 
       Log.i(getClass().getSimpleName(), "key found ==> "+ key); 
      } 

      if(LocationResult.hasResult(intent)){ 
       Log.i(getClass().getSimpleName(), "intent contains location"); 
      } 

      LocationResult locationResult = LocationResult.extractResult(intent); 

      if(locationResult == null){// check for null pointer 
       Log.i(getClass().getSimpleName(), "location result is null ..."); 
       return; 
      } 

      Log.i(getClass().getSimpleName(), "location result found"); 

      location = locationResult.getLastLocation(); 
     } 

     if(isBetterLocation(location, currentBestLocation)){ 
      currentBestLocation = location; 
     }else { 
      return; 
     } 

     if (mGeoFire != null) { 
      mGeoFire.setLocation("location", new GeoLocation(location.getLatitude(), location.getLongitude())); 
     } 
    } 

    private static final int TWO_MINUTES = 1000 * 60 * 2; 

    /** Determines whether one Location reading is better than the current Location fix 
    * @param location The new Location that you want to evaluate 
    * @param currentBestLocation The current Location fix, to which you want to compare the new one 
    */ 
    protected boolean isBetterLocation(Location location, Location currentBestLocation) { 
     if (currentBestLocation == null) { 
      // A new location is always better than no location 
      return true; 
     } 

     // Check whether the new location fix is newer or older 
     long timeDelta = location.getTime() - currentBestLocation.getTime(); 
     boolean isSignificantlyNewer = timeDelta > TWO_MINUTES; 
     boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES; 
     boolean isNewer = timeDelta > 0; 

     // If it's been more than two minutes since the current location, use the new location 
     // because the user has likely moved 
     if (isSignificantlyNewer) { 
      return true; 
      // If the new location is more than two minutes older, it must be worse 
     } else if (isSignificantlyOlder) { 
      return false; 
     } 

     // Check whether the new location fix is more or less accurate 
     int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy()); 
     boolean isLessAccurate = accuracyDelta > 0; 
     boolean isMoreAccurate = accuracyDelta < 0; 
     boolean isSignificantlyLessAccurate = accuracyDelta > 200; 

     // Check if the old and new location are from the same provider 
     boolean isFromSameProvider = isSameProvider(location.getProvider(), 
       currentBestLocation.getProvider()); 

     // Determine location quality using a combination of timeliness and accuracy 
     if (isMoreAccurate) { 
      return true; 
     } else if (isNewer && !isLessAccurate) { 
      return true; 
     } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) { 
      return true; 
     } 
     return false; 
    } 

    /** Checks whether two providers are the same */ 
    private boolean isSameProvider(String provider1, String provider2) { 
     if (provider1 == null) { 
      return provider2 == null; 
     } 
     return provider1.equals(provider2); 
    } 
} 
Смежные вопросы