Skip to content
Closed
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
4 changes: 3 additions & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.

**Device (please complete the following information):**

**Please complete the following information**
- Device: [e.g. Pixel 2 XL]
- OS: [e.g. Android 8.1/LineageOS 15.1/…]
- App version: [e.g. 3.1.2]

**Additional context**
Add any other context about the problem here.
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ ext {
mockitoVersion = '2.28.2'
okHttpVersion = '3.12.0'
osmbonuspackVersion = '6.6.0'
osmdroidMapforgeVersion = '6.0.1'
osmdroidVersion = '6.1.0'
playServicesVersion = '17.0.0'
retrofitVersion = '2.6.1' // Dictates version of okhttp in their dependencies which clashes in tests.
Expand Down Expand Up @@ -213,6 +214,7 @@ dependencies {
implementation "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion"
implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion"
implementation "org.osmdroid:osmdroid-android:$osmdroidVersion"
implementation "org.osmdroid:osmdroid-mapsforge:$osmdroidMapforgeVersion"

googleImplementation "com.google.android.gms:play-services-analytics:$playServicesVersion"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@

import org.osmdroid.tileprovider.tilesource.TileSourceFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import fi.bitrite.android.ws.R;
import fi.bitrite.android.ws.model.ZoomedLocation;

Expand All @@ -28,6 +34,9 @@ public enum DistanceUnit {
private final static String HIDE_CURRENT_LOCATION_BTN = "hide_current_location_button";

private final String mKeyDistanceUnit;
private final String mOfflineMapEnabled;
private final String mOfflineMapSource;
private final String mOfflineMapStyle;
private final String mKeyTileSource;
private final String mKeyMessageRefreshInterval;
private final String mKeyDataSaverMode;
Expand Down Expand Up @@ -55,6 +64,11 @@ public enum DistanceUnit {

final Resources res = context.getResources();
mKeyDistanceUnit = res.getString(R.string.prefs_distance_unit_key);

mOfflineMapEnabled= res.getString(R.string.prefs_offline_map_enabled);
mOfflineMapSource = res.getString(R.string.prefs_offline_map_source);
mOfflineMapStyle = res.getString(R.string.prefs_offline_map_style);

mKeyTileSource = res.getString(R.string.prefs_tile_source_key);
mKeyMessageRefreshInterval = res.getString(R.string.prefs_message_refresh_interval_min_key);
mKeyDataSaverMode = res.getString(R.string.prefs_data_saver_mode_key);
Expand Down Expand Up @@ -114,6 +128,22 @@ public String getDistanceUnitShort() {
}
}

public boolean isOfflineMapEnabled() {
return mSharedPreferences.getBoolean(mOfflineMapEnabled, false);
}
public File[] getOfflineMapSourceFiles() {
Set<String> sources = mSharedPreferences.getStringSet(mOfflineMapSource, Collections.singleton(""));
List<File> sourceFiles = new ArrayList<>();
for (String source : sources) {
sourceFiles.add(new File(source));
}
return sourceFiles.toArray(new File[0]);
}

public String getOfflineMapStyle() {
return mSharedPreferences.getString(mOfflineMapStyle, "");
}

public String getTileSourceStr() {
return mSharedPreferences.getString(mKeyTileSource, mDefaultTileSource);
}
Expand Down
39 changes: 35 additions & 4 deletions app/src/main/java/fi/bitrite/android/ws/ui/MapFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,19 @@
import android.widget.TextView;
import android.widget.Toast;

import org.mapsforge.map.rendertheme.ExternalRenderTheme;
import org.mapsforge.map.rendertheme.XmlRenderTheme;
import org.osmdroid.api.IGeoPoint;
import org.osmdroid.api.IMapController;
import org.osmdroid.bonuspack.clustering.StaticCluster;
import org.osmdroid.config.Configuration;
import org.osmdroid.events.MapListener;
import org.osmdroid.events.ScrollEvent;
import org.osmdroid.events.ZoomEvent;
import org.osmdroid.mapsforge.MapsForgeTileProvider;
import org.osmdroid.mapsforge.MapsForgeTileSource;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.tileprovider.util.SimpleRegisterReceiver;
import org.osmdroid.util.BoundingBox;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
Expand All @@ -48,6 +53,8 @@
import org.osmdroid.views.overlay.mylocation.IMyLocationProvider;
import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -124,6 +131,7 @@ public class MapFragment extends BaseFragment {
mDistanceUnit = mSettingsRepository.getDistanceUnit();
mDistanceUnitShort = mSettingsRepository.getDistanceUnitShort();
}
// TODO: reflect changes in offline/online map
};

private static final int POSITION_PRIORITY_ESTIMATE = 0;
Expand Down Expand Up @@ -177,6 +185,10 @@ public void onCreate(Bundle savedInstanceState) {
mMarkerClusterer.setOnClusterClickListener(this::onClusterClick);

mHideLocationBtn = mSettingsRepository.getHideLocationButton();

if (mSettingsRepository.isOfflineMapEnabled()) {
MapsForgeTileSource.createInstance(getActivity().getApplication());
}
}

@Nullable
Expand Down Expand Up @@ -215,11 +227,30 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
mMap.setBuiltInZoomControls(false);
mMap.setMultiTouchControls(true);

String tileSourceStr = mSettingsRepository.getTileSourceStr();
if (!TileSourceFactory.containsTileSource(tileSourceStr)) {
tileSourceStr = TileSourceFactory.DEFAULT_TILE_SOURCE.name();
if (mSettingsRepository.isOfflineMapEnabled()) {
// use offline map
File style = new File(mSettingsRepository.getOfflineMapStyle());
XmlRenderTheme theme = null;
try {
theme = new ExternalRenderTheme(style);
} catch (FileNotFoundException ignore) {
// default rendering theme is used if theme == null
}

MapsForgeTileSource fromFiles = MapsForgeTileSource.createFromFiles(
mSettingsRepository.getOfflineMapSourceFiles(), theme, style.getName());
MapsForgeTileProvider forge = new MapsForgeTileProvider(
new SimpleRegisterReceiver(getContext()),
fromFiles, null);
mMap.setTileProvider(forge);
} else {
// use online map
String tileSourceStr = mSettingsRepository.getTileSourceStr();
if (!TileSourceFactory.containsTileSource(tileSourceStr)) {
tileSourceStr = TileSourceFactory.DEFAULT_TILE_SOURCE.name();
}
mMap.setTileSource(TileSourceFactory.getTileSource(tileSourceStr));
}
mMap.setTileSource(TileSourceFactory.getTileSource(tileSourceStr));

if (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
addMyLocationOverlay();
Expand Down
85 changes: 82 additions & 3 deletions app/src/main/java/fi/bitrite/android/ws/ui/SettingsFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Environment;
import android.support.v14.preference.MultiSelectListPreference;
import android.support.v14.preference.SwitchPreference;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import android.support.v4.util.Pair;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
Expand All @@ -13,6 +17,8 @@
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
Expand All @@ -37,6 +43,9 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Inject

@BindString(R.string.prefs_distance_unit_key) String mKeyDistanceUnit;
@BindString(R.string.prefs_tile_source_key) String mTileMapSource;
@BindString(R.string.prefs_offline_map_enabled) String mOfflineMap;
@BindString(R.string.prefs_offline_map_source) String mOfflineMapSource;
@BindString(R.string.prefs_offline_map_style) String mOfflineMapStyle;
@BindString(R.string.prefs_message_refresh_interval_min_key) String mKeyMessageRefreshInterval;

public static Fragment create() {
Expand Down Expand Up @@ -81,6 +90,11 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key == null) {
return;
}

// TODO: only update changed preference specified by key
setSummary();
}

Expand All @@ -90,8 +104,17 @@ private void setSummary() {
R.string.prefs_distance_unit_summary,
mSettingsRepository.getDistanceUnitLong()));

// map sources
setAvailableMapSources((ListPreference) findPreference(mTileMapSource));
// offline map sources
SwitchPreference offlineMap = (SwitchPreference) findPreference(mOfflineMap);
// offline maps need at least one source to be enabled
offlineMap.setEnabled(mSettingsRepository.getOfflineMapSourceFiles().length > 0);
setAvailableOfflineMapSources(
(MultiSelectListPreference) findPreference(mOfflineMapSource));
setAvailableOfflineStyleSources((ListPreference) findPreference(mOfflineMapStyle));

// online map sources
findPreference(mTileMapSource).setEnabled(!offlineMap.isChecked());
setAvailableOnlineMapSources((ListPreference) findPreference(mTileMapSource));

// message refresh interval
Resources res = getResources();
Expand All @@ -117,7 +140,63 @@ public void onDisplayPreferenceDialog(Preference preference) {
}
}

private void setAvailableMapSources(final ListPreference tileSourcePreference) {
private void setAvailableOfflineMapSources(MultiSelectListPreference pref) {
File[] sourceFiles = mSettingsRepository.getOfflineMapSourceFiles();
StringBuilder summary = new StringBuilder();
if (sourceFiles.length > 0) {
for (File source : sourceFiles) {
summary.append(source.getName()).append(", ");
}
summary.replace(summary.lastIndexOf(","), summary.length(), "");
}
pref.setSummary(summary.toString());

File folder = new File(Environment.getExternalStorageDirectory(), "/oruxmaps/mapfiles");
Pair<CharSequence[], CharSequence[]>
entries = setAvailableOfflineSources(
findFiles(new ArrayList<>(), folder.listFiles(), ".map"));
pref.setEntries(entries.first);
pref.setEntryValues(entries.second);
}

private void setAvailableOfflineStyleSources(ListPreference pref) {
pref.setSummary(new File(mSettingsRepository.getOfflineMapStyle()).getName());
File folder = new File(Environment.getExternalStorageDirectory(), "/oruxmaps/mapstyles");
Pair<CharSequence[], CharSequence[]>
entries = setAvailableOfflineSources(
findFiles(new ArrayList<>(), folder.listFiles(), ".xml"));
pref.setEntries(entries.first);
pref.setEntryValues(entries.second);
}

private Pair<CharSequence[], CharSequence[]> setAvailableOfflineSources(
List<File> rawSourceValues) {
final List<String> sourceNames = new LinkedList<>();
final List<String> sourceValues = new LinkedList<>();
for (File f : rawSourceValues) {
sourceNames.add(f.getName());
sourceValues.add(f.getAbsolutePath());
}
return new Pair<>(sourceNames.toArray(new CharSequence[0]),
sourceValues.toArray(new CharSequence[0]));
}

private List<File> findFiles(List<File> foundFiles, File[] filesArray, String ext) {
for (File file : filesArray) {
if (file.isDirectory()) {
findFiles(foundFiles,
file.listFiles(path -> (path.isDirectory() || path.getName()
.toLowerCase()
.endsWith(ext))),
ext);
} else if (file.getName().toLowerCase().endsWith(ext)) {
foundFiles.add(file);
}
}
return foundFiles;
}

private void setAvailableOnlineMapSources(final ListPreference tileSourcePreference) {
tileSourcePreference.setSummary(getString(
R.string.prefs_tile_source_summary,
mSettingsRepository.getTileSourceStr()));
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@
<string name="prefs_tile_source_summary" translatable="false">%1$s</string>
<string name="prefs_tile_source_us_only">%1$s (US only)</string>

<string name="prefs_offline_map_enabled" translatable="false">offline_map_enabled</string>
<string name="prefs_offline_map_source" translatable="false">offline_map_source</string>
<string name="prefs_offline_map_style" translatable="false">offline_map_style</string>

<string name="prefs_message_refresh_interval_min_key" translatable="false">message_reload_interval_min</string>
<string name="prefs_message_refresh_interval_min_title">Messages poll frequency</string>
<plurals name="prefs_message_refresh_interval_min_summary">
Expand Down
51 changes: 39 additions & 12 deletions app/src/main/res/xml/preferences.xml
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:android="http://schemas.android.com/apk/res/android" >

<ListPreference
android:defaultValue="@string/prefs_distance_unit_default"
android:entries="@array/prefs_distance_unit_entries"
android:entryValues="@array/prefs_distance_unit_entry_values"
android:key="@string/prefs_distance_unit_key"
android:summary="@string/prefs_distance_unit_summary"
android:title="@string/prefs_distance_unit_title" />
<PreferenceCategory
android:title="Map">

<SwitchPreference
android:key="@string/prefs_offline_map_enabled"
android:title="Offline maps"
android:summaryOn="Enabled (this disables online maps)"
android:summaryOff="Disabled (this enables online maps)"
android:checked="false" />

<MultiSelectListPreference
android:key="@string/prefs_offline_map_source"
android:title="Offline map source" />

<ListPreference
android:key="@string/prefs_offline_map_style"
android:title="Offline map style" />

<ListPreference
android:key="@string/prefs_tile_source_key"
android:summary="@string/prefs_tile_source_summary"
android:title="Online map style" />
<!-- android:title="@string/prefs_tile_source_title" /> -->

<ListPreference
android:key="@string/prefs_tile_source_key"
android:summary="@string/prefs_tile_source_summary"
android:title="@string/prefs_tile_source_title" />

</PreferenceCategory>

<PreferenceCategory
android:title="Messaging">

<fi.bitrite.android.ws.ui.preference.RefreshIntervalPreference
android:defaultValue="@integer/prefs_message_refresh_interval_min_default"
Expand All @@ -28,4 +45,14 @@
android:title="@string/prefs_data_saver_mode_title"
android:summary="@string/prefs_data_saver_mode_summary"/>

</PreferenceCategory>

<ListPreference
android:defaultValue="@string/prefs_distance_unit_default"
android:entries="@array/prefs_distance_unit_entries"
android:entryValues="@array/prefs_distance_unit_entry_values"
android:key="@string/prefs_distance_unit_key"
android:summary="@string/prefs_distance_unit_summary"
android:title="@string/prefs_distance_unit_title" />

</PreferenceScreen>