0

I'm trying to acquire GPS coordinates on my android application.

Criteria criteria = new Criteria();
criteria.setAltitudeRequired(false);
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setBearingRequired(false);
criteria.setCostAllowed(false);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
LocationManager locationManager =
        (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

Intent i = new Intent(context, IntentListener.class);
i.setAction(Actions.ACTION_UPDATE_LOCATION);
PendingIntent pi = PendingIntent.getBroadcast(
        context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
String provider = locationManager.getBestProvider(criteria, true);
if (provider == null) return;
locationManager.requestLocationUpdates(provider, 90 * 1000, 30, pi);

and here's receiving code.

Intent service = new Intent(context, WorkerService.class);
service.setAction(Actions.ACTION_UPDATE_LOCATION);
Location location = (Location) intent.getExtras().get(
        LocationManager.KEY_LOCATION_CHANGED);

if (location == null) { // <-- Always true
    return;
}

service.putExtra("lat", location.getLatitude());
service.putExtra("lon", location.getLongitude());
context.startService(service);

As you can see, I'm unable to obtain Location instance by calling intent.getExtras()... etc. Returned value is always null. I'm testing on my emulator running android 4.1.2 and telnet client, using geo fix longitude latitude. Anyone knows what's wrong? Thanks.

P.S. Manifest contains all required permissions and GPS is enabled in the emulator.

P.P.S. This application is a corporate app, that runs as a service, without UI and should collect GPS coordinates.

Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
Davita
  • 8,928
  • 14
  • 67
  • 119
  • if you close and re-open your phone it clears cache about your location. Just open google maps or anoother location service and wait till phone finds your location to save another cache, then go on.. – Sercan Ozdemir Nov 08 '13 at 11:58

6 Answers6

5

You casually mentioned that you're testing on an emulator. The emulator doesn't receive mock locations by itself; you have to specifically send them through the DDMS interface.

Additionally, due to a bug in the emulator, the time offset in incoming locations is set to midnight, so your location criteria will likely not match it.

I strongly suggest you test with a physical device to confirm that the problem is still occurring.

Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
1

Use the new Location API.

You'd have to include Google Play services into your project. Add this in onCreate:

mIntentService = new Intent(this,LocationService.class);
mPendingIntent = PendingIntent.getService(this, 1, mIntentService, 0);

int resp =GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
    if(resp == ConnectionResult.SUCCESS){
        locationclient = new LocationClient(this,this,this);
        locationclient.connect();
    }

And you'd have to override these methods:

@Override
protected void onDestroy() {
    super.onDestroy();
    if(locationclient!=null)
        locationclient.disconnect();
}

@Override
public void onConnected(Bundle connectionHint) {
    Log.i(TAG, "onConnected");
    //to get last location
    Location loc =locationclient.getLastLocation();

    //to get updates via service
    locationrequest = LocationRequest.create();
    locationrequest.setInterval(100);
    locationclient.requestLocationUpdates(locationrequest, mPendingIntent);
}

@Override
public void onDisconnected() {
    Log.i(TAG, "onDisconnected");
}

@Override
public void onConnectionFailed(ConnectionResult result) {
    Log.i(TAG, "onConnectionFailed");
}

@Override
public void onLocationChanged(Location location) {
    if(location!=null){
        Log.i(TAG, "Location Request :" + location.getLatitude() + "," + location.getLongitude());
    }

}

Here's the service where I'm creating a notification for every new location, you can remove that and update location there.

public class LocationService extends IntentService {

private String TAG = this.getClass().getSimpleName();
public LocationService() {
    super("Fused Location");
}

public LocationService(String name) {
    super("Fused Location");
}

@Override
protected void onHandleIntent(Intent intent) {

        Location location = intent.getParcelableExtra(LocationClient.KEY_LOCATION_CHANGED);
        if(location !=null){
            Log.i(TAG, "onHandleIntent " + location.getLatitude() + "," + location.getLongitude());
            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 
            Builder noti = new NotificationCompat.Builder(this);
            noti.setContentTitle("Fused Location");
            noti.setContentText(location.getLatitude() + "," + location.getLongitude());
            noti.setSmallIcon(R.drawable.ic_launcher);

            notificationManager.notify(1234, noti.build());

        }

}

}

Rahul Sainani
  • 3,437
  • 1
  • 34
  • 48
  • I have to say that I resent needing to use the new location API. It relies on Google Play Services, which is a 68MB download when only 2 years ago phones were being sold with only 80-90MB available storage, so is a *huge* ask for people with old phones. But it seems that the `android.location` API *simply doesn't work* on many newer devices. :( – Jules Sep 27 '16 at 15:47
  • @Jules Check out this [smart location lib](https://github.com/mrmans0n/smart-location-lib), it might help you. – Rahul Sainani Sep 27 '16 at 20:57
0

Follow the tutorial to get the location in Android app

PgmFreek
  • 6,374
  • 3
  • 36
  • 47
  • I want my service to be notified when new fix is available. I did this in an old project of myne, but don't remember how :) – Davita Nov 11 '13 at 08:20
0

You should take your location by implementing LocationListener

@Override
public void onLocationChanged(Location loc) {
}
0

Take a look at this implementation, works really nice and i have tested it on several devices.

package ro.gebs.captoom.activities;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.bugsense.trace.BugSenseHandler;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

import ro.gebs.captoom.R;
import ro.gebs.captoom.database.ReceiptDataSource;
import ro.gebs.captoom.utils.Constants;
import ro.gebs.captoom.utils.Utils;

public class LocationActivity extends FragmentActivity {

    private GoogleMap map;
    private long rec_id;
    private String address;
    private Marker selectedLoc;
    private boolean isSessionClosed;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        BugSenseHandler.initAndStartSession(this, Constants.BugSenseKEY);
        setContentView(R.layout.preview_location);
        RelativeLayout cancel_btn = (RelativeLayout) findViewById(R.id.cancel_btn);
        LinearLayout save_location_btn = (LinearLayout) findViewById(R.id.delete_btn);

        save_location_btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                if (address != null) {
                    ReceiptDataSource r = new ReceiptDataSource();
                    r.updateReceiptLocation(rec_id, address);
                    Intent returnIntent = new Intent(getBaseContext(), EditReceiptActivity.class);
                    returnIntent.putExtra("result", address);
                    setResult(RESULT_OK, returnIntent);
                    finish();
                } else {
                    Utils.showToast(getApplicationContext(), getString(R.string.c_unknownLocation), Toast.LENGTH_SHORT);
                }
            }
        });

        cancel_btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                onBackPressed();
            }
        });

        if (map == null) {

            map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();

            if (isGoogleMapsInstalled()) {
                if (map != null) {
                    retrieveLocation();
                }
            } else {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage("Install Google Maps");
                builder.setCancelable(false);
                builder.setPositiveButton("Install", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.android.apps.maps"));
                        startActivity(intent);
                        finish();
                    }
                });
                AlertDialog dialog = builder.create();
                dialog.show();
            }
        }

    }

    @Override
    protected void onResume() {
        super.onResume();
        if (isSessionClosed) {
            BugSenseHandler.startSession(this);
            isSessionClosed = false;
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        BugSenseHandler.closeSession(this);
        isSessionClosed = true;
    }

    @Override
    public void onBackPressed() {
        map.clear();
        super.onBackPressed();
    }

    private void retrieveLocation() {
        Intent intent = getIntent();
        address = intent.getStringExtra("location");
        assert address != null;
        if (address.equalsIgnoreCase("")) {
            address = Utils.getCurrentLocation(LocationActivity.this);
        }
        rec_id = intent.getLongExtra("receipt_to_update_location", 0);
        final Geocoder geocoder = new Geocoder(this, Locale.US);
        double latitude = 0, longitude = 0;
        try {
            List<Address> loc = geocoder.getFromLocationName(address, 5);
            if (loc.size() > 0) {
                latitude = loc.get(0).getLatitude();
                longitude = loc.get(0).getLongitude();
            } else {
                Utils.showToast(LocationActivity.this, getString(R.string.UnableToFindLocation), Toast.LENGTH_SHORT);
            }


            selectedLoc = map.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title(address).draggable(true));
            map.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener() {
                @Override
                public void onMarkerDragStart(Marker marker) {

                }

                @Override
                public void onMarkerDrag(Marker marker) {

                }

                @Override
                public void onMarkerDragEnd(Marker marker) {
                    try {
                        List<Address> addresses = geocoder.getFromLocation(selectedLoc.getPosition().latitude, selectedLoc.getPosition().longitude, 1);
                        StringBuilder sb = new StringBuilder();
                        if (addresses.size() > 0) {
                            Address address = addresses.get(0);

                            if (address.getAddressLine(0) != null)
                                sb.append(address.getAddressLine(0)).append(", ");
                            if (address.getLocality() != null)
                                sb.append(address.getLocality()).append(", ");
                            if (address.getCountryName() != null)
                                sb.append(address.getCountryName());
                        }

                        address = sb.toString();
                    } catch (IOException e) {
                    }

                }
            });

            map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 12));

            // Zoom in, animating the camera.
            map.animateCamera(CameraUpdateFactory.zoomTo(12), 2000, null);

        } catch (IOException e) {
            Log.e("IOException", e.getMessage());
            Utils.showToast(LocationActivity.this, getString(R.string.c_unknownLocation), Toast.LENGTH_LONG);
        }

    }

    public boolean isGoogleMapsInstalled() {
        try {
            getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }
    }


}
Adrian Olar
  • 2,883
  • 4
  • 35
  • 63
0

I see you implement the intent.putExtra after you get the extra! You should do the put in the activity that receives the location data and when you want to receive the data from the intent.extra you should do this:

Bundle extras = getIntent().getExtras();
    if (extras != null) {
        latitude= (double)extras.getDouble("lat");
        longitude=(double)extras.getDouble("lon");
    }
Remi
  • 1,289
  • 1
  • 18
  • 52
  • And for getting the location you should follow this: http://stackoverflow.com/questions/1513485/how-do-i-get-the-current-gps-location-programmatically-in-android – Remi Nov 15 '13 at 15:54