Search code examples
androidservicegoogle-api-clientfusedlocationproviderapi

Location only updating TextView when app is out of focus


For some reason it only updates the textviews when the app hits onPause, like when I hit the home button, or multitasking button. Can someone help me figure out why that is?

MainActivity.java:

import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private String lat, lon;
    private TextView longTextView, latTextView;
    LocationService locationService = new LocationService(this);
    private Intent intentService;
    private PendingIntent pendingIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        latTextView = (TextView) findViewById(R.id.latitude_textview);
        longTextView = (TextView) findViewById(R.id.longitude_textview);  
    }

    @Override
    protected void onStart() {
        super.onStart();
        locationService.buildGoogleApiClient();
        locationService.apiConnect();

        if (latTextView != null && longTextView != null) {
            latTextView.setText( locationService.getLat());
            longTextView.setText( locationService.getLon());
            Toast.makeText(getApplicationContext(), " Actually got location", Toast.LENGTH_SHORT)
                    .show();
        } else {
            Toast.makeText(getApplicationContext(), "The shit was null fam", Toast.LENGTH_LONG)
                    .show();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        locationService.apiDisconnect();   
    }  
}

LocationService.java:

import android.Manifest;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
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 com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

import static com.google.android.gms.wearable.DataMap.TAG;

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

    // =============================================================  Variables

    Context context;
    Location mLastLocation;
    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;
    private String lat, lon;
    final static String[] LOCATION_PERMISSIONS = {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
    public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
    public static final long UPDATE_FASTEST_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
    public static boolean isEnded = false;
    public static Boolean requestingLocationUpdates;
    protected String lastUpdateTime;

    final int GOOGLEAPI_REQUEST_CODE = 24;
    private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;    

    // =============================================================  Constructor    

    public LocationService(Context context) {
        this.context = context;
    }

    // =============================================================  Getters / Setters    

    public String getLon() {
        return lon;
    }

    public void setLon(String lon) {
        this.lon = lon;
    }

    public String getLat() {
        return lat;
    }

    public void setLat(String lat) {
        this.lat = lat;
    }    

    // ============================================================= Methods
    synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(context)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

    public void apiConnect() {
        mGoogleApiClient.connect();
    }

    public void apiDisconnect() {
        mGoogleApiClient.disconnect();
    }

    void updateUI() {    
    }

    // ============================================================= Implemented Location Methods
    @Override
    public void onLocationChanged(Location location) {
        setLat(String.valueOf(location.getLatitude()));
        setLon(String.valueOf(location.getLongitude()));
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS); // Sets Location to update every second
        mLocationRequest.setFastestInterval(UPDATE_FASTEST_INTERVAL_IN_MILLISECONDS); // The fastest location can update is every half-second

        startLocationUpdates();

        // TODO come back to this to see whats up
       /* mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                mGoogleApiClient);*/
        if (mLastLocation != null) {
            setLat(String.valueOf(mLastLocation.getLatitude()));
            setLon(String.valueOf(mLastLocation.getLongitude()));    
        }
    }

    @Override
    public void onConnectionSuspended(int i) {    
    }

    protected void startLocationUpdates() {
        /*if (!requestingLocationUpdates) {
            requestingLocationUpdates = true;*/

            if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_COARSE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions((Activity) context, LOCATION_PERMISSIONS, GOOGLEAPI_REQUEST_CODE);

            } else {
                LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            }
            Log.i(TAG, " startLocationUpdates===");
            isEnded = true;
        //}
    }    

    // ============================================================= Implemented Service Methods

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // Within {@code onPause()}, we pause location updates, but leave the
        // connection to GoogleApiClient intact.  Here, we resume receiving
        // location updates if the user has requested them.
        Log.d("LOC", "Service init...");
        isEnded = false;
        requestingLocationUpdates = false;
        lastUpdateTime = "";
        buildGoogleApiClient();
        if (mGoogleApiClient.isConnected() && requestingLocationUpdates) {
            startLocationUpdates();
        }
        return Service.START_REDELIVER_INTENT;
    }
}

Solution

  • The reason why you are not getting the location updated in textview is because your code doesn't have a way for the service to communicate back to the activity.

    If you want to obtain location only when the activity is in foreground don't use Service and please look into this google's example for obtaining location and updating on a TextView using fused location provider.

    I am not sure why you are using a Service.Use Service only when you want to continuously fetch the location even when the app is running background. For this use any one of the method mentioned here to inform the activity that a new location has been obtained.LocalBroadcast would be your best bet. Anyway explore the best possible solution that suits your usecase in the previous link.