将JitPack仓库添加进您的项目的build.gradle文件中:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
添加依赖
dependencies {
implementation 'moe.sunjiao:osmunda:1.1.0'
}
关于数据的获取,参见 开放街道地图数据网站
实例化一个OsmosisReader。
val reader : OsmReader = OsmosisReader()
设置导入关系和路径数据,如果您不需要,请不要编写以下代码。参见 存储空间
reader.options.add(ImportOption.INCLUDE_RELATIONS) //导入关系数据
reader.options.add(ImportOption.INCLUDE_WAYS) //导入路径数据
设置提交频率,否则将使用默认设置(5,000)。参见 commitFrequency(提交频率)
(reader as OsmosisReader).commitFrequency = 100000
设置OSM数据文件,context和数据库文件名,开始读取。
reader.readData(File(requireContext().filesDir.absolutePath + "/hubei-latest.osm.pbf"), requireContext(), "hubei" )
使用reader.read
获取已读取的OSM记录数目,reader.insert
获取已插入数据库的OSM记录数目。(二者不一致的原因参见 性能/提升性能)
使用reader.progress
获取百分比形式的当前估计进度。
使用Osmunda(requireContext()).getDatabaseList()
获取已经导入的数据库列表。
使用Osmunda(requireContext()).getDatabaseByName(databaseName)
根据名称获取某一特定数据库。
使用Geocoder类的search函数进行搜索,搜索时可以指定在数据库中的LIMIT和OFFSET,也可用经纬度指定范围。
例如,在武汉市范围内搜索「华中师范大学」,不设OFFSET,结果取前十条:
val hubeiDatabase: SQLiteDatabase = Osmunda(requireContext()).getDatabaseByName("hubei")
val list: List<SearchResult> = Geocoder(hubeiDatabase).search("华中师范大学", 10, 0, 30.7324, 114.6589, 30.3183, 114.0588)
如果不设置范围,将会在数据库的所有记录中搜索:
val list2: List<SearchResult> = Geocoder(hubeiDatabase).search("华中师范大学", 10, 0)
如果是在地图上进行搜索,可以直接将当前MapView的BoundingBox传入:
val box : BoundingBox = mapView.boundingBox
val list3: List<SearchResult> = Geocoder(hubeiDatabase).search("华中师范大学", 10, 0, box)
使用ReverseGeocoder类的search函数进行搜索,搜索时可以指定在数据库中的LIMIT和OFFSET。
val list: List<SearchResult> = ReverseGeocoder(hubeiDatabase).search(30.51910, 114.35775, 10, 0)
可以将Android的Location或Osmdroid的GeoPoint及IGeoPoint直接作为参数传入:
val location : Location = Location(GPS_PROVIDER)
val list2: List<SearchResult> = ReverseGeocoder(hubeiDatabase).search(location, 100, 0)
val geoPoint : GeoPoint = GeoPoint(30.51910, 114.35775)
val list3: List<SearchResult> = ReverseGeocoder(hubeiDatabase).search(geoPoint, 100, 0)
val iGeoPoint : IGeoPoint = mapView.mapCenter
val list4: List<SearchResult> = ReverseGeocoder(hubeiDatabase).search(iGeoPoint, 100, 0)
获得搜索结果列表后,使用result.toAddress()
获取地址,然后从返回的Address
类中获取完整地址,也可获取国家、地区、城市、道路、门牌号等信息。
for (result in list) {
val address : Address = result.toAddress()
val fullAddress : String = address.fullAddress // 完整地址
val country : String = address.country // 国家
val state : String = address.state // 省或州
val city : String = address.city // 城市
val county : String = address.county // 区、县
val town : String = address.town // 乡、镇、街道
val street : String = address.street // 通讯地址所在道路
val housenumber : String = address.housenumber // 门牌号
val neighbourhood : String = address.neighbourhood // 小区、社区、学校、机关单位、村庄等
val housename : String = address.housename //
val postcode : String = address.postcode // 邮政编码
val phone : String = address.phone // 电话号码
val website : String = address.website // 网址
}
目前正向地理编码的结果排序和筛选还是有些问题的:
val list: List<SearchResult> = Geocoder(hubeiDatabase).search("华中师范大学", 100, 0, 30.7324, 114.6589, 30.3183, 114.0588)
反向地理编码基本上已经可用:
val list: List<SearchResult> = ReverseGeocoder(hubeiDatabase).search(30.51910, 114.35775, 100, 0)
在osm网站上搜索:
测试机器:Google Pixel 3,Android Q (10.0)
测试文件:hubei.osm.pbf,rhode-island.osm.bz2
以下测试数据均在以上环境中测得。
湖北省的pbf文件大小为11.64 MiB (17,237,672 字节),其中含有2,417,117个元素,转换为5,505,162条数据库记录。
解压出的数据库文件273.91 MiB (287,219,712 字节),约为pbf的16.78倍。
罗德岛的osm.bz2文件大小为21.9 MiB (23,009,830 字节),其中含有1,897,371个元素,转换为4,525,039条数据库记录。
解压出的数据库文件198.67 MiB (208,318,464 字节),约为osm.bz2的9.05倍。
不同区域的文件大小并非「区域越大,数据越多」,还受到当地人口数量、人类聚居地密集程度、经济发展程度影响,还与开放街道地图服务的可用性有关。例如,人口密集、经济发达的广东省拥有73M的数据,而地广人稀的新疆和西藏仅分别有17M和18M的数据(均为pbf格式),请根据数据的实际大小合理安排您的应用中的数据,如果没有可用的数据,您可以从overpass-api自行下载。
您还可以根据自己应用的需求,选择是否导入 relation 数据和 way 数据,具体代码见导入数据
由于读取操作发生在Osmosis库而非本库中,本库中的OsmosisReader类仅在每次Osmosis库读取一个元素后被调用一次process()函数,因此无法将所有插入操作包含在同一个Transaction中。
为了避免进行逐条数据插入时频繁开关Transaction造成的高耗时,我在OsmosisReader类中设置了commitFrequency变量,当待插入的记录达到commitFrequency规定的数量时,将会开启一个Transaction进行批量插入操作。
在批量插入之前,所有当前已读取的待插入记录都在内存中,如果commitFrequency过高,将会导致过高的内存占用;而如果commitFrequency过低,则会频繁开关Transaction,导致过高的耗时。
commitFrequency的默认值为 5,000,您可以自行修改,还可以在您的应用中根据操作环境设置不同的值。
就具体操作而言,pbf文件的读取速度远大于xml格式,读取25万条数据约需要0.3-1秒不等,而读取相同大小的xml数据耗时5-15秒。插入25万条数据耗时4-7秒,与文件格式无关。
就总耗时而言,当commitFrequency设为 1,000 ~ 500,000 时,湖北省的pbf文件导出耗时均约为2分钟,罗德岛的osm.bz2文件导出耗时则约为4分钟,过低或过高均会导致操作耗时延长,甚至几乎不能完成。
反向地理编码的查询操作耗时3-5秒,根据查询结果获取完整地址的操作耗时0.3-2秒。如果您一次查询多条地理信息记录,请不要将其一次性全部获取完整地址,而是在用户访问某条记录时再进行操作。
数据读取及数据库写入操作的CPU占用约为10%-30%。
数据读取及数据库写入操作的内存占用约为200M-1G。
Planet OSM是所有数据的原始来源,由开放街道地图运营,但其下载速度受限。
可从其它镜像数据网站下载:网站列表
对于中国用户,我推荐开放街道地图法国社区网站,其中有中国的分省数据,大大方便了下载和使用。
您还可以自行导出特定地区的xml文件:https://overpass-api.de/api/map?bbox=min_longitude,min_latitude,max_longitude,max_latitude。
只要条件允许,请尽可能选择pbf格式,因为其占用空间和导入耗时均有显著优势。
https://github.com/sun-jiao/Osmunda