Android Question Exception with OkHttpUtils2

Wosl

Member
Dear All!

I need some guidance ...

What I want to do:

geocoding of a given postal address which results in details like GPS coordinates

A simplified version of my App is as following:
Geocoding example:
Sub Activity_Create(FirstTime As Boolean)
    Private cAddress As String ="10117 Berlin, Pariser Platz 5"

    Log ("Address: " & cAddress)   
    Wait for (Geocoding(cAddress)) Complete(Result As Int)
    Log ("Return Code: " & Result)

End Sub
Sub Geocoding(aquery As String) As ResumableSub
    '#####################################################################
    '
    '  Geocoding a specific postal address (PLZ Stadt, Straße Hausnummer)
    '
    '  aquery        String with postal address
    '
    '#####################################################################
    Dim su As StringUtils
    Dim q As String=su.EncodeUrl(aquery,"UTF8")
    Dim s As String=$"https://nominatim.openstreetmap.org/?addressdetails=1&q=${q}&format=json"$
    Dim j As HttpJob
    Dim ier As Int

    Log ("Geocoding Query = '" & s & "'")
    Try
        j.Initialize("Geocoding", Me)
        j.Download(s)
        Wait For (j) JobDone(j As HttpJob)
        If j.Success Then
            Log ("Geocoding successfully done")
            Log ("Result = '" & j.GetString & "'")
            '
            ' ... parse for the GPS coordinates
            '
            ier = 0
        Else
            Log ("Geocoding failed (#1)")
            ier = 1
        End If
    Catch
        Log ("Geocoding failed (#2): " & LastException.Message)
        ier = 2
    End Try

    If j.IsInitialized Then    j.Release

    Return ier
End Sub

With that I receive following messages in the log:
Error message:
** Activity (main) Create (first time) **
Address: 10117 Berlin, Pariser Platz 5
Geocoding Query = 'https://nominatim.openstreetmap.org/?addressdetails=1&q=10117+Berlin%2C+Pariser+Platz+5&format=json'
** Activity (main) Resume **
*** Receiver (httputils2service) Receive (first time) ***
ResponseError. Reason: , Response: Access denied. See https://operations.osmfoundation.org/policies/nominatim/
Geocoding failed (#1)
Return Code: 1
** Activity (main) Pause, UserClosed = false **

I did some variations (example: w/ and w/o try/catch - structures) which results some times in a different exception:
(ErrnoException) android.system.ErrnoException: open failed: ENOENT (No such file or directory)

When I type in the query into a browser I receive the excepted result.

It seams to me that the query result should be written to a place on my phone where I don't have access to.

What is wrong with my code?

Android version: 14
Smartphone: Galaxy A16 5G
B4A Version: 13.10
Libraries.PNG

Any help appreciated ...
Wosl

PS: I use a similar code in an older android version ... and it worked. When I compile it on a newer Android version it fails.
 

drgottjr

Expert
Licensed User
Longtime User
read the response error. follow the link. do what it says: add user-agent and referer headers to your rquest. it's a recent change in osm's conditions of use. (note: it's also the case if you're accessing osm's map tiles). both will work when you follow the rules.
 
Last edited:
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
see:
In OSM, a valid User-Agent is VERY important.
When you make requests to its servers (for example, to the API or tiles), OSM requires you to authenticate correctly.

Example of a valid User-Agent for OSM:
MyApp/1.0 (https://myapp.com/contact)
OR:
MyApp/1.0 (user@email.com)

Add: Application name and valid email address

B4X:
        j.GetRequest.SetHeader("Content-Type", "application/json")
        j.GetRequest.SetHeader("User-Agent", "MyApp/1.0 (user@email.com)")
 
Upvote 0

Wosl

Member
Thank you to both!

Setting header was the solution. I used the following coding:

j.Download(s)
j.GetRequest.SetHeader("Content-Type", "application/json")
j.GetRequest.SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.92 Safari/537.36")

coming from
https://www.b4x.com/android/forum/threads/set-http-request-header-with-okhttputils2.39413/#content

Important is to keep the sequence (call to Downloads before GetRequest.SetHeader) otherwise a null pointer exception will come up.

Wosl
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
Thank you to both!

Setting header was the solution. I used the following coding:

j.Download(s)
j.GetRequest.SetHeader("Content-Type", "application/json")
j.GetRequest.SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.92 Safari/537.36")

coming from
https://www.b4x.com/android/forum/threads/set-http-request-header-with-okhttputils2.39413/#content

Important is to keep the sequence (call to Downloads before GetRequest.SetHeader) otherwise a null pointer exception will come up.

Wosl
You can use that browser-style user agent, but it's "not recommended for OpenStreetMap (especially for services like Nominatim)."

Problem with that user agent:
Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 ...

* It's generic; it looks like a normal browser.
* It doesn't identify your application.

It goes against the OSM usage policy.

It can lead to:
* IP blocking
* Stricter rate limiting

What you should do instead:

Use a descriptive user agent that clearly identifies your application:

MyMapApp/1.0 (myemail@example.com)

Or, if you prefer, you can combine both:

MyMapApp/1.0 (myemail@example.com) Mozilla/5.0 (...)

Simple rule:

If you make automated requests:
Always include the application name, version, and contact information.

Review the OSM documentation
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
Tip: use j.GetRequest.SetContentType for the content type header, otherwise it will be overridden.
Why use what you say?
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
sample:
B4X:
Private Sub GeoCoderNominatim (Query As String) As ResumableSub
    Dim Result As String
    Dim Parameters() As String = Array As String ("q", Query, "format", "json", "addressdetails", "1")
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download2("https://nominatim.openstreetmap.org/search", Parameters)
'    j.GetRequest.SetContentType("application/json") ' It generates an error.
    j.GetRequest.SetHeader("Content-Type", "application/json")
    j.GetRequest.SetHeader("User-Agent", "appname/1.0 (youuser@email.com)")
    j.GetRequest.Timeout = 60 * DateTime.TicksPerSecond
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        Result = j.GetString
    Else
        Log(j.ErrorMessage)
    End If
    j.Release
    Return Result
End Sub

1776112495447.png
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Why use what you say?
Good point. You are correct.

For GET (Job.Download) requests, the Content-Type should be set with SetHeader.
 
Upvote 0
Top