Technical Articles

Creating a consistent user experience

Usability of our complex features is decisively enhanced by wording and good translations, and as much consistency as possible. It is worth thinking about many expressions or sentences for a little while :-)

Please try to adhere to the following points and conventions:

(1) Consistent Wording:

Use only _one_ expression for a certain feature, do not mix two possible expressions. Examples:

  • check for existing expressions and re-use them in new strings, also in translations,of course
  • use "navigation", not "routing", throughout.
  • use "tracking", not "monitoring"
  • understand that "position" is where you are, while "location" refers to arbitrary points
  • use "destination", not "target"
  • use "speed", not "velocity"
  • know the difference between "elevation" and "altitude"
  • It is "OsmAnd" now, not "Osmand" any more :-)

(2) Authoring Text:

  • Moreover, please try to re-use existing string constants as much as possible, it is good for memory and performance :-)
  • When changing existing strings, please double-check with _all_ their occurrences in the code
  • In general, please be short and precise. EVERY word you write should convey _necessary_ information, so be as precise and as short as possible. Unnecessary text clutters screens without helping much.
  • Please double-check appearance of wording in the app, in particular in low-density devices. Too many line breaks, cut-off text or blown-up menu buttons may make a screen almost unusable.
  • In some cases there are conventions, which may be worth checking, rather than "inventing something"... So if 99% of commercial navigation systems in your language announce "you have reached your destination", then using "you have arrived at where you wanted to go" may not be the best of choices ... :-)
  • Clearly mark all features which require Internet access with the expression "online"

(3) Rendering:

  • A note about rendering: The appearance our default renderer creates has been tested at a multitude of map locations, with many devices, and under very different light conditions. "Spontaneous improvements" to the renderer are almost always questionable, may at least require more investigation and testing than you may think ... :-)

Back to top

How to translate OsmAnd - we need your assistance!

We very much appreciate your help providing translations for OsmAnd! Provideing translations is not very complicated, the preferred way to provide string transaltions is described here: OsmAnd @ Hosted Weblate.

Additional Information
  • All translated strings are stored in resources, where you can check if there is already a 'values-{language}' directory for your language, e.g. 'values-sk' for Slovak.
  • Existing language files could be modified by editing the respective strings.xml file (requires a github account) as desired, but please use the easier way of prividing translations and corrections as described above. The master string data is kept in the english strings.xml file, please do also check out the hints I have added to the beginning of that file.
  • To create a translation for a new OsmAnd language, download the english strings.xml file, translate it and open an Issue at Github (requires an account) announcing that a translation has been created
  • The same applies to theswing_messages_{language}.properties files in DataExtractionOsm project if you want to translate the map data extractor

Please use these described methods rather than publishing changes to strings.xml as issues or e-mailing them.

Thank you for your help !


Q: Which strings should I translate?*

A: In the strings.xml the strings look like:

        Save as GPX track
Translate only the 'Save route as GPX track' part. In the the strings looks like:
IndexCreator.INDEX_CITIES=Indexing cities...
Translate only the right part 'Indexing cities...'

Q: I don't want to create github, can I still post you the file?*

A: Yes, you can email the file, but still for us is the best way to use the github, it is easy.

Q: How should I check what has changed in the _english strings.xml_ ?*

A: New strings are added always on the top of the file. You can download the english file, your file and use some utility like pspad, or vim, or whatever you like to compare them for the new keys. You can also *blame* the english file to see the last line modifications.

Back to top

What languages will be included in OsmAnd ?
Dear translators,

Thank you all very much for your efforts to complete our display language translations, and also to localize OsmAnd in more and more languages on Weblate!

Please note the following: I am happy to include in OsmAnd's display language selection menu any new language with >10% translation rate, (will mark it as "incomplete" until it reaches ~80%). Please post an issue with OsmAnd if you need this done, I only sporadically watch these figures on Weblate.

Unfortunately, languages featuring 3-letter ISO 639-2 codes currently seem to have issues in Android, see e.g.
    This means that, unfortunately, any such language may not display in the OsmAnd menus on your device. (This issue only affects the language used in the app menus, not in the map, of course.)
  • Thanks,
    Dr. Hardy Mueller

    Back to top

    Documentation of OsmAnd Settings Development

    Read about it in FAQ.

    Back to top

    Voice Routing - Current Status (by Hardy)

    The current feature set is documented in each (new, v1.5-style) tts-config.p file in this comment block in the file header:

    % IMPLEMENTED (X) or MISSING ( ) FEATURES, (N/A) if not needed in this language:
    % (X) Basic navigation prompts: route (re)calculated (with distance and time support), turns, roundabouts, u-turns, straight/follow, arrival
    % (X) Announce nearby point names (destination / intermediate / GPX waypoint / favorites / POI)
    % (X) Other prompts: gps lost, off route, back to route
    % (X) Street name and prepositions (onto / on / to) and street destination (toward) support
    % (X) Distance unit support (meters / feet / yard)
    % (N/A) Special grammar: (please specify which)

    The file's string contents are sorted accordingly, in this fashion we can easily check which file already supports which feature.


    Let me quickly document here which prompt is played when in our voice router module:

    1. "Route recalculated":
      1. Is played after the route has been recalculated, but only if the new route "is useful", i.e. now guides you in "forward direction"
      2. Is suppressed entirely for GPX routing (as it makes no sense then)
    2. "GPS signal lost":

      Is played after GPS signal has been lost for continuous 20 sec and this was not caused by user action (still buggy, see Issue 893)

    3. "Make a U-turn when possible":

      This prompt is an interim advice for cases where you continuously head in the wrong direction, and does only sound (once) if a new route in forward direction could not be found in x (currently 10) seconds:

      1. When you head down a long dead end road, where the only possible route out is 'backwards'.
      2. Where a new route in forward direction could not yet be re-calculated within the x seconds.
      3. The prompt is only played once, until the situation is resolved, i.e. you have either turned in the right direction, or route has been recalculated in "forward" direction.
    4. Turn instructions:

      Are suppressed if traveling in a weird directions (account for GPS issues)

    5. Lead distances (lead time):
    6. 1. CAR profile (DEFAULT_SPEED = 12m/s=43km/h):
      (a) >3000m out "Follow the course of the road for..."
      (b) 3000m-2000m PREPARE_LONG
      (c) 1500m-1200m PREPARE
      (d) 300m-168m (or <25sec) TURN_IN
      (e) <60m (or <5sec) TURN
      2. BICYCLE profile (DEFAULT_SPEED = 5m/s=18 km/h):
      (b) 500m-300m PREPARE_LONG
      (c) ~~500m-350m~~ 200m-120m PREPARE
      (d) ~~225m-80m (or <45sec)~~ 80m-60m (or <16sec) TURN_IN
      (e) ~~<45m (or <9sec)~~ <30m (or <6sec) TURN
      3. PEDESTRIAN profile (DEFAULT_SPEED = 2 m/s=7.2km/h):
      (c) ~~200m-150m~~ 100m-70m PREPARE
      (d) ~~100m-70m (or <50sec)~~ 50m-30m (or <25sec) TURN_IN
      (e) ~~25m or (or <12sec)~~ 15m (or <7.5sec) TURN

      (Corrected values for bike and ped from forum feedback June 2013.)

      Back to top

    Background Track Recording - Strategies and Known Issues

    This article addresses our GPS track recording. 'Background' means to refer to the OsmAnd app not being displayed in the foreground, in particular when the device screen is off.

    The following issues have been observed over time in different Android versions:

    (A) The system may kill background apps to save power:

    Starting with Android 4.4 (or maybe before), new Android power saving options limit CPU max speed, screen brightness, and may kill running apps. Mitigations:

    • (A1) For outdoor use (screen brightness), map rendering (CPU limit), and 'background' track recording I like none of these power saving features and usually turn the device (Android) power saving to entirely off.
    • (A2) On some systems it may be sufficient to just exempt the OsmAnd app from power optimization, your mileage may vary. (Issue #5255)
    • (A3) Android 8 introduced a new Foreground service in connection with a system notification. Ever since OsmAnd v3.2 we use this foreground service which should also solve the issue, but only for Android 8+. (Issues #5255, #5587). Read more - Dontkillmyapp
    • .

    (B) GPS Wake-up Strategy:

    • (B1) While OsmAnd is used for e.g. Navigation: We keep the system's GPS module on all the time, as continuous location information is key here. Effect on battery use (order of magnitude) seems about 5% per hour on older systems up to Android 4.4, 2-3% for newer systems.
    • (B2) For 'background' track recording without concurrent navigation: For recording intervals up to 15sec, we also keep the GPS on, no big battery saving can be achieved by other strategies.
    • (B3) For intervals >=30sec, we turn GPS on only for each sampling point. This has some noticeable effect on the accuracy of the points recorded, but reduces battery usage to order-of-magnitude 1.2% per hour for 30sec track recording.

    (C) GPS Wake-up Issues

    In order to achieve the GPS wake-up, so far we use the Android AlarmManger to wake up the device periodically (also from Doze mode, which was introduced in Android 6). New Android versions introduced the following issues:

    • (C1) AlarmManager's setRepeating() became inexact starting with Android 4.4:

      Mitigation: We now use setRepeating() only up to Android 4.2, the new setExact() method starting with Android 4.4, and setExactAndAllowWhileIdle() for Android 8+. (Issue #5632)

    • (C2) Starting from Android 4.4, systems limit the number of times setExact() is executed repeatedly to e.g. once per 5 or even 15 minutes. (The actual value seems wildly device specific.)

      No good solution found for now. Current mitigation is we do not use AlarmManager wake-up, instead keep GPS always on for background track logging on devices with Android 5+ for all recording intervals shorter than 5 minutes. This produces reliable and precise tracks at the cost of the higher battery use. (Issue #5632)

    Back to top

    Creating a New TTS Voice Language

    Some hints:

    • The pronunciation of the voice prompts depends on the TTS engine you use on your device and its settings (outside OsmAnd), most prominently set it to the same language you intend to use for the OsmAnd voice guidance to avoid bad pronunciation effects. See also our FAQ article TTS does not funtion properly
    • OsmAnd only provides the wording, word order, grammar in temrs of declinations, cases, singular/plural, etc.
    • This is done in a single voice definition file per language, and now in js (migrated from former PROLOG to make it more mainstream).
    • The file name is xx_tts.js, located in your OsmAnd-data-folder/voice/voice/xx-tts, where xx is the respective ISO language_region code.
    • You can test your own tts file (or your improvements to existing ones) yourself locally, prior to a pull request, see my comment at
    • When generating a new language, it makes sense to start from, or at least look at, existing language files from languages with similar structure or grammar, it will greatly simplify to see how things are already solved.
    • In order to generate a starting point for contributors, I had once provided some rudimentary language files simply based on dictionary translations and with little specific grammar considerations. When you come across a 'strange one', its probably one of them. :)

    Back to top

    Installation of different builds

    Different builds of OsmAnd should install over any other build of the same strain (older or newer) without any issues, and with all Offline data being preserved.

    The latest development build (not necessarily stable !) for testing can be found here.

    This will update over any more recent existing development build with no problems at all. Should trying to update produce a signing or "not installed" error (like if you currently use the market or a very old dev build), please

    • export your Favorites first (Menu/Export in the fav list)
    • export your Navigation profiles
    • uninstall the previous version
    • re-install the new development build
    • re-import your Favorites again (Menu/Import)

    All maps/tracks etc. are kept in place unchanged during this procedure.

    Back to top

    Create offline maps for yourself

    OsmAndMapCreator can also be used to create maps for yourself if you want maps that are more up-to-date then the ones you can download from OsmAnd. We will explain this via a Un*x/Linux/OS X like shell script and we will use the nightly generated maps from Geofabrik, a German company that sells OpenstreetMap based maps and appliances.

    Shell script
    # First download all the data
    cd "$WORK_FOLDER/osm_files"
    echo "Now in pwd\n"
    rm *
    wget -v -O Netherlands_europe.osm.pbf "​/europe/netherlands-latest.osm.pbf"
    #wget -v -O Luxembourg_europe.osm.pbf "​/europe/luxembourg-latest.osm.pbf"
    #wget -v -O Belgium_europe.osm.pbf "​/europe/belgium-latest.osm.pbf"
    echo date > starttime.txt
    echo "Now converting from osm.pbf to osmand obf\n"
    cd "$WORK_FOLDER/OsmAndMapCreator"
    java -Djava.util.logging.config.file=​ -Xms256M -Xmx2560M -cp "./OsmAndMapCreator.jar:​./lib/OsmAnd-core.jar:./lib/*.jar"​index.IndexBatchCreator ./batch.xml
    echo date > endtime.txt
    echo "And finally moving the obf files from the index folder to the osmandmaps folder\n"
    mv index_files/*.obf osmandmaps/

    The line _WORK_FOLDER="/opt/OpenStreetMap"_ is a variable to set our working folder. Inside this folder we have the maps _osm_files_, _OsmAndMapCreator_, _index_files_ and _gen_files_.

    We move into our download folder _osm_files_ and we use the command _wget_ to download our map(s). The wget command is used with the parameter _-O <name>_ as we will download the latest nightly map from Geofabrik, but we will save it immediately in the nameformat OsmAnd prefers.

    We move into the folder _OsmAndMapCreator_ where we installed/copied the OsmAndMapCreator program. It is best to really use the program from this folder, otherwise you have to set all kind of environment variables. The line:

    _java -Djava.util.logging.config.file=​ -Xms256M -Xmx2560M -cp "./OsmAndMapCreator.jar:​./lib/OsmAnd-core.jar:./lib/*.jar"​index.IndexBatchCreator ./batch.xml_
    runs OsmAndMapcreator on our downloaded maps. OsmAndMapCreator will process all maps it will find in the download map. this also means that it will process older maps if you still had them there.

    We will log the process to file (, give OsmAndMapCreator a minimum amount of 256MB and a maximum amount of 2560MB (preferably more then 1024MB), and we use the setup as specified in _batch.xml_.
    Note: a 32bit Operating system can address up to approximately 1.5GB. This means that your -Xmx value can no larger be then -Xmx1720M. A larger specification is accepted without errors, but not used.

    The _batch.xml_ file can be found in the OsmAndMapCreator folder, together with the program, and contains settings for running the program. The line:

    _process directory_for_osm_files=​"/opt/OpenStreetMap/osm_files" directory_for_index_files=​"/opt/OpenStreetMap/index_files" directory_for_generation=​"/opt/OpenStreetMap/gen_files"_
    specifies our working folders.

    The next line:
    _skipExistingIndexesAt="/..." indexPOI="true" indexRouting="true" indexMap="true"        indexTransport="true" indexAddress="true">_ 
    gives you options to modify parts of your map. If you don't need routing and/or addresses, you can simply skip these by setting the parameters to "false".

    You can also use multiple batch.xml files for different purposes.

    The last two lines in the script move the created maps to the osmandmaps folder where we store our maps (in this case).

    The lines

    _echo date > starttime.txt_ 
    _echo date > endtime.txt_ 
    are not really neccessary but simply display how long the process takes.


    The shell script can be scheduled as well. You have to take notice of the Geofabrik schedule for the maps creations (calculate for your own time zone).

    If you want to create a new map every night, you could add a crontab line like:

    _01 03 * * 7 /opt/OpenStreetMap/​ > /dev/null 2>&1_

    This will start the creation of the map at 03:01 in the morning which is currently after the Geofabrik netherlands osm.pbf map has been generated (local time zone).

    Performance and tuning

    Creating maps is a memory hungry and very I/O intensive (disk intensive) process. In other words: It takes long to very long!

    What can you do to improve performance:

    • SSD disks.
    • Use multiple disks.
    • Use "in memory" processing.
    SSD disks

    The modern "solid state" disks are 2-6 times as fast as conventional hard-disks and can improve your map creation performance dramatically.

    Multiple disks

    Modern operating systems can access multiple disks simultaneously. Note that this really means *multiple disks* and *NOT* multiple partitions on one disk.

    If you have your _process directory_for_osm_files_ on one disk and your _directory_for_generation_ on another disk you will see an nice and noticeable performance gain.

    In memory processing

    You can do a great deal of the map creation not on disk but in memory. In your batch.xml one of the top lines contains:

    <process_attributes mapZooms="" renderingTypesFile="" zoomWaySmoothness="" osmDbDialect="sqlite" mapDbDialect="sqlite"/>

    The osmDbDialect="sqlite" mapDbDialect="sqlite" determines where your map generation process will take place.

    The line osmDbDialect="sqlite" mapDbDialect="sqlite" means that it will take place on disk.

    If you change this to osmDbDialect="sqlite_in_memory" mapDbDialect="sqlite_in_memory" the process will take place in memory.

    This "in memory" processing will speed up the map generation by 10-50% but requires a lot of memory. The 10% to 50% is dependent on the map size. Smaller maps benefit less from in memory processing than larger maps, as still the normal disk access (initial reading and final map writing) plays a major role in smaller maps, where as the processing of all the data (and their relations) in larger maps requires more "calculation".

    In normal "on disk" processing a nodes.tmp.odb file is created from your .osm or .osm.pbf file. This nodes.tmp.odb file is a sqlite database file and it is about 15 to 25 times as big as the original .osm.pbf file which you downloaded from

    So if your original .osm.pbf file is 300MB, your nodes.tmp.odb file will be 5GB to 6GB! Note that smaller maps will be around the 15x factor whereas big maps (>350MB) will end up in the 20x to 25X space increase.

    With "in memory" processing this nodes.tmp.odb file will be created in your working memory. It means that the -Xmx parameter, which we discussed in the Explanation sections, needs to be big enough for both the nodes.tmp.odb and the normal processing that takes place in memory.

    You will need "the size of the nodes.tmp.odb" + 20-25%.

    It means that for a 250MB .osm.pbf, which will generate a ~4.5GB nodes.tmp.odb file, you need about 5GB heapspace which requires an -Xmx value of -Xmx5120M.

    Note: a 32bit Operating system can address up to approximately 1.5GB. This means that your -Xmx value can no larger be then -Xmx1720M. A larger specification is accepted without errors, but not used.

    So in effect you really need a 64bit Operating system to really benefit from "in memory" processing.

    Note also that your -Xmx value should not be that big that your operating system starts swapping to disk. This will even decrease your performance below that of normal "on disk" processing.

    Finally: your source .osm.pbf file can be no larger then 600MB as this would require up to 20GB working memory. If your source file exceeds 600MB, OsmAndMapCreator will switch back to normal "on disk" processing. You will be notified early in the process with a warning "Switching SQLITE in memory dialect to SQLITE"

    Back to top

    Creating a country polygon

    This article describes how to create a poly(gon) for a missing country in and how to add this poly to the map generation server of OsmAnd


    OsmAnd comes with a lot of maps for a lot of countries. Most maps are created from "raw data" maps downloaded from Geofabrik supplies these raw data maps for free to everyone and they deliver (commercial) services and products based on these maps. has the strategy to deliver maps for the countries that are requested by larger numbers of users or by their customers. This means that some maps never make it on geofabrik as there are simply not enough requests for (or none at all), like some exotic countries like the Seychelles or Burundi, etc.

    Server process

    Because of this strategic decision of geofabrik, OsmAnd has an option to generate maps for these exotic rare countries and the tools OsmAndMapCreator and osmconvert are used for this. For OsmAndMapCreator this is a three step process:

    • OsmAndMapCreator needs a polygon which surrounds the outer border of the country.
    • OsmAndMapCreator needs the "raw data map" from the next level incorporating this country. For Burundi it mean that OsmAndMapCreator needs the Africa map. For Nordrhein-Westfalen it means that OsmAndMapCreator needs the Germany map.
    • Osmconvert will create a "raw data" map from the poly extracting the map data from the "parent" map.
    • OsmAndMapCreator will create an OsmAnd obf map based on the intermediate "raw data" map generated by osmconvert.
    Necessary actions

    Depending on the complexity of the (generated) polygon this complete chain of actions can take from 10 minutes to 2 hours in total.

    Get the OpenStreetMap relation from Nominatim
    • Go to
    • Fill in your country name
    • Once found click on the link "(details)"
    • In Details scroll down to "OSM: relation " and write down or copy the relation ID number.
    Retrieve the poly(gon) from
    Generate the polygon
    • Go to
    • Fill in (or paste) the "OSM: relation " ID number you retrieved from Nominatim for your desired country into the "Id of relation" field.
    • This will create a default polygon, consisting of 250 to 3500 nodes (NPoints). The poly itself can be found in the "poly" column.
    • In case of more then 350 nodes you will need to simplify the polygon. The simpler the polygon, the faster the country map can be created (of course depending on the contents)
    Simplify the polygon

    The number of Node Points (NPoints) needs to be as low as possible for the fastest possible creation of the map by OsmAndMapCreator. As mentioned: In case of more then 350 node points try to reduce them by simplifying the polygon.

    • In case of more then 350 nodes, try to reduce them by "playing" with the X variable (in my experience the others don't really matter)
    • Sometimes you get great results (90 NPoints, 200 NPoints, 270 NPoints) and then you are done with this step. Sometimes you simply can't get below 450 NPoints or so. Then you need to apply further manual steps.
    • Save your final polygon to file. Use the correct default name for it, like france.poly. Stick to lowercase characters.
    Further modification and simplification of the polygon
    • Open JOSM (download if necessary) and open the polygon file you created (did you make a copy/backup of the original polygon that you saved?).
    • Add a background from the "Images" menu and select the default "OpenStreetMap (Mapnik)" background.
    • Manually remove node points where possible. *Note:* Keep the polygon as close as possible around the border. You do need some overlap but try to keep it below 2-5 kilometers. Overlap in countries will be generated twice for each country. Less overlap, means less rendering time and rendering errors. At coastlines and around islands try to keep more distance (20 kilometers). This is widely acepted and the sea is "empty" anyway.
    • When you have done the best you can you can save the updated, corrected poly. As said: try to get as little node points as possible, but sometimes a country border is so complicated that you simply need more node points to describe it and to keep the polygon as close as possible around the border: so be it.
    • *Do not upload the polygon to OSM*. JOSM will ask you to upload your work to OpenStreetMap. Don't do this for these polygons unless you know exactly what you do. Almost every country in the world is already perfectly covered in OpenStreetMap (otherwise nominatim would not be able to give you the details about the country, and would not be able to generate the polygon based on the OSM relation id.)
    Adding the poly(gon) to the OsmAnd server

    To be able to do this you must register as a user.

    To make the map generation possible there are two steps required:

    • Adding the polygon to the map data section
    • Adding the country to the data file that is used to generate the OsmAnd obf maps.
    Adding the polygon to the map data section
    • Go to the web address of the OsmAnd development server at
    • Select the OsmAnd-misc section.
    • Select "fork" to create your own personal repository
    • In your personal repository go to the folder osm-planet/polygons and select the relevant continent.

      Note: The "master" repository is at Your repository is at<your user name>/OsmAnd-misc.

    • Create a new file and copy your poly data inside. Save the file.
    • Create a pull request.
    Add the map creation to the batch list
    • Go to the web address of the OsmAnd development server at
    • Select the OsmAnd-tools section.
    • Select "fork" to create your own personal repository.
    • In your personal repository go to the folder obf-generation/regions.
    • Select the file indexes.xml and click edit.
    • Add your country at the relevant location and save the file.
    • Create a pull request.
    Creating your own personal maps from a poly

    You can create for example polygons from countries, counties/provinces/states, regions and cities.

    Say your daughter is going to Paris for a couple of days with a friend. She is not interested in navigation, walking or cycling (unless absolutely necessary), but she wants to know where she is, where to go to and where to find the interesting places (POIs). Next to that she has a small phone (low end CPU, low on memory) and small SD-card (stuffed with music). So the map needs to be as small as possible: both for storage as well as performance. You can of course download the map for france_ile-de-france.obf containing Paris, but you can also generate a "custom made" Paris map.

    • Let your daughter download OsmAnd, or even better: let her buy OsmAnd+
    • Get the OSM relation id for Paris from Nominatim.
    • Get the (simplified) poly for the Paris id from
    • download or compile osmconvert
    • download "raw data" map of ile-de-france from
    • create raw data map of Paris from the ile-de-france map and the Paris poly like:
       $ osmconvert ile-de-france.osm.pbf -B=paris.poly --out-pbf > Paris.osm.pbf
    • Download the OsmAndMapCreator application from
    • create your OsmAnd obf map from the Paris.osm.pbf data map using OsmAndMapCreator.

    Back to top

    OsmAnd Data Structure

    Many questions are about content of and issues with map data in the application. This topic unveils some technical details of the internal data format and data processing. It can be interesting for non-developers who are familar with the OSM data structure.

    All the OsmAnd data is contained in 'obf' files. 'obf' files have a complex structure and can consist of many parts. It is highly recommended to keep file sizes below 2 Gb. Currently obf files can have many parts consisting of multiple POI parts, multiple routing data parts, multiple Map parts, multiple Transport parts and multiple Address data parts. That list can be extended in future. To combine or split or delete some parts from the obf file use 'binary_inspector' console tool provided with OsmAndMapCreator.

    POI, Transport part
    Map part
    Address part

    Q: How does mapcreator generate its list of all places that will appear later in OsmAnd's offline address search? What objects are used in detail for that? What nodes with a place tag are included, and which are excluded?

    A: All places that are visible in OsmAnd as Cities are taken from nodes that have the tag "place" Currently city, town, suburb, village, hamlet are used.

    Q: How does mapcreator handle an area polygon that is given via a relation with boundary=administrative? How do you associate a place given as a node with its boundary when it is present in the OSM data?

    A: Simply saying: it currently works by name. Mapcreator tries to visit all boundaries and creates a closed (!) boundary from the relation or from separated ways and associates it with only one name. After that it tries to match *place* with *boundary name* using the *contains of* algorithm. There is also an additional check if that boundary contains the place. If there are many boundaries of different admin_level with the same name (containing each_other like district/town/region having the same name) the highest admin_level with exact matching will be chosen. TODO More details should be here (about districts of the city ...) ...

    Q: Where is documentation describing what admin level is right to build an association to a certain place node? What countries prefer what admin level?

    A: Currently the association between admin_level relation and admin_centre is not used. Because only few relations provide that information.

    Q: How does MapCreator know what street belongs to what place? Are there different cases when a boundary polygon is given and when there is none?

    A: There are many strategies to check and they are prioritized in the following order:

    • The most important are places and their boundaries. In order for the street management algorithm to work correctly, the place matching boundaries should be correct. If the street belongs to many boundaries, it will be registered in all appropriate places.
    • is_in tag (it is deprecated). So if a street has the is_in tag, it will be parsed and splitted by comma and the street will be attached to all relevant cities (by exact name matching). (TO CHECK: basic check street is in city radius?)
    • If the street doesn't belong to any boundary (not properly closed boundaries could be an issue here), it tries to find the closest/biggest city and register the stret in that city (sometimes it registers in a town at 1 km distance and misses the closest hamlet at only 100m distance).

    The last part is very inaccurate. That's why many streets get attached to a neighbor city.

    At MapCreator's preferences you have five more settings for street suffixes, zoom, smoothness and rendering ... what are the detailed effects that you can achieve with each of them? Are those settings actually used?

    • OsmAndMapCreator can display what streets are associated to what city (context menu -> Show address). Local obf files should be present and configured in Settings.
    • Binary inspector tool can show a list of streets for each city. Run the tool without parameters to see the possible parameters.
    • Currently all index files contain gen.log. Viewing the log file you can find errors in the map creation process and that could give an answer why some streets are not in the proper address index place.
    Address Part - workflow

    There are these relations:

    city -> 0..1 boundary
    boundary -> 0..** city (used to define suburb of city)
    1. iterate all Osm NODEs and register as cities if the tag = PLACE is present:

      • extract cities (TOWN, CITY).
      • extract villages (anything else).
    2. iterate all RELATIONs and WAYs with type=boundary and register all boundaries:

      • boundary is called Entity (way or relation) with tag 'boundary=administrative' or with tag 'place=...'.
      • boundary should be admin_level > 4 or not have an admin_level.
      • boundary is not always associated with a city (or state, ...).
      • boundary can have 'admin_center', 'label' member pointing to a city node.
      • boundary exactly matches by name city node and the city node falls within the boundary.
      • boundary matches start, end or substring by name city node and city node falls within the boundary.

      Many boundaries can be associated with one city. Here is the order on how the most important boundary is taken and associated with the city:

      • Boundary is matched by name exactly and has the tag place.
      • Boundary is matched by name exactly and has admin_level 8 > 7 > 6 > 9 > 10 > 5... or nothing.
      • Boundary has admin_id matching.
      • All other cases including sorting of admin_level.
    3. if the city doesn't have any assigned boundary then all boundaries that don't have cities centers and contain that city will be checked and the boundary with admin_level >=7 will be assigned.

    4. for each boundary, make a list of cities that are inside it.

    5. iterate all RELATIONS and find addresses (Postal_Addresses):

      • relation with "address" tag type, and is "house" or "a6" address_type.
      • search for associated Street relation and house members.
      • try to find the city for the street and city for house address.
      • look up cities (we already must have found it in the steps before!).
      • if we have city and street, register it to database:
        • for streetregistration, see: register street for a city
          • if street is registered, and we are processing street:
          • iterate over all relation members:
            • find street -> write the nodes of the street to db
            • find house -> write the house to to the street
          • if street is registered, and we are processing house:
            • find house number
            • find house border: if found, store: building for the street

          register street (street, location of street (los), cities):

          Note: we might register a street to more cities = this means, the street can be in nested areas, suburb, city, hamlet, etc... For each area, we want to register the street it is in.

          • for each city:
            • find existing street registration within the city:
              • if street exists:
                • if citypart is unknown -> update the existing street's city part
                • try to find city Part for our street, and lookup the street again
              • if street does not exist: (might change after the lookup)
                • register the street for city, city part, location, and street name

          findOrRegister street

          • find close cities to the street
          • if the street is in the boundary of the city, add the city for search
          • if no city was find, using boundary, find closest city for the street
          • register street: for the found cities
    6. iterate all NODES, then WAYS, then RELATIONS (iterate main entity)

      1. find ways - interpolations:

        • for each interpolation, findOrRegister a street with the location of the interpolation
        • for each two nodes create a building representing the interpolation
      2. for any entity, find addr:housenumber and addr:street tag (can also be the interpolation of nodes again!!!):

        • skip if building for this entity already exists!
        • findOrRegister streets for the street
        • find the house number
        • if housenumber contains '-', try to create interpolated house number (missing latlon2?)
        • if housenumber contains '/', try to lookup second street addr:street2 --> seems only for RU osm:
        • there are more variations for this: adr:housenumber2, addr2:street, addr2:housenumber etc...
        • for each street, store the existing house
      3. for way with tag - name & tag - highway, but without addr:housenumber and addr:street:
        • Note: this might be ways for cars, with names (highway, or so)
        • skip if such street already exists
        • findOrRegister the street for city
        • write the nodes for each found street in each city
      4. Each relation with "postal_code", store for later use.

        Note: this does not include the address:type = pc and addr:postalcode

    7. process post codes:

      • for each stored postal_code relation
      • for each building member, update the postal_code
    8. write the index:

      • split cities to: cities+towns, suburbs (suburb with is_in tag), villages (not city or town)
      • write cities+towns using suburbs
        • read street from cities+towns + apropriate suburbs for each town
          • in here, there might be more streets with the same name for one city, in such case we try to find a cityPart for the street (suburb), where the street is in. There should be not more streets with same name within one city part!
        • for each street
          • for each building, register/create/find postcode, register the street
      • write villages
        • same as towns...
      • write extracted postcodes and their streets

    Back to top

    How to inspect an obf binary file

    If you want inspect the content of an obf file, you need to download OsmAndMapCreator. There you can find a console application Inspector (.sh, .bat). This console application has optional parameters [-vmap, -vaddress, -vtransport] and one required parameter (input obf file). By specifying optional parameters you can trace all information from the obf file (be aware: it could be huge!).

    Example and step-by-step for Windows users:

    • have Java Runtime Environment installed
    • download or copy any Osmand offline map from your device to your PC, place that obf file ideally in the folder with all the unzipped Mapcreator files
    • Open Windows commandline (e.g. by pressing Windows-key and "r", then enter cmd and press return
    • go to the folder where you have unzipped the Osmand-Mapcreator by command cd and folder name
    • type dir to see whether you are in the right folder with file inspector.bat
    • type inspector -h to see some help text
    • type inspector -vaddress name_of_your_map.obf >output.csv
    • if you get a Java console error about not enough memory or similar, edit the file inspector.bat by increasing the number at parameter -Xmx512M (or similar) step-by step to a higher value
    • try to load that (eventually very big) CSV text file into any editor or program that can load very big files, like Notepad++ ... or try an import into any spreadsheet programm like Excel or LibreOffice calc (choose TAB as field separator)
    • use any search feature to find place names or street names

    Back to top

    OBF routing debugging on a PC with OSM map display
    • go to and download from the link on the right screen side, and unzip it,
    • copy the obf file from your phone or tablet into that folder,
    • start OsmandMapCreator via bat file or sh file,
    • be sure to have an internet connection so that mapcreator can download map tiles, check all menus and settings inside mapcreator,
    • set the working directory of mapcreator to the folder where mapcreator itself and the obf file is located.
    • pan and zoom the map to that place where you have routing issues and that is covered by the mentioned OBF file,
    • do right clicks in the map to set start and end points and different routing engines
    Find the place name a street is associated with in offline OBF maps
    • Have a Java framework installed on your desktop computer.
    • Download Osmand's Mapcreator, for example from and unzip it to your PC.
    • Take any map file with extensiuon OBF and put it in the same folder where all files from mapcreator are located.
    • Start Mapcreator on your PC by clicking OsmAndMapCreator.bat or
    • Be sure that you have internet access on your PC, and Mapcreator's settings are that tiles are downloaded when you drag and zoom the map to your location where your issue is located.
    • If you have zoomed to your area, do a right-click with the mouse on the map and choose "show address" from the popup-menu.
    • Normally, now all the street names should be displayed from the obf file, and the place name to where each street is associated in Osmand's offline search.

    Back to top

    Using KML Files

    In GoogleEarth (GE) you can add you own Placemarks on the map and collect them into a folder. From GE you can save the folder in kml format. When you have a different format you can use QGIS or other opensource software to convert to KML format. Maybe you can convert it directly to osm. You may use any format containing your POIs, if you are able to convert it to osm format. You can format KML to GPX here.

    Converting KML (or Other Formats) into osm Format

    To perform this task we need to use gpsbabel. It is very useful to convert waypoints, tracks, and routes between popular GPS receivers and mapping programs. The syntax is very simple, and GPS Babel has an interface to create the syntax for you:

    $ gpsbabel -i kml -f my_places.kml -o osm,tagnd="tourism:museum",​created_by -F my_places.osm

    The generated file is like this:

    <?xml version='1.0' encoding='UTF-8'?>
    <osm version='0.5' generator='GPSBabel-1.4.0'>
      <node id='-1' visible='true' lat='41.890121' lon='12.492265'>
        <tag k='name' v='place01'/>
        <tag k='note' v='place01'/>
        <tag k='tourism' v='museum'/>
    <node id='-2' visible='true' lat='41.892241' lon='12.489031'>>
        <tag k='name' v='place02'/>
        <tag k='note' v='place02'/>
        <tag k='tourism' v='museum'/>

    All points inside the kml file are converted into osm points, assigning them some properties like tourism category and museum type. The created_by= option with missing value means that the properties will be ignored. If your poi belongs to different categories, I suggest you create multiple osm files and create OsmAnd odf files and merge them together later with OsmAndMapCreator, or create multiple obf files.

    Converting OSM Format into OBF Format

    Now you are ready to perform the final step. The conversion will be done using OsmAndMapCreator. Download, unzip and run this program.

    • Deselect all choices except Build POI Index as shown:
    • Select the work dir (File/Specify working directory…)
    • Load my_places.osm (File/Select osm file…)

    If all is right you'll find My_places.obf into your workdir folder. Simply upload this file into your OsmAnd phone folder and you have done.

    Good luck!!!

    Back to top

    How to produce customized vector data

    It is possible to create a customized obf file with specific (own) vector data (hiking paths, speed cams, transport routes debug way info), and adjust the rendere to display it.

    OsmAndMapCreator can process only OSM files (osm-xml, bz2, pbf). However the set of tags can be custom. To specify what tags/values need to be indexed by Creator please download and change this file. OsmAndMapCreator has an option to use custom rendering_types.xml in the settings. Once file is created you can double check that data is present by utility binaryInspector with '-vmap' argument. This utility is packaged with OsmAndMapCreator.

    Once the .obf file is ready you can create custom rendering file to display missing attributes. There is a default rendering style which contains all information about rendering. It is good to have a look at it but it is very hard to open/edit it and understand. More convenient way to create your own rendering style is to create style that depends (inherits) default style. A good example of custom rendering style you can find here.

    Currently OsmAndMapCreator doesn't support relation tagging. So you need to manually copy all tags from relations (like route color) to way tags by script.


    Back to top

    Specification of OsmAnd's SQLite format

    The SQLIte format used in OsmAnd is based on the "BigPlanet" SQLite as supported by MOBAC. In OsmAnd we add a number of tables extending the format:

    Table Column Spec and Purpose
    "info" "url" String. URL template to download tiles with zoom ≣ {z}{0}, {x}{1}, {y}{2}, server name ≣ {rnd}
    "randoms" String. The names of the mirrors of server. Comma-separated. One of these values will randomly replace the placeholder {rdn} in "url" field.
    "referer" String. HTTP Referer. As used for downloading.
    "minzoom" Integer. Min zoom level. Respective integer. (Also inverted in case of BigPlanet).
    "maxzoom" Integer. Max zoom level. Respective integer. (Also inverted in case of BigPlanet).
    "ellipsoid" Integer 0 or 1. 1 for Elliptic Mercator (Yandex tiles). 0 for regular Spheric Web Mercator (OSM, Google maps)
    "inverted_y" Integer 0 or 1. 1 for inverted Y tile number ( tiles).
    "timeSupported" Bool "yes" or "no". A tiles table with a "time" column indicates when each tile was retrieved.
    "expireminutes" Integer. Specifies if tiles shall expire after the given number of minutes. They would still be displayed, but also re-downloaded.
    "tilenumbering" String "" or "BigPlanet". If "BigPlanet", zoom will be inverted and calculated as z = 17 - zoom.
    "tiles" "x", "y", "z" Integer. Indicates tile Mercator coordinates. Note that zoom could be inverted for the BigPlanet case.
    "image" Blob of image bytes.
    "time" Integer. Time stamp when image was downloaded.

    The class supporting this is SQLiteTileSource at or near

    Back to top

    Specification of OsmAnd's Metainfo format

    The Metainfo format used in OsmAnd to store the tile layers preferences. In OsmAnd we add a number of tables extending the format:

    Field Spec and Purpose
    "[url_template]" String. URL template to download tiles with zoom - {1}, x - {2} , y - {3}, server name - {rnd}
    "[randoms]" String. The names of the mirrors of server. Comma-separated. One of these values will randomly replace the placeholder {rdn} in "url" field.
    "[minzoom]" Integer. Min zoom level. In regular format (OSM, Google maps).
    "[maxzoom]" Integer. Max zoom level. In regular format (OSM, Google maps).
    "[ellipsoid]" Bool "true" or "false". True for Elliptic Mercator (Yandex tiles). False for regular Spheric Web Mercator (OSM, Google maps)
    "[inverted_y]" Bool "true" or "false". True for inverted Y tile number ( tiles).
    "[tile_size]" Integer 256 or 512. Side size of downloading tile in px.
    "[img_density]" Integer. Tile image density.
    "[avg_img_size]" Integer.Average tile image size.
    "[expiration_time_minutes]" Integer. Specifies if tiles shall expire after the given number of minutes. They would still be displayed, but also re-downloaded.

    The class supporting this tile sourcw is at or near

    Back to top