Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

387 offline mappacks #417

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ ext {
buildToolsVersion='29.0.3'

// centrally manage some other dependencies
mapsforgeVersion = '0.13.0'
mapsforgeVersion = '0.14.0'
osmdroidVersion = '6.1.6'

// test dependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import android.os.Bundle

class CycleStreets : MainNavDrawerActivity(), RouteMapActivity, PhotoMapActivity {
public override fun onCreate(savedInstanceState: Bundle?) {
MainSupport.switchMapFile(intent, this)

super.onCreate(savedInstanceState)

MainSupport.handleLaunchIntent(intent, this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.pm.PackageManager

import net.cyclestreets.api.client.RetrofitApiClient
import net.cyclestreets.core.R
import kotlin.collections.Map

interface CycleStreetsApi {
fun getJourneyJson(plan: String, leaving: String?, arriving: String?, speed: Int, lonLat: DoubleArray): String
Expand All @@ -22,6 +23,7 @@ interface CycleStreetsApi {
fun getPOIs(key: String, lonW: Double, latS: Double, lonE: Double, latN: Double): List<POI>
fun getPOIs(key: String, lon: Double, lat: Double, radius: Int): List<POI>
fun getBlogEntries(): Blog
fun getMaps(): Maps
}

object ApiClient : CycleStreetsApi {
Expand Down Expand Up @@ -130,7 +132,9 @@ object ApiClient : CycleStreetsApi {
override fun getBlogEntries(): Blog {
return delegate.getBlogEntries()
}

override fun getMaps(): Maps {
return delegate.getMaps()
}
}

class ApiClientImpl(private val retrofitApiClient: RetrofitApiClient): CycleStreetsApi {
Expand Down Expand Up @@ -230,6 +234,10 @@ class ApiClientImpl(private val retrofitApiClient: RetrofitApiClient): CycleStre
return retrofitApiClient.blogEntries
}

override fun getMaps(): Maps {
return retrofitApiClient.maps
}

/////////////////////////////////////////////////////
private fun itineraryPoints(vararg lonLat: Double): String {
val sb = StringBuilder()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package net.cyclestreets.api

import android.os.AsyncTask

class Maps(
private val packs: Collection<VectorMap>
): Iterable<VectorMap> {
val size get() = packs.size
override operator fun iterator() = packs.iterator()

companion object {
private var loaded_: Maps? = null

fun get(): Maps? {
if (loaded_ == null)
backgroundLoad()
return loaded_
} // get


private fun backgroundLoad() {
GetMapsTask().execute()
}

private class GetMapsTask : AsyncTask<Void?, Void?, Maps?>() {
override fun doInBackground(vararg params: Void?): Maps? {
return load()
}

override fun onPostExecute(maps: Maps?) {
loaded_ = maps
}
}

private fun load(): Maps? {
try {
return ApiClient.getMaps()
} catch (e: Exception) {
println(e.message)
}
return null
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package net.cyclestreets.api

data class VectorMap(
val id: String,
val name: String,
val url: String,
val parent: String,
val size: String,
val lastModified: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import net.cyclestreets.api.Blog;
import net.cyclestreets.api.GeoPlaces;
import net.cyclestreets.api.Maps;
import net.cyclestreets.api.POI;
import net.cyclestreets.api.POICategories;
import net.cyclestreets.api.PhotomapCategories;
Expand All @@ -24,6 +25,7 @@
import net.cyclestreets.api.client.dto.UserCreateResponseDto;
import net.cyclestreets.api.client.dto.UserJourneysDto;
import net.cyclestreets.api.client.geojson.GeoPlacesFactory;
import net.cyclestreets.api.client.geojson.MapsFactory;
import net.cyclestreets.api.client.geojson.PhotosFactory;
import net.cyclestreets.api.client.geojson.PoiFactory;

Expand Down Expand Up @@ -222,6 +224,11 @@ public UserJourneys getUserJourneys(final String username) throws IOException {
return response.body().toUserJourneys();
}

public Maps getMaps() throws IOException {
Response<FeatureCollection> response = v2Api.getMaps().execute();
return MapsFactory.Companion.toMaps(response.body());
}

public Result register(final String username,
final String password,
final String name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ Call<FeatureCollection> geoCoder(@Query("q") String search,
@GET("/v2/journeys.user?format=flat&datetime=friendly")
Call<UserJourneysDto> getUserJourneys(@Query("username") String username);

@GET("/v2/mapdownloads.list")
Call<FeatureCollection> getMaps();

@FormUrlEncoded
@POST("/v2/user.create")
Call<UserCreateResponseDto> register(@Field("username") String username,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class AbstractObjectFactory {
@SuppressWarnings("unchecked")
protected static <V> V propertyOrDefault(Feature feature, String propertyName, V defaultValue) {
static <V> V propertyOrDefault(Feature feature, String propertyName, V defaultValue) {
return (feature.getProperty(propertyName) == null) ? defaultValue : (V)feature.getProperty(propertyName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package net.cyclestreets.api.client.geojson

import net.cyclestreets.api.VectorMap
import net.cyclestreets.api.Maps
import net.cyclestreets.api.client.geojson.AbstractObjectFactory.propertyOrDefault
import org.geojson.Feature
import org.geojson.FeatureCollection

class MapsFactory {
companion object {
fun toMaps(featureCollection: FeatureCollection): Maps {
return Maps(
featureCollection.features
.map { f -> toMap(f) }
.filter { m -> isBritainOrIreland(m) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this restriction as a starting point. We can consider adding others subsequently as part of #46.

)
}

private fun toMap(feature: Feature): VectorMap {
return VectorMap(
feature.getProperty("id"),
feature.getProperty("name"),
feature.getProperty("url"),
propertyOrDefault(feature, "parent", ""),
propertyOrDefault(feature, "size", ""),
propertyOrDefault(feature, "lastModified", ""),
)
}

private fun isBritainOrIreland(m: VectorMap): Boolean {
return isBritainOrIreland(m.id)
}
private fun isBritainOrIreland(p: String): Boolean {
return p.contains("great-britain") || p.contains("ireland")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,6 @@ private val TAG = Logging.getTag(MainSupport::class.java)

object MainSupport {

fun switchMapFile(intent: Intent, context: Context): Boolean {
val mapPackage = intent.getStringExtra("mapfile") ?: return false
val pack = MapPack.findByPackage(context, mapPackage) ?: return false
CycleStreetsPreferences.enableMapFile(pack.path())
return true
}

fun handleLaunchIntent(intent: Intent, activity: Activity): Boolean {
val launchUri = intent.data ?: return false
Log.d(TAG, "Handling launch intent with URI: $launchUri")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,25 @@ import net.cyclestreets.util.MessageBox
private val TAG = Logging.getTag(SettingsFragment::class.java)
private const val PREFERENCE_SCREEN_ARG: String = "preferenceScreenArg"
private val SETTINGS_ICONS = mapOf(
"screen-maps-display" to GoogleMaterial.Icon.gmd_map,
"mapstyle" to null,
"confirm-new-route" to null,
"screen-routing-preferences" to GoogleMaterial.Icon.gmd_directions,
"routetype" to null,
"speed" to null,
"units" to null,
"screen-liveride" to GoogleMaterial.Icon.gmd_navigation,
"nearing-turn-distance" to null,
"offtrack-distance" to null,
"replan-distance" to null,
"screen-locations" to GoogleMaterial.Icon.gmd_edit_location,
"screen-account" to GoogleMaterial.Icon.gmd_account_circle,
"cyclestreets-account" to null,
"username" to null,
"password" to null,
"uploadsize" to null,
"screen-about" to GoogleMaterial.Icon.gmd_info_outline
"screen-maps-display" to GoogleMaterial.Icon.gmd_map,
"mapstyle" to null,
"mapfile" to null,
"confirm-new-route" to null,
"screen-routing-preferences" to GoogleMaterial.Icon.gmd_directions,
"routetype" to null,
"speed" to null,
"units" to null,
"screen-liveride" to GoogleMaterial.Icon.gmd_navigation,
"nearing-turn-distance" to null,
"offtrack-distance" to null,
"replan-distance" to null,
"screen-locations" to GoogleMaterial.Icon.gmd_edit_location,
"screen-account" to GoogleMaterial.Icon.gmd_account_circle,
"cyclestreets-account" to null,
"username" to null,
"password" to null,
"uploadsize" to null,
"screen-about" to GoogleMaterial.Icon.gmd_info_outline
)


Expand All @@ -49,11 +50,13 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
super.onCreate(savedInstance)

setupMapStyles()
setupMapFileList()

setSummary(CycleStreetsPreferences.PREF_ROUTE_TYPE_KEY)
setSummary(CycleStreetsPreferences.PREF_UNITS_KEY)
setSummary(CycleStreetsPreferences.PREF_SPEED_KEY)
setSummary(CycleStreetsPreferences.PREF_MAPSTYLE_KEY)
setSummary(CycleStreetsPreferences.PREF_MAPFILE_KEY)
setSummary(CycleStreetsPreferences.PREF_UPLOAD_SIZE)
setSummary(CycleStreetsPreferences.PREF_NEARING_TURN)
setSummary(CycleStreetsPreferences.PREF_OFFTRACK_DISTANCE)
Expand Down Expand Up @@ -114,7 +117,28 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP

private fun setupMapStyles() {
findPreference<ListPreference>(CycleStreetsPreferences.PREF_MAPSTYLE_KEY)?.apply {
TileSource.configurePreference(this)

if (this.value == CycleStreetsPreferences.MAPSTYLE_MAPSFORGE && MapPack.availableMapPacks(context).isEmpty()) {
Log.i(TAG, "Offline Vector Maps were selected, but there are no available map packs; default to OSM")
this.value = CycleStreetsPreferences.MAPSTYLE_OSM
}

TileSource.configurePreference(this)
}
}

private fun setupMapFileList() {
findPreference<ListPreference>(CycleStreetsPreferences.PREF_MAPFILE_KEY)?.apply {
populateMapFileList(this)
}
}

private fun populateMapFileList(mapfilePref: ListPreference) {
context?.let {
val titles = MapPack.availableMapPacks(it).map { pack: MapPack -> pack.title }
val ids = MapPack.availableMapPacks(it).map { pack: MapPack -> pack.id }
mapfilePref.entries = titles.toTypedArray()
mapfilePref.entryValues = ids.toTypedArray()
}
}

Expand Down Expand Up @@ -143,9 +167,36 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
prefUI.summary = prefUI.entry
if (prefUI is EditTextPreference)
prefUI.summary = prefUI.text
}

private fun setAccountSummary() {
if (CycleStreetsPreferences.PREF_MAPSTYLE_KEY == key)
setMapFileSummary((prefUI as ListPreference).value)
}

private fun setMapFileSummary(style: String) {
val pref = findPreference<Preference>(CycleStreetsPreferences.PREF_MAPFILE_KEY) ?: return
val mapfilePref = pref as ListPreference

val enabled = style == CycleStreetsPreferences.MAPSTYLE_MAPSFORGE
mapfilePref.isEnabled = enabled

if (!enabled)
return

if (mapfilePref.entryValues.isEmpty()) {
mapfilePref.isEnabled = false
return
}

val mapfile = CycleStreetsPreferences.mapfile()
var index = mapfilePref.findIndexOfValue(mapfile)
if (index == -1)
index = 0 // default to something

mapfilePref.setValueIndex(index)
mapfilePref.summary = mapfilePref.entries[index]
}

private fun setAccountSummary() {
val pref = findPreference<Preference>(CycleStreetsPreferences.PREF_ACCOUNT_KEY) ?: return
val account = pref as PreferenceScreen

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,19 @@ public static ITileSource mapRenderer(final Context context) {
final ITileSource renderer = source.renderer();

if (renderer instanceof MapsforgeOSMTileSource) {
final String mapFile = CycleStreetsPreferences.mapfile();
final MapPack pack = MapPack.findByPackage(context, mapFile);
if (pack.current())
((MapsforgeOSMTileSource)renderer).setMapFile(mapFile);
else {
MessageBox.YesNo(context,
R.string.tiles_map_pack_out_of_date,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
MapPack.searchGooglePlay(context);
}
});
final String mapId = CycleStreetsPreferences.mapfile();
final MapPack pack = MapPack.findById(context, mapId);
if (pack == null) {
CycleStreetsPreferences.resetMapstyle();
return source(DEFAULT_RENDERER).renderer();
}

if (pack.getDownloaded())
((MapsforgeOSMTileSource)renderer).setMapFile(pack.getPath());
else {
pack.download(context);
return source(DEFAULT_RENDERER).renderer();
}
}

return renderer;
Expand Down Expand Up @@ -197,6 +195,7 @@ private static void addBuiltInSources(final Context context) {
addTileSource("OpenCycleMap (shows hills)", OPENCYCLEMAP);
addTileSource("OpenStreetMap default style", OPENSTREETMAP);
addTileSource("Ordnance Survey OpenData", OSMAP);
addTileSource("Offline Vector Maps", MAPSFORGE);

builtInsAdded_ = true;
}
Expand Down
Loading