Attempting to use GetAddressesForPositionAsync() in order to find the list of possible addresses that my coordinates can point too. I call the map using esri ArcGIS mapping and add it to a mapview
Esri.ArcGISRuntime.Mapping.Map myMap = new Esri.ArcGISRuntime.Mapping.Map(SpatialReference.Create(4326));
myMapView = new Esri.ArcGISRuntime.Xamarin.Forms.MapView();
geoCoder = new Geocoder();
//assign the map to a mapview
myMapView.Map = myMap;
then use an event handler to wait for the user to double tap the screen.
//event handler
myMapView.GeoViewDoubleTapped += new EventHandler<Esri.ArcGISRuntime.Xamarin.Forms.GeoViewInputEventArgs>(geotappedMap);
//the location for the pin and sent to geothings()
double Lat = ((((Esri.ArcGISRuntime.Xamarin.Forms.GeoViewInputEventArgs)e).Location.X));
double Lng = ((((Esri.ArcGISRuntime.Xamarin.Forms.GeoViewInputEventArgs)e).Location.Y));
myLocation = new MapPoint(Lat, Lng);
The program places a marker there and then uses the coordinates of where the tap was to call get position.
public async void geothings(Object sender, EventArgs e, Position p)
{
try
{
var possibleAddresses = await geoCoder.GetAddressesForPositionAsync(p);
foreach (var address in possibleAddresses)
_label2.Text += "\n\n" + address;
}
catch (Exception ex)
{
await MainPage.DisplayAlert("Error Getting Address", ex.Message, "Close");
}
}
the function runs without a problem except the label is updated with the value 'Antarctica' after being called. Does anyone know why or how this is happening?
Related
API call is triggered by a button press, this button calls AnchoredMapMarkers which should display lat/long pins on the pre-loaded map
Returns print('step5.1_APICALL'); okay after async
Error shows as type 'Future<Stations>' is not a subtype of type 'Iterable<dynamic>'
Any help is greatly appreciated
The API calls and displays in list form fine - I am now trying to extract the lat/long from the Json and plot it on my map SDK
class MapMarkerExample{
void showAnchoredMapMarkers() {
var stations;
stations = fetchStations();
for (Station stations in stations) {
GeoCoordinates geoCoordinates = GeoCoordinates (stations.place.location.lat, stations.place.location.lng);
_addCircleMapMarker(geoCoordinates, 0);
_addPOIMapMarker(geoCoordinates, 1);
}
}
Future<Stations> fetchStations() async {
print('step5.1_APICALL');
var client = http.Client();
final response = await client.get(
'https://transit.hereapi.com/v8/stations?in=lat,-long&return=transport&apiKey=API_KEY');
if (response.statusCode == 200) {
return Stations.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to load stations');
}
}
You are not awaiting your future. And to make it extra complicated for the compiler, you somehow split declaration and assignment. And reused a variable name.
Fix:
Future<void> showAnchoredMapMarkers() async {
final stations = await fetchStations();
for (Station station in stations) {
...
you need await
Future<void> showAnchoredMapMarkers() async {
var stations = await fetchStations();
for (Station stations in stations) {
GeoCoordinates geoCoordinates = GeoCoordinates (stations.place.location.lat, stations.place.location.lng);
_addCircleMapMarker(geoCoordinates, 0);
_addPOIMapMarker(geoCoordinates, 1);
}
}
This is my code,
I am trying to add a bookmark to google maps, and also to initialize the map in a specific place, but I can not understand how SupporMapFragment works, if someone could help me explaining how to do it, thanks
internal class DetailMapFragment : BaseFragment , IOnMapReadyCallback
{
private GoogleMap GoogleMap;
private SupportMapFragment _mapFragment;
public override int LayoutId => Resource.Layout.map_page;
protected override void InitViews()
{
//var mapView = mView.FindViewById<MapView>(Resource.Id.mapView);
//mapView.GetMapAsync(this);
try
{
_mapFragment = Activity.SupportFragmentManager.FindFragmentByTag("map") as SupportMapFragment;
if (_mapFragment == null)
{
GoogleMapOptions mapOptions = new GoogleMapOptions()
.InvokeMapType(GoogleMap.MapTypeNormal)
.InvokeZoomControlsEnabled(false)
.InvokeMaxZoomPreference(20)
.InvokeCompassEnabled(true);
FragmentTransaction fragTx = FragmentManager.BeginTransaction();
_mapFragment = SupportMapFragment.NewInstance(mapOptions);
fragTx.Add(Resource.Id.mapView, _mapFragment, "map");
fragTx.Commit();
LatLng latlong = new LatLng(40.776408,-73.970755);
MarkerOptions mark = new MarkerOptions()
.SetPosition(latlong)
.SetTitle("New York")
.SetSnippet("Apple");
_mapFragment.AddMarker(mark);
}
_mapFragment.GetMapAsync(this);
}
catch (System.Exception ex)
{
ex.Message.ToString();
}
public void OnMapReady(GoogleMap googleMap)
{
//this.GoogleMap = googleMap;
}
void IOnMapReadyCallback.OnMapReady(GoogleMap googleMap)
{
//try
//{
// this.GoogleMap = googleMap;
// if (googleMap != null)
// {
// googleMap.AnimateCamera(CameraUpdateFactory.NewLatLng(new LatLng(-11.083271, -76.207374)));
// }
//}
//catch (System.Exception ex)
//{
// ex.Message.ToString();
//}
}
}
i new in xamarin android, i cant achieved understand how add de marker to map
Its very easy actually all you have to do is the following:
In your variable of type, Google maps in your case this private GoogleMap GoogleMap;you need to add the markers
Now adding markers can be tricky as you need to add them not when your google map object is null and this object gets its value runtime, so you need to be sure that it's not null because if it is then your app will crash for sure
(If not handled).
What i do for this case is always null check before adding a marker, and since it is bitmap(Which is the main reason for a thousand types of memory leaks in Android usually),On destroy of my map fragment i call the garbage collector and i clear my google maps object by calling GoogleMap.Clear(); whenever i leave the maps page.
Coming to the point the code for adding markers is as follows:
LatLng latlngall = new LatLng(double.Parse(point.Latitude), double.Parse(point.Loungitude));
MarkerOptions options = new MarkerOptions().SetPosition(latlngall).SetTitle(point.Landmark);
options.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.marker));
Marker marker = GMap.AddMarker(options);
marker.Tag = point.Id.ToString();
Here you need latitude, longitude and a title for your marker, also if you want to provide your custom marker then you can put it in place of the Drawable.marker also lat and long are mandatory here.
In case you have any other problems revert here.
Goodluck!
Happy coding
I have a specific requirement that i want to collect all the tweets according to the following parameters
1) Im using search API , for example i want to search for "Iphone6"
2) Region wise , ie if i specify the latitude and longitude as per city I get the results, is it possible to fetch all the results country wise( as in the code when i specity the latitude and longitude of india
it doesnt work !)
3) At what intervals should I run my application , so that I get the newly updated tweets , without getting the previously fetched tweets.
This is the code that I have written
public final class twitterdate {
public static void main(String[] args)throws Exception {
double res;
double lat,lon;
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setOAuthConsumerKey("MyKEY")
.setOAuthConsumerSecret("MySecret")
.setOAuthAccessToken("MyAccesstoken")
.setOAuthAccessTokenSecret("MyTokenSecret").setHttpConnectionTimeout(100000);
TwitterFactory tf = new TwitterFactory(cb.build());
Twitter twitter = tf.getInstance();
lat=18.9750; // THis works , but it doenst work when I specify latitude and longitude of India
lon=72.8258;
res=1;
try {
QueryResult result=twitter.search(new Query("iphone").since("2014-11-19").until("2014-11-22").geoCode(new GeoLocation(lat, lon), res,"1mi"));
// Since and untill doesnt work as expected sometimes it fetches the date tweets specified on "since" method sometimes fetches the tweets specified on the date of until method
// Also since and until doesnt work when i specify a time stamp.
List<Status> qrTweets = result.getTweets();
System.out.println("hi");
for (Status tweet : qrTweets )
{
System.out.println( tweet.getId() + " " + "#" + tweet.getUser().getScreenName() + " : " + tweet.getText() + " :::" + tweet.getCreatedAt() );
}
} catch (TwitterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I would be greatful if somebody can help me with the requirement that I have as I have googled a lot but couldnt find any proper solution.
Thanks in advance !
Have you tried using FilterQuery? The code snippet below would give you a continuous stream of tweets.
As per my understanding you want to fetch tweets from India with content related to iphone6.
With Search query you may end up getting same set of tweets over and again.
You can try something like this below, I am not sure what co-ordinates you have used to fetch tweets from India !, you have to do some trial and error and fine tune the co-ordinates you want to locate your tweets around.
StatusListener listener = new StatusListener(){
public void onStatus(Status status) {
//if (status.getText().contains)
if(status.getUser().getLang().equalsIgnoreCase("en")
|| status.getUser().getLang().equalsIgnoreCase("en_US")) {
System.out.println(status.getUser().getName() + " :: " + status.getText() + " :: " + status.getGeoLocation());
}
}
public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {}
public void onTrackLimitationNotice(int numberOfLimitedStatuses) {}
public void onException(Exception ex) {
ex.printStackTrace();
}
public void onScrubGeo(long arg0, long arg1) {
}
public void onStallWarning(StallWarning arg0) {
}
};
ConfigurationBuilder config = new ConfigurationBuilder();
config.setOAuthConsumerKey("");
config.setOAuthConsumerSecret("");
config.setOAuthAccessToken("");
config.setOAuthAccessTokenSecret("");
TwitterStream twitterStream = new TwitterStreamFactory(config.build()).getInstance();
twitterStream.addListener(listener);
FilterQuery query = new FilterQuery();
// New Delhi India
double lat = 28.6;
double lon = 77.2;
double lon1 = lon - .5;
double lon2 = lon + .5;
double lat1 = lat - .5;
double lat2 = lat + .5;
double box[][] = {{lon1, lat1}, {lon2, lat2}};
query.locations(box);
String[] trackArray = {"iphone"};
query.track(trackArray);
twitterStream.filter(query);
There is however one caveat with FilterQuery that it uses location OR trackList for fetching data. To counter this may be you can put a content filter logic in onStatus() method.
Hope this helps you.
I am working on a BlackBerry Application that is supposed to update the location at fixed intervals. The interval value can be selected/changed from a slider. It varies between 1 minute, 2 minutes, 5 minutes, 30 minutes etc. On the very first load (Start App), location interval is 30 seconds. After this, I store the slider value in a persistent store and location is updated accordingly with the set interval. Background thread running to update location is as follows:
private boolean startLocationUpdate()
{
boolean retval = false;
try
{
LocationProvider locationProvider = LocationProvider.getInstance(null);
if ( locationProvider == null )
{
Runnable showGpsUnsupportedDialog = new Runnable()
{
public void run()
{
Dialog.alert("GPS is not supported on this platform, exiting...");
//System.exit( 1 );
}
};
UiApplication.getUiApplication().invokeAndWait( showGpsUnsupportedDialog ); // Ask event-dispatcher thread to display dialog ASAP.
}
else
{
locationProvider.setLocationListener(new LocationListenerImpl(), interval, -1, -1);
retval = true;
}
}
catch (LocationException le)
{
System.err.println("Failed to instantiate the LocationProvider object, exiting...");
System.err.println(le);
System.exit(0);
}
return retval;
}
private class LocationListenerImpl implements LocationListener
{
public void locationUpdated(LocationProvider provider, Location location)
{
if(location.isValid())
{
double longitude = location.getQualifiedCoordinates().getLongitude();
double latitude = location.getQualifiedCoordinates().getLatitude();
updateLocationScreen(latitude, longitude);
}
}
public void providerStateChanged(LocationProvider provider, int newState)
{
}
}
private void updateLocationScreen(final double latitude, final double longitude)
{
UiApplication.getUiApplication().invokeAndWait(new Runnable()
{
public void run()
{
double lat = latitude;
double longi = longitude;
lblLatitude.setText(Double.toString(lat));
spacing.setText(", ");
lblLongitude.setText(Double.toString(longi));
}
});
}
Along with this, there is a "Refresh" button available that will start acquiring a location update immediately once clicked. This button calls a method is another class to acquire the location. The method is as follows:
try {
Criteria myCriteria = new Criteria();
myCriteria.setCostAllowed(false);
LocationProvider myLocationProvider = LocationProvider.getInstance(myCriteria);
double heading = 0;
double velocity = 0;
try {
Location myLocation = myLocationProvider.getLocation(6000);
if(myLocation.isValid())
{
double longitude = myLocation.getQualifiedCoordinates().getLongitude();
double latitude = myLocation.getQualifiedCoordinates().getLatitude();
}
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
//Dialog.alert("Location Updated");
}
});
setLocation(myLocation.getQualifiedCoordinates(),velocity,heading);
} catch ( InterruptedException iex ) {
System.out.println(iex.getMessage());
} catch ( LocationException lex ) {
System.out.println(lex.getMessage());
}
} catch ( LocationException lex ) {
System.out.println(lex.getMessage());
}
Problems I am facing:
1) Interval value not changing. I am implementing the change by picking the value from the persistent store as:
if (PersistentStoreHelper.persistentHashtable.containsKey("gpsInterval"))
{
String intervalValue=((String) PersistentStoreHelper.persistentHashtable.get("gpsInterval"));
MyScreen.interval=Integer.parseInt(intervalValue);
}
This is never empty as navigation to this page inserts a value of 30 minutes to it.
2) Once the "Refresh" button is clicked, the background thread seems to be cancelled. It no longer runs at any interval value.
I read that there is only one instance of the location provider created and with "Refresh" it is cancelled after acquiring the location and thus the background thread stops. Is this true? If yes, how can I achieve my desired result.
EDIT: The gpsInterval value is read as follows:
if (PersistentStoreHelper.persistentHashtable.containsKey("gpsInterval"))
{
String intervalValue=((String)PersistentStoreHelper.persistentHashtable.get("gpsInterval"));
interval=Integer.parseInt(intervalValue);
}
else
{
interval=10;
}
Saving the Interval
So, first of all, make sure that when you let the user change the update interval, via the slider, you properly save it to the PersistentStore. The code should look something like this:
// NOTE: I would recommend persisting the slider value as an Integer, not a String,
// but, the original code used String, so that's what this uses
hashtable.put("gpsInterval", (new Integer(intervalSlider.getValue())).toString());
PersistentObject po = PersistentStore.getPersistentObject(APP_BUNDLE_ID);
po.setContents(hashtable);
po.commit();
Since you didn't post that code, I just wanted to be sure that it was being saved to the persistent store correctly.
Updating the Location Provider / Listener
The other issue, that is a problem, is that you kick off the location updates in startLocationUpdate() with this code:
locationProvider.setLocationListener(new LocationListenerImpl(), interval, -1, -1);
That uses the value of the interval variable at the instant that setLocationListener() is called. If you later update the interval variable,
String intervalValue=((String) PersistentStoreHelper.persistentHashtable.get("gpsInterval"));
MyScreen.interval=Integer.parseInt(intervalValue);
this will have no effect on the location listener. It will keep updating with the original interval value, not the new one. You would have to call setLocationListener() again, with the new value of interval. With your code, you should probably just call startLocationUpdate() again:
String intervalValue=((String) PersistentStoreHelper.persistentHashtable.get("gpsInterval"));
MyScreen.interval=Integer.parseInt(intervalValue);
startLocationUpdate();
Refresh Problem
I'm not 100% sure, but my guess would be that in your existing code that's used when the Refresh button is pressed, you are changing to a different LocationProvider with different criteria. That's probably why the first one is cancelled.
Try changing your startLocationUpdate() method to save the provider as a member variable:
/** this is the one location provider used by this class! */
private LocationProvider _locationProvider;
private boolean startLocationUpdate()
{
boolean retval = false;
try
{
_locationProvider = LocationProvider.getInstance(null);
then, in your refresh code, use the same location provider to get the current location:
double heading = 0;
double velocity = 0;
try {
Location myLocation = _locationProvider.getLocation(6000);
if(myLocation.isValid())
Note: if you really do want to setCostAllowed(false), that's fine. Do that the first time that you assign the _locationProvider member variable. And use that provider/criteria both for normal periodic location updates, and your Refresh button handler. I think the key is to use the same provider, not create a new one with different criteria.
What I want to do is have the a map open with the click of a buttonfield with two Criterias, the user must either specify the location and then the image must be added to the location otherwise the Image must be added to the users current location.
The problem I am having is adding both criterias into an if statement in a thread / new thread or even in a FieldChangeListener.
The error I keep getting is:
Error in location :javax.microedition.location.LocationException:
getLocation() method cannot be cal[0.0] led from event thread [0.0]
Error in location :getLocation() method cannot be called from event
thread
My code:
FieldChangeListener Listener = new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
ButtonField buttonClicked = (ButtonField) field;
if ((buttonClicked.getLabel()).equals("Push")) {
CustomMapField mMapField;
Coordinates mCoordinates;
BlackBerryCriteria blackBerryCriteria = null;
BlackBerryLocation blackBerryLocation = null;
BlackBerryLocationProvider blackBerryLocationProvider = null;
double Doublelat = 0.0;
double Doublelng = 0.0;
blackBerryCriteria = new BlackBerryCriteria();
if(GPSInfo.isGPSModeAvailable(GPSInfo.GPS_MODE_CELLSITE)){
blackBerryCriteria.setMode(GPSInfo.GPS_MODE_CELLSITE);
}else if(GPSInfo.isGPSModeAvailable(GPSInfo.GPS_MODE_ASSIST)){
blackBerryCriteria.setMode(GPSInfo.GPS_MODE_ASSIST);
}else if(GPSInfo.isGPSModeAvailable(GPSInfo.GPS_MODE_AUTONOMOUS)){
blackBerryCriteria.setMode(GPSInfo.GPS_MODE_AUTONOMOUS);
}else{
blackBerryCriteria.setCostAllowed(true);
blackBerryCriteria.setPreferredPowerConsumption(Criteria.POWER_USAGE_LOW);
} try {
blackBerryLocationProvider = (BlackBerryLocationProvider) BlackBerryLocationProvider.getInstance(blackBerryCriteria);
blackBerryLocation = (BlackBerryLocation) blackBerryLocationProvider.getLocation(60);
QualifiedCoordinates qualifiedCoordinates = blackBerryLocation.getQualifiedCoordinates();
Doublelat = qualifiedCoordinates.getLatitude();
Doublelng = qualifiedCoordinates.getLongitude();
mCoordinates = new Coordinates(Doublelat, Doublelng, 0);
mMapField = new CustomMapField();
mMapField.mIcon = Bitmap.getBitmapResource("coin_silver.png");
mMapField.moveTo(mCoordinates);
mMapField.setZoom(1);
add(mMapField);
}catch(Exception e){
System.out.println("Debug 5");
System.out.println("Error in location :"+e.toString());
System.out.println("Error in location :"+e.getMessage());
}
}
}
};
public class CustomMapField extends MapField {
Bitmap mIcon;
XYRect mDest;
public void moveTo(Coordinates coordinates) {
super.moveTo(coordinates);
mDest = null;
}
protected void paint(Graphics graphics) {
super.paint(graphics);
if (null != mIcon) {
if (null == mDest) {
XYPoint fieldOut = new XYPoint();
convertWorldToField(getCoordinates(), fieldOut);
int imgW = mIcon.getWidth();
int imgH = mIcon.getHeight();
mDest = new XYRect(fieldOut.x - imgW / 2,
fieldOut.y - imgH, imgW, imgH);
}
graphics.drawBitmap(mDest, mIcon, 0, 0);
}
}
}
The error Is with the following line add(mMapField);
Doublelat = qualifiedCoordinates.getLatitude();
Doublelng = qualifiedCoordinates.getLongitude();
mCoordinates = new Coordinates(Doublelat, Doublelng, 0);
mMapField = new CustomMapField();
mMapField.mIcon=Bitmap.getBitmapResource("coin_silver.png");
mMapField.moveTo(mCoordinates);
mMapField.setZoom(1);
add(mMapField);
/*MapView mapView = new MapView();
mapView.setLatitude(finalintlat);
mapView.setLongitude(finalintlng);
mapView.setZoom(10);
MapsArguments mapsArgs = new MapsArguments(mapView);
Invoke.invokeApplication(Invoke.APP_TYPE_MAPS, mapsArgs);
Please advise me more in detail how to do so, and please give an example; I can't understand how as "mMapField" is a custom MapField and "mapView" is a class Mapview (please see my code snippet above).
Obtaining a location is a time-consuming task, it can take as much as 1 minute even with good satellite visibility, although newer berries have improved a lot the time-to-first-fix (TTFF).
Time consuming tasks, like opening connections, or obtaining a fix, should not be performed in the event thread, because this thread has to respond to user events, and if you hog it, then the GUI frozens. And everything running inside fieldChanged runs in the event thread. So it is a good thing RIM implemented a thread detection in its new BlackBerryLocationProvider and throws exceptions, now you are aware of the bad design and can take corrective measures.
You have several options to get a fix asynchronously:
Use LocationListener.
Spawn a new thread.
Preemtively obtain a fix long before you need it (or at regular intervals), then you'll have it quickly available when the button is pressed, (either retrieving it from somewhere you previously saved it or calling LocationProvider.getLastKnownLocation).
You should use Invoke.invokeApplication(Invoke.APP_TYPE_MAPS, new MapsArguments(mMapField)); in place of add(mMapField);