Hi,
I'm a newbie in developing ArcGIS maps. Currently, I am able to display the map. But how can I create a default location using the longitude and latitude and implement this in my code?
For example, I want to set these coordinates: (1.3002, 103.8641). When you open the map, it will automatically zoom in to those coordinates.
Thank you in advance.
This is my code:
public class HelloWorld extends Activity {
MapView mMapView = null;
ArcGISTiledMapServiceLayer tileLayer;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Retrieve the map and initial extent from XML layout
mMapView = (MapView)findViewById(R.id.map);
/* create a #ArcGISTiledMapServiceLayer */
tileLayer = new ArcGISTiledMapServiceLayer(
"http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer");
// Add tiled layer to MapView
mMapView.addLayer(tileLayer);
}
#Override
protected void onPause() {
super.onPause();
mMapView.pause();
}
#Override
protected void onResume() {
super.onResume();
mMapView.unpause();
}
}
Before adding any layers to the MapView, set its OnStatusChangedListener. Add code to the listener that projects the longitude/latitude coordinates to map coordinates and centers the map at the map coordinates.
You could do it like this:
mMapView = (MapView)findViewById(R.id.map);
final double longitude = 103.8641;
final double latitude = 1.3002;
mMapView.setOnStatusChangedListener(new OnStatusChangedListener() {
#Override
public void onStatusChanged(Object source, STATUS status) {
if (STATUS.INITIALIZED.equals(status)) {
Point mapPoint = GeometryEngine.project(longitude, latitude, mMapView.getSpatialReference());
mMapView.centerAt(mapPoint, false);
}
}
});
/* create a #ArcGISTiledMapServiceLayer */
tileLayer = new ArcGISTiledMapServiceLayer(
"http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer");
// Add tiled layer to MapView
mMapView.addLayer(tileLayer);
If you want to both center and zoom to a certain scale, you can call zoomToScale instead of centerAt.
Related
how can I get degrees from the values of the Accelerometer ? I'm useing libGDX and code in Java with Android Studio.
I ve got a sprite animation, which walks straight. The point of View is orthogonal from top, and I want to rotate the sprite when I tilt the smartphone.
How can I get the 360° degrees on the screen, for example like a compass just instead that it points to north it should point to the direction where the smartphone is tilted. How is it possible with the Accelerometer Sensor ? Or what other possibility do I have ?
Sorry for my English
A simple way of doing this is to use a SensorManager and implement SensorEventListener. The basic idea is you use the SensorManager to register the Orientation sensor and then respond to changes in the orientation of the device in the onSensorChanged delegate method implemented with SensorEventListener. Make sure you unregister the listener onPause() or else it will kill your battery.
As a high level example:
public class SensorActivity extends Activity implements SensorEventListener {
private Sensor mOrientationSensor;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SensorManager mSensorManager = (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE);
mOrientationSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
}
#Override
public void onResume() {
super.onResume();
if (mSensorManager != null) {
mSensorManager.registerListener(this, mOrientationSensor, SensorManager.SENSOR_DELAY_UI);
}
}
#Override
public void onPause() {
super.onPause();
mSensorManager.unregisterListener(this, mOrientationSensor);
}
#Override
public void onSensorChanged(SensorEvent event) {
float degree = Math.round(event.values[0]);
// do something here
}
note: The orientation sensor has been deprecated, although I still think it works best. The updated approach is below if you'd like to try that.
From the android documentation: https://developer.android.com/guide/topics/sensors/sensors_position.html#sensors-pos-orient
public class SensorActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private final float[] mAccelerometerReading = new float[3];
private final float[] mMagnetometerReading = new float[3];
private final float[] mRotationMatrix = new float[9];
private final float[] mOrientationAngles = new float[3];
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do something here if sensor accuracy changes.
// You must implement this callback in your code.
}
#Override
protected void onResume() {
super.onResume();
// Get updates from the accelerometer and magnetometer at a constant rate.
// To make batch operations more efficient and reduce power consumption,
// provide support for delaying updates to the application.
//
// In this example, the sensor reporting delay is small enough such that
// the application receives an update before the system checks the sensor
// readings again.
mSensorManager.registerListener(this, Sensor.TYPE_ACCELEROMETER,
SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
mSensorManager.registerListener(this, Sensor.TYPE_MAGNETIC_FIELD,
SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
}
#Override
protected void onPause() {
super.onPause();
// Don't receive any more updates from either sensor.
mSensorManager.unregisterListener(this);
}
// Get readings from accelerometer and magnetometer. To simplify calculations,
// consider storing these readings as unit vectors.
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor == Sensor.TYPE_ACCELEROMETER) {
System.arraycopy(event.values, 0, mAccelerometerReading,
0, mAccelerometerReading.length);
}
else if (event.sensor == Sensor.TYPE_MAGNETIC_FIELD) {
System.arraycopy(event.values, 0, mMagnetometerReading,
0, mMagnetometerReading.length);
}
}
// Compute the three orientation angles based on the most recent readings from
// the device's accelerometer and magnetometer.
public void updateOrientationAngles() {
// Update rotation matrix, which is needed to update orientation angles.
mSensorManager.getRotationMatrix(mRotationMatrix, null,
mAccelerometerReading, mMagnetometerReading);
// "mRotationMatrix" now has up-to-date information.
mSensorManager.getOrientation(mRotationMatrix, mOrientationAngles);
// "mOrientationAngles" now has up-to-date information.
}
}
In my Android application (Wheather app), I have a main activity (displaying the wheater on the screen) and a class (getting the current location of the phone).
The "Position" class gets the latitude and longitude, which I would like to send in my main activity to use them. To do that, I tried to use getters but that does not seem to work. Here is the code for both classes :
Location class: (just pay attention to the getters at the end)
public class Position extends AppCompatActivity implements LocationListener {
private double longitude;
private double latitude;
private LocationManager locationManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
return;
}
Location location = locationManager.getLastKnownLocation(locationManager.NETWORK_PROVIDER);
onLocationChanged(location);
}
#Override
public void onLocationChanged(Location location) {
longitude=location.getLongitude();
latitude=location.getLatitude();
}
public double getLongitude1() {
return this.longitude;
}
public double getLatitude1() {
return this.latitude;
}
Main_Activity: (again just pay attention to the last four lines where I i'm trying to use latitude and longitude)
public class MainActivity extends AppCompatActivity {
TextView cityField, detailsField, currentTemperatureField, humidity_field, pressure_field, weatherIcon, updatedField;
Typeface weatherFont;
Position position = new Position();
private double latitude1;
private double longitude1;
private String latitude2;
private String longitude2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_main);
weatherFont = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/weathericons-regular-webfont.ttf");
cityField = (TextView)findViewById(R.id.city_field);
updatedField = (TextView)findViewById(R.id.updated_field);
detailsField = (TextView)findViewById(R.id.details_field);
currentTemperatureField = (TextView)findViewById(R.id.current_temperature_field);
humidity_field = (TextView)findViewById(R.id.humidity_field);
pressure_field = (TextView)findViewById(R.id.pressure_field);
weatherIcon = (TextView)findViewById(R.id.weather_icon);
weatherIcon.setTypeface(weatherFont);
Function.placeIdTask asyncTask =new Function.placeIdTask(new Function.AsyncResponse() {
public void processFinish(String weather_city, String weather_description, String weather_temperature, String weather_humidity, String weather_pressure, String weather_updatedOn, String weather_iconText, String sun_rise) {
cityField.setText(weather_city);
updatedField.setText(weather_updatedOn);
detailsField.setText(weather_description);
currentTemperatureField.setText(weather_temperature);
humidity_field.setText("Humidity: "+weather_humidity);
pressure_field.setText("Pressure: "+weather_pressure);
weatherIcon.setText(Html.fromHtml(weather_iconText));
}
});
latitude1 = position.getLatitude1();
longitude1 = position.getLongitude1();
latitude2 = String.valueOf(latitude1);
longitude2 = String.valueOf(longitude1);
asyncTask.execute(latitude2, longitude2); // asyncTask.execute("Latitude", "Longitude")
}
Why do I always get latitude2 = 0.0 and longitude2 = 0.0 in my android monitor ?
You have two different activities. Not an activity and a background service. There is only a single UI thread that runs the Activities. So when MainActivity is running, the Position activity is in the background and not running. And you can't create an object of an Activity using Position position = new Position();.
Why is your Position class an Activity? The onCreate method will never be called there unless you start the class as an Activity. Remove the AppCompatActivity from it and move the onCreate method in a separate method e.g. getLocation.
You also want to pass the Context to the Position class. Create a constructor for that
public Position(Context context) {
this.context = context;
}
and use that for the system calls.
Private variables can't be shared. Change it to.
public double longitude1;
public double latitude1;
You don't really need Position extend from an Activity. I can understand what you are trying to do, you just want to get the location from LocationManager, and send the result to the MainActivity. It should be fine if you just make a LocationManager instance in your MainActivity and pass the result of the location to whatever you want inside MainActivity.
public class MainActivity extends AppCompatActivity {
TextView cityField, detailsField, currentTemperatureField, humidity_field, pressure_field, weatherIcon, updatedField;
Typeface weatherFont;
Position position = new Position();
private double latitude1;
private double longitude1;
private String latitude2;
private String longitude2;
private LocationManager mLocationManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_main);
weatherFont = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/weathericons-regular-webfont.ttf");
cityField = (TextView)findViewById(R.id.city_field);
updatedField = (TextView)findViewById(R.id.updated_field);
detailsField = (TextView)findViewById(R.id.details_field);
currentTemperatureField = (TextView)findViewById(R.id.current_temperature_field);
humidity_field = (TextView)findViewById(R.id.humidity_field);
pressure_field = (TextView)findViewById(R.id.pressure_field);
weatherIcon = (TextView)findViewById(R.id.weather_icon);
weatherIcon.setTypeface(weatherFont);
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
// do check permission staff as you post before
Location location = locationManager.getLastKnownLocation(locationManager.NETWORK_PROVIDER);
// do what you want with the location now.
Basically I think you don't have to make a Position class. You can get location directly and just use it then.
I suggest you to add following reforms to your code.
You need to create object of Position class inside onCreate() method of MainActivity. As onCreate() runs before everything else, it's necessary to have the definition of Position class inside this method.
Make your variables for longitude and latitude public to make them accessible in other class.
Position class need not to extend AppCompatActivity. Instead of using this and OnCreate() method, you can use Constructor and define all your stuff there.
This application purposed to get the distance from 2 points of coordinate. The ways is just to click in the map of the position place that you want to count the distance. But there's problem in the point's start, where the application cannot changes the position place.
this is my code:
public class MapsActivity extends FragmentActivity {
// the Google Map object
private GoogleMap mMap;
//ArrayList markerPoints;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// we set the layout for the Activity
setContentView(R.layout.activity_maps);
// the geocoder is instantiated for the first time
geocoder=new Geocoder(this);
// if there isn't a map, it will be created
setUpMapIfNeeded();
}
// LatLng objects store a pair of terrestrial coordinates (latitude and longitude)
private static LatLng STARTING_MARKER_POSITION =new LatLng(3.099465, 101.717111);
/* distanceFrom indicates the starting point to calculate the distance from.
It's initialized with STARTING_MARKER_POSITION
*/
private LatLng distanceFrom= STARTING_MARKER_POSITION;
// line will be drawn at the click event
private Polyline line=null;
// A Geocoder can transform a pair of latitude/longitude into a street address and viceversa.
// We'll use it in the listener
private static Geocoder geocoder=null;
private GoogleMap.OnMapClickListener clickListener=new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(final LatLng pos) {
// this method is called when the user taps the map
// if a line already appears, it's removed
if (line!=null)
line.remove();
// a new line is created
line = mMap.addPolyline(new PolylineOptions()
.add(distanceFrom, pos)
.width(9) // width of the line
.color(Color.BLUE)); // line color
// call the converter object for geocoding invocation and distance calculation
new AddressConverter().execute(distanceFrom, pos);
}
};
#Override
protected void onResume() {
super.onResume();
// the availability of the GoogleMap will be checked before the Activity starts interacting with the user
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
// the map is created only it has not been initialized
if (mMap == null) {
// the map is located in the layout
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
// if a map exists, we proceed with initialization
if (mMap != null) {
setUpMap();
}
}
}
// Now it's time to configure the map. We can add markers, shapes, event handlers and so on
private void setUpMap() {
// the camera will be positioned according to the new coordinates
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(STARTING_MARKER_POSITION, 14));
// we choose the type of the map: Satellite in this case
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
// markerOptions describes the marker we want to place
MarkerOptions markerOptions=new MarkerOptions()
.position(STARTING_MARKER_POSITION)
.draggable(true);
// the marker has to be draggable as we'll move it
// the marker is rendered on the map
mMap.addMarker(markerOptions);
// we define the object to invoke when the marker is dragged
mMap.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener()
{
#Override
public void onMarkerDragStart(Marker arg0)
{
// this method is called when the drag starts
// the operation we need is the cancellation of a preexisting line
if (line!=null)
line.remove();
}
#Override
public void onMarkerDragEnd(final Marker pos)
{
// we get the final position of the marker
distanceFrom=pos.getPosition();
}
#Override
public void onMarkerDrag(Marker arg0)
{
// operations performed during the movement. Nothing to do
}
});
// the callback to invoke is set
mMap.setOnMapClickListener(clickListener);
}
// we want to know which address corresponds to this location
// we use AsyncTask to perform slower operations on a separate thread
private class AddressConverter extends AsyncTask<LatLng,Void,String>
{
// The ProgressDialog window we'll show during the calculation
private ProgressDialog progress=null;
// this method is called before the background job starts. It works on the main thread
#Override
protected void onPreExecute() {
// ProgressDialog is shown
progress= ProgressDialog.show(MapsActivity.this,"Distance calculator","We are calcultating the distance...", true,false);
}
// this method works on a separate thread
// it performs geocoding operations to retrieve the address of the points and calculates the distance in meters between them
#Override
protected String doInBackground(LatLng... params) {
float[] distance=new float[1];
try {
// the Location class contains what we need to calculate distances
Location.distanceBetween(params[0].latitude,params[0].longitude,params[1].latitude,params[1].longitude,distance);
// geocoding operations
List<Address> fromResult=geocoder.getFromLocation(params[0].latitude,params[0].longitude,1);
List<Address> toResult=geocoder.getFromLocation(params[1].latitude,params[1].longitude,1);
// the message informs the user about the distance from the marker to the point selected with the click
// if we have got both the addresses, we use them to compose the message, otherwise we show only the distance
if (fromResult.size()>0 && toResult.size()>0)
{
// ((TextView) findViewById(R.id.tvDuration)).setText(route.duration.text);
return "The distance between " + getAddressDescription(fromResult.get(0)) + " and " + getAddressDescription(toResult.get(0)) + " is " + Math.round(distance[0]) + " meters";
}
else
return "The distance is " + Math.round(distance[0]) + " meters";
}
catch (IOException e) {
return "The distance is " + Math.round(distance[0]) + " meters";
}
}
#Override
protected void onPostExecute(String message)
{
if (progress!=null)
progress.dismiss();
// The builder of the window is instantiated
AlertDialog.Builder builder=new AlertDialog.Builder(MapsActivity.this);
builder.setTitle("Distance");
builder.setMessage(message);
// the Alert dialog appears
builder.show();
}
}
// this method only formats the message with addresses
private String getAddressDescription(Address a)
{
String city=a.getLocality();
String address=a.getAddressLine(0);
return "'"+address+"' ("+city+")";
}}
Use distanceBetween() method, It will give you exact distance in meters.
Location.distanceBetween(double startLatitude, double startLongitude,
double endLatitude, double endLongitude, float[] results);
I want to get true and magnetic heading of compass in android.
I have read many tutorials but not give my required output.
It gives just heading.
My code is here...
public class MainActivity extends Activity implements SensorEventListener {
// device sensor manager
private SensorManager mSensorManager;
TextView tvHeading;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// TextView that will tell the user what degree is he heading
tvHeading = (TextView) findViewById(R.id.tvHeading);
// initialize your android device sensor capabilities
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
}
#Override
protected void onResume() {
super.onResume();
// for the system's orientation sensor registered listeners
mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_GAME);
}
#Override
protected void onPause() {
super.onPause();
// to stop the listener and save battery
mSensorManager.unregisterListener(this);
}
#Override
public void onSensorChanged(SensorEvent event) {
// get the angle around the z-axis rotated
float degree = Math.round(event.values[0]);
tvHeading.setText("Heading: " + Float.toString(degree) + " degrees");
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// not in use
}
}
This code give accurate value for a compass.
How can i modify this code for getting magnetic heading and true heading?
what is missing here?
Any one can help me.
Thanks
i am really stuck on this:
I have longitude / latitude points to draw on a google map within an android app.
Therefor I created a class extending Overlay...
I get the current longitude/latitude portion of view via:
GeoPoint topLeft = proj.fromPixels(0, 0);
GeoPoint bottomRight = proj.fromPixels(width-1, height-1);
int topLat = topLeft.getLatitudeE6();
int topLon = topLeft.getLongitudeE6();
int bottomLat = bottomRight.getLatitudeE6();
int bottomLon = bottomRight.getLongitudeE6();
The following works (only latitudes):
if(latLon[0] >= bottomLat && latLon[0] <= topLat){ // do something; }
but this does not work (longitudes):
if(latLon[1] >= topLon && latLon[1] <= bottomLon) { // do something; }
latLon[0] is the latitude I want to check
latLon[1] is the longitude I want to check
Anybody an idea?
Greetz!
Longitude numbers are negative from the 0 meridian in England, westward. They're negative in North America and South America.
Use a google map and insert your marker on it.
See below :
public class MapActivity extends GeolocationActivity implements GoogleMap.OnInfoWindowClickListener{
private final String TAG = "MapFragment";
private MapView _mapView;
private GoogleMap _gmap;
/**
* the logo of the marker on the map
*/
private Bitmap _littlePin;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map);
_mapView = (MapView) findViewById(R.id.location_map);
_mapView.onCreate(savedInstanceState);
_gmap = _mapView.getMap(); // initalise the map
if (_gmap != null)
{
setUpMap();
}
}
/**
* set up the map; Add the market on it with a blue dot for the location of the user in real time
* #return false if something goes wrong, true otherwise
* _latitude = latitude of the user, get from the GeolocationActivity
* _longitude = longitude of the user, get from the GeolocationActivity
*/
private boolean setUpMap()
{
// Gets to GoogleMap from the MapView and does initialization stuff
_gmap.getUiSettings().setMyLocationButtonEnabled(false);
_gmap.setMyLocationEnabled(true);
if (_gmap == null) {
Toast.makeText(this, "Google Maps not available", Toast.LENGTH_LONG).show();
return false;
}
// Needs to call MapsInitializer before doing any CameraUpdateFactory calls
MapsInitializer.initialize(this);
BitmapDrawable bitmapDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.pin); // file stored in /res/drawable/
Bitmap bitmap = bitmapDrawable.getBitmap();
_littlePin = Bitmap.createScaledBitmap(bitmap, 96, 96, false); // 96/96px
_gmap.setOnInfoWindowClickListener(this);// add listener on this class
// here the _lat and _long should be the user of this cafe, at the moment I am using the one of the user
this.addMarker("Cafe", "Best cafe in London", new LatLng(_latitude, _longitude));
// camera, 13 if the zoon, you can change it manually, or dynamically in order to see all your markers
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(_latitude, _longitude), 13);
_gmap.animateCamera(cameraUpdate); // zoom effect
return true;
}
/**
* Add markers on the map view
* #param title title of place / marker
* #param description short description
* #param position geposition, LatLng object, filled with latitude and longitude.
*/
private void addMarker(String title, String description, LatLng position)
{
_gmap.addMarker(new MarkerOptions()
.position(position)
.title(title)
.snippet(description)
.icon(BitmapDescriptorFactory.fromBitmap(_littlePin)));
}
/**
* The user click on the marker on the map, this callback is called
* #param marker clicked marker
*/
#Override
public void onInfoWindowClick(Marker marker) {
Log.d(TAG, "onMarkerClick " + marker.getTitle());
}
#Override
public void onResume() {
_mapView.onResume();
super.onResume();
}
#Override
public void onDestroy() {
super.onDestroy();
_mapView.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
_mapView.onLowMemory();
}
}
Here is a good example which gonna help you.
and the github with the code sample is here.
Hope this help.