Related
so im running this sample app i got on github which deals with google maps and geo fences: https://github.com/androidfu/GeofenceExample
And when I run the code I get this error : Caused by: java.lang.SecurityException: com.androidfu.example.geofences from uid 10170 not allowed to perform MOCK_LOCATION
Here is the code for the class followed by the stack trace. Hope you guys can give me some insight. Also i have mock location in manifest. The error is coming from the onResume() method.
public class MapsActivity extends FragmentActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, View.OnClickListener, ResultCallback<Status> {
public static final String TAG = MapsActivity.class.getSimpleName();
private static final long LOCATION_ITERATION_PAUSE_TIME = 1000;
private static final int NUMBER_OF_LOCATION_ITERATIONS = 10;
private GoogleMap googleMap; // Might be null if Google Play services APK is not available.
private MyPlaces happyPlace;
private MyPlaces home;
private List<Geofence> myFences = new ArrayList<>();
private GoogleApiClient googleApiClient;
private PendingIntent geofencePendingIntent;
private UpdateLocationRunnable updateLocationRunnable;
private LocationManager locationManager;
private int marker = 0;
private Location lastLocation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
ImageButton happyPlaceBtn = (ImageButton) findViewById(R.id.ib_happy_place);
happyPlaceBtn.setOnClickListener(this);
ImageButton homeBtn = (ImageButton) findViewById(R.id.ib_home);
homeBtn.setOnClickListener(this);
ImageButton resetBtn = (ImageButton) findViewById(R.id.ib_reset);
resetBtn.setOnClickListener(this);
setUpMapIfNeeded();
}
/**
* Called when a view has been clicked.
*
* #param v The view that was clicked.
*/
#Override
public void onClick(View v) {
MyPlaces place;
switch (v.getId()) {
case R.id.ib_happy_place:
Toast.makeText(this, "You Clicked Happy Place", Toast.LENGTH_SHORT).show();
place = happyPlace;
moveToLocation(place);
break;
case R.id.ib_home:
Toast.makeText(this, "You Clicked Home", Toast.LENGTH_SHORT).show();
place = home;
moveToLocation(place);
break;
case R.id.ib_reset:
Toast.makeText(this, "Resetting Our Map", Toast.LENGTH_SHORT).show();
if (updateLocationRunnable != null) {
updateLocationRunnable.interrupt();
}
googleApiClient.disconnect();
googleMap.clear();
myFences.clear();
setUpMap();
break;
}
}
#Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Log.i(TAG, "Setup MOCK Location Providers");
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
Log.i(TAG, "GPS Provider");
locationManager.addTestProvider(LocationManager.GPS_PROVIDER, false, true, false, false, false, false, false, Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);
Log.i(TAG, "Network Provider");
locationManager.addTestProvider(LocationManager.NETWORK_PROVIDER, true, false, true, false, false, false, false, Criteria.POWER_MEDIUM, Criteria.ACCURACY_FINE);
locationManager.setTestProviderEnabled(LocationManager.NETWORK_PROVIDER, true);
}
#Override
protected void onPause() {
this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// Interrupt our runnable if we're going into the background or exiting
if (updateLocationRunnable != null) {
updateLocationRunnable.interrupt();
}
Log.i(TAG, "Cleanup Our Fields");
locationManager.removeTestProvider(LocationManager.GPS_PROVIDER);
locationManager.removeTestProvider(LocationManager.NETWORK_PROVIDER);
locationManager = null;
updateLocationRunnable = null;
super.onPause();
}
#Override
protected void onStop() {
googleApiClient.disconnect();
super.onStop();
}
/**
* Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly
* installed) and the map has not already been instantiated.. This will ensure that we only ever
* call {#link #setUpMap()} once when {#link #googleMap} is not null.
* <p/>
* If it isn't installed {#link SupportMapFragment} (and
* {#link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to
* install/update the Google Play services APK on their device.
* <p/>
* A user can return to this FragmentActivity after following the prompt and correctly
* installing/updating/enabling the Google Play services. Since the FragmentActivity may not
* have been completely destroyed during this process (it is likely that it would only be
* stopped or paused), {#link #onCreate(Bundle)} may not be called again so we should call this
* method in {#link #onResume()} to guarantee that it will be called.
*/
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (googleMap == null) {
// Try to obtain the map from the SupportMapFragment.
googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
// Check if we were successful in obtaining the map.
if (googleMap != null) {
setUpMap();
}
}
}
/**
* This is where we can add markers or lines, add listeners or move the camera.
* <p/>
* This should only be called once and when we are sure that {#link #googleMap} is not null.
*/
private void setUpMap() {
googleMap.setBuildingsEnabled(true);
// PRES 1
/*
1. Create a "Place" that will become a Geofence
2. Add a place marker on our Map
3. Add our place to our list of Geofences
4. Repeat for each place
*/
// Add a place with a Geofence
happyPlace = new MyPlaces("Pier # Folly Beach", "This is my Happy Place!", new LatLng(32.652411, -79.938063), 10000, 10, R.drawable.ic_palm_tree);
addPlaceMarker(happyPlace);
addFence(happyPlace);
// Add a place with a Geofence
// Work 39.3336585, -84.3146718
// Home 39.2697455, -84.269921
home = new MyPlaces("Home", "This is where I live.", new LatLng(39.3336585, -84.3146718), 10000, 10, R.drawable.ic_home);
addPlaceMarker(home);
addFence(home);
// Add a place w/o a Geofence
MyPlaces charleston = new MyPlaces("Charleston, SC", "This is where I want to live!", new LatLng(32.8210454, -79.9704779), 0, 10, R.drawable.ic_heart);
addPlaceMarker(charleston);
addFence(charleston);
/*
After all your places have been created and markers added you can monitor your fences.
*/
monitorFences(myFences);
googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
if (updateLocationRunnable != null && updateLocationRunnable.isAlive() && !updateLocationRunnable.isInterrupted()) {
updateLocationRunnable.interrupt();
}
updateLocationRunnable = new UpdateLocationRunnable(locationManager, latLng);
updateLocationRunnable.start();
MyPlaces touchedPlace = new MyPlaces(String.format("Marker %1$d", ++marker), "", latLng, 65, 12, 0);
addPlaceMarker(touchedPlace);
}
});
}
/**
* Add a map marker at the place specified.
*
* #param place the place to take action on
*/
private void addPlaceMarker(MyPlaces place) {
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(place.getCoordinates())
.title(place.getTitle());
if (!TextUtils.isEmpty(place.getSnippet())) {
markerOptions.snippet(place.getSnippet());
}
if (place.getIconResourceId() > 0) {
markerOptions.icon(BitmapDescriptorFactory.fromResource(place.getIconResourceId()));
}
googleMap.addMarker(markerOptions);
drawGeofenceAroundTarget(place);
}
/**
* If our place has a fence radius greater than 0 then draw a circle around it.
*
* #param place the place to take action on
*/
private void drawGeofenceAroundTarget(MyPlaces place) {
if (place.getFenceRadius() <= 0) {
// Nothing to draw
return;
}
CircleOptions circleOptions = new CircleOptions();
circleOptions.center(place.getCoordinates());
circleOptions.fillColor(Color.argb(0x55, 0x00, 0x00, 0xff));
circleOptions.strokeColor(Color.argb(0xaa, 0x00, 0x00, 0xff));
circleOptions.radius(place.getFenceRadius());
googleMap.addCircle(circleOptions);
}
/**
* Update our map's location to the place specified.
*
* #param place the place to take action on
*/
private void moveToLocation(final MyPlaces place) {
// Move the camera instantly to "place" with a zoom of 5.
if (place.getTitle().equals("Charleston, SC")) {
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(place.getCoordinates(), place.getDefaultZoomLevel()));
}
// Fly to our new location and then set the correct zoom level for the given place.
googleMap.animateCamera(CameraUpdateFactory.newLatLng(place.getCoordinates()), new GoogleMap.CancelableCallback() {
#Override
public void onFinish() {
googleMap.animateCamera(CameraUpdateFactory.zoomTo(place.getDefaultZoomLevel()), 2000, null);
}
#Override
public void onCancel() {
// Nothing to see here.
}
});
}
/**
* If our place has a fence radius > 0 then add it to our monitored fences.
*
* #param place the place to take action on
*/
private void addFence(MyPlaces place) {
if (place.getFenceRadius() <= 0) {
// Nothing to monitor
return;
}
Geofence geofence = new Geofence.Builder()
.setCircularRegion(place.getCoordinates().latitude, place.getCoordinates().longitude, place.getFenceRadius())
.setRequestId(place.getTitle()) // every fence must have an ID
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) // can also have DWELL
.setExpirationDuration(Geofence.NEVER_EXPIRE) // how long do we care about this geofence?
//.setLoiteringDelay(60000) // 1 min.
.build();
myFences.add(geofence);
}
/**
* Connect our GoogleApiClient so we can begin monitoring our fences.
*
* #param fences our list of Geofences to monitor
*/
private void monitorFences(List<Geofence> fences) {
if (fences.isEmpty()) {
throw new RuntimeException("No fences to monitor. Call addPlaceMarker() First.");
}
// PRES 2
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
googleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
/*
TODO
1. Display a spinner in the progress bar while we're waiting for location
2. When connected & not null update map position to location
3. If location null try again once every 10 seconds until we get an answer or quit after x minutes
4. ?
*/
Toast.makeText(this, "GoogleApiClient Connected", Toast.LENGTH_SHORT).show();
lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
String lastLocationMessage;
if (lastLocation == null) {
lastLocationMessage = "Last Location is NULL";
moveToLocation(home);
} else {
lastLocationMessage = String.format("Last Location (%1$s, %2$s)", lastLocation.getLatitude(), lastLocation.getLongitude());
moveToLocation(new MyPlaces("Last Location", "I am here.", new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude()), 0, 13, 0));
}
Toast.makeText(this, lastLocationMessage, Toast.LENGTH_SHORT).show();
// PRES 3
geofencePendingIntent = getRequestPendingIntent();
PendingResult<Status> result = LocationServices.GeofencingApi.addGeofences(googleApiClient, myFences, geofencePendingIntent);
result.setResultCallback(this);
}
#Override
public void onConnectionSuspended(int i) {
Toast.makeText(this, "GoogleApiClient Connection Suspended", Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(this, "GoogleApiClient Connection Failed", Toast.LENGTH_SHORT).show();
}
#Override
public void onResult(Status status) {
String toastMessage;
// PRES 4
if (status.isSuccess()) {
toastMessage = "Success: We Are Monitoring Our Fences";
} else {
toastMessage = "Error: We Are NOT Monitoring Our Fences";
}
Toast.makeText(this, toastMessage, Toast.LENGTH_SHORT).show();
}
/**
* Returns the current PendingIntent to the caller.
*
* #return The PendingIntent used to create the current set of geofences
*/
public PendingIntent getRequestPendingIntent() {
return createRequestPendingIntent();
}
/**
* Get a PendingIntent to send with the request to add Geofences. Location
* Services issues the Intent inside this PendingIntent whenever a geofence
* transition occurs for the current list of geofences.
*
* #return A PendingIntent for the IntentService that handles geofence
* transitions.
*/
private PendingIntent createRequestPendingIntent() {
if (geofencePendingIntent != null) {
return geofencePendingIntent;
} else {
Intent intent = new Intent(this, GeofenceTransitionReceiver.class);
intent.setAction("geofence_transition_action");
return PendingIntent.getBroadcast(this, R.id.geofence_transition_intent, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
}
// /////////////////////////////////////////////////////////////////////////////////////////
// // UpdateLocationRunnable //
// /////////////////////////////////////////////////////////////////////////////////////////
private Location createMockLocation(String locationProvider, double latitude, double longitude) {
Location location = new Location(locationProvider);
location.setLatitude(latitude);
location.setLongitude(longitude);
location.setAccuracy(1.0f);
location.setTime(System.currentTimeMillis());
/*
setElapsedRealtimeNanos() was added in API 17
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
try {
Method locationJellyBeanFixMethod = Location.class.getMethod("makeComplete");
if (locationJellyBeanFixMethod != null) {
locationJellyBeanFixMethod.invoke(location);
}
} catch (Exception e) {
// There's no action to take here. This is a fix for Jelly Bean and no reason to report a failure.
}
return location;
}
// /////////////////////////////////////////////////////////////////////////////////////////
// // CreateMockLocation //
// /////////////////////////////////////////////////////////////////////////////////////////
class UpdateLocationRunnable extends Thread {
private final LocationManager locMgr;
private final LatLng latlng;
Location mockGpsLocation;
Location mockNetworkLocation;
UpdateLocationRunnable(LocationManager locMgr, LatLng latlng) {
this.locMgr = locMgr;
this.latlng = latlng;
}
/**
* Starts executing the active part of the class' code. This method is
* called when a thread is started that has been created with a class which
* implements {#code Runnable}.
*/
#Override
public void run() {
try {
Log.i(TAG, String.format("Setting Mock Location to: %1$s, %2$s", latlng.latitude, latlng.longitude));
/*
Location can be finicky. Iterate over our desired location every second for
NUMBER_OF_LOCATION_ITERATIONS seconds to help it figure out where we want it to
be.
*/
for (int i = 0; !isInterrupted() && i <= NUMBER_OF_LOCATION_ITERATIONS; i++) {
mockGpsLocation = createMockLocation(LocationManager.GPS_PROVIDER, latlng.latitude, latlng.longitude);
locMgr.setTestProviderLocation(LocationManager.GPS_PROVIDER, mockGpsLocation);
mockNetworkLocation = createMockLocation(LocationManager.NETWORK_PROVIDER, latlng.latitude, latlng.longitude);
locMgr.setTestProviderLocation(LocationManager.NETWORK_PROVIDER, mockNetworkLocation);
Thread.sleep(LOCATION_ITERATION_PAUSE_TIME);
}
} catch (InterruptedException e) {
Log.i(TAG, "Interrupted.");
// Do nothing. We expect this to happen when location is successfully updated.
} finally {
Log.i(TAG, "Done moving location.");
}
}
}
}
stack trace:
09-26 11:08:07.870 10417-10417/com.androidfu.example.geofences E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.androidfu.example.geofences, PID: 10417
java.lang.RuntimeException: Unable to resume activity {com.androidfu.example.geofences/com.androidfu.example.geofences.GeofenceExampleLauncher}: java.lang.SecurityException: com.androidfu.example.geofences from uid 10170 not allowed to perform MOCK_LOCATION
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3121)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3152)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2499)
at android.app.ActivityThread.access$900(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
Caused by: java.lang.SecurityException: com.androidfu.example.geofences from uid 10170 not allowed to perform MOCK_LOCATION
at android.os.Parcel.readException(Parcel.java:1599)
at android.os.Parcel.readException(Parcel.java:1552)
at android.location.ILocationManager$Stub$Proxy.addTestProvider(ILocationManager.java:1096)
at android.location.LocationManager.addTestProvider(LocationManager.java:1298)
at com.androidfu.example.geofences.MapsActivity.onResume(MapsActivity.java:120)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1258)
at android.app.Activity.performResume(Activity.java:6347)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3110)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3152)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2499)
at android.app.ActivityThread.access$900(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
I guess you have not allowed mock locations from phones developer options.
It should be under Debug section.
Here is my manifest of how i declared my MapsActivity
<activity android:name=".MapsActivity"/>
It still shows an error Validates resource references inside android xml files Android And the activity crashes. Here is my MapsActivity
package com.todaysfuture.autometer;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.IntentSender;
import android.graphics.Color;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
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.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class MapsActivity extends Fragment implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
public static final String TAG = MapsActivity.class.getSimpleName();
/*
* Define a request code to send to Google Play services
* This code is returned in Activity.onActivityResult
*/
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private GoogleMap mMap; // Might be null if Google Play services APK is not available.
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private TextView tvStartRide;
private TextView tvStopRide;
private Location startingLocation;
private Location endingLocation;
private String origin = null ;
private String destination = null ;
private Location location1 ;
private Location location2 ;
private LatLng loc1 ;
private LatLng loc2 ;
private float distance = 0 ;
private float fare = 0 ;
private double startLatitude ;
private double startLongitude ;
private double endLatitude ;
private double endLongitude ;
private float[] results ;
public MapsActivity(){
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.activity_maps, container, false);
setUpMapIfNeeded();
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
tvStartRide = (TextView) view.findViewById(R.id.startRideText);
tvStopRide = (TextView) view.findViewById(R.id.stopRideText);
tvStopRide.setVisibility(View.INVISIBLE);
tvStartRide.setOnClickListener(startRideOnClickListener);
tvStopRide.setOnClickListener(stopRideOnClickListener);
return view;
}
View.OnClickListener startRideOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
tvStartRide.setVisibility(View.INVISIBLE);
tvStopRide.setVisibility(View.VISIBLE);
startingLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
location1 = startingLocation ;
startLatitude = location1.getLatitude();
startLongitude = location1.getLongitude();
loc1 = new LatLng(startLatitude, startLongitude) ;
try {
origin = retrieveAddress(startingLocation) ;
Toast.makeText(getContext(), "Ride starting from: " + origin, Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
}
};
View.OnClickListener stopRideOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
endingLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
try {
destination = retrieveAddress(endingLocation) ;
Toast.makeText(getContext(), "Ride ended at: " + destination, Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
fare = calculateFare(distance) ;
}
};
public String retrieveAddress(Location location) throws IOException {
Geocoder geocoder;
List<Address> addresses;
geocoder = new Geocoder(getActivity(), Locale.getDefault());
double latitude = location.getLatitude();
double longitude = location.getLongitude();
addresses = geocoder.getFromLocation(latitude, longitude, 1); // Here 1 represent max location result to returned, by documents it recommended 1 to 5
String address = addresses.get(0).getAddressLine(0); // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
/*String city = addresses.get(0).getLocality();
String state = addresses.get(0).getAdminArea();
String country = addresses.get(0).getCountryName();
String postalCode = addresses.get(0).getPostalCode(); */
String knownName = addresses.get(0).getFeatureName(); // Only if available else return NULL
if (address != null)
return address;
else if (knownName != null)
return knownName;
else
return null;
}
public void drawPolyline(LatLng location1, LatLng location2){
Polyline line = mMap.addPolyline(new PolylineOptions()
.add(location1, location2)
.width(5)
.color(Color.RED));
}
/*#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
setUpMapIfNeeded();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
} */
#Override
public void onResume() {
super.onResume();
setUpMapIfNeeded();
mGoogleApiClient.connect();
}
#Override
public void onPause() {
super.onPause();
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
/**
* Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly
* installed) and the map has not already been instantiated.. This will ensure that we only ever
* call {#link #setUpMap()} once when {#link #mMap} is not null.
* <p/>
* If it isn't installed {#link SupportMapFragment} (and
* {#link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to
* install/update the Google Play services APK on their device.
* <p/>
* A user can return to this FragmentActivity after following the prompt and correctly
* installing/updating/enabling the Google Play services. Since the FragmentActivity may not
* have been completely destroyed during this process (it is likely that it would only be
* stopped or paused), {#link #onCreate(Bundle)} may not be called again so we should call this
* method in {#link #onResume()} to guarantee that it will be called.
*/
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
//mMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
mMap = ((SupportMapFragment) getChildFragmentManager()
.findFragmentById(R.id.map)).getMap();
// Check if we were successful in obtaining the map.
if (mMap != null) {
setUpMap();
}
}
}
/**
* This is where we can add markers or lines, add listeners or move the camera. In this case, we
* just add a marker near Africa.
* <p/>
* This should only be called once and when we are sure that {#link #mMap} is not null.
*/
private void setUpMap() {
mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
}
private void handleNewLocation(Location location) {
Log.d(TAG, location.toString());
double currentLatitude = location.getLatitude();
double currentLongitude = location.getLongitude();
LatLng latLng = new LatLng(currentLatitude, currentLongitude);
//mMap.addMarker(new MarkerOptions().position(new LatLng(currentLatitude, currentLongitude)).title("Current Location"));
MarkerOptions options = new MarkerOptions()
.position(latLng)
.title("I am here!");
mMap.addMarker(options);
//mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14.0f));
if (location2 == null) {
location2 = location ;
loc2 = latLng ;
endLatitude = loc2.latitude ;
endLongitude = loc2.longitude ;
//drawPolyline(loc1, loc2);
//android.location.Location.distanceBetween(startLatitude, startLongitude, endLatitude, endLongitude, results);
//if ( results != null )
//distance += results[0] ;
Toast.makeText(getActivity(), "Distance: " + distance, Toast.LENGTH_SHORT).show();
}
else {
loc1 = loc2 ;
loc2 = latLng ;
startLatitude = loc1.latitude ;
startLongitude = loc1.longitude ;
endLatitude = loc2.latitude ;
endLongitude = loc2.longitude ;
drawPolyline(loc1, loc2);
android.location.Location.distanceBetween(startLatitude, startLongitude, endLatitude, endLongitude, results);
distance += results[0] ;
Toast.makeText(getActivity(), "Distance: " + distance, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onConnected(Bundle bundle) {
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
} else {
handleNewLocation(location);
}
}
#Override
public void onConnectionSuspended(int i) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Oops!");
builder.setMessage("An error occurred.");
AlertDialog dialog = builder.create();
dialog.show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
/*
* Google Play services can resolve some errors it detects.
* If the error has a resolution, try sending an Intent to
* start a Google Play services activity that can resolve
* error.
*/
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(getActivity(), CONNECTION_FAILURE_RESOLUTION_REQUEST);
/*
* Thrown if Google Play services canceled the original
* PendingIntent
*/
} catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
} else {
/*
* If no resolution is available, display a dialog to the
* user with the error.
*/
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Oops!");
builder.setMessage("An error occurred.");
AlertDialog dialog = builder.create();
dialog.show();
Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
}
}
#Override
public void onLocationChanged(Location location) {
handleNewLocation(location);
}
public float calculateFare(float distance) {
float distanceInkm = distance/1000 ;
float firstTwokm = 2 ;
float restOfDistance = distanceInkm - firstTwokm ;
if (distanceInkm >= firstTwokm)
{
fare = 25 ;
while (restOfDistance>=0) {
fare += 0.8 ;
restOfDistance -= 0.1 ;
}
return fare ;
}
else {
while (distanceInkm>=0) {
fare += 1.25 ;
distanceInkm -= 0.1 ;
}
return fare ;
}
}
}
What could be the solution? It is extending a fragment hence it should still be an activity. When i hover the cursor on the declare of the activity in the manifest it says 'com.todaysfuture.autometer.MapsActivity' is not assignable to 'android.app.Activity'
I have used latest api. I have implement FusedLocationApi and i am getting current location if gps is on. I have connected with google play services still i am not getting current location.
I use this code:
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.provider.Settings;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class GPSTracker implements ConnectionCallbacks,
OnConnectionFailedListener, com.google.android.gms.location.LocationListener {
private OnLocationChangedListener mLocationChangedListener;
// The minimum distance to change Updates in meters
private static final float MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 10 meters
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
MIN_TIME_BW_UPDATES / 2;
private final Context mContext;
// Declaring a Location Manager
protected LocationRequest mLocationRequest;
// flag for GPS status
boolean isGPSEnabled = false;
// flag for network status
boolean isNetworkEnabled = false;
// flag for GPS status
boolean canGetLocation = false;
// Current best location estimate
private Location mBestReading;
private GoogleApiClient mGoogleApiClient;
Location mCurrentLocation; // location
double latitude; // latitude
double longitude; // longitude
public void setLocationChangedListener(OnLocationChangedListener listener) {
mLocationChangedListener = listener;
}
public GPSTracker(Context context) {
this.mContext = context;
buildGoogleApiClient();
}
/**
* Builds a GoogleApiClient. Uses the addApi() method to request the LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(mContext)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
if (mCurrentLocation == null) {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mCurrentLocation != null)
canGetLocation = true;
}
mGoogleApiClient.connect();
}
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(MIN_TIME_BW_UPDATES);
// 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.setSmallestDisplacement(MIN_DISTANCE_CHANGE_FOR_UPDATES);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
/**
* Function to get latitude
*/
public double getLatitude() {
if (mCurrentLocation != null) {
latitude = mCurrentLocation.getLatitude();
}
// return latitude
return latitude;
}
/**
* Function to get longitude
*/
public double getLongitude() {
if (mCurrentLocation != null) {
longitude = mCurrentLocation.getLongitude();
}
// return longitude
return longitude;
}
/**
* Function to check GPS/wifi enabled
*
* #return boolean
*/
public boolean canGetLocation() {
return this.canGetLocation;
}
/**
* Function to show settings alert dialog On pressing Settings button will
* lauch Settings Options
*/
public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// Setting Dialog Title
alertDialog.setTitle("GPS is settings");
// Setting Dialog Message
alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing Settings button
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
/**
* Removes location updates from the FusedLocationApi.
*/
protected void stopLocationUpdates() {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onLocationChanged(Location mCurrentLocation) {
canGetLocation = true;
this.mCurrentLocation = mCurrentLocation;
mLocationChangedListener.onReceiveLocation(mCurrentLocation, 1);
stopLocationUpdates();
}
#Override
public void onConnected(Bundle bundle) {
if (mCurrentLocation == null) {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mCurrentLocation != null) {
canGetLocation = true;
mLocationChangedListener.onReceiveLocation(mCurrentLocation, 1);
}
}
if (mCurrentLocation == null && mGoogleApiClient.isConnected()) {
startLocationUpdates();
}
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
public interface OnLocationChangedListener {
void onReceiveLocation(Location receiveLocation, int resultCode);
}
}
Here is the code. While GPS is off onLocationChanged(Location location) callback method not called by Api.
Without the GPS is not possible to update the current lat long. The below code is working when the GPS is on but in some case the GPS is able to track the current lat long in the case the AGPS is fetching the lat long from the wifi connection or telecom network and it will only work when the device have the AGPS hardware.
import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import java.text.DateFormat;
import java.util.Date;
/**
* Getting Location Updates.
*
* Demonstrates how to use the Fused Location Provider API to get updates about a device's
* location. The Fused Location Provider is part of the Google Play services location APIs.
*
* For a simpler example that shows the use of Google Play services to fetch the last known location
* of a device, see
* https://github.com/googlesamples/android-play-location/tree/master/BasicLocation.
*
* This sample uses Google Play services, but it does not require authentication. For a sample that
* uses Google Play services for authentication, see
* https://github.com/googlesamples/android-google-accounts/tree/master/QuickStart.
*/
public class MainActivity extends ActionBarActivity implements
ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
protected static final String TAG = "location-updates-sample";
/**
* The desired interval for location updates. Inexact. Updates may be more or less frequent.
*/
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
/**
* 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;
// Keys for storing activity state in the Bundle.
protected final static String REQUESTING_LOCATION_UPDATES_KEY = "requesting-location-updates-key";
protected final static String LOCATION_KEY = "location-key";
protected final static String LAST_UPDATED_TIME_STRING_KEY = "last-updated-time-string-key";
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Stores parameters for requests to the FusedLocationProviderApi.
*/
protected LocationRequest mLocationRequest;
/**
* Represents a geographical location.
*/
protected Location mCurrentLocation;
// UI Widgets.
protected Button mStartUpdatesButton;
protected Button mStopUpdatesButton;
protected TextView mLastUpdateTimeTextView;
protected TextView mLatitudeTextView;
protected TextView mLongitudeTextView;
/**
* Tracks the status of the location updates request. Value changes when the user presses the
* Start Updates and Stop Updates buttons.
*/
protected Boolean mRequestingLocationUpdates;
/**
* Time when the location was updated represented as a String.
*/
protected String mLastUpdateTime;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Locate the UI widgets.
mStartUpdatesButton = (Button) findViewById(R.id.start_updates_button);
mStopUpdatesButton = (Button) findViewById(R.id.stop_updates_button);
mLatitudeTextView = (TextView) findViewById(R.id.latitude_text);
mLongitudeTextView = (TextView) findViewById(R.id.longitude_text);
mLastUpdateTimeTextView = (TextView) findViewById(R.id.last_update_time_text);
mRequestingLocationUpdates = false;
mLastUpdateTime = "";
// Update values using data stored in the Bundle.
updateValuesFromBundle(savedInstanceState);
// Kick off the process of building a GoogleApiClient and requesting the LocationServices
// API.
buildGoogleApiClient();
//turnGPSOn();
}
/**
* Updates fields based on data stored in the bundle.
*
* #param savedInstanceState The activity state saved in the Bundle.
*/
private void updateValuesFromBundle(Bundle savedInstanceState) {
Log.i(TAG, "Updating values from bundle");
if (savedInstanceState != null) {
// Update the value of mRequestingLocationUpdates from the Bundle, and make sure that
// the Start Updates and Stop Updates buttons are correctly enabled or disabled.
if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
mRequestingLocationUpdates = savedInstanceState.getBoolean(
REQUESTING_LOCATION_UPDATES_KEY);
setButtonsEnabledState();
}
// Update the value of mCurrentLocation from the Bundle and update the UI to show the
// correct latitude and longitude.
if (savedInstanceState.keySet().contains(LOCATION_KEY)) {
// Since LOCATION_KEY was found in the Bundle, we can be sure that mCurrentLocation
// is not null.
mCurrentLocation = savedInstanceState.getParcelable(LOCATION_KEY);
}
// Update the value of mLastUpdateTime from the Bundle and update the UI.
if (savedInstanceState.keySet().contains(LAST_UPDATED_TIME_STRING_KEY)) {
mLastUpdateTime = savedInstanceState.getString(LAST_UPDATED_TIME_STRING_KEY);
}
updateUI();
}
}
/**
* Builds a GoogleApiClient. Uses the {#code #addApi} method to request the
* LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
/**
* Sets up the location request. Android has two location request settings:
* {#code ACCESS_COARSE_LOCATION} and {#code ACCESS_FINE_LOCATION}. These settings control
* the accuracy of the current location. This sample uses ACCESS_FINE_LOCATION, as defined in
* the AndroidManifest.xml.
* <p/>
* When the ACCESS_FINE_LOCATION setting is specified, combined with a fast update
* interval (5 seconds), the Fused Location Provider API returns location updates that are
* accurate to within a few feet.
* <p/>
* These settings are appropriate for mapping applications that show real-time location
* updates.
*/
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);
}
/**
* Handles the Start Updates button and requests start of location updates. Does nothing if
* updates have already been requested.
*/
public void startUpdatesButtonHandler(View view) {
if (!mRequestingLocationUpdates) {
mRequestingLocationUpdates = true;
setButtonsEnabledState();
startLocationUpdates();
}
}
/**
* Handles the Stop Updates button, and requests removal of location updates. Does nothing if
* updates were not previously requested.
*/
public void stopUpdatesButtonHandler(View view) {
if (mRequestingLocationUpdates) {
mRequestingLocationUpdates = false;
setButtonsEnabledState();
stopLocationUpdates();
}
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
/**
* Ensures that only one button is enabled at any time. The Start Updates button is enabled
* if the user is not requesting location updates. The Stop Updates button is enabled if the
* user is requesting location updates.
*/
private void setButtonsEnabledState() {
if (mRequestingLocationUpdates) {
mStartUpdatesButton.setEnabled(false);
mStopUpdatesButton.setEnabled(true);
} else {
mStartUpdatesButton.setEnabled(true);
mStopUpdatesButton.setEnabled(false);
}
}
/**
* Updates the latitude, the longitude, and the last location time in the UI.
*/
private void updateUI() {
if (mCurrentLocation != null) {
mLatitudeTextView.setText(String.valueOf(mCurrentLocation.getLatitude()));
mLongitudeTextView.setText(String.valueOf(mCurrentLocation.getLongitude()));
mLastUpdateTimeTextView.setText(mLastUpdateTime);
}
}
/**
* Removes location updates from the FusedLocationApi.
*/
protected void stopLocationUpdates() {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
// The final argument to {#code requestLocationUpdates()} is a LocationListener
// (http://developer.android.com/reference/com/google/android/gms/location/LocationListener.html).
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
public void onResume() {
super.onResume();
// 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.
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
protected void onPause() {
super.onPause();
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
}
}
#Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "Connected to GoogleApiClient");
// If the initial location was never previously requested, we use
// FusedLocationApi.getLastLocation() to get it. If it was previously requested, we store
// its value in the Bundle and check for it in onCreate(). We
// do not request it again unless the user specifically requests location updates by pressing
// the Start Updates button.
//
// Because we cache the value of the initial location in the Bundle, it means that if the
// user launches the activity,
// moves to a new location, and then changes the device orientation, the original location
// is displayed as the activity is re-created.
if (mCurrentLocation == null) {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();
}
// If the user presses the Start Updates button before GoogleApiClient connects, we set
// mRequestingLocationUpdates to true (see startUpdatesButtonHandler()). Here, we check
// the value of mRequestingLocationUpdates and if it is true, we start location updates.
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
}
/**
* Callback that fires when the location changes.
*/
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();
Toast.makeText(this, getResources().getString(R.string.location_updated_message),
Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionSuspended(int cause) {
// The connection to Google Play services was lost for some reason. We call connect() to
// attempt to re-establish the connection.
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
}
/**
* Stores activity data in the Bundle.
*/
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(REQUESTING_LOCATION_UPDATES_KEY, mRequestingLocationUpdates);
savedInstanceState.putParcelable(LOCATION_KEY, mCurrentLocation);
savedInstanceState.putString(LAST_UPDATED_TIME_STRING_KEY, mLastUpdateTime);
super.onSaveInstanceState(savedInstanceState);
}
}
I am creating an app in android -studio , and I have a problem .
The app contains the Google Maps which shows us our location , but what really would make was that the push of a button , our location was sent by sms to a number of mobile phone , it will be possible ?
I created a demo app and it can:
Show your current location on the map as a marker.
Have a button. When you click it, it will create a SMS massage that you can send
your location via SMS.
Sample code:
public class MapsActivity extends FragmentActivity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener,
ResultCallback<LocationSettingsResult>,
View.OnClickListener {
public static final String TAG = MapsActivity.class.getSimpleName();
/*
* Define a request code to send to Google Play services
* This code is returned in Activity.onActivityResult
*/
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
protected static final int REQUEST_CHECK_SETTINGS = 0x1;
private GoogleMap mMap; // Might be null if Google Play services APK is not available.
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private LocationSettingsRequest mLocationSettingsRequest;
private Button btn_send_location;
private double mCurrentLatitude;
private double mCurrentLongitude;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
setUpMapIfNeeded();
btn_send_location = (Button) findViewById(R.id.send_my_location_btn);
btn_send_location.setOnClickListener(this);
long interval = 10 * 1000; // 10 seconds, in milliseconds
long fastestInterval = 1 * 1000; // 1 second, in milliseconds
float minDisplacement = 0;
// // Check if has GPS
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
buildAlertMessageNoGps();
}
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
// Create the LocationRequest object
// mLocationRequest = LocationRequest.create()
// .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
// .setInterval(interval)
// .setFastestInterval(fastestInterval)
// .setSmallestDisplacement(minDisplacement);
// Check if has GPS by using Google play service
// buildLocationSettingsRequest();
// checkLocationSettings();
}
#Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
mGoogleApiClient.connect();
}
#Override
protected void onPause() {
super.onPause();
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
/**
* Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly
* installed) and the map has not already been instantiated.. This will ensure that we only ever
* call {#link #setUpMap()} once when {#link #mMap} is not null.
* <p/>
* If it isn't installed {#link SupportMapFragment} (and
* {#link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to
* install/update the Google Play services APK on their device.
* <p/>
* A user can return to this FragmentActivity after following the prompt and correctly
* installing/updating/enabling the Google Play services. Since the FragmentActivity may not
* have been completely destroyed during this process (it is likely that it would only be
* stopped or paused), {#link #onCreate(Bundle)} may not be called again so we should call this
* method in {#link #onResume()} to guarantee that it will be called.
*/
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
}
}
private void handleNewLocation(Location location) {
Log.d(TAG, location.toString());
mCurrentLatitude = location.getLatitude();
mCurrentLongitude = location.getLongitude();
LatLng latLng = new LatLng(mCurrentLatitude, mCurrentLongitude);
//mMap.addMarker(new MarkerOptions().position(new LatLng(currentLatitude, currentLongitude)).title("Current Location"));
MarkerOptions options = new MarkerOptions()
.position(latLng)
.title("I am here!");
mMap.addMarker(options);
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));
}
#Override
public void onConnected(Bundle bundle) {
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
} else {
handleNewLocation(location);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
/*
* Google Play services can resolve some errors it detects.
* If the error has a resolution, try sending an Intent to
* start a Google Play services activity that can resolve
* error.
*/
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
/*
* Thrown if Google Play services canceled the original
* PendingIntent
*/
} catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
} else {
/*
* If no resolution is available, display a dialog to the
* user with the error.
*/
Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
}
}
#Override
public void onLocationChanged(Location location) {
handleNewLocation(location);
}
private void buildAlertMessageNoGps() {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Your GPS seems to be disabled, do you want to enable it?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(#SuppressWarnings("unused") final DialogInterface dialog, #SuppressWarnings("unused") final int id) {
startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, #SuppressWarnings("unused") final int id) {
dialog.cancel();
}
});
final AlertDialog alert = builder.create();
alert.show();
}
/**
* Uses a {#link com.google.android.gms.location.LocationSettingsRequest.Builder} to build
* a {#link com.google.android.gms.location.LocationSettingsRequest} that is used for checking
* if a device has the needed location settings.
*/
protected void buildLocationSettingsRequest() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build();
}
protected void checkLocationSettings() {
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(
mGoogleApiClient,
mLocationSettingsRequest
);
result.setResultCallback(this);
}
#Override
public void onResult(LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// NO need to show the dialog;
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. Show the user a dialog
try {
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
status.startResolutionForResult(this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
//unable to execute request
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are inadequate, and cannot be fixed here. Dialog not created
break;
}
}
#Override
public void onClick(View v) {
Intent sendIntent = new Intent(Intent.ACTION_VIEW);
sendIntent.setData(Uri.parse("sms:"));
sendIntent.putExtra("sms_body", "My location at \nLatitude: " + mCurrentLatitude + " \nLongitude: " + mCurrentLongitude);
startActivity(sendIntent);
}
}
And the xml file activity_maps.xml is:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="#+id/send_my_location_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send My location via SMS"/>
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MapsActivity"/>
</LinearLayout>
If you want to get the whole project, please refer to here.
I have an app in which I am continuously tracking user's location using Google Plays new service API for Maps. I am updating the location every single second and I am also checking user activity like STILL, TILTING, IN VEHICLE, etc to get the better location tracking. I am able to draw a path using my code but it's not accurate and differs very much from the road where the user actually drives/walk. It always draws the line someway far from the actual user's path.
My Service:-
public class MyService extends Service implements LocationListener {
private final Context mContext;
private static MyService mInstance = null;
private final static String TAG = "RidingTimerService";
boolean isGPSEnabled = false;
private long mStartTime = 0L;
private long timeInMilliseconds = 0L;
private long timeSwapBuff = 0L;
private long updatedTime = 0L;
private Handler mHandler = null;
private int mHours = 0;
// Declaring a Location Manager
private LocationManager mLocationManager = null;
private Location mCurrentLocation = null; // location
private double[][] positions;
private long[] times;
private final Integer data_points = 2; // how many data points to calculate
private double mTravelledDistance = 0.0f;
private SharedPreferences mPreferences = null;
private ArrayList<LatLng> mDirectionsPoints = new ArrayList<LatLng>();
public boolean mIsPhoneMoving = false;
public int mActivityType = -1;
int counter = 0;
private IntentFilter mBroadcastFilter;
private DetectionRequester mDetectionRequester;
private DetectionRemover mDetectionRemover;
public MyService() {
mContext = this;
}
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
// two arrays for position and time.
positions = new double[data_points][2];
times = new long[data_points];
mStartTime = SystemClock.uptimeMillis();
mHandler = new Handler();
mHandler.postDelayed(countDownTimerThread, 0);
mPreferences = getSharedPreferences(MyPreferences.PREFERENCES,
Context.MODE_PRIVATE);
// Create a new Intent filter for the broadcast receiver
mBroadcastFilter = new IntentFilter(
MyConstants.ACTION_REFRESH_STATUS_LIST);
mBroadcastFilter.addCategory(MyConstants.CATEGORY_LOCATION_SERVICES);
// Get detection requester and remover objects
mDetectionRequester = new DetectionRequester(this);
mDetectionRemover = new DetectionRemover(this);
mDirectionsPoints.clear();
}
/**
* Pause the timer
*/
public void pauseRide() {
timeSwapBuff += timeInMilliseconds;
mHandler.removeCallbacks(countDownTimerThread);
mLocationManager.removeUpdates(this);
}
/**
* Restart the timer
*/
public void reStartRide() {
mStartTime = SystemClock.uptimeMillis();
mHandler.postDelayed(countDownTimerThread, 0);
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
0, 0, this);
}
#Override
public void onDestroy() {
mHandler.removeCallbacks(countDownTimerThread);
mLocationManager.removeUpdates(this);
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
getLocation();
return super.onStartCommand(intent, flags, startId);
}
/**
* Timer thread
*/
private final Runnable countDownTimerThread = new Runnable() {
public void run() {
mHours = 0;
timeInMilliseconds = SystemClock.uptimeMillis() - mStartTime;
updatedTime = timeSwapBuff + timeInMilliseconds;
int secs = (int) (updatedTime / 1000);
final int mins = secs / 60;
mHours = mins / 60;
secs = secs % 60;
final Message msg = new Message();
final Bundle bundle = new Bundle();
bundle.putInt(MyPreferences.BROADCAST_CODES, 300);
bundle.putString(
"time",
String.format("%02d", mHours) + ":"
+ String.format("%02d", mins) + ":"
+ String.format("%02d", secs));
msg.setData(bundle);
final Intent intent = new Intent(MyConstants.BROADCAST_INTENT);
intent.putExtras(bundle);
sendBroadcast(intent);
mHandler.postDelayed(this, 1000);
}
};
#Override
public IBinder onBind(final Intent intent) {
return null;
}
#Override
public void onLocationChanged(final Location location) {
if (location != null) {
LocationUtils.sLatitude = location.getLatitude();
LocationUtils.sLongitude = location.getLongitude();
mDirectionsPoints.add(new LatLng(LocationUtils.sLatitude,
LocationUtils.sLongitude));
riderLocation(location);
} else {
Log.i(TAG, "Location is not available.");
}
}
/**
* Calculate speed, distance and average speed. Send Broadcast which
* received by activities
*
* #param location
*/
private void riderLocation(final Location location) {
DecimalFormat formatter = new DecimalFormat("#0.00");
double distance = 0.0;
Double speed = 0.0;
long t1 = 0l;
final float[] results = new float[3];
positions[counter][0] = location.getLatitude();
positions[counter][1] = location.getLongitude();
times[counter] = location.getTime();
final Bundle bundle = new Bundle();
bundle.putInt(MyPreferences.BROADCAST_CODES, 200);
distance = calculateDistance(positions[counter][0],
positions[counter][1], positions[(counter + (data_points - 1))
% data_points][0],
positions[(counter + (data_points - 1)) % data_points][1]);
Location.distanceBetween(positions[counter][0], positions[counter][1],
positions[(counter + (data_points - 1)) % data_points][0],
positions[(counter + (data_points - 1)) % data_points][1],
results);
mTravelledDistance += results[0] / 1000;
LocationUtils.sDistance = formatter
.format((mTravelledDistance * 100.0) / 100.0);
final double averageSpeed = mTravelledDistance / mHours;
LocationUtils.sAverageSpeed = formatter
.format((averageSpeed * 100.0) / 100.0);
if (location.hasSpeed()) {
speed = location.getSpeed() * 3.6;
LocationUtils.sSpeed = speed.intValue();
} else {
try {
t1 = times[counter]
- times[(counter + (data_points - 1)) % data_points];
} catch (final NullPointerException e) {
// all good, just not enough data yet.
}
speed = (distance / t1) * 3.6;
LocationUtils.sSpeed = speed.intValue();
counter = (counter + 1) % data_points;
}
LocationUtils.sLatitude = location.getLatitude();
LocationUtils.sLongitude = location.getLongitude();
final Intent intent = new Intent(MyConstants.BROADCAST_INTENT);
intent.putExtras(bundle);
sendBroadcast(intent);
}
public void onProviderDisabled(final String arg0) {
Toast.makeText(getApplicationContext(), "Gps Disabled",
Toast.LENGTH_LONG).show();
}
public void onProviderEnabled(final String arg0) {
Toast.makeText(getApplicationContext(), "Gps Enabled",
Toast.LENGTH_SHORT).show();
}
/**
* #return location
*/
public Location getLocation() {
try {
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = mLocationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!isGPSEnabled) {
// no network provider is enabled
showSettingsAlert();
} else {
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0, this);
Log.d(TAG, "GPS Enabled");
if (mCurrentLocation == null) {
if (mLocationManager != null) {
mCurrentLocation = mLocationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (mCurrentLocation != null) {
LocationUtils.sLatitude = mCurrentLocation
.getLatitude();
LocationUtils.sLongitude = mCurrentLocation
.getLongitude();
}
}
} else {
LocationUtils.sLatitude = mCurrentLocation
.getLatitude();
LocationUtils.sLongitude = mCurrentLocation
.getLongitude();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return mCurrentLocation;
}
/**
* #fn public static RidingTimerService getInstance()
* #brief returns instance of the service.
* #return RidingTimerService instance
*/
public static MyService getInstance() {
return mInstance;
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
/**
* Reset all the values stored in Preferences
*/
public void resetAllText() {
mPreferences.edit().putString(MyPreferences.LATITUDE, "0.0").commit();
mPreferences.edit().putString(MyPreferences.LONGITUDE, "0.0")
.commit();
mPreferences.edit().putString(MyPreferences.SPEED, "0.0").commit();
mPreferences.edit().putString(MyPreferences.AVERAGE_SPEED, "0.0")
.commit();
mPreferences.edit().putString(MyPreferences.DISTANCE, "0.0").commit();
}
/**
* Respond to "Start" button by requesting activity recognition updates.
*
* #param view
* The view that triggered this method.
*/
public void onStartUpdates() {
// Pass the update request to the requester object
mDetectionRequester.requestUpdates();
}
/**
* Respond to "Stop" button by canceling updates.
*
* #param view
* The view that triggered this method.
*/
public void onStopUpdates() {
// Pass the remove request to the remover object
mDetectionRemover.removeUpdates(mDetectionRequester
.getRequestPendingIntent());
/*
* Cancel the PendingIntent. Even if the removal request fails,
* canceling the PendingIntent will stop the updates.
*/
mDetectionRequester.getRequestPendingIntent().cancel();
}
/**
* Function to show settings alert dialog On pressing Settings button will
* lauch Settings Options
* */
public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
alertDialog.setTitle("GPS");
alertDialog.setMessage("GPS is not enabled. Do you want to enable it?");
// On pressing Settings button
alertDialog.setPositiveButton("Settings",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
/**
* #return List of Direction points
*/
public ArrayList<LatLng> getDirectionsPoints() {
if (mDirectionsPoints != null) {
return mDirectionsPoints;
} else {
mDirectionsPoints = new ArrayList<LatLng>();
return mDirectionsPoints;
}
}
/**
* Calculate distance
*
* #param lat1
* #param lon1
* #param lat2
* #param lon2
* #return
*/
private double calculateDistance(final double lat1, final double lon1,
final double lat2, final double lon2) {
// haversine great circle distance approximation, returns meters
final double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2))
+ Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2))
* Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60; // 60 nautical miles per degree of seperation
dist = dist * 1852; // 1852 meters per nautical mile
return dist;
}
private double deg2rad(final double deg) {
return (deg * Math.PI / 180.0);
}
private double rad2deg(final double rad) {
return (rad * 180.0 / Math.PI);
}
}
I kept location updates every 1 seconds and activity recognition updates every 3 seconds. I am able to get the location but path is not drawn properly in Google maps.
Code to draw path :-
public class MapsActivity extends FragmentActivity {
private static GoogleMap mGoogleMap = null;
private static final String TAG = "MapsActivity";
private Button mBtnStartRide, mBtnPauseRide, mBtnStopRide = null;
private static TextView mTxtLatLong, mTxtTimer, mTxtTotalSize,
mTxtSpeed = null;
private static PolylineOptions mPolyLineOptions = null;
// Storing the directions returned by the direcction api
private SharedPreferences mPreferences = null;
private MapsBroadcastReceiver receiver = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
receiver = new MapsBroadcastReceiver();
mPreferences = getSharedPreferences(TestPreferences.PREFERENCES,
Context.MODE_PRIVATE);
mTxtLatLong = (TextView) findViewById(R.id.txtLatLong);
mTxtTimer = (TextView) findViewById(R.id.txtTimer);
mTxtTotalSize = (TextView) findViewById(R.id.txtDirectionsSize);
mTxtSpeed = (TextView) findViewById(R.id.txtSpeed);
mBtnStartRide = (Button) findViewById(R.id.btn_start_ride);
mBtnPauseRide = (Button) findViewById(R.id.btn_pause_ride);
mBtnStopRide = (Button) findViewById(R.id.btn_stop_ride);
final Button mBtnCenter = (Button) findViewById(R.id.btn_center);
mBtnCenter.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
animateCameraTo();
}
});
mBtnStartRide.setOnClickListener(btnStartRideClickListener);
mBtnPauseRide.setOnClickListener(btnPauseRideClickListener);
mBtnStopRide.setOnClickListener(btnStopRideClickListener);
initilizeMap();
}
/**
* Start Ride Button Click Listener
*/
private OnClickListener btnStartRideClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
if (mPreferences.getBoolean(TestPreferences.IS_RIDE_PAUSE, false)) {
if (MyService.getInstance() != null) {
MyService.getInstance().reStartRide();
}
} else {
startService(new Intent(MapsActivity.this,
MyService.class));
}
mPreferences.edit().putBoolean(TestPreferences.IS_RIDE_START, true)
.commit();
mPreferences.edit().remove(TestPreferences.IS_RIDE_PAUSE).commit();
mPreferences.edit().remove(TestPreferences.IS_RIDE_STOPPED)
.commit();
mBtnStartRide.setVisibility(View.GONE);
mBtnPauseRide.setVisibility(View.VISIBLE);
mBtnStopRide.setVisibility(View.VISIBLE);
}
};
/**
* Start Ride Button Click Listener
*/
private OnClickListener btnPauseRideClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
MyService.getInstance().pauseRide();
mPreferences.edit().putBoolean(TestPreferences.IS_RIDE_PAUSE, true)
.commit();
mPreferences.edit()
.putBoolean(TestPreferences.IS_RIDE_START, false).commit();
mBtnStartRide.setVisibility(View.VISIBLE);
mBtnPauseRide.setVisibility(View.GONE);
mBtnStopRide.setVisibility(View.VISIBLE);
}
};
/**
* Stop Ride Button Click Listener
*/
private OnClickListener btnStopRideClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
stopService(new Intent(MapsActivity.this, MyService.class));
mPreferences.edit().remove(TestPreferences.IS_RIDE_PAUSE).commit();
mPreferences.edit()
.putBoolean(TestPreferences.IS_RIDE_START, false).commit();
mPreferences.edit()
.putBoolean(TestPreferences.IS_RIDE_STOPPED, true).commit();
mBtnStartRide.setVisibility(View.VISIBLE);
mBtnPauseRide.setVisibility(View.GONE);
mBtnStopRide.setVisibility(View.GONE);
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(receiver, new IntentFilter(
MyConstants.BROADCAST_INTENT));
initilizeMap();
if (mPreferences.getBoolean(TestPreferences.IS_RIDE_START, false)) {
mBtnStartRide.setVisibility(View.GONE);
mBtnPauseRide.setVisibility(View.VISIBLE);
mBtnStopRide.setVisibility(View.VISIBLE);
} else if (mPreferences
.getBoolean(TestPreferences.IS_RIDE_PAUSE, false)) {
mBtnStartRide.setVisibility(View.VISIBLE);
mBtnPauseRide.setVisibility(View.GONE);
mBtnStopRide.setVisibility(View.VISIBLE);
} else if (mPreferences.getBoolean(TestPreferences.IS_RIDE_STOPPED,
false)) {
// Show start button and gone Pause & Stop both
mBtnStartRide.setVisibility(View.VISIBLE);
mBtnPauseRide.setVisibility(View.GONE);
mBtnStopRide.setVisibility(View.GONE);
} else {
// Show start button and gone Pause & Stop both
mBtnStartRide.setVisibility(View.VISIBLE);
mBtnPauseRide.setVisibility(View.GONE);
mBtnStopRide.setVisibility(View.GONE);
}
setAllText();
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
#Override
protected void onDestroy() {
super.onDestroy();
mGoogleMap = null;
}
/**
* Function to load map. If map is not created it will create it for you
* */
private void initilizeMap() {
if (mGoogleMap == null) {
mGoogleMap = ((MapFragment) getFragmentManager().findFragmentById(
R.id.map)).getMap();
// check if map is created successfully or not
if (mGoogleMap == null) {
Toast.makeText(getApplicationContext(),
"Sorry! unable to create maps", Toast.LENGTH_SHORT)
.show();
} else {
mPolyLineOptions = new PolylineOptions().width(6).color(
Color.BLUE);
mGoogleMap.setTrafficEnabled(true);
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
mGoogleMap.getUiSettings().setRotateGesturesEnabled(true);
mGoogleMap.getUiSettings().setCompassEnabled(true);
mGoogleMap.getUiSettings().setZoomGesturesEnabled(true);
mGoogleMap.getUiSettings().setZoomControlsEnabled(true);
if (MyService.getInstance() != null
&& MyService.getInstance().getDirectionsPoints() != null
&& !MyService.getInstance().getDirectionsPoints()
.isEmpty()
&& MyService.getInstance().getDirectionsPoints()
.size() >= 1) {
mGoogleMap.addMarker(new MarkerOptions()
.position(
MyService.getInstance()
.getDirectionsPoints().get(0))
.anchor(0.8f, 1.0f).title("Your Location"));
animateCameraTo(MyService.getInstance()
.getDirectionsPoints().get(0).latitude,
MyService.getInstance().getDirectionsPoints()
.get(0).longitude);
}
}
} else {
mPolyLineOptions = new PolylineOptions().width(6).color(Color.BLUE);
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
mGoogleMap.getUiSettings().setRotateGesturesEnabled(true);
mGoogleMap.getUiSettings().setCompassEnabled(true);
mGoogleMap.getUiSettings().setZoomGesturesEnabled(true);
mGoogleMap.getUiSettings().setZoomControlsEnabled(true);
if (MyService.getInstance() != null
&& MyService.getInstance().getDirectionsPoints() != null
&& !MyService.getInstance().getDirectionsPoints()
.isEmpty()
&& MyService.getInstance().getDirectionsPoints().size() >= 1) {
Log.i(TAG, "Lat long in resume2222222222 = "
+ MyService.getInstance().getDirectionsPoints()
.get(0).latitude
+ ", "
+ MyService.getInstance().getDirectionsPoints()
.get(0).longitude);
mGoogleMap.addMarker(new MarkerOptions()
.position(
MyService.getInstance().getDirectionsPoints()
.get(0)).anchor(0.8f, 1.0f)
.title("Your Location"));
animateCameraTo(MyService.getInstance().getDirectionsPoints()
.get(0).latitude, MyService.getInstance()
.getDirectionsPoints().get(0).longitude);
}
}
}
/**
* #author Scorpion
*
*/
private class MapsBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
switch (intent.getExtras().getInt(TestPreferences.BROADCAST_CODES)) {
case 100:
showErrorDialog(intent.getExtras().getInt(
TestPreferences.BROADCAST_CODES));
break;
case 200:
setAllText();
break;
case 300:
if (intent.getExtras().getString("time") != null) {
mTxtTimer.setText("Timer - "
+ intent.getExtras().getString("time"));
} else {
mTxtTimer.setText("Timer - 00:00:00");
}
break;
default:
break;
}
if (MyService.getInstance() != null
&& !MyService.getInstance().getDirectionsPoints()
.isEmpty()
&& MyService.getInstance().getDirectionsPoints().size() == 1) {
mGoogleMap.addMarker(new MarkerOptions()
.position(
MyService.getInstance().getDirectionsPoints()
.get(0)).anchor(0.8f, 1.0f)
.title("Your Location"));
}
}
}
/**
*
*/
public void setAllText() {
mTxtLatLong.setText("Lat - " + LocationUtils.sLatitude + ", Lng - "
+ LocationUtils.sLongitude);
mTxtSpeed.setText("Speed - " + LocationUtils.sSpeed);
mTxtTotalSize.setText("Distance - " + LocationUtils.sDistance);
}
/**
* Animate to position on Google Maps
*
* #param lat
* #param lng
*/
private void animateCameraTo() {
// Saving the points in a polyline
if (MyService.getInstance() != null
&& MyService.getInstance().getDirectionsPoints() != null
&& !MyService.getInstance().getDirectionsPoints().isEmpty()) {
mPolyLineOptions.geodesic(true);
mPolyLineOptions.addAll(MyService.getInstance()
.getDirectionsPoints());
// Drawing the path on the map Polyline route =
mGoogleMap.addPolyline(mPolyLineOptions);
int index = MyService.getInstance().getDirectionsPoints().size() - 1;
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(MyService.getInstance().getDirectionsPoints()
.get(index)).zoom(20).build();
mGoogleMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
}
}
/**
* Animate to position on Google Maps
*
* #param lat
* #param lng
*/
private void animateCameraTo(final double lat, final double lng) {
// Saving the points in a polyline
if (MyService.getInstance() != null
&& MyService.getInstance().getDirectionsPoints() != null
&& !MyService.getInstance().getDirectionsPoints().isEmpty()) {
mPolyLineOptions.geodesic(true);
mPolyLineOptions.addAll(MyService.getInstance()
.getDirectionsPoints());
// Drawing the path on the map
mGoogleMap.addPolyline(mPolyLineOptions);
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(new LatLng(lat, lng)).zoom(20).build();
mGoogleMap.animateCamera(CameraUpdateFactory
.newCameraPosition(cameraPosition));
}
}
/**
* Show a dialog returned by Google Play services for the connection error
* code
*
* #param errorCode
* An error code returned from onConnectionFailed
*/
private void showErrorDialog(int errorCode) {
// Get the error dialog from Google Play services
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(errorCode,
MapsActivity.this,
LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);
// If Google Play services can provide an error dialog
if (errorDialog != null) {
// Create a new DialogFragment in which to show the error dialog
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
// Set the dialog in the DialogFragment
errorFragment.setDialog(errorDialog);
// Show the error dialog in the DialogFragment
errorFragment.show(getSupportFragmentManager(),
LocationUtils.APPTAG);
}
}
}
Coordinate results got from Location provider :-
23.030392522689674, 72.5570888165469, 23.030408166940184, 72.55708600340783, 23.030451207802273, 72.55708215400317, 23.030448342522195, 72.5570607428365, 23.03045605637773, 72.55702903413072, 23.03046687434995, 72.55702007867455, 23.030481227996425, 72.55702017125606, 23.03049188235562, 72.55701618151457, 23.030501580461667, 72.55701051075931, 23.030506644074638, 72.55700568837983, 23.030510243171772, 72.55699463185964, 23.03051656621021, 72.55698811382064, 23.030523584332027, 72.55698589863236, 23.030527893257556, 72.5569835596, 23.03052731568596, 72.55698681171178, 23.030533706759005, 72.55699683791043, 23.03053795413862, 72.5570022232021, 23.03054422659466, 72.55700788646914, 23.030550353227323, 72.5570133047868, 23.03056167617575, 72.5570171806126, 23.030572274532982, 72.55702744953462, 23.03057623596164, 72.55703687229187, 23.03058756510295, 72.55703589208271, 23.030591797598742, 72.5570396833694, 23.030597556470788, 72.55703954449652, 23.030602030769657, 72.55704359454182, 23.030606735158617, 72.55704993131606, 23.030611670633565, 72.55705060538087,23.030618875802222, 72.55705181604097, 23.030629137631596, 72.55705043471286, 23.030651405170016, 72.55705440295588, 23.03066642161307, 72.55705285209174, 23.030690454277963, 72.55703884780276, 23.030708214416187, 72.55703489882957, 23.03072341369183, 72.5570340196122, 23.030737371000015, 72.55703289416898, 23.03075088423441, 72.55703750535102, 23.030767572625837, 72.55704489874579, 23.030794398930176, 72.55703870239826, 23.03081655932613, 72.55702474270966, 23.030827505666753, 72.5570121351611, 23.03083720431765, 72.55700390084714, 23.03084624667527, 72.55700122660554, 23.030859495795887, 72.55699948514881, 23.030870357210333, 72.55699625144317, 23.030881843633054
This code will work
GoogleMap map;
// ... get a map.
// Add a thin red line from London to New York.
Polyline line = map.addPolyline(new PolylineOptions()
.add(new LatLng(51.5, -0.1), new LatLng(40.7, -74.0))
.width(5)
.color(Color.RED));
You should split your problem into the aspects of data collection and data display.
Therefore take two coordinates you precisely know and draw a straight polyline on google maps.
If it's really displayed at the wrong location, GoogleMap has indeed a bug, which BTW I don't believe.
Then print out your coordinates e.g. to LogCat before drawing them and check the coordinates. If they are wrong, it is not a problem of GoogleMaps but of the LocationProvider or of how you use it.
If the coordinates are collected correctly, you may pick them somehow up from LogCat and use them directly in your code to draw a polyline. If then the polyline is displaced, you may again have found a bug in GoogleMap. Then you should paste the coordinates here, so someone can reproduce it. It may be device dependent. I never had a polyline which did not match the map.
Your code for drawing the path looks strange.
Inside the for-loop you should only add the points to an instance of PolylineOptions (which you create before entering the for loop).
Then, after the for-loop you can add the width, color etc. to the polylineOptions object and finally use that in mGoogleMap.addPolyline().
In your coding, you are somehow adding a new polyline for each point (I am wondering that this draws lines at all, as each "line" consists of one point only.).