I normally don't get this error but it occurred a few times while loading the map.
Below is my stacktrace and java code
Here's the stacktrace:
E/MAP(23027): java.lang.NullPointerException
E/MAP(23027): at java.nio.ReadWriteDirectByteBuffer.put(ReadWriteDirectByteBuffer.java:137)
E/MAP(23027): at java.nio.ShortToByteBufferAdapter.put(ShortToByteBufferAdapter.java:160)
12-26 17:53:57.519: E/MAP(23027): at com.google.maps.api.android.lib6.gmm6.o.c.a.d.d(Unknown Source)
12-26 17:53:57.519: E/MAP(23027): at com.google.maps.api.android.lib6.gmm6.o.c.a.d.a(Unknown Source)
12-26 17:53:57.519: E/MAP(23027): at com.google.maps.api.android.lib6.gmm6.o.a.a(Unknown Source)12-26 17:53:57.519: E/MAP(23027): at com.google.maps.api.android.lib6.gmm6.o.c.b(Unknown Source)
12-26 17:53:57.519: E/MAP(23027): at com.google.maps.api.android.lib6.gmm6.o.c.a(Unknown Source)
12-26 17:53:57.519: E/MAP(23027): at com.google.maps.api.android.lib6.gmm6.o.l.a(Unknown Source)
12-26 17:53:57.519: E/MAP(23027): at com.google.maps.api.android.lib6.gmm6.o.l.b(Unknown Source)
12-26 17:53:57.519: E/MAP(23027): at com.google.maps.api.android.lib6.gmm6.o.dc.k(Unknown Source)
12-26 17:53:57.519: E/MAP(23027): at com.google.maps.api.android.lib6.gmm6.o.dc.run(Unknown Source)
12-26 17:53:57.531: E/AndroidRuntime(23027): FATAL EXCEPTION: GLThread 4935
12-26 17:53:57.531: E/AndroidRuntime(23027): java.lang.NullPointerException
12-26 17:53:57.531: E/AndroidRuntime(23027): at java.nio.ReadWriteDirectByteBuffer.put(ReadWriteDirectByteBuffer.java:137)
12-26 17:53:57.531: E/AndroidRuntime(23027): at java.nio.ShortToByteBufferAdapter.put(ShortToByteBufferAdapter.java:160)
12-26 17:53:57.531: E/AndroidRuntime(23027): at com.google.maps.api.android.lib6.gmm6.o.c.a.d.d(Unknown Source)
12-26 17:53:57.531: E/AndroidRuntime(23027): at com.google.maps.api.android.lib6.gmm6.o.c.a.d.a(Unknown Source)
12-26 17:53:57.531: E/AndroidRuntime(23027): at com.google.maps.api.android.lib6.gmm6.o.a.a(Unknown Source)
Here is my java code :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(isGooglePlay()){
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_start_meter);
// Get handles to the UI view objects
mLatLng = (TextView) findViewById(R.id.lat_lng);
mLatLng.setVisibility(View.GONE);
mAddress = (TextView) findViewById(R.id.address);
mActivityIndicator = (ProgressBar) findViewById(R.id.address_progress);
mConnectionState = (TextView) findViewById(R.id.text_connection_state);
tvStartUpdates = (TextView) findViewById(R.id.start_updates);
tvStopUpdates = (TextView) findViewById(R.id.stop_updates);
showHideCallayout=(LinearLayout) findViewById(R.id.showHideCalLayout);
showHideButlayout=(LinearLayout) findViewById(R.id.showHideButLayout);
btShowHide=(Button) findViewById(R.id.btShowHide);
btShowHide.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(btShowHide.getText().toString().equalsIgnoreCase("-")){
showHideButlayout.setVisibility(View.GONE);
showHideCallayout.setVisibility(View.GONE);
btShowHide.setText("+");
}else if(btShowHide.getText().toString().equalsIgnoreCase("+")){
showHideButlayout.setVisibility(View.VISIBLE);
showHideCallayout.setVisibility(View.VISIBLE);
btShowHide.setText("-");
}
}
});
showHideButlayout.setVisibility(View.VISIBLE);
showHideCallayout.setVisibility(View.VISIBLE);
tvStartUpdates.setEnabled(true);
tvStopUpdates.setEnabled(false);
mConnectionState.setVisibility(View.GONE);
mConnectionStatus = (TextView) findViewById(R.id.text_connection_status);
mConnectionStatus.setVisibility(View.GONE);
distancekmm = (TextView) findViewById(R.id.label_lat_lng);
tvTotalFaree = (TextView) findViewById(R.id.tvTotalFareee);
tvBaseFare = (TextView) findViewById(R.id.tvbaseFare);
Toast.makeText(StartMeterActivity.this, "GPS signal not found", Toast.LENGTH_LONG).show();
gps = new GPSTracker(StartMeterActivity.this);
if(gps.canGetLocation()){
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(LocationUtils.UPDATE_INTERVAL_IN_MILLISECONDS);
// Use high accuracy
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the interval ceiling to one minute
mLocationRequest.setFastestInterval(LocationUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS);
// Note that location updates are off until the user turns them on
mUpdatesRequested = false;
if (mGoogleMap == null) {
SupportMapFragment fm = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
// Getting Map for the SupportMapFragment
mGoogleMap = fm.getMap();
// check if map is created successfully or not
if (mGoogleMap == null) {
Toast.makeText(getApplicationContext(),
"Sorry! unable to create maps", Toast.LENGTH_SHORT)
.show();
}
// while(mGoogleMap==null){
//
// }
// if(mGoogleMap!=null){
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
//mGoogleMap.setPadding(0, 0, 0, 520);
// Enable MyLocation Button in the Map
mGoogleMap.setMyLocationEnabled(true);
//mGoogleMap.getUiSettings().setZoomControlsEnabled(true);
// LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
//
// // Creating a criteria object to retrieve provider
// Criteria criteria = new Criteria();
//
// // Getting the name of the best provider
// String provider = locationManager.getBestProvider(criteria, true);
//
// // Getting Current Location From GPS
Location l = getLocationn();
LatLng ll=new LatLng(l.getLatitude(), l.getLongitude());
// CameraPosition cameraPosition = new CameraPosition.Builder()
// .target(ll) // Sets the center of the map to Mountain View
// .zoom(14) // Sets the zoom
// //.bearing(90) // Sets the orientation of the camera to east
// // .tilt(30) // Sets the tilt of the camera to 30 degrees
// .build(); // Creates a CameraPosition from the builder
// mGoogleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(ll, 16));
//
// Open Shared Preferences
// mPrefs = getSharedPreferences(LocationUtils.SHARED_PREFERENCES, Context.MODE_PRIVATE);
// Get an editor
// mEditor = mPrefs.edit();
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
mLocationClient = new LocationClient(this, this, this); }
} else{
// // can't get location
// // GPS or Network is not enabled
// // Ask user to enable GPS/network in settings
gps.showSettingsAlert();
//
}
}}
private void setRetainInstance(boolean b) {
// TODO Auto-generated method stub
}
/*
* Called when the Activity is no longer visible at all.
* Stop updates and disconnect.
*/
#Override
public void onStop() {
if (mLocationClient.isConnected()) {
mLocationClient.removeLocationUpdates(this);
}
mLocationClient.disconnect();
// If the client is connected
// if (mLocationClient.isConnected()) {
// stopPeriodicUpdates();
// }
//
// // After disconnect() is called, the client is considered "dead".
// mLocationClient.disconnect();
super.onStop();
}
/*
* Called when the Activity is going into the background.
* Parts of the UI may be visible, but the Activity is inactive.
*/
#Override
public void onPause() {
// Save the current setting for updates
// mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, mUpdatesRequested);
// mEditor.commit();
super.onPause();
}
/*
* Called when the Activity is restarted, even before it becomes visible.
*/
#Override
public void onStart() {
super.onStart();
/*
* Connect the client. Don't re-start any requests here;
* instead, wait for onResume()
*/
mLocationClient.connect();
mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(16));
}
/*
* Called when the system detects that this Activity is now visible.
*/
#Override
public void onResume() {
super.onResume();
mLocationClient.connect();
int errorCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if(errorCode != ConnectionResult.SUCCESS && GooglePlayServicesUtil.isUserRecoverableError(errorCode)){
Dialog d = GooglePlayServicesUtil.getErrorDialog(errorCode, this, 0);
d.show();
}
// locationManager.requestLocationUpdates(provider, 400, 1, this);
// If the app already has a setting for getting location updates, get it
// if (mPrefs.contains(LocationUtils.KEY_UPDATES_REQUESTED)) {
// mUpdatesRequested = mPrefs.getBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false);
//
// // Otherwise, turn off location updates until requested
// } else {
// mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false);
// mEditor.commit();
// }
}
/*
* Handle results returned to this Activity by other Activities started with
* startActivityForResult(). In particular, the method onConnectionFailed() in
* LocationUpdateRemover and LocationUpdateRequester may call startResolutionForResult() to
* start an Activity that handles Google Play services problems. The result of this
* call returns here, to onActivityResult.
*/
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
// Choose what to do based on the request code
switch (requestCode) {
// If the request code matches the code sent in onConnectionFailed
case LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST :
switch (resultCode) {
// If Google Play services resolved the problem
case Activity.RESULT_OK:
// Log the result
Log.d(LocationUtils.APPTAG, getString(R.string.resolved));
// Display the result
mConnectionState.setText(R.string.connected);
mConnectionStatus.setText(R.string.resolved);
mConnectionStatus.setVisibility(View.GONE);
mConnectionState.setVisibility(View.GONE);
break;
// If any other result was returned by Google Play services
default:
// Log the result
Log.d(LocationUtils.APPTAG, getString(R.string.no_resolution));
// Display the result
mConnectionState.setText(R.string.disconnected);
mConnectionStatus.setText(R.string.no_resolution);
mConnectionStatus.setVisibility(View.GONE);
mConnectionState.setVisibility(View.GONE);
break;
}
// If any other request code was received
default:
// Report that this Activity received an unknown requestCode
Log.d(LocationUtils.APPTAG,
getString(R.string.unknown_activity_request_code, requestCode));
break;
}
}
/**
* Verify that Google Play services is available before making a request.
*
* #return true if Google Play services is available, otherwise false
*/
private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode =
GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d(LocationUtils.APPTAG, getString(R.string.play_services_available));
// Continue
return true;
// Google Play services was not available for some reason
} else {
// Display an error dialog
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0);
if (dialog != null) {
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
errorFragment.setDialog(dialog);
errorFragment.show(getSupportFragmentManager(), LocationUtils.APPTAG);
}
return false;
}
}
/**
* Invoked by the "Get Location" button.
*
* Calls getLastLocation() to get the current location
*
* #param v The view object associated with this method, in this case a Button.
*/
public void getLocation(View v) {
// If Google Play Services is available
Intent i=new Intent(getApplicationContext(), WaitingActivity.class);
startActivity(i);
}
}
/**
* Invoked by the "Get Address" button.
* Get the address of the current location, using reverse geocoding. This only works if
* a geocoding service is available.
*
* #param v The view object associated with this method, in this case a Button.
*/
// For Eclipse with ADT, suppress warnings about Geocoder.isPresent()
#SuppressLint("NewApi")
public void getAddress(View v) {
// In Gingerbread and later, use Geocoder.isPresent() to see if a geocoder is available.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD && !Geocoder.isPresent()) {
// No geocoder is present. Issue an error message
Toast.makeText(this, R.string.no_geocoder_available, Toast.LENGTH_LONG).show();
return;
}
if (servicesConnected()) {
// Get the current location
Location currentLocation = mLocationClient.getLastLocation();
// Turn the indefinite activity indicator on
mActivityIndicator.setVisibility(View.VISIBLE);
// Start the background task
(new StartMeterActivity.GetAddressTask(this)).execute(currentLocation);
}
}
/**
* Invoked by the "Start Updates" button
* Sends a request to start location updates
*
* #param v The view object associated with this method, in this case a Button.
*/
public void startUpdates(View v) {
mUpdatesRequested = true;
// tvBaseFare.setVisibility(View.VISIBLE);
// tvTotalFare.setVisibility(View.VISIBLE);
if (servicesConnected()) {
startPeriodicUpdates();
}
}
/**
* Invoked by the "Stop Updates" button
* Sends a request to remove location updates
* request them.
*
* #param v The view object associated with this method, in this case a Button.
*/
public void stopUpdates(View v) {
mUpdatesRequested = false;
if (servicesConnected()) {
stopPeriodicUpdates();
}
}
/*
* Called by Location Services when the request to connect the
* client finishes successfully. At this point, you can
* request the current location or start periodic updates
*/
#Override
public void onConnected(Bundle bundle) {
mConnectionStatus.setText(R.string.connected);
mConnectionStatus.setVisibility(View.GONE);
// prevLocation = getLocation(mLocationClient);
if (mUpdatesRequested) {
startPeriodicUpdates();
}
}
/*
* Called by Location Services if the connection to the
* location client drops because of an error.
*/
#Override
public void onDisconnected() {
mConnectionStatus.setText(R.string.disconnected);
mConnectionStatus.setVisibility(View.GONE);
}
/*
* Called by Location Services if the attempt to
* Location Services fails.
*/
#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,
LocationUtils.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.
showErrorDialog(connectionResult.getErrorCode());
}
}
/**
* Report location updates to the UI.
*
* #param location The updated location.
*/
#Override
public void onLocationChanged(Location location) {
changedLocation=location;
// LatLng endPosition = new LatLng(changedLocation.getLatitude(), changedLocation.getLongitude());
mConnectionStatus.setText(R.string.location_updated);
// In the UI, set the latitude and longitude to the value received
// if (marker != null) {
// marker.remove();
// }
// Report to the UI that the location was updated
mConnectionStatus.setText(R.string.location_updated);
mConnectionStatus.setVisibility(View.GONE);
mConnectionState.setVisibility(View.GONE);
// In the UI, set the latitude and longitude to the value received
double lat = location.getLatitude();
double lng = location.getLongitude();
Toast.makeText(this, "Location " + lat+","+lng,
1000).show();
LatLng coordinate = new LatLng(lat, lng);
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(coordinate));
//mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(16));
//mLatLng.setText(lat+" "+lng);
// mLatLng.setText(df.format(lat)+" " +df.format(lng));
// Toast.makeText(this, "Location " + coordinate.latitude+","+coordinate.longitude,1000).show();
// mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(coordinate));
// mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(17));
rectOptions.add(new LatLng(lat, lng));
this.savePolyline=rectOptions;
mGoogleMap.addPolyline(rectOptions);
}
Related
I am developing an android application and I am fetching device current location by Fused Location.
I am checking if a user has grant permission or not if yes I am fetching location but If a user has not granted the permission I am opening permission dialog box and a user clicks on allow then google is showing following dialog box:
How should I handle this dialog box click event because what is happing if a user clicks on OK but it's not fetching device location or I am not getting any location update callback? I want when user click on OK it should fetch location.
How should I achieve this?
publi void myLocationButtonClicked(){
GpsLocationTracker mGpsLocationTracker = new GpsLocationTracker(activity);
if (mGpsLocationTracker.canGetLocation()) {
latitude = mGpsLocationTracker.getLatitude();
longitude = mGpsLocationTracker.getLongitude();
if ((latitude != 0 && longitude != 0)
} else {
showLocationSnackBar(activity.getString(R.string.wait));
}
} else {
locationChecker();
}
// this function to show dialog to open GPS if it is closed
public void locationChecker() {
LocationRequest mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
SettingsClient client = LocationServices.getSettingsClient(activity);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
task.addOnSuccessListener(activity, locationSettingsResponse -> myLocationButtonClicked());
task.addOnFailureListener(activity, e -> {
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(activity,
REQUEST_GPS_RESULT_CODE_FOR_MAP_LOCATION);
} catch (IntentSender.SendIntentException sendEx) {
// Ignore the error.
}
}
});
}
}
this is the GpsLocationTracker class to fetch user location
public class GpsLocationTracker extends Service implements LocationListener {
/**
* min distance change to get location update
*/
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATE = 10;
/**
* min time for location update
* 60000 = 1min
*/
private static final long MIN_TIME_FOR_UPDATE = 60000;
/**
* context of calling class
*/
private Context mContext;
/**
* flag for gps status
*/
private boolean isGpsEnabled = false;
/**
* flag for network status
*/
private boolean isNetworkEnabled = false;
/**
* flag for gps
*/
private boolean canGetLocation = false;
/**
* location
*/
private Location mLocation;
/**
* latitude
*/
private double mLatitude;
/**
* longitude
*/
private double mLongitude;
/**
* location manager
*/
private LocationManager mLocationManager;
/**
* #param mContext constructor of the class
*/
public GpsLocationTracker(Context mContext) {
this.mContext = mContext;
getLocation();
}
/**
* #return location
*/
public Location getLocation() {
try {
mLocationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
/*getting status of the gps*/
isGpsEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
/*getting status of network provider*/
isNetworkEnabled = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGpsEnabled && !isNetworkEnabled) {
/*no location provider enabled*/
} else {
this.canGetLocation = true;
/*getting location from network provider*/
if (isNetworkEnabled) {
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_FOR_UPDATE, MIN_DISTANCE_CHANGE_FOR_UPDATE, this);
if (mLocationManager != null) {
mLocation = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (mLocation != null) {
mLatitude = mLocation.getLatitude();
mLongitude = mLocation.getLongitude();
}
}
/*if gps is enabled then get location using gps*/
if (isGpsEnabled) {
if (mLocation == null) {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_FOR_UPDATE, MIN_DISTANCE_CHANGE_FOR_UPDATE, this);
if (mLocationManager != null) {
mLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (mLocation != null) {
mLatitude = mLocation.getLatitude();
mLongitude = mLocation.getLongitude();
}
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return mLocation;
}
/**
* call this function to stop using gps in your application
*/
public void stopUsingGps() {
if (mLocationManager != null) {
mLocationManager.removeUpdates(GpsLocationTracker.this);
}
}
/**
* #return latitude
* <p/>
* function to get latitude
*/
public double getLatitude() {
if (mLocation != null) {
mLatitude = mLocation.getLatitude();
}
return mLatitude;
}
/**
* #return longitude
* function to get longitude
*/
public double getLongitude() {
if (mLocation != null) {
mLongitude = mLocation.getLongitude();
}
return mLongitude;
}
/**
* #return to check gps or wifi is enabled or not
*/
public boolean canGetLocation() {
return this.canGetLocation;
}
/**
* function to prompt user to open
* settings to enable gps
*/
public void showSettingsAlert() {
AlertDialog.Builder mAlertDialog = new AlertDialog.Builder(new ContextThemeWrapper(mContext, R.style.AppTheme));
mAlertDialog.setTitle(R.string.gps_disabled);
mAlertDialog.setMessage(R.string.enable_gps);
mAlertDialog.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent mIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(mIntent);
}
});
mAlertDialog.setNegativeButton(R.string.dialog_button_cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
final AlertDialog mcreateDialog = mAlertDialog.create();
mcreateDialog.show();
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
and when user click ok button the you have to check the result in onActivityResult().
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_GPS_RESULT_CODE_FOR_MAP_LOCATION && resultCode == RESULT_OK)
myLocationButtonClicked();
}
Try this Function call this function on button click listner and disable your gps.. and when you clicking on button gps dialog will appear and gps enable and when again you clicking on button toast will show that handle by status code
private void EnableGPSAutoMatically() {
GoogleApiClient googleApiClient = null;
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
googleApiClient.connect();
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(30 * 1000);
locationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
// **************************
builder.setAlwaysShow(true); // this is the key ingredient
// **************************
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi
.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates state = result
.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
toast("Success");
isgpson = true;
// All location settings are satisfied. The client can
// initialize location
// requests here.
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// toast("GPS is not on");
isgpson = false;
// Location settings are not satisfied. But could be
// fixed by showing the user
// a dialog.
try {
// Show the dialog by calling
// startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(Activity_Splash.this, 1000);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// toast("Setting change not allowed");
// Location settings are not satisfied. However, we have
// no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
}
}
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.
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 am trying to create a page that will outlay (using Google Maps) a race circuit and will use a dot of some kind to show and update the users current location.
The code I have for this is:
public class TopGearLocationTracker extends FragmentActivity implements
//Specifies methods that Location Services calls when a location client
//is connected or disconnected.//
GooglePlayServicesClient.ConnectionCallbacks,
//Specifies a method that Location Services calls if an error occurs while
//attempting to connect the location client. This method uses the previously-
//defined showErrorDialog method to display an error dialog that attempts to
//fix the problem using Google Play services.
GooglePlayServicesClient.OnConnectionFailedListener,
//The callback method that Location Services invokes to send a location update
//to your application is specified in the LocationListener interface, in the method
//onLocationChanged(). The incoming argument is a Location object containing the
//location's latitude and longitude. The following snippet shows how to specify
//the interface and define the method:
LocationListener
{
// Global constants
/*
* 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;
// Global variable to hold the current location
Location mCurrentLocation;
private GoogleMap aMap;
// Global constants
// Milliseconds per second
private static final int MILLISECONDS_PER_SECOND = 1000;
// Update frequency in seconds
public static final int UPDATE_INTERVAL_IN_SECONDS = 5;
// Update frequency in milliseconds
private static final long UPDATE_INTERVAL =
MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
// The fastest update frequency, in seconds
private static final int FASTEST_INTERVAL_IN_SECONDS = 1;
// A fast frequency ceiling in milliseconds
private static final long FASTEST_INTERVAL =
MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
// Define an object that holds accuracy and frequency parameters
LocationRequest mLocationRequest;
// Global variables
LocationClient mLocationClient;
boolean mUpdatesRequested;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.top_gear_location_tracker);
// Set the map up
// Set the map to Top Gear track location
LatLng topGearTrack = new LatLng(51.116492, -0.541767);
aMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
aMap.getUiSettings().setAllGesturesEnabled(false);
aMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
aMap.setMyLocationEnabled(true);
aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(topGearTrack, 15));
setUpMapIfNeeded();
// Create the LocationRequest object
mLocationRequest = LocationRequest.create();
// Use high accuracy
mLocationRequest.setPriority(
LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the update interval to 5 seconds
mLocationRequest.setInterval(UPDATE_INTERVAL);
// Set the fastest update interval to 1 second
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
// Open the shared preferences
//mPrefs = getSharedPreferences("SharedPreferences",
//Context.MODE_PRIVATE);
// Get a SharedPreferences editor
//mEditor = mPrefs.edit();
/*
* Create a new location client, using the enclosing class to
* handle callbacks.
*/
mLocationClient = new LocationClient(this, this, this);
// Start with updates turned off
mUpdatesRequested = false;
}
public void setUpMapIfNeeded()
{
//Do a null check to confirm that we have not already instantiated the map.
if (aMap == null)
{
aMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))
.getMap();
//Check if we were successful in obtaining the map.
if (aMap != null)
{
//The Map is verified. It is now safe to manipulate the map.
}
}
}
/*
* Called when the Activity becomes visible.
*/
#Override
protected void onStart()
{
super.onStart();
// Connect the client.
mLocationClient.connect();
}
/*
* Called when the Activity is no longer visible.
*/
#Override
protected void onStop()
{
// Disconnecting the client invalidates it.
mLocationClient.disconnect();
super.onStop();
}
// *************** CHECK FOR GOOGLE PLAY SERVICES *************** //
#SuppressWarnings("unused")
private boolean servicesConnected()
{
// Check that Google Play services is available
int resultCode =
GooglePlayServicesUtil.
isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode)
{
// In debug mode, log the status
Log.d("Location Updates",
"Google Play services is available.");
// Continue
return true;
// Google Play services was not available for some reason
}
else
{
// Get the error code
// Get the error dialog from Google Play services
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
resultCode,
this,
CONNECTION_FAILURE_RESOLUTION_REQUEST);
// If Google Play services can provide an error dialog
if (errorDialog != null)
{
// Create a new DialogFragment for 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(),
"Location Updates");
}
}
return false;
}
// Define a DialogFragment that displays the error dialog
public static class ErrorDialogFragment extends DialogFragment
{
// Global field to contain the error dialog
private Dialog mDialog;
// Default constructor. Sets the dialog field to null
public ErrorDialogFragment()
{
super();
mDialog = null;
}
// Set the dialog to display
public void setDialog(Dialog dialog)
{
mDialog = dialog;
}
// Return a Dialog to the DialogFragment.
#Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
return mDialog;
}
}
/*
* Handle results returned to the FragmentActivity
* by Google Play services
*/
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data)
{
// Decide what to do based on the original request code
switch (requestCode)
{
case CONNECTION_FAILURE_RESOLUTION_REQUEST :
/*
* If the result code is Activity.RESULT_OK, try
* to connect again
*/
switch (resultCode) {
case Activity.RESULT_OK :
/*
* Try the request again
*/
break;
}
}
}
// ******************** CALLBACK METHODS AND INTERFACES ******************** //
/*
* Called by Location Services when the request to connect the
* client finishes successfully. At this point, you can
* request the current location or start periodic updates
*/
#Override
public void onConnected(Bundle dataBundle)
{
// Display the connection status
Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
// If already requested, start periodic updates
if (mUpdatesRequested)
{
mLocationClient.requestLocationUpdates(mLocationRequest, this);
}
}
/*
* Called by Location Services if the connection to the
* location client drops because of an error.
*/
#Override
public void onDisconnected()
{
// Display the connection status
Toast.makeText(this, "Disconnected. Please re-connect.",
Toast.LENGTH_SHORT).show();
}
/*
* Called by Location Services if the attempt to
* Location Services fails.
*/
#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 cancelled 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.
*/
showErrorDialog(connectionResult.getErrorCode());
}
}
private void showErrorDialog(int errorCode)
{
new AlertDialog.Builder(this)
.setMessage(String.valueOf(errorCode))
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.dismiss();
}
}).show();
}
// Define the callback method that receives location updates
#Override
public void onLocationChanged(Location location)
{
// Report to the UI that the location was updated
String msg = "Updated Location: " +
Double.toString(location.getLatitude()) + "," +
Double.toString(location.getLongitude());
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
}
When I try to load this 'page' by clicking a button from a previous page it doesn't load up. I was at least expecting the map (of Top Gear test track) to load up.
What could be stopping the map from loading up?
Is my approach to creating what I'm after correct?
I have pretty much followed:
http://developer.android.com/training/location/retrieve-current.html
http://developer.android.com/training/location/receive-location-updates.html
(I haven't bothered with the Shared Preferences thing).
I think to test it I would be best to use my home location lat/lang but for the moment I can't get the map to appear? This was tested on my HTC One so shouldn't be a Google Play Services issue as the screen that loads this one is a static (except zoom in/out) Map of the same place.
I appreciate this is a 'large' question and I would appreciate feedback from people that have experience/created a 'location-aware' application.
Thanks.
You may refer to the article https://software.intel.com/en-us/articles/implementing-map-and-geofence-features-in-android-business-apps
Add Android Manifest permissions:
<uses-permission android:name=”android.permission.INTERNET"/>
and
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="copy your API Key here"/>
To add a map fragment:
and
…
private static final LatLng CHANDLER = new LatLng(33.455,-112.0668);
…
private static final StoreLocation[] ALLRESTURANTLOCATIONS = new StoreLocation[] {
new StoreLocation(new LatLng(33.455,-112.0668), new String("Phoenix, AZ")),
new StoreLocation(new LatLng(33.5123,-111.9336), new String("SCOTTSDALE, AZ")),
new StoreLocation(new LatLng(33.3333,-111.8335), new String("Chandler, AZ")),
new StoreLocation(new LatLng(33.4296,-111.9436), new String("Tempe, AZ")),
new StoreLocation(new LatLng(33.4152,-111.8315), new String("Mesa, AZ")),
new StoreLocation(new LatLng(33.3525,-111.7896), new String("Gilbert, AZ"))
};
…
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.geolocation_view);
mMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.storelocationmap)).getMap();
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(CHANDLER, ZOOM_LEVEL));
Drawable iconDrawable = getResources().getDrawable(R.drawable.ic_launcher);
Bitmap iconBmp = ((BitmapDrawable) iconDrawable).getBitmap();
for(int ix = 0; ix < ALLRESTURANTLOCATIONS.length; ix++) {
mMap.addMarker(new MarkerOptions()
.position(ALLRESTURANTLOCATIONS[ix].mLatLng)
.icon(BitmapDescriptorFactory.fromBitmap(iconBmp)));
}
Then you add the LocationListener and the location update callbacks.
I have stored places in the database with their Longitude and Latitude, and i want to get the Latlngs for all the places and show them on Google Map v2.
I tried to put a test marker in the OnCreate function, but it dose not work, maybe because i put it in a wrong place ?
Here is my code: (the code works without the part of the add marker):
public class NearbyActivity extends FragmentActivity implements LocationListener,OnInfoWindowClickListener,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener{
private GoogleMap mMap;
private LocationManager locationManager;
private SupportMapFragment mapFragment;
private GoogleMap map;
private LocationClient mLocationClient;
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
// Define a DialogFragment that displays the error dialog
public static class ErrorDialogFragment extends DialogFragment {
// Global field to contain the error dialog
private Dialog mDialog;
// Default constructor. Sets the dialog field to null
public ErrorDialogFragment() {
super();
mDialog = null;
}
// Set the dialog to display
public void setDialog(Dialog dialog) {
mDialog = dialog;
}
// Return a Dialog to the DialogFragment.
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return mDialog;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nearby);
mLocationClient = new LocationClient(this, this, this);
mapFragment = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map));
map = mapFragment.getMap();
map.setMyLocationEnabled(true);
// This is working byt with fixed values not from database..
Marker melbourne = map.addMarker(new MarkerOptions()
.position(new LatLng(26.2412591, 50.5961323))
.title("0000")
.snippet("Manama Capital of Arab Tourism")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.palace)));
onInfoWindowClick(melbourne);
map.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
Intent intent = new Intent(NearbyActivity.this,Description.class);
intent.putExtra("id", "klkl");
startActivity(intent);
} });
// end of add marker.
}
#Override
protected void onStart() {
super.onStart();
// Connect the client.
if(isGooglePlayServicesAvailable()){
mLocationClient.connect();
}
}
/*
* Called when the Activity is no longer visible.
*/
#Override
protected void onStop() {
// Disconnecting the client invalidates it.
mLocationClient.disconnect();
super.onStop();
}
/*
* Handle results returned to the FragmentActivity
* by Google Play services
*/
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
// Decide what to do based on the original request code
switch (requestCode) {
case CONNECTION_FAILURE_RESOLUTION_REQUEST:
/*
* If the result code is Activity.RESULT_OK, try
* to connect again
*/
switch (resultCode) {
case Activity.RESULT_OK:
mLocationClient.connect();
break;
}
}
}
private boolean isGooglePlayServicesAvailable() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d("Location Updates", "Google Play services is available.");
return true;
} else {
// Get the error dialog from Google Play services
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog( resultCode,
this,
CONNECTION_FAILURE_RESOLUTION_REQUEST);
// If Google Play services can provide an error dialog
if (errorDialog != null) {
// Create a new DialogFragment for the error dialog
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
errorFragment.setDialog(errorDialog);
errorFragment.show(getSupportFragmentManager(), "Location Updates");
}
return false;
}
}
/*
* Called by Location Services when the request to connect the
* client finishes successfully. At this point, you can
* request the current location or start periodic updates
*/
#Override
public void onConnected(Bundle dataBundle) {
// Display the connection status
Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
Location location = mLocationClient.getLastLocation();
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 17);
map.animateCamera(cameraUpdate);
}
/*
* Called by Location Services if the connection to the
* location client drops because of an error.
*/
#Override
public void onDisconnected() {
// Display the connection status
Toast.makeText(this, "Disconnected. Please re-connect.",
Toast.LENGTH_SHORT).show();
}
/*
* Called by Location Services if the attempt to
* Location Services fails.
*/
#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 {
Toast.makeText(getApplicationContext(), "Sorry. Location services not available to you", Toast.LENGTH_LONG).show();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.nearby, menu);
return true;
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 15);
mMap.animateCamera(cameraUpdate);
locationManager.removeUpdates(this);
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onInfoWindowClick(Marker arg0) {
// TODO Auto-generated method stub
}
}
Try adding the marker in onResume(). I'm surprised you're not getting a null pointer exception on map.setMyLocationEnabled(true), because in my experience, the map in a map fragment is not instantiated until onStart. Therefore you can't add markers to it in onCreate().
First you need to get all your database values to a list: example a store list with latitude and longitude. Then you have to add each and every marker to the map in this way (below code handles the click also):
private final void addLocationsToMap() {
int i = 0;
for (Stores store : storeList) {
LatLng l = new LatLng(store.getLatitude(), store.getLongtitude());
MarkerOptions marker = new MarkerOptions()
.position(l)
.title(store.getStoreName())
.snippet("" + i)
.icon(BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
googleMap.addMarker(marker);
++i;
}
googleMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
try {
popUpWindow.setVisibility(View.VISIBLE);
Stores store = storeList.get(Integer.parseInt(marker
.getSnippet()));
// set details
email.setText(store.getEmail());
phoneNo.setText(store.getPhone());
address.setText(store.getAddress());
// setting test value to phone number
tempString = store.getPhone();
SpannableString spanString = new SpannableString(tempString);
spanString.setSpan(new UnderlineSpan(), 0,
spanString.length(), 0);
phoneNo.setText(spanString);
// setting test value to email
tempStringemail = store.getEmail();
SpannableString spanString1 = new SpannableString(tempStringemail);
spanString1.setSpan(new UnderlineSpan(), 0, spanString1.length(), 0);
email.setText(spanString1);
storeLat = store.getLatitude();
storelng = store.getLongtitude();
} catch (ArrayIndexOutOfBoundsException e) {
Log.e("ArrayIndexOutOfBoundsException", " Occured");
}
}
});
}
you should draw marker in onResume(), and you must be sure check the map != null before operate it.