Gluon Maps doesn't load the map and throws an exception - android

When using Gluon Maps on android the actual map doesn't get loaded. Instead the empty white space is shown, and I can see this in logs:
05-31 14:20:34.041 E/CachedOsmTileRetriever(18834): null
05-31 14:20:34.041 E/CachedOsmTileRetriever(18834): java.io.FileNotFoundException: http://tile.openstreetmap.org/16/33497/22228.png
05-31 14:20:34.041 E/CachedOsmTileRetriever(18834): at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:251)
05-31 14:20:34.041 E/CachedOsmTileRetriever(18834): at com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever$CacheThread.doCache(CachedOsmTileRetriever.java:189)
05-31 14:20:34.041 E/CachedOsmTileRetriever(18834): at com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever$CacheThread.run(CachedOsmTileRetriever.java:157)
The code itself is trivial:
private void showMap(Double lat, Double lon) {
mapView = new MapView();
PoiLayer poiLayer = new PoiLayer();
MapPoint mapPoint = new MapPoint(lat, lon);
poiLayer.addPoint(mapPoint, new Circle(7, Color.RED));
mapView.setZoom(16);
mapView.addLayer(poiLayer);
mapView.flyTo(0.1, mapPoint, 0.1);
tabMap.setContent(mapView);
}
The same code works just fine on iOS: the map is loaded as expected.
Using
compile 'com.gluonhq:maps:1.0.2'
in build.gradle (same thing with 1.0.3)
Note, that if I enter the URL (from the exception mentioned above) in browser, I get redirected to https:
http://tile.openstreetmap.org/16/33497/22228.png
to
https://tile.openstreetmap.org/16/33497/22228.png
Any ideas why the exception on android?

It looks like something has changed recently from the OpenStreetMaps servers. Gluon Maps fails on desktop as well.
I've tested with http, and I get the reported 403 error:
java.io.IOException: Server returned HTTP response code: 403 for URL: http://tile.openstreetmap.org/5/19/10.png
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1913)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1509)
at com.gluonhq.maps/com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever$CacheThread.doCache(CachedOsmTileRetriever.java:190)
at com.gluonhq.maps/com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever$CacheThread.run(CachedOsmTileRetriever.java:157)
and also with https, and now I get a different error:
java.io.IOException: Server returned HTTP response code: 429 for URL: https://tile.openstreetmap.org/6/37/22.png
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1913)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1509)
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:245)
at com.gluonhq.maps/com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever$CacheThread.doCache(CachedOsmTileRetriever.java:190)
at com.gluonhq.maps/com.gluonhq.impl.maps.tile.osm.CachedOsmTileRetriever$CacheThread.run(CachedOsmTileRetriever.java:157)
In both cases (http or https), the URL works fine on a browser, which might suggest the need of adding "User-agent" to the URLConnection request.
Initially this seemed to solve the issue, as there were no more http errors. However the tiles were blank.
Finally, the solution that fully worked for me, at least on desktop, was this one:
static {
System.setProperty("http.agent", "Gluon Mobile/1.0.3");
}
Since this is a system property, it can be added to the project that uses Gluon Maps, so it can be tested before a new release is done to solve this issue.
Android
On Android it looks like you need to set a valid agent.
Again, this is far from a solution, but it is a quick fix.
Add to your project, and deploy to your Android device:
static {
String userAgent = System.getProperty("http.agent");
System.out.println("HTTP.AGENT: " + userAgent);
System.setProperty("http.agent", userAgent);
}
With your device plugged, open a terminal, go to the Android SDK folder, and type:
cd platform-tools
adb logcat -v threadtime
And now launch the application and see the console for the output.
In my case, I see:
06-10 09:57:40.784 32630 32656 I System.out: HTTP.AGENT: Dalvik/2.1.0 (Linux; U; Android 9; Pixel XL Build/PQ3A.190505.001)
which means Android provides a valid agent, but somehow it has to be explicitly set.
Now the tiles are downloaded.
However, once this is working, I can remove this static block from my app, and install it again fresh. And the tiles are downloaded as well. It looks like it has to be done only once. Maybe the OSM servers include that agent/device/app bundle/IP in a whitelist, but this is just a pure speculation.
iOS
As mentioned, on iOS it works just fine, even if user.agent returns null.
EDIT
Finally, a proper solution can be this:
static {
String httpAgent = System.getProperty("http.agent");
if (httpAgent == null) {
httpAgent = "(" + System.getProperty("os.name") + " / " + System.getProperty("os.version") + " / " + System.getProperty("os.arch") + ")";
}
System.setProperty("http.agent", "Gluon Mobile/1.0.3 " + httpAgent);
}

Related

UnityWebRequest.SendWebRequest doens't send on mobile

I am downloading Assetbundles using the UnitywebRequest method from HTTPS, however the UnityWebRequest.SendWebRequest seems to take its sweet time to actually start receiving any data.
public static IEnumerator DownloadMenuAssetBundle(string fileName)
{
string path = Path.Combine(Globals.Platform, fileName);
UnityWebRequest www = new UnityWebRequest(FileManager.RequestFile(path));//this returns the complete url to the bundle e.g https://mywebsite.com/unity/myBundle
www.downloadHandler = new DownloadHandlerBuffer();
www.SendWebRequest();
while (!www.isDone)
{
Debug.Log("response: " + www.responseCode);
if (www.isNetworkError)
{
Debug.Log(www.error);
}
Debug.Log("downloaded:" + www.downloadedBytes);
yield return null;
}
Debug.Log("downloaded bytes: " + www.downloadedBytes);
Debug.Log("final response:" + www.responseCode);
if (www.error != null)
{
Debug.LogError("Encountered error while downloading: <color=blue>" + fileName + "</color>: " + www.error);
}
else
{
//rest of the logic, this works
}
Debug.Log("response: " + www.downloadedBytes); will return 0 for a random amount of time (ranging from a few to up to a couple minutes at times). But www. isNetworkError is never hit, and once bytes do start to be received it'll download the entire thing in a couple of miliseconds.
Previously i was using the exact same script on a http server and it worked flawlessly without any delays, but once i switched over to https it started taking a while. The delay also does not happen in the editor (Unity version 2017.2.1f1 runtime version .net 3.5 with 2.0 subset api compability) but happens on all my mobile devices (Oneplus 3, samsung galaxy s8, samsung galaxy s6).
At first www.responseCode returned a 301 Moved Permanently, i resolved this by using the new https url instead of the http url hoping this would fix it. However it didn't and now i only get 200 OK.
It is also an inconsistent issue because the timing it takes isn't ever the same, neither does it even happen all the time (but does most of the time)
Can this be an issue by the security layer taking additional time or the server taking its time to respond? if this is the issue how would i be able to track this down (though i doubt this as it works well in the editor)?
EDIT: workaround
I got around the issue by using a WWW class instead of UnityWebRequest. the delay is completely gone now but no SSL certificate validation is being done as Unity seems to deny them by default. I wouldn't really call it a fix but works for now.
Always trouble with UnityWebRequest - sometimes nothing makes sense with UnityWebRequests...
You can try to replace
UnityWebRequest www = new UnityWebRequest(FileManager.RequestFile(path));
with
UnityWebRequest www = new UnityWebRequestAssetBundle(FileManager.RequestFile(path), 0);
Optional for testing:
Also I think your while loop is not "save" to catch the network error.
I would prefer the following like mentioned in the documentation
UnityWebRequest www = new UnityWebRequestAssetBundle(FileManager.RequestFile(path);
yield return www.SendWebRequest();
if (request.isNetworkError || request.isHttpError)
{
Debug.Log(www.error.ToString());
}
else
{
// for testing only // if yield return www.SendWebRequest(); is working as expected www.isDone = true here!
while (!www.isDone)
{
Debug.Log("Something is wrong! " + www.responseCode);
yield return new WaitForSeconds(0.1f);
}
// do whatever you want
}
Hope this helps.

Meteor Mobile Server on Heroku - No Access-Control-Allow-Origin header is present

Let me start by saying I've found several proposed solutions online, but none of them seem to work for me.
Issue:
I have a meteor app I'm trying to run on android. For this, I've deployed the app on Heroku and I call the run android-device command using the --mobile-server https://myapp.heroku.com parameter.
I permanently receive the error
"XMLHttpRequest cannot load https://myapp.heroku.com/sockjs/... . No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:12848' is therefore not allowed access. The response had HTTP status code 404.", source: http://localhost:12848/ (0)
Here is what I've tried so far:
I set ROOT URL at meteor startup:
process.env.ROOT_URL = "https://myapp.heroku.com";
I tried setting the Access Control like this, server-side at meteor startup:
WebApp.connectHandlers.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, OPTIONS');
res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
res.header('Access-Control-Allow-Origin', 'https://myapp.heroku.com');
res.header('Access-Control-Allow-Origin', 'http://localhost:12848');
res.header('Access-Control-Allow-Origin', 'http://meteor.local');
res.header("Access-Control-Allow-Headers", "Content-type,Accept,X-Custom-Header");
return next();
});
I tried to use the browser-policy package, like this, server-side at meteor startup:
BrowserPolicy.content.allowSameOriginForAll();
BrowserPolicy.content.allowOriginForAll('*');
BrowserPolicy.content.allowOriginForAll('http://meteor.local');
BrowserPolicy.content.allowOriginForAll('https://myapp.heroku.com');
BrowserPolicy.content.allowOriginForAll('https://*.myapp.heroku.com');
BrowserPolicy.content.allowEval();
I tried adding access rules to "mobile-config.js":
App.accessRule("*");
I made sure the name in the "package.json" file under root is identical to the App name under "mobile-config.js"
What else am I missing?
Edit:
I've also tried adding the express and cors packages to whitelist local host:
var whitelist = [
'http://localhost:3000',
'http://localhost:12848',
'https://myapp.heroku.com'
];
var corsOptions = {
origin: function(origin, callback){
var originIsWhitelisted = whitelist.indexOf(origin) !== -1;
callback(null, originIsWhitelisted);
},
credentials: true
};
app.use(cors(corsOptions));
Also tried to enable pre-flight, like this:
app.options('*', cors())
This is probably the stupidest problem I ever ran into. Trying to run the app using the --mobile-server https://myapp.heroku.com parameter was wrong. Instead, it should be https://myapp.herokuapp.com
That was it. That was the problem all along...
Adding '*' to whitelist should do the job. The ultimate solution lies within config.xml, this should be helpful: https://stackoverflow.com/a/36124935/8056323

Ionic With Facebook connect on Android Device - probleme return url?

I've general question with location for "ionic framework" -> lastest version installed..( CLI v 1.3.0)
for testing app with ionic serve and chrome : no probleme, we can get full path url
(principally for return url with services ""openfb.js"" per examples)
//////////
context = window.location.pathname.substring(0, window.location.pathname.indexOf("/",2)),
baseURL = location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : '') + context,
OR :
if (!window.location.origin) {
window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
}
//////
BUT with ionic run android, i have popup theses informations of my path url or location on android (debug)..
result is :
file://android_asset/www/index.html#/app/messages (for my general location in page messages)
BUT return url for services fbconnect is calculated with context : " file://android_asset/ "
and facebook connect in this case get error :
" uri must be absolute" .. or... if i force location for my url to: "127.0.0.1" or "localhost" ( : 8100 with or not infos port is also testing )
i always get an error with " uri must be absolute" or connection refused with error popup and force close app...
i've no solution for this.. all other function of my app with api server connection is ok...
thank for help me to resolve openfb probleme on android device (i think same probleme for ios)...
Oby.
For this you have replace your openFb file with this repository oepenfb file.
And also you have to add one plugin 'org.apache.cordova.inappbrowser'.
In facebook OAuth redirect add this "http://localhost/oauthcallback.html"

PhoneGap App: jQuery getJSON getting 404 error when getting local file with relative URL

I have an HTML/JavaScript app that I'm trying to convert to an App using PhoneGap via the Phonegap Build app
Everything works fine through the browser, and the only problem the app is having is that the call to getJSON is returning a 404 error when trying to load my local resources.
Here is the culprit:
$.getJSON( "./shapes/json/" + abbr + '.json', gotJSON(abbr) );
I have whitelisted every domain, just to be sure:
<access origin="*" />
Is this something that is not possible from the phonegap environment? Or am I doing something wrong?
If needed, I can host the files elsewhere and do a cross-domain ajax call, but I'd rather have the files right there on the device.
This is currently happening on Android, which is the only system I can test at the moment.
UPDATE:
I'm now trying:
var xhrShapes = new XMLHttpRequest(), xhrSuccess = gotJSON(abbr);
xhrShapes.open('GET', config.path + "/shapes/json/" + abbr + ".json");
xhrShapes.onreadystatechange = function(e){
if( this.readyState === 4 ){
if( this.status === xhrSuccessCode ){
xhrSuccess(JSON.parse(this.responseText));
}
}
}
xhrShapes.send();
config.path is "file:///android_asset/www" and I'm getting 0 as a success code (which indicates success for 'file://' requests). but xhrShapes.responseText is blank and everything stops at the call to JSON.parse. I feel like I'm missing something simple...
The problem had nothing to do with the code, but rather with the file names being case-sensitive... my abbr variable was uppercase, but filenames are lowercase. $.getJSON works perfectly, now that I've corrected this (though now my pride needs some repairs).

Appcelerator HTTPClient Request not authenticating with Server

I can't seem to figure this one out, and I've tried googling that my fingers now hurt.
I am performing a HTTPClient request to my Domino Server that has SSL enabled. My request works perfectly when testing on iOS, but fails every time when testing through the Android Emulator and Mobile Web.
I'm running Android 2.2 SDK.
When I try to sign in from the App, I am definitely reaching the Server, because HTML is returned (the Login Web Form). When HTML is returned, it either means that the Authentication failed, or that the Redirect didn't work. When signing in through iOS the page redirects 100%.
Below is my code:
var orderReq = Titanium.Network.createHTTPClient();
var myurl = 'https://domain/db.nsf?login';
orderReq.setEnableKeepAlive;
orderReq.open('POST',myurl, false);
var params = {
username: "Joe Smith",
password: "Password",
redirectto: "path/db.nsf/response.xsp"
};
orderReq.send(params);
var myreturn = orderReq.responseText;
if((myreturn.charAt(0) === '<') || (myreturn === ""))
{
Ti.API.info('Fail');
return 'Fail';
}
else
{
Ti.API.info('Pass');
var json = orderReq.responseText;
var response = eval('(' + json + ')');
return response.username;
}
I have tried many properties and to no avail. I can confirm that the Android Emulator can connect to the Internet. It feels like either the Parameters are not being passed or the Redirect is not being triggered on the Web Page.
NOTE: I notice when authenticating through Android emulator that it fails immediately, where iOS returns true or false after 1-2 seconds.
Okay i know the question is too old. But, for anyone who is looking for an answer, this is what worked for me.
Make sure params is stringified before sending it to the server
orderReq.send(JSON.stringify(params));
Include the following right after the lines - orderReq.open('POST',myurl, false);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('charset','utf-8');

Categories

Resources