Bing Maps API URL - bing

I am currently at the stage of passing a 'quadkey' to the Bing Maps API to return me the tiles, but i am getting stuck with what URL i pass this to.
Currently my code looks something like:
if (zoomLevel < 16 && zoomLevel > 13)
{
uri = new Uri("??" + qk.Key + ".png", UriKind.RelativeOrAbsolute);
}
I am wondering am i doing this correctly? I have an API key as well but were does that get used?

If you are using one of the Bing Maps controls you don't need to directly access the map tiles as they are already in the map control. Simply change the map type. Which map control are you using?

Related

Google Maps directions limit

I have an app that opens routes created by other users. In first essence, if a user does not have an app that supports .gpx files, the app will tell the user to simply get a supported app e.g. Strava.
But then it came to mind that perhaps I could merge the lattitudes and longtitudes in a Google Maps url.
String urlStart = "https://www.google.com/maps/dir/";
LocationParser locParser = new LocationParser();
List<LatLng> latLongList = await locParser.parseGPX(Uri.parse(route.file!));
latLongList.forEach((ltlng) {
urlStart += '${ltlng.latitude.toStringAsFixed(3)},${ltlng.longitude.toStringAsFixed(3)}/';
});
Uri uri = Uri.parse(urlStart);
launchUrl(uri, mode: LaunchMode.externalApplication);
as you may expect this url becomes huge and the Google Maps app is not able to handle this input. It is however able to handle the following url:
for (int i = 0; i < 50; i++) {
var ltlng = latLongList[i];
urlStart += '${ltlng.latitude.toString()},${ltlng.longitude.toString()}/';
}
Update
I figured the main issue is url-length. I only want to open Maps thus perhaps there is a way to send the directions directly to the app other than opening a maps url? If not I have to have peace with the fact I cant do it
For example, some parameters use a pipe character (|) as a separator, which you must encode as %7C in the final URL. Other parameters use comma-separated values, such as latitude/longitude coordinates or City, State. You must encode the comma as %2C. Encode spaces with %20, or replace them with a plus sign (+).
Additionally, URLs are limited to 2,048 characters for each request. Be aware of this limit when constructing your URLs.
SOURCE: Constructing valid URLs

Bing Maps throwing "Invalid Geocode" error on street intersection that it is able to get the Latitudes and Longitude from

I am currently working on a project that involves calculating Duration matrices from a collection of thousands of addresses using NEO4J and Bing Maps API. Since the data is sensitive, we're going to use the mock address (which actually produces the same issue I'm describing) '72ND & DODGE, OMAHA, NE 68132' to represent the format intersection addresses are being sent to Bing Maps API using their keys and basic url requests.
To preface this: the issue isn't with my code (which is also sensitive data), as all my code is doing is sending one url string of the above format plus the authorization key to Bing Maps and awaiting a response that contains the duration data of the trip. My issue is Bing Maps being seemingly unable to handle or work with intersections of streets to calculate distances/durations from other locations. When I throw these addresses into Bing/Google Maps in the web browser, they are able to be found and calculated in the exact same format as the above example.
I start off my program checking if an address exists/is valid by having it find the latitude and longitude of each address, so for the example '72ND & DODGE, OMAHA, NE 68132' it found: Lat: '41.259690' and Long: '-96.023770'. If it is unable to find the Lat/Long of an addresses, then it throws the 'Invalid Geocode' error, but in this initialization context it means the address does not exist, or is poorly formatted, which makes sense and is why I did this for the initialization phase.
However, if I go to use '72ND & DODGE, OMAHA, NE 68132' for any duration calculations between other addresses, it throws the 'Invalid Geocode' for '72ND & DODGE, OMAHA, NE 68132' over and over again with no explanation on why even though it passed the Lat/Long check. I'd also like to mention that this issue isn't consistent, as some intersections do not work while others do, but there is no consistency in knowing which ones will or will not work. Thus, I am ultimately wondering if Bing Maps is unable to calculate certain addresses no matter their formatting or whatnot.
Be sure to encode your query before putting it into the URL. Especially when you have & in your query since it would then break your query up, thinking you were asking just for 72ND and the rest of your query is query string parameter name. This is documented in the best practices section here.
In Java you can encode the query parameter like this:
String baseURL = "https://dev.virtualearth.net/REST/v1/Locations?key={BingMapsKey}&query=";
// query string
String query = "72ND & DODGE, OMAHA, NE 68132";
// URL encode query string
String encodeStr = URLEncoder.encode(query, StandardCharsets.UTF_8.name());
// final url
String url = baseURL + encodeStr;
Here is an example of how your query URL should look:
https://dev.virtualearth.net/REST/v1/Locations?key={BingMapsKey}&query= 72ND%20%26%20DODGE%2C%20OMAHA%2C%20NE%2068132

How to filter by dimension using Google Analytics Data API (GA4) Java client library?

I am trying to call Google Analytics Data API (GA4) using the Java client library and applying a dimension filter. This is the call which is working if I don't use the setDimensionFilter call:
RunReportRequest request =
RunReportRequest.newBuilder()
.setProperty(propertyId)
.addDimensions(com.google.analytics.data.v1beta.Dimension.newBuilder().setName("pageLocation"))
.addMetrics(com.google.analytics.data.v1beta.Metric.newBuilder().setName("screenPageViews"))
.addMetrics(com.google.analytics.data.v1beta.Metric.newBuilder().setName("activeUsers"))
// .setDimensionFilter(FilterExpression.newBuilder().setFilter(Filter.newBuilder().setStringFilter(
// Filter.StringFilter.newBuilder()
// .setMatchType(Filter.StringFilter.MatchType.FULL_REGEXP)
// .setField(Descriptors.FieldDescriptor, "pageLocation")
// .setValue("MY_REGEXP")
// .build())))
.addDateRanges(com.google.analytics.data.v1beta.DateRange.newBuilder()
.setStartDate(startDate.toStringYYYYMMDDWithDashes())
.setEndDate(endDate.toStringYYYYMMDDWithDashes()))
.setKeepEmptyRows(true)
.build();
I don't know how to use setDimensionFilter. If the usage which is commented in the previous code is correct, then the only thing missing is the call to setField. I don't know how to generate the Descriptors.FieldDescriptor instance (or even its meaning).
I have reviewed the client library javadoc, and also the code samples (which are really simple and unfortunately do not show any usage of setDimensionFilter).
The Descriptors.FieldDescriptor isn't part of the GA4 Data API and is an internal functionality of the protobuf framework
If you are trying to call this filter on a field with the name 'pageLocation' instead of using setField, I think you can do something like this
RunReportRequest request =
RunReportRequest.newBuilder()
.setProperty("properties/" + propertyId)
.addDimensions(com.google.analytics.data.v1beta.Dimension.newBuilder().setName("pageLocation"))
.addMetrics(com.google.analytics.data.v1beta.Metric.newBuilder().setName("screenPageViews"))
.addMetrics(com.google.analytics.data.v1beta.Metric.newBuilder().setName("activeUsers"))
.setDimensionFilter(FilterExpression.newBuilder()
.setFilter(Filter.newBuilder()
.setFieldName("pageLocation")
.setStringFilter(Filter.StringFilter.newBuilder()
.setMatchType(Filter.StringFilter.MatchType.FULL_REGEXP)
.setValue("MY_REGEXP"))))
.addDateRanges(com.google.analytics.data.v1beta.DateRange.newBuilder()
.setStartDate("2020-03-31")
.setEndDate("2021-03-31"))
.build();
Also, if you want an additional example of how to use setDimensionFilter, here is another code example that might help
RunReportRequest request =
RunReportRequest.newBuilder()
.setProperty("properties/" + propertyId)
.addDimensions(Dimension.newBuilder().setName("city"))
.addMetrics(Metric.newBuilder().setName("activeUsers"))
.addDateRanges(DateRange.newBuilder().setStartDate("2020-03-31").setEndDate("today"))
.setDimensionFilter(FilterExpression.newBuilder()
.setAndGroup(FilterExpressionList.newBuilder()
.addExpressions(FilterExpression.newBuilder()
.setFilter(Filter.newBuilder()
.setFieldName("platform")
.setStringFilter(Filter.StringFilter.newBuilder()
.setMatchType(Filter.StringFilter.MatchType.EXACT)
.setValue("Android"))))
.addExpressions(FilterExpression.newBuilder()
.setFilter(Filter.newBuilder()
.setFieldName("eventName")
.setStringFilter(Filter.StringFilter.newBuilder()
.setMatchType(Filter.StringFilter.MatchType.EXACT)
.setValue("in_app_purchase"))))))
.setMetricFilter(FilterExpression.newBuilder()
.setFilter(Filter.newBuilder()
.setFieldName("sessions")
.setNumericFilter(Filter.NumericFilter.newBuilder()
.setOperation(Filter.NumericFilter.Operation.GREATER_THAN)
.setValue(NumericValue.newBuilder()
.setInt64Value(1000)))))
.build();

Firebase: Authenticate an existing user using REST API and Firebases hidden Auth URL

For the past 3 years we have used HTML/Js only with Firebase but now we are using Unity as well.
The current Unity/Firebase only works on Android/iOS when deployed and 99% of our work is on the windows store.
I've actually got a pretty decent Unity/Firebase codebase going but it requires me to use a full App Secret.
All the other libraries expose a method to login with Email/Password but the REST API only allows the use of a token or your app secret that it then states is ill advised to put into your client; I guess the thinking is if you're using a different library that you'll have your own auth/user method which we don't...
Now, I've pulled apart the web version and got this:
https://auth.firebase.com/v2/<myfirebase>/auth/password?&email=dennis%40<mysite>&password=<mypassword>v=js-2.2.9&transport=json&suppress_status_codes=true
So there IS an endpoint that I can send stuff to and I've tested it inside unity with good results.
Obviously the URL isn't guaranteed to stay working but I'm wondering if there is any reason NOT to use this?
Also, Why not just expose this endpoint in the official REST API?
As I understand it, that URL will continue to work for your Legacy Firebase project. You will have to do the same sort of reverse engineering if you want to update to the new Firebase 3.0 API. However, if you are still using a legacy Firebase project -- I encourage you to take a look at this. It has not been updated to work with Firebase 3.0 -- so I needed to do something similar to what you did to allow login to the new API.
I was able to do this with the new API using C# as follows (where FirebaseManager is a Singleton I wrote for Global variables and functions to write and read from/to the DB :
Hashtable loginData = new Hashtable();
loginData.Add ("email", <EMAIL-GOES-HERE>);
loginData.Add ("password", <PASSWORD-GOES-HERE>);
loginData.Add ("returnSecureToken", true);
UnityHTTP.Request loginRequest = new UnityHTTP.Request ("post",
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key="
+ <YOUR-PROJECT-API-KEY-GOES-HERE>, loginData);
loginRequest.Send ((request) => {
Hashtable jsonResponse = (Hashtable)JSON.JsonDecode(request.response.Text);
if (jsonResponse == null) {
DisplayErrorMessage("Error logging in. Server returned null or malformed response");
}
FirebaseManager.Instance.idToken = (string)jsonResponse["idToken"]; // This is your auth token
FirebaseManager.Instance.uid = (string)jsonResponse["localId"]; // this is your "uid"
});
// I have a list of users in my db keyed by the "uid" -- I access them like this
UnityHTTP.Request fullnameRequest = new UnityHTTP.Request ("get",
<YOUR-DATABASE-ROOT-URL-HERE>
+ "/users/" + FirebaseManager.Instance.uid + ".json?auth=" + FirebaseManager.Instance.idToken);
fullnameRequest.Send ((request) => {
Debug.Log(request.response.Text);
Hashtable jsonResponse = (Hashtable)JSON.JsonDecode(request.response.Text);
if (jsonResponse == null) {
DisplayErrorMessage("Error getting user info. Server returned null or malformed response");
}
FirebaseManager.Instance.fullname = (string)jsonResponse["fullname"];
FirebaseManager.Instance.groupId = (string)jsonResponse["group"]; // just storing this in memory
});
So I don't think there is any harm in using the URL, just make sure you budget time for more work when things change.

Nokia MapImage Route REST API max. number of POIs

We are using Route REST API and we experience problem when passing many POIs to HTTP request (parameters "poixN"). Our request has about 1000 POIs and some of them are truncated (hard to count, but definitely not all are shown). Here's an example request (first line is URL, the others are parameters passed with POST):
http://maps.nlp.nokia.com/mia/1.6/route?app_code=<APP_CODE>&app_id=<APP_ID>
h=440
w=1030
poix0=52.2420610745,21.0951604874;FFFFEA00;FFFFEA00;1;.
poix1=52.2420610745,21.0952168365;FFFFEA00;FFFFEA00;1;.
poix2=52.2420610745,21.0951024308;FFFFEA00;FFFFEA00;1;.
poix3=52.2047067699,20.9944339802;FFFFEA00;FFFFEA00;1;.
...
poix940=52.1749134848,20.9056261531;FFEE7AFF;FFEE7AFF;1;.
q=100
Is there a limit for number of POIs? What about other parameters like "r"?
We use enterprise version. Thank you in advance.
Edit
Ok, after some research I know the limit for "poixN" is 99. Any way to increase the limit?
I don't think it is possible to increase the number of POIs available using the Map Image API, but it would be possible to obtain a screenshot of a more complex map using the Enterprise Maps API for JavaScript using the ContextMenu.captureHandler
You can add the captureHandler to a context menu as shown:
var contextMenu = new nokia.maps.map.component.ContextMenu();
contextMenu.addHandler(nokia.maps.map.component.ContextMenu.captureHandler);
map.components.add(contextMenu);
You can then obtain a screenshot with all your POIs, which could then be used for printing for example.The HERE Maps Community on GitHub hosts a working example specifically for printing which uses hi-res tiles from the Map Tile API as well. Note that screen capture only works on the Firefox Browser.
Since you have such a high number of POIs, I would also recommend looking at clustering to avoid overwhelming your users with too much information.