Merge pull request #439 from zod/remove-coordinate-readers

Remove coordinate readers

Sorry for the delay I didn't recognize the ready sign.
This commit is contained in:
afischerdev 2022-06-26 15:25:20 +02:00 committed by GitHub
commit 9d37e2c648
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 492 additions and 1181 deletions

View file

@ -63,6 +63,7 @@ public class RoutingEngine extends Thread
private Object[] extract; private Object[] extract;
private boolean directWeaving = !Boolean.getBoolean( "disableDirectWeaving" ); private boolean directWeaving = !Boolean.getBoolean( "disableDirectWeaving" );
private String outfile;
public RoutingEngine( String outfileBase, String logfileBase, File segmentDir, public RoutingEngine( String outfileBase, String logfileBase, File segmentDir,
List<OsmNodeNamed> waypoints, RoutingContext rc ) List<OsmNodeNamed> waypoints, RoutingContext rc )
@ -185,6 +186,7 @@ public class RoutingEngine extends Thread
track.writeGpx( filename ); track.writeGpx( filename );
foundTrack = track; foundTrack = track;
alternativeIndex = i; alternativeIndex = i;
outfile = filename;
} }
else else
{ {
@ -1369,4 +1371,7 @@ public class RoutingEngine extends Thread
return terminated; return terminated;
} }
public String getOutfile() {
return outfile;
}
} }

View file

@ -17,6 +17,7 @@ android {
setProperty("archivesBaseName", "BRouterApp." + defaultConfig.versionName) setProperty("archivesBaseName", "BRouterApp." + defaultConfig.versionName)
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 30
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@ -73,21 +74,6 @@ android {
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
flavorDimensions "api"
productFlavors {
api19 {
dimension "api"
targetSdkVersion 19
}
api30 {
dimension "api"
targetSdkVersion 30
}
}
applicationVariants.all { applicationVariants.all {
variant -> variant ->
{ {

View file

@ -0,0 +1,82 @@
package btools.routingapp;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.notNullValue;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.FileWriter;
public class CoordinateReaderTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@Test
public void readNogoRoute() throws Exception {
File importFolder = temporaryFolder.newFolder("brouter", "import", "tracks");
File tempFile = new File(importFolder, "nogo_test.gpx");
try (FileWriter writer = new FileWriter(tempFile)) {
writer.write("<?xml version=\"1.0\"?>\n" +
"<gpx version=\"1.1\"\n" +
"creator=\"Viking 1.9 -- http://viking.sf.net/\"\n" +
"xmlns=\"http://www.topografix.com/GPX/1/1\" xmlns:gpxx=\"http://www.garmin.com/xmlschemas/GpxExtensions/v3\" xmlns:wptx1=\"http://www.garmin.com/xmlschemas/WaypointExtension/v1\" xmlns:gpxtpx=\"http://www.garmin.com/xmlschemas/TrackPointExtension/v2\" xmlns:gpxpx=\"http://www.garmin.com/xmlschemas/PowerExtension/v1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www8.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/WaypointExtension/v1 http://www8.garmin.com/xmlschemas/WaypointExtensionv1.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v2 http://www.garmin.com/xmlschemas/TrackPointExtensionv2.xsd http://www.garmin.com/xmlschemas/PowerExtensionv1.xsd\">\n" +
" <name>Nogo Route</name>\n" +
" <metadata>\n" +
" </metadata>\n" +
"<rte>\n" +
" <name>Nogo Oststadt</name>\n" +
" <extensions><gpxx:TrackExtension><gpxx:DisplayColor>Red</gpxx:DisplayColor></gpxx:TrackExtension></extensions>\n" +
" <rtept lat=\"49.009516920259095\" lon=\"8.423623305130004\">\n" +
" </rtept>\n" +
" <rtept lat=\"49.01034732709107\" lon=\"8.434330683517455\">\n" +
" </rtept>\n" +
" <rtept lat=\"49.01247254251079\" lon=\"8.445338469314574\">\n" +
" </rtept>\n" +
"</rte>\n" +
"</gpx>");
}
CoordinateReader coordinateReader = CoordinateReader.obtainValidReader(temporaryFolder.getRoot().getAbsolutePath(), false);
assertThat(coordinateReader.nogopoints, hasSize(1));
// Name should return "Nogo Oststadt", "Nogo Route" or "nogo_test.gpx"
assertThat(coordinateReader.nogopoints.get(0).name, equalTo("nogo_test"));
assertThat(coordinateReader.nogopoints.get(0).radius, closeTo(810.0, 5.0));
}
@Test
public void readWaypoints() throws Exception {
File importFolder = temporaryFolder.newFolder("brouter", "import");
File tempFile = new File(importFolder, "favourites.gpx");
try (FileWriter writer = new FileWriter(tempFile)) {
// https://en.wikipedia.org/wiki/GPS_Exchange_Format#Sample_GPX_document
writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<gpx\n" +
" version=\"1.1\"\n" +
" creator=\"Runkeeper - http://www.runkeeper.com\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xmlns=\"http://www.topografix.com/GPX/1/1\"\n" +
" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\"\n" +
" xmlns:gpxtpx=\"http://www.garmin.com/xmlschemas/TrackPointExtension/v1\">\n" +
"<wpt lat=\"37.778259000\" lon=\"-122.391386000\"><ele>3.4</ele><time>2016-06-17T23:41:03Z</time><name>from</name></wpt>\n" +
"<wpt lat=\"37.778194000\" lon=\"-122.391226000\"><ele>3.4</ele><time>2016-06-17T23:41:13Z</time><name>to</name></wpt>\n" +
"<wpt lat=\"37.778297000\" lon=\"-122.391174000\"><ele>3.4</ele><time>2016-06-17T23:41:18Z</time><name>via1</name></wpt>\n" +
"<wpt lat=\"37.778378000\" lon=\"-122.391117000\"><ele>3.4</ele><time>2016-06-17T23:41:23Z</time><name>nogo100 Test</name></wpt>\n" +
"</gpx>");
}
CoordinateReader coordinateReader = CoordinateReader.obtainValidReader(temporaryFolder.getRoot().getAbsolutePath(), false);
assertThat(coordinateReader, notNullValue());
// from, to, viaX are parsed into waypoints
assertThat(coordinateReader.waypoints, hasSize(3));
assertThat(coordinateReader.nogopoints, hasSize(1));
coordinateReader.readAllPoints();
assertThat(coordinateReader.allpoints, hasSize(4));
}
}

View file

@ -7,7 +7,6 @@
<uses-permission <uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" /> tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
@ -92,5 +91,15 @@
android:exported="true" android:exported="true"
android:process=":brouter_service" /> android:process=":brouter_service" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="btools.routing.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
</application> </application>
</manifest> </manifest>

View file

@ -9,11 +9,10 @@ import android.content.pm.PackageManager;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.StatFs; import android.os.StatFs;
import android.widget.EditText; import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import androidx.core.os.EnvironmentCompat; import androidx.core.os.EnvironmentCompat;
@ -22,6 +21,7 @@ import java.io.File;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -43,30 +43,32 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
private static final int DIALOG_SELECTBASEDIR_ID = 11; private static final int DIALOG_SELECTBASEDIR_ID = 11;
private static final int DIALOG_MAINACTION_ID = 12; private static final int DIALOG_MAINACTION_ID = 12;
private static final int DIALOG_OLDDATAHINT_ID = 13; private static final int DIALOG_OLDDATAHINT_ID = 13;
private static final int DIALOG_SHOW_WP_HELP_ID = 14;
private static final int DIALOG_SHOW_WP_SCANRESULT_ID = 15;
private static final int DIALOG_SHOW_REPEAT_TIMEOUT_HELP_ID = 16; private static final int DIALOG_SHOW_REPEAT_TIMEOUT_HELP_ID = 16;
private static final int DIALOG_SHOW_API23_HELP_ID = 17; private final Set<Integer> dialogIds = new HashSet<>();
private BRouterView mBRouterView; private BRouterView mBRouterView;
private PowerManager mPowerManager; private String[] availableProfiles;
private WakeLock mWakeLock; private String selectedProfile = null;
private List<File> availableBasedirs;
private String[] basedirOptions;
private int selectedBasedir;
private String[] availableWaypoints;
private String[] routingModes;
private boolean[] routingModesChecked;
private String message = null;
private String[] availableVias;
private Set<String> selectedVias;
private List<OsmNodeNamed> nogoList;
private String errorMessage;
private String title;
private int wpCount;
/** /**
* Called when the activity is first created. * Called when the activity is first created.
*/ */
@Override @Override
@SuppressWarnings("deprecation")
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// Get an instance of the PowerManager
mPowerManager = (PowerManager) getSystemService(POWER_SERVICE);
// Create a bright wake lock
mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, getClass().getName());
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass(); int memoryClass = am.getMemoryClass();
@ -77,7 +79,6 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
} }
@Override @Override
@SuppressWarnings("deprecation")
protected Dialog onCreateDialog(int id) { protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder; AlertDialog.Builder builder;
builder = new AlertDialog.Builder(this); builder = new AlertDialog.Builder(this);
@ -131,47 +132,6 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
} }
}); });
return builder.create(); return builder.create();
case DIALOG_SHOW_WP_HELP_ID:
builder
.setTitle("No Waypoint Database found")
.setMessage(
"The simple scan did not find any map-tool directory including a waypoint database. "
+ "Reason could be there is no map-tool installed (osmand, locus or oruxmaps), or at an "
+ "unusual path, or it contains no waypoints yet. That's o.k. if you want to use BRouter "
+ "in server-mode only - in that case you can still use the 'Server-Mode' button to "
+ "configure the profile mapping. But you will not be able to use nogo-points or do "
+ "long distance calculations. If you know the path to your map-tool, you can manually "
+ "configure it in 'storageconfig.txt'. Or I can do an extended scan searching "
+ "your sd-card for a valid waypoint database").setPositiveButton("Scan", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mBRouterView.startWpDatabaseScan();
}
}).setNegativeButton("Exit", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
});
return builder.create();
case DIALOG_SHOW_API23_HELP_ID:
builder
.setTitle("Android >=6 limitations")
.setMessage(
"You are using the BRouter APP on Android >= 6, where classic mode is no longer supported. "
+ "Reason is that security policy does not permit any longer to read the waypoint databases of other apps. "
+ "That's o.k. if you want to use BRouter in server-mode only, where the apps actively send the waypoints "
+ "via a remote procedure call to BRouter (And Locus can also send nogo areas). "
+ "So the only functions you need to start the BRouter App are 1) to initially define the base directory "
+ "2) to download routing data files and 3) to configure the profile mapping via the 'Server-Mode' button. "
+ "You will eventually not be able to define nogo-areas (OsmAnd, Orux) or to do "
+ "very long distance calculations. If you want to get classic mode back, you can manually install "
+ "the APK of the BRouter App from the release page ( http://brouter.de/brouter/revisions.html ), which "
+ "is still built against Android API 10, and does not have these limitations. "
).setNegativeButton("Exit", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
});
return builder.create();
case DIALOG_SHOW_REPEAT_TIMEOUT_HELP_ID: case DIALOG_SHOW_REPEAT_TIMEOUT_HELP_ID:
builder builder
.setTitle("Successfully prepared a timeout-free calculation") .setTitle("Successfully prepared a timeout-free calculation")
@ -185,20 +145,6 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
} }
}); });
return builder.create(); return builder.create();
case DIALOG_SHOW_WP_SCANRESULT_ID:
builder
.setTitle("Waypoint Database ")
.setMessage("Found Waypoint-Database(s) for maptool-dir: " + maptoolDirCandidate
+ " Configure that?").setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mBRouterView.saveMaptoolDir(maptoolDirCandidate);
}
}).setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
});
return builder.create();
case DIALOG_OLDDATAHINT_ID: case DIALOG_OLDDATAHINT_ID:
builder builder
.setTitle("Local setup needs reset") .setTitle("Local setup needs reset")
@ -238,7 +184,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
builder.setTitle("Enter SDCARD base dir:"); builder.setTitle("Enter SDCARD base dir:");
builder.setMessage(message); builder.setMessage(message);
final EditText input = new EditText(this); final EditText input = new EditText(this);
input.setText(defaultbasedir); // input.setText(defaultbasedir);
builder.setView(input); builder.setView(input);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) { public void onClick(DialogInterface dialog, int whichButton) {
@ -305,31 +251,46 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
}); });
return builder.create(); return builder.create();
case DIALOG_SHOWRESULT_ID: case DIALOG_SHOWRESULT_ID:
String leftLabel = wpCount < 0 ? (wpCount != -2 ? "Exit" : "Help") : (wpCount == 0 ? "Select from" : "Select to/via"); // -3: Repeated route calculation
String rightLabel = wpCount < 2 ? (wpCount == -3 ? "Help" : "Server-Mode") : "Calc Route"; // -2: Unused?
// -1: Route calculated
// other: Select waypoints for route calculation
builder.setTitle(title).setMessage(errorMessage);
builder.setTitle(title).setMessage(errorMessage).setPositiveButton(leftLabel, new DialogInterface.OnClickListener() { // Neutral button
public void onClick(DialogInterface dialog, int id) { if (wpCount == 0) {
if (wpCount == -2) { builder.setNeutralButton("Server-Mode", (dialog, which) -> {
showWaypointDatabaseHelp();
} else if (wpCount == -1 || wpCount == -3) {
finish();
} else {
mBRouterView.pickWaypoints();
}
}
}).setNegativeButton(rightLabel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
if (wpCount == -3) {
showRepeatTimeoutHelp();
} else if (wpCount < 2) {
mBRouterView.startConfigureService(); mBRouterView.startConfigureService();
} else { });
} else if (wpCount == -3) {
builder.setNeutralButton("Info", (dialog, which) -> {
showRepeatTimeoutHelp();
});
} else if (wpCount >= 2) {
builder.setNeutralButton("Calc Route", (dialog, which) -> {
mBRouterView.finishWaypointSelection(); mBRouterView.finishWaypointSelection();
mBRouterView.startProcessing(selectedProfile); mBRouterView.startProcessing(selectedProfile);
}
}
}); });
}
// Positive button
if (wpCount == -3 || wpCount == -1) {
builder.setPositiveButton("Share GPX", (dialog, which) -> {
mBRouterView.shareTrack();
finish();
});
} else if (wpCount >= 0) {
String selectLabel = wpCount == 0 ? "Select from" : "Select to/via";
builder.setPositiveButton(selectLabel, (dialog, which) -> {
mBRouterView.pickWaypoints();
});
}
// Negative button
builder.setNegativeButton("Exit", (dialog, which) -> {
finish();
});
return builder.create(); return builder.create();
case DIALOG_MODECONFIGOVERVIEW_ID: case DIALOG_MODECONFIGOVERVIEW_ID:
builder.setTitle("Success").setMessage(message).setPositiveButton("Exit", new DialogInterface.OnClickListener() { builder.setTitle("Success").setMessage(message).setPositiveButton("Exit", new DialogInterface.OnClickListener() {
@ -355,41 +316,18 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
private boolean[] getCheckedBooleanArray(int size) { private boolean[] getCheckedBooleanArray(int size) {
boolean[] checked = new boolean[size]; boolean[] checked = new boolean[size];
for (int i = 0; i < checked.length; i++) checked[i] = true; Arrays.fill(checked, true);
return checked; return checked;
} }
private String[] availableProfiles;
private String selectedProfile = null;
private List<File> availableBasedirs;
private String[] basedirOptions;
private int selectedBasedir;
private String[] availableWaypoints;
private String[] routingModes;
private boolean[] routingModesChecked;
private String defaultbasedir = null;
private String message = null;
private String[] availableVias;
private Set<String> selectedVias;
private List<OsmNodeNamed> nogoList;
private String maptoolDirCandidate;
@SuppressWarnings("deprecation")
public void selectProfile(String[] items) { public void selectProfile(String[] items) {
availableProfiles = items; availableProfiles = items;
Arrays.sort(availableProfiles);
// show main dialog // show main dialog
showDialog(DIALOG_MAINACTION_ID); showDialog(DIALOG_MAINACTION_ID);
} }
@SuppressWarnings("deprecation")
public void startDownloadManager() { public void startDownloadManager() {
if (!mBRouterView.hasUpToDateLookups()) { if (!mBRouterView.hasUpToDateLookups()) {
showDialog(DIALOG_OLDDATAHINT_ID); showDialog(DIALOG_OLDDATAHINT_ID);
@ -398,19 +336,17 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
} }
} }
@SuppressWarnings("deprecation") public void selectBasedir(ArrayList<File> items, String message) {
public void selectBasedir(ArrayList<File> items, String defaultBasedir, String message) {
this.defaultbasedir = defaultBasedir;
this.message = message; this.message = message;
availableBasedirs = items; availableBasedirs = items;
ArrayList<Long> dirFreeSizes = new ArrayList<Long>(); ArrayList<Long> dirFreeSizes = new ArrayList<>();
for (File f : items) { for (File f : items) {
long size = 0L; long size = 0L;
try { try {
StatFs stat = new StatFs(f.getAbsolutePath()); StatFs stat = new StatFs(f.getAbsolutePath());
size = (long) stat.getAvailableBlocks() * stat.getBlockSize(); size = (long) stat.getAvailableBlocks() * stat.getBlockSize();
} catch (Exception e) { /* ignore */ } } catch (Exception e) { /* ignore */ }
dirFreeSizes.add(Long.valueOf(size)); dirFreeSizes.add(size);
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
@ -431,7 +367,6 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
showDialog(DIALOG_SELECTBASEDIR_ID); showDialog(DIALOG_SELECTBASEDIR_ID);
} }
@SuppressWarnings("deprecation")
public void selectRoutingModes(String[] modes, boolean[] modesChecked, String message) { public void selectRoutingModes(String[] modes, boolean[] modesChecked, String message) {
routingModes = modes; routingModes = modes;
routingModesChecked = modesChecked; routingModesChecked = modesChecked;
@ -439,74 +374,45 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
showDialog(DIALOG_ROUTINGMODES_ID); showDialog(DIALOG_ROUTINGMODES_ID);
} }
@SuppressWarnings("deprecation")
public void showModeConfigOverview(String message) { public void showModeConfigOverview(String message) {
this.message = message; this.message = message;
showDialog(DIALOG_MODECONFIGOVERVIEW_ID); showDialog(DIALOG_MODECONFIGOVERVIEW_ID);
} }
@SuppressWarnings("deprecation")
public void selectVias(String[] items) { public void selectVias(String[] items) {
availableVias = items; availableVias = items;
selectedVias = new HashSet<String>(availableVias.length); selectedVias = new HashSet<>(availableVias.length);
for (String via : items) Collections.addAll(selectedVias, items);
selectedVias.add(via);
showDialog(DIALOG_VIASELECT_ID); showDialog(DIALOG_VIASELECT_ID);
} }
@SuppressWarnings("deprecation")
public void selectWaypoint(String[] items) { public void selectWaypoint(String[] items) {
availableWaypoints = items; availableWaypoints = items;
showNewDialog(DIALOG_PICKWAYPOINT_ID); showNewDialog(DIALOG_PICKWAYPOINT_ID);
} }
@SuppressWarnings("deprecation")
public void showWaypointDatabaseHelp() {
if (mBRouterView.canAccessSdCard) {
showNewDialog(DIALOG_SHOW_WP_HELP_ID);
} else {
showNewDialog(DIALOG_SHOW_API23_HELP_ID);
}
}
@SuppressWarnings("deprecation")
public void showRepeatTimeoutHelp() { public void showRepeatTimeoutHelp() {
showNewDialog(DIALOG_SHOW_REPEAT_TIMEOUT_HELP_ID); showNewDialog(DIALOG_SHOW_REPEAT_TIMEOUT_HELP_ID);
} }
@SuppressWarnings("deprecation")
public void showWpDatabaseScanSuccess(String bestGuess) {
maptoolDirCandidate = bestGuess;
showNewDialog(DIALOG_SHOW_WP_SCANRESULT_ID);
}
@SuppressWarnings("deprecation")
public void selectNogos(List<OsmNodeNamed> nogoList) { public void selectNogos(List<OsmNodeNamed> nogoList) {
this.nogoList = nogoList; this.nogoList = nogoList;
showDialog(DIALOG_NOGOSELECT_ID); showDialog(DIALOG_NOGOSELECT_ID);
} }
private Set<Integer> dialogIds = new HashSet<Integer>();
private void showNewDialog(int id) { private void showNewDialog(int id) {
if (dialogIds.contains(Integer.valueOf(id))) { if (dialogIds.contains(id)) {
removeDialog(id); removeDialog(id);
} }
dialogIds.add(Integer.valueOf(id)); dialogIds.add(id);
showDialog(id); showDialog(id);
} }
private String errorMessage;
private String title;
private int wpCount;
@SuppressWarnings("deprecation")
public void showErrorMessage(String msg) { public void showErrorMessage(String msg) {
errorMessage = msg; errorMessage = msg;
showNewDialog(DIALOG_EXCEPTION_ID); showNewDialog(DIALOG_EXCEPTION_ID);
} }
@SuppressWarnings("deprecation")
public void showResultMessage(String title, String msg, int wpCount) { public void showResultMessage(String title, String msg, int wpCount) {
errorMessage = msg; errorMessage = msg;
this.title = title; this.title = title;
@ -514,50 +420,31 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
showNewDialog(DIALOG_SHOWRESULT_ID); showNewDialog(DIALOG_SHOWRESULT_ID);
} }
@Override
protected void onResume() {
super.onResume();
/*
* when the activity is resumed, we acquire a wake-lock so that the screen
* stays on, since the user will likely not be fiddling with the screen or
* buttons.
*/
mWakeLock.acquire();
}
@Override @Override
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
/*
* When the activity is paused, we make sure to stop the router
*/
// Stop the simulation // When the activity is paused, we make sure to stop the router
mBRouterView.stopRouting(); mBRouterView.stopRouting();
// and release our wake-lock
mWakeLock.release();
}
private String getStorageState(File f) {
return EnvironmentCompat.getStorageState(f); //Environment.MEDIA_MOUNTED
} }
public ArrayList<File> getStorageDirectories() { public ArrayList<File> getStorageDirectories() {
ArrayList<File> list = null; ArrayList<File> list = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
list = new ArrayList<File>(Arrays.asList(getExternalMediaDirs())); list = new ArrayList<>(Arrays.asList(getExternalMediaDirs()));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
list = new ArrayList<File>(Arrays.asList(getExternalFilesDirs(null))); list = new ArrayList<>(Arrays.asList(getExternalFilesDirs(null)));
} }
ArrayList<File> res = new ArrayList<File>(); ArrayList<File> res = new ArrayList<>();
if (list != null) {
for (File f : list) { for (File f : list) {
if (f != null) { if (f != null) {
if (getStorageState(f).equals(Environment.MEDIA_MOUNTED)) if (EnvironmentCompat.getStorageState(f).equals(Environment.MEDIA_MOUNTED))
res.add(f); res.add(f);
} }
} }
}
if (checkExternalStorageWritable()) { if (checkExternalStorageWritable()) {
res.add(Environment.getExternalStorageDirectory()); res.add(Environment.getExternalStorageDirectory());
@ -588,7 +475,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
} }
@Override @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults); super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 0) { if (requestCode == 0) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {

View file

@ -1,7 +1,16 @@
package btools.routingapp; package btools.routingapp;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Base64;
import android.util.Log;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -10,26 +19,9 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.zip.GZIPOutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.zip.GZIPOutputStream;
import android.Manifest;
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.util.Base64;
import androidx.core.content.ContextCompat;
import btools.router.OsmNodeNamed; import btools.router.OsmNodeNamed;
@ -185,18 +177,7 @@ public class BRouterService extends Service {
private void readNogos(BRouterWorker worker, String baseDir) throws Exception { private void readNogos(BRouterWorker worker, String baseDir) throws Exception {
// add nogos from waypoint database // add nogos from waypoint database
int deviceLevel = android.os.Build.VERSION.SDK_INT; CoordinateReader cor = CoordinateReader.obtainValidReader(baseDir, true);
int targetSdkVersion = getApplicationInfo().targetSdkVersion;
boolean canAccessSdCard = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !Environment.isExternalStorageLegacy()) {
canAccessSdCard = false;
}
if (ContextCompat.checkSelfPermission(BRouterService.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
canAccessSdCard = false;
}
AppLogger.log("dev/target=" + deviceLevel + "/" + targetSdkVersion + " canAccessSdCard=" + canAccessSdCard);
CoordinateReader cor = CoordinateReader.obtainValidReader(baseDir, worker.segmentDir, canAccessSdCard, true);
worker.nogoList = new ArrayList<OsmNodeNamed>(cor.nogopoints); worker.nogoList = new ArrayList<OsmNodeNamed>(cor.nogopoints);
worker.nogoPolygonsList = new ArrayList<OsmNodeNamed>(); worker.nogoPolygonsList = new ArrayList<OsmNodeNamed>();
} }

View file

@ -2,19 +2,19 @@ package btools.routingapp;
import android.Manifest; import android.Manifest;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.os.Build;
import android.os.Environment;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
@ -26,7 +26,6 @@ import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -47,10 +46,11 @@ import btools.router.RoutingHelper;
import btools.util.CheapRuler; import btools.util.CheapRuler;
public class BRouterView extends View { public class BRouterView extends View {
private final int memoryClass;
RoutingEngine cr; RoutingEngine cr;
private int imgw; private int imgw;
private int imgh; private int imgh;
private int centerLon; private int centerLon;
private int centerLat; private int centerLat;
private double scaleLon; // ilon -> pixel private double scaleLon; // ilon -> pixel
@ -60,45 +60,35 @@ public class BRouterView extends View {
private List<OsmNodeNamed> nogoList; private List<OsmNodeNamed> nogoList;
private List<OsmNodeNamed> nogoVetoList; private List<OsmNodeNamed> nogoVetoList;
private OsmTrack rawTrack; private OsmTrack rawTrack;
private File retryBaseDir; private File retryBaseDir;
private File modesDir; private File modesDir;
private File tracksDir; private File tracksDir;
private File segmentDir; private File segmentDir;
private File profileDir; private File profileDir;
private String profilePath;
private String profileName; private String profileName;
private String sourceHint;
private boolean waitingForSelection = false; private boolean waitingForSelection = false;
private boolean waitingForMigration = false; private boolean waitingForMigration = false;
private String rawTrackPath; private String rawTrackPath;
private String oldMigrationPath; private String oldMigrationPath;
private String trackOutfile;
private boolean needsViaSelection; private boolean needsViaSelection;
private boolean needsNogoSelection; private boolean needsNogoSelection;
private boolean needsWaypointSelection; private boolean needsWaypointSelection;
private WpDatabaseScanner dataBaseScanner;
private long lastDataTime = System.currentTimeMillis(); private long lastDataTime = System.currentTimeMillis();
private CoordinateReader cor; private CoordinateReader cor;
private int[] imgPixels; private int[] imgPixels;
private long lastTs = System.currentTimeMillis();
private int memoryClass; private long startTime = 0L;
public boolean canAccessSdCard;
public void stopRouting() {
if (cr != null) cr.terminate();
}
public BRouterView(Context context, int memoryClass) { public BRouterView(Context context, int memoryClass) {
super(context); super(context);
this.memoryClass = memoryClass; this.memoryClass = memoryClass;
} }
public void stopRouting() {
if (cr != null) cr.terminate();
}
public void init() { public void init() {
try { try {
// get base dir from private file // get base dir from private file
@ -115,28 +105,26 @@ public class BRouterView extends View {
// don't ask twice // don't ask twice
String version = "v" + getContext().getString(R.string.app_version); String version = "v" + getContext().getString(R.string.app_version);
File vFile = new File(brd, "profiles2/" + version); File vFile = new File(brd, "profiles2/" + version);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q if (vFile.exists()) {
&& vFile.exists()) {
startSetup(baseDir, false); startSetup(baseDir, false);
return; return;
} }
String message = "(previous basedir " + baseDir + " has to migrate )"; String message = "(previous basedir " + baseDir + " has to migrate )";
((BRouterActivity) getContext()).selectBasedir(((BRouterActivity) getContext()).getStorageDirectories(), guessBaseDir(), message); ((BRouterActivity) getContext()).selectBasedir(((BRouterActivity) getContext()).getStorageDirectories(), message);
waitingForSelection = true; waitingForSelection = true;
waitingForMigration = true; waitingForMigration = true;
oldMigrationPath = brd.getAbsolutePath(); oldMigrationPath = brd.getAbsolutePath();
return;
} else { } else {
startSetup(baseDir, false); startSetup(baseDir, false);
return;
} }
return;
} }
} }
String message = baseDir == null ? "(no basedir configured previously)" : "(previous basedir " + baseDir String message = baseDir == null ? "(no basedir configured previously)" : "(previous basedir " + baseDir
+ (bdValid ? " does not contain 'brouter' subfolder)" : " is not valid)"); + (bdValid ? " does not contain 'brouter' subfolder)" : " is not valid)");
((BRouterActivity) getContext()).selectBasedir(((BRouterActivity) getContext()).getStorageDirectories(), guessBaseDir(), message); ((BRouterActivity) getContext()).selectBasedir(((BRouterActivity) getContext()).getStorageDirectories(), message);
waitingForSelection = true; waitingForSelection = true;
} catch (Exception e) { } catch (Exception e) {
String msg = e instanceof IllegalArgumentException ? e.getMessage() : e.toString(); String msg = e instanceof IllegalArgumentException ? e.getMessage() : e.toString();
@ -168,7 +156,7 @@ public class BRouterView extends View {
retryBaseDir = baseDir; retryBaseDir = baseDir;
ActivityCompat.requestPermissions((BRouterActivity) getContext(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0); ActivityCompat.requestPermissions((BRouterActivity) getContext(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
} else { } else {
((BRouterActivity) getContext()).selectBasedir(((BRouterActivity) getContext()).getStorageDirectories(), guessBaseDir(), "Cannot access " + baseDir.getAbsolutePath() + "; select another"); ((BRouterActivity) getContext()).selectBasedir(((BRouterActivity) getContext()).getStorageDirectories(), "Cannot access " + baseDir.getAbsolutePath() + "; select another");
} }
return; return;
} }
@ -180,24 +168,7 @@ public class BRouterView extends View {
String basedir = baseDir.getAbsolutePath(); String basedir = baseDir.getAbsolutePath();
AppLogger.log("using basedir: " + basedir); AppLogger.log("using basedir: " + basedir);
String version = "v" + getContext().getString(R.string.app_version); populateBasedir(basedir);
// create missing directories
assertDirectoryExists("project directory", new File(basedir, "brouter"), null, null);
segmentDir = new File(basedir, "/brouter/segments4");
if (assertDirectoryExists("data directory", segmentDir, "segments4.zip", null)) {
ConfigMigration.tryMigrateStorageConfig(
new File(basedir + "/brouter/segments3/storageconfig.txt"),
new File(basedir + "/brouter/segments4/storageconfig.txt"));
}
profileDir = new File(basedir, "brouter/profiles2");
assertDirectoryExists("profile directory", profileDir, "profiles2.zip", version);
modesDir = new File(basedir, "/brouter/modes");
assertDirectoryExists("modes directory", modesDir, "modes.zip", version);
assertDirectoryExists("readmes directory", new File(basedir, "brouter/readmes"), "readmes.zip", version);
File inputDir = new File(basedir, "brouter/import");
assertDirectoryExists("input directory", inputDir, null, version);
// new init is done move old files // new init is done move old files
if (waitingForMigration) { if (waitingForMigration) {
@ -207,23 +178,11 @@ public class BRouterView extends View {
waitingForMigration = false; waitingForMigration = false;
} }
int deviceLevel = Build.VERSION.SDK_INT; cor = CoordinateReader.obtainValidReader(basedir);
int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
canAccessSdCard = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !Environment.isExternalStorageLegacy()) {
canAccessSdCard = false;
}
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
canAccessSdCard = false;
}
cor = CoordinateReader.obtainValidReader(basedir, segmentDir, canAccessSdCard);
wpList = cor.waypoints; wpList = cor.waypoints;
nogoList = cor.nogopoints; nogoList = cor.nogopoints;
nogoVetoList = new ArrayList<OsmNodeNamed>(); nogoVetoList = new ArrayList<>();
sourceHint = "(dev/trgt=" + deviceLevel + "/" + targetSdkVersion + " coordinate-source: " + cor.basedir + cor.rootdir + ")";
needsViaSelection = wpList.size() > 2; needsViaSelection = wpList.size() > 2;
needsNogoSelection = nogoList.size() > 0; needsNogoSelection = nogoList.size() > 0;
@ -232,34 +191,16 @@ public class BRouterView extends View {
if (cor.tracksdir != null) { if (cor.tracksdir != null) {
tracksDir = new File(cor.basedir, cor.tracksdir); tracksDir = new File(cor.basedir, cor.tracksdir);
assertDirectoryExists("track directory", tracksDir, null, null); assertDirectoryExists("track directory", tracksDir, null, null);
// output redirect: look for a pointerfile in tracksdir
File tracksDirPointer = new File(tracksDir, "brouter.redirect");
if (tracksDirPointer.isFile()) {
String tracksDirStr = readSingleLineFile(tracksDirPointer);
if (tracksDirStr == null)
throw new IllegalArgumentException("redirect pointer file is empty: " + tracksDirPointer);
tracksDir = new File(tracksDirStr);
if (!(tracksDir.isDirectory()))
throw new IllegalArgumentException("redirect pointer file " + tracksDirPointer + " does not point to a directory: " + tracksDir);
} else {
File writeTest = new File(tracksDir + "/brouter.writetest");
try {
writeTest.createNewFile();
writeTest.delete();
} catch (Exception e) {
tracksDir = null;
}
}
} }
if (tracksDir == null) { if (tracksDir == null) {
tracksDir = new File(basedir, "brouter"); // fallback tracksDir = new File(basedir, "brouter"); // fallback
} }
String[] fileNames = profileDir.list(); String[] fileNames = profileDir.list();
ArrayList<String> profiles = new ArrayList<String>(); ArrayList<String> profiles = new ArrayList<>();
boolean lookupsFound = false; boolean lookupsFound = false;
if (fileNames != null) {
for (String fileName : fileNames) { for (String fileName : fileNames) {
if (fileName.endsWith(".brf")) { if (fileName.endsWith(".brf")) {
profiles.add(fileName.substring(0, fileName.length() - 4)); profiles.add(fileName.substring(0, fileName.length() - 4));
@ -267,6 +208,7 @@ public class BRouterView extends View {
if (fileName.equals("lookups.dat")) if (fileName.equals("lookups.dat"))
lookupsFound = true; lookupsFound = true;
} }
}
// add a "last timeout" dummy profile // add a "last timeout" dummy profile
File lastTimeoutFile = new File(modesDir + "/timeoutdata.txt"); File lastTimeoutFile = new File(modesDir + "/timeoutdata.txt");
@ -304,9 +246,31 @@ public class BRouterView extends View {
waitingForSelection = true; waitingForSelection = true;
} }
private void populateBasedir(String basedir) {
String version = "v" + getContext().getString(R.string.app_version);
// create missing directories
assertDirectoryExists("project directory", new File(basedir, "brouter"), null, null);
segmentDir = new File(basedir, "/brouter/segments4");
if (assertDirectoryExists("data directory", segmentDir, "segments4.zip", null)) {
ConfigMigration.tryMigrateStorageConfig(
new File(basedir + "/brouter/segments3/storageconfig.txt"),
new File(basedir + "/brouter/segments4/storageconfig.txt"));
}
profileDir = new File(basedir, "brouter/profiles2");
assertDirectoryExists("profile directory", profileDir, "profiles2.zip", version);
modesDir = new File(basedir, "/brouter/modes");
assertDirectoryExists("modes directory", modesDir, "modes.zip", version);
assertDirectoryExists("readmes directory", new File(basedir, "brouter/readmes"), "readmes.zip", version);
File inputDir = new File(basedir, "brouter/import");
assertDirectoryExists("input directory", inputDir, null, version);
}
private void moveFolders(String oldMigrationPath, String basedir) { private void moveFolders(String oldMigrationPath, String basedir) {
File oldDir = new File(oldMigrationPath); File oldDir = new File(oldMigrationPath);
File[] oldFiles = oldDir.listFiles(); File[] oldFiles = oldDir.listFiles();
if (oldFiles != null) {
for (File f : oldFiles) { for (File f : oldFiles) {
if (f.isDirectory()) { if (f.isDirectory()) {
int index = f.getAbsolutePath().lastIndexOf("/"); int index = f.getAbsolutePath().lastIndexOf("/");
@ -320,22 +284,21 @@ public class BRouterView extends View {
} }
} }
}
private void moveFile(String inputPath, String inputFile, String outputPath) { private void copyFile(String inputPath, String inputFile, String outputPath) {
InputStream in;
OutputStream out;
InputStream in = null;
OutputStream out = null;
try { try {
//create output directory if it doesn't exist //create output directory if it doesn't exist
File dir = new File(outputPath); File dir = new File(outputPath);
if (!dir.exists()) { if (!dir.exists()) {
dir.mkdirs(); dir.mkdirs();
} }
in = new FileInputStream(new File(inputPath, inputFile));
in = new FileInputStream(inputPath + "/" + inputFile); out = new FileOutputStream(new File(outputPath, inputFile));
out = new FileOutputStream(outputPath + "/" + inputFile);
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int read; int read;
@ -343,23 +306,22 @@ public class BRouterView extends View {
out.write(buffer, 0, read); out.write(buffer, 0, read);
} }
in.close(); in.close();
in = null;
// write the output file // write the output file
out.flush(); out.flush();
out.close(); out.close();
out = null;
// delete the original file } catch (FileNotFoundException fileNotFoundException) {
new File(inputPath + "/" + inputFile).delete(); Log.e("tag", fileNotFoundException.getMessage());
} catch (FileNotFoundException fnfe1) {
Log.e("tag", fnfe1.getMessage());
} catch (Exception e) { } catch (Exception e) {
Log.e("tag", e.getMessage()); Log.e("tag", e.getMessage());
} }
}
private void moveFile(String inputPath, String inputFile, String outputPath) {
copyFile(inputPath, inputFile, outputPath);
// delete the original file
new File(inputPath, inputFile).delete();
} }
public boolean hasUpToDateLookups() { public boolean hasUpToDateLookups() {
@ -374,7 +336,7 @@ public class BRouterView extends View {
} }
public void updateViaList(Set<String> selectedVias) { public void updateViaList(Set<String> selectedVias) {
ArrayList<OsmNodeNamed> filtered = new ArrayList<OsmNodeNamed>(wpList.size()); ArrayList<OsmNodeNamed> filtered = new ArrayList<>(wpList.size());
for (OsmNodeNamed n : wpList) { for (OsmNodeNamed n : wpList) {
String name = n.name; String name = n.name;
if ("from".equals(name) || "to".equals(name) || selectedVias.contains(name)) if ("from".equals(name) || "to".equals(name) || selectedVias.contains(name))
@ -399,7 +361,7 @@ public class BRouterView extends View {
try { try {
cor.readAllPoints(); cor.readAllPoints();
} catch (Exception e) { } catch (Exception e) {
msg = "Error reading waypoints: " + e.toString(); msg = "Error reading waypoints: " + e;
} }
int size = cor.allpoints.size(); int size = cor.allpoints.size();
@ -434,24 +396,13 @@ public class BRouterView extends View {
} }
} }
public void startWpDatabaseScan() {
dataBaseScanner = new WpDatabaseScanner();
dataBaseScanner.start();
invalidate();
}
public void saveMaptoolDir(String dir) {
ConfigMigration.saveAdditionalMaptoolDir(segmentDir, dir);
((BRouterActivity) getContext()).showResultMessage("Success", "please restart to use new config", -1);
}
public void finishWaypointSelection() { public void finishWaypointSelection() {
needsWaypointSelection = false; needsWaypointSelection = false;
} }
private List<OsmNodeNamed> readWpList(BufferedReader br, boolean isNogo) throws Exception { private List<OsmNodeNamed> readWpList(BufferedReader br, boolean isNogo) throws Exception {
int cnt = Integer.parseInt(br.readLine()); int cnt = Integer.parseInt(br.readLine());
List<OsmNodeNamed> res = new ArrayList<OsmNodeNamed>(cnt); List<OsmNodeNamed> res = new ArrayList<>(cnt);
for (int i = 0; i < cnt; i++) { for (int i = 0; i < cnt; i++) {
OsmNodeNamed wp = OsmNodeNamed.decodeNogo(br.readLine()); OsmNodeNamed wp = OsmNodeNamed.decodeNogo(br.readLine());
wp.isNogo = isNogo; wp.isNogo = isNogo;
@ -480,7 +431,7 @@ public class BRouterView extends View {
rawTrackPath = modesDir + "/remote_rawtrack.dat"; rawTrackPath = modesDir + "/remote_rawtrack.dat";
} }
profilePath = profileDir + "/" + profile + ".brf"; String profilePath = profileDir + "/" + profile + ".brf";
profileName = profile; profileName = profile;
if (needsViaSelection) { if (needsViaSelection) {
@ -499,15 +450,15 @@ public class BRouterView extends View {
} }
if (needsWaypointSelection) { if (needsWaypointSelection) {
String msg; StringBuilder msg;
if (wpList.size() == 0) { if (wpList.size() == 0) {
msg = "Expecting waypoint selection\n" + sourceHint; msg = new StringBuilder("Expecting waypoint selection\n" + "(coordinate-source: " + cor.basedir + cor.rootdir + ")");
} else { } else {
msg = "current waypoint selection:\n"; msg = new StringBuilder("current waypoint selection:\n");
for (int i = 0; i < wpList.size(); i++) for (int i = 0; i < wpList.size(); i++)
msg += (i > 0 ? "->" : "") + wpList.get(i).name; msg.append(i > 0 ? "->" : "").append(wpList.get(i).name);
} }
((BRouterActivity) getContext()).showResultMessage("Select Action", msg, wpList.size()); ((BRouterActivity) getContext()).showResultMessage("Select Action", msg.toString(), wpList.size());
return; return;
} }
@ -587,7 +538,7 @@ public class BRouterView extends View {
File vtag = new File(path, versionTag); File vtag = new File(path, versionTag);
try { try {
exists = !vtag.createNewFile(); exists = !vtag.createNewFile();
} catch (IOException io) { } catch (IOException ignored) {
} // well.. } // well..
} }
@ -608,7 +559,7 @@ public class BRouterView extends View {
} }
String name = ze.getName(); String name = ze.getName();
File outfile = new File(path, name); File outfile = new File(path, name);
if (!outfile.exists()) { if (!outfile.exists() && outfile.getParentFile() != null) {
outfile.getParentFile().mkdirs(); outfile.getParentFile().mkdirs();
FileOutputStream fos = new FileOutputStream(outfile); FileOutputStream fos = new FileOutputStream(outfile);
@ -656,7 +607,7 @@ public class BRouterView extends View {
int ir = (int) (n.radius * scaleMeter2Pixel); int ir = (int) (n.radius * scaleMeter2Pixel);
if (ir > minradius) { if (ir > minradius) {
Paint paint = new Paint(); Paint paint = new Paint();
paint.setColor(Color.RED); paint.setColor(color);
paint.setStyle(Paint.Style.STROKE); paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle((float) x, (float) y, (float) ir, paint); canvas.drawCircle((float) x, (float) y, (float) ir, paint);
} }
@ -703,9 +654,6 @@ public class BRouterView extends View {
lastDataTime += 4000; // give time for the toast before exiting lastDataTime += 4000; // give time for the toast before exiting
} }
private long lastTs = System.currentTimeMillis();
private long startTime = 0L;
@Override @Override
protected void onDraw(Canvas canvas) { protected void onDraw(Canvas canvas) {
try { try {
@ -717,58 +665,14 @@ public class BRouterView extends View {
cr = null; cr = null;
try { try {
Thread.sleep(2000); Thread.sleep(2000);
} catch (InterruptedException ie) { } catch (InterruptedException ignored) {
} }
((BRouterActivity) getContext()).showErrorMessage(t.toString()); ((BRouterActivity) getContext()).showErrorMessage(t.toString());
waitingForSelection = true; waitingForSelection = true;
} }
} }
private void showDatabaseScanning(Canvas canvas) {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
}
Paint paint1 = new Paint();
paint1.setColor(Color.WHITE);
paint1.setTextSize(20);
Paint paint2 = new Paint();
paint2.setColor(Color.WHITE);
paint2.setTextSize(10);
String currentDir = dataBaseScanner.getCurrentDir();
String bestGuess = dataBaseScanner.getBestGuess();
if (currentDir == null) // scan finished
{
if (bestGuess.length() == 0) {
((BRouterActivity) getContext()).showErrorMessage("scan did not find any possible waypoint database");
} else {
((BRouterActivity) getContext()).showWpDatabaseScanSuccess(bestGuess);
}
cr = null;
dataBaseScanner = null;
waitingForSelection = true;
return;
}
canvas.drawText("Scanning:", 10, 30, paint1);
canvas.drawText(currentDir, 0, 60, paint2);
canvas.drawText("Best Guess:", 10, 90, paint1);
canvas.drawText(bestGuess, 0, 120, paint2);
canvas.drawText("Last Error:", 10, 150, paint1);
canvas.drawText(dataBaseScanner.getLastError(), 0, 180, paint2);
invalidate();
}
private void _onDraw(Canvas canvas) { private void _onDraw(Canvas canvas) {
if (dataBaseScanner != null) {
showDatabaseScanning(canvas);
return;
}
if (waitingForSelection) if (waitingForSelection)
return; return;
@ -780,7 +684,7 @@ public class BRouterView extends View {
try { try {
Thread.sleep(sleeptime); Thread.sleep(sleeptime);
} catch (InterruptedException ie) { } catch (InterruptedException ignored) {
} }
lastTs = System.currentTimeMillis(); lastTs = System.currentTimeMillis();
@ -788,9 +692,6 @@ public class BRouterView extends View {
if (cr != null) { if (cr != null) {
if (cr.getErrorMessage() != null) { if (cr.getErrorMessage() != null) {
((BRouterActivity) getContext()).showErrorMessage(cr.getErrorMessage()); ((BRouterActivity) getContext()).showErrorMessage(cr.getErrorMessage());
cr = null;
waitingForSelection = true;
return;
} else { } else {
String memstat = memoryClass + "mb pathPeak " + ((cr.getPathPeak() + 500) / 1000) + "k"; String memstat = memoryClass + "mb pathPeak " + ((cr.getPathPeak() + 500) / 1000) + "k";
String result = "version = BRouter-" + getContext().getString(R.string.app_version) + "\n" + "mem = " + memstat + "\ndistance = " + cr.getDistance() / 1000. + " km\n" + "filtered ascend = " + cr.getAscend() String result = "version = BRouter-" + getContext().getString(R.string.app_version) + "\n" + "mem = " + memstat + "\ndistance = " + cr.getDistance() / 1000. + " km\n" + "filtered ascend = " + cr.getAscend()
@ -808,10 +709,11 @@ public class BRouterView extends View {
title += " / " + cr.getAlternativeIndex() + ". Alternative"; title += " / " + cr.getAlternativeIndex() + ". Alternative";
((BRouterActivity) getContext()).showResultMessage(title, result, rawTrackPath == null ? -1 : -3); ((BRouterActivity) getContext()).showResultMessage(title, result, rawTrackPath == null ? -1 : -3);
trackOutfile = cr.getOutfile();
}
cr = null; cr = null;
waitingForSelection = true; waitingForSelection = true;
return; return;
}
} else if (System.currentTimeMillis() > lastDataTime) { } else if (System.currentTimeMillis() > lastDataTime) {
System.exit(0); System.exit(0);
} }
@ -824,17 +726,18 @@ public class BRouterView extends View {
paintPosition(openSet[si], openSet[si + 1], 0xffffff, 1); paintPosition(openSet[si], openSet[si + 1], 0xffffff, 1);
} }
// paint nogos on top (red) // paint nogos on top (red)
int minradius = 4;
for (int ngi = 0; ngi < nogoList.size(); ngi++) { for (int ngi = 0; ngi < nogoList.size(); ngi++) {
OsmNodeNamed n = nogoList.get(ngi); OsmNodeNamed n = nogoList.get(ngi);
int color = 0xff0000; int color = 0xff0000;
paintPosition(n.ilon, n.ilat, color, 4); paintPosition(n.ilon, n.ilat, color, minradius);
} }
// paint start/end/vias on top (yellow/green/blue) // paint start/end/vias on top (yellow/green/blue)
for (int wpi = 0; wpi < wpList.size(); wpi++) { for (int wpi = 0; wpi < wpList.size(); wpi++) {
OsmNodeNamed n = wpList.get(wpi); OsmNodeNamed n = wpList.get(wpi);
int color = wpi == 0 ? 0xffff00 : wpi < wpList.size() - 1 ? 0xff : 0xff00; int color = wpi == 0 ? 0xffff00 : wpi < wpList.size() - 1 ? 0xff : 0xff00;
paintPosition(n.ilon, n.ilat, color, 4); paintPosition(n.ilon, n.ilat, color, minradius);
} }
canvas.drawBitmap(imgPixels, 0, imgw, (float) 0., (float) 0., imgw, imgh, false, null); canvas.drawBitmap(imgPixels, 0, imgw, (float) 0., (float) 0., imgw, imgh, false, null);
@ -843,10 +746,10 @@ public class BRouterView extends View {
for (int ngi = 0; ngi < nogoList.size(); ngi++) { for (int ngi = 0; ngi < nogoList.size(); ngi++) {
OsmNodeNamed n = nogoList.get(ngi); OsmNodeNamed n = nogoList.get(ngi);
if (n instanceof OsmNogoPolygon) { if (n instanceof OsmNogoPolygon) {
paintPolygon(canvas, (OsmNogoPolygon) n, 4); paintPolygon(canvas, (OsmNogoPolygon) n, minradius);
} else { } else {
int color = 0xff0000; int color = Color.RED;
paintCircle(canvas, n, color, 4); paintCircle(canvas, n, color, minradius);
} }
} }
@ -865,42 +768,6 @@ public class BRouterView extends View {
invalidate(); invalidate();
} }
private String guessBaseDir() {
File basedir = Environment.getExternalStorageDirectory();
try {
File bd2 = new File(basedir, "external_sd");
ArrayList<String> basedirGuesses = new ArrayList<String>();
basedirGuesses.add(basedir.getAbsolutePath());
if (bd2.exists()) {
basedir = bd2;
basedirGuesses.add(basedir.getAbsolutePath());
}
ArrayList<CoordinateReader> rl = new ArrayList<CoordinateReader>();
for (String bdg : basedirGuesses) {
rl.add(new CoordinateReaderOsmAnd(bdg));
rl.add(new CoordinateReaderLocus(bdg));
rl.add(new CoordinateReaderOrux(bdg));
}
long tmax = 0;
CoordinateReader cor = null;
for (CoordinateReader r : rl) {
long t = r.getTimeStamp();
if (t > tmax) {
tmax = t;
cor = r;
}
}
if (cor != null) {
return cor.basedir;
}
} catch (Exception e) {
System.out.println("guessBaseDir:" + e);
}
return basedir.getAbsolutePath();
}
private void writeRawTrackToMode(String mode) { private void writeRawTrackToMode(String mode) {
writeRawTrackToPath(modesDir + "/" + mode + "_rawtrack.dat"); writeRawTrackToPath(modesDir + "/" + mode + "_rawtrack.dat");
} }
@ -909,7 +776,7 @@ public class BRouterView extends View {
if (rawTrack != null) { if (rawTrack != null) {
try { try {
rawTrack.writeBinary(rawTrackPath); rawTrack.writeBinary(rawTrackPath);
} catch (Exception e) { } catch (Exception ignored) {
} }
} else { } else {
new File(rawTrackPath).delete(); new File(rawTrackPath).delete();
@ -928,7 +795,7 @@ public class BRouterView extends View {
public void configureService(String[] routingModes, boolean[] checkedModes) { public void configureService(String[] routingModes, boolean[] checkedModes) {
// read in current config // read in current config
TreeMap<String, ServiceModeConfig> map = new TreeMap<String, ServiceModeConfig>(); TreeMap<String, ServiceModeConfig> map = new TreeMap<>();
BufferedReader br = null; BufferedReader br = null;
String modesFile = modesDir + "/serviceconfig.dat"; String modesFile = modesDir + "/serviceconfig.dat";
try { try {
@ -940,12 +807,12 @@ public class BRouterView extends View {
ServiceModeConfig smc = new ServiceModeConfig(line); ServiceModeConfig smc = new ServiceModeConfig(line);
map.put(smc.mode, smc); map.put(smc.mode, smc);
} }
} catch (Exception e) { } catch (Exception ignored) {
} finally { } finally {
if (br != null) if (br != null)
try { try {
br.close(); br.close();
} catch (Exception ee) { } catch (Exception ignored) {
} }
} }
@ -971,27 +838,29 @@ public class BRouterView extends View {
for (ServiceModeConfig smc : map.values()) { for (ServiceModeConfig smc : map.values()) {
bw.write(smc.toLine()); bw.write(smc.toLine());
bw.write('\n'); bw.write('\n');
msg.append(smc.toString()).append('\n'); msg.append(smc).append('\n');
} }
} catch (Exception e) { } catch (Exception ignored) {
} finally { } finally {
if (bw != null) if (bw != null)
try { try {
bw.close(); bw.close();
} catch (Exception ee) { } catch (Exception ignored) {
} }
} }
((BRouterActivity) getContext()).showModeConfigOverview(msg.toString()); ((BRouterActivity) getContext()).showModeConfigOverview(msg.toString());
} }
private String readSingleLineFile(File f) { public void shareTrack() {
try (FileInputStream fis = new FileInputStream(f); File track = new File(trackOutfile);
InputStreamReader isr = new InputStreamReader(fis); // Copy file to cache to ensure FileProvider allows sharing the file
BufferedReader br = new BufferedReader(isr)) { File cacheDir = getContext().getCacheDir();
return br.readLine(); copyFile(track.getParent(), track.getName(), cacheDir.getAbsolutePath());
} catch (Exception e) { Intent intent = new Intent();
return null; intent.setDataAndType(FileProvider.getUriForFile(getContext(), "btools.routing.fileprovider", new File(cacheDir, track.getName())),
"application/gpx+xml");
intent.setAction(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
getContext().startActivity(intent);
} }
} }
}

View file

@ -1,8 +1,18 @@
package btools.routingapp; package btools.routingapp;
import android.graphics.Point;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -10,47 +20,182 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import android.os.Environment;
import btools.router.OsmNodeNamed; import btools.router.OsmNodeNamed;
import btools.router.RoutingHelper; import btools.router.OsmNogoPolygon;
/** /**
* Read coordinates from a gpx-file * Read coordinates from a gpx-file
*/ */
public abstract class CoordinateReader { public class CoordinateReader {
protected static String[] posnames
= new String[]{"from", "via1", "via2", "via3", "via4", "via5", "via6", "via7", "via8", "via9", "to"};
private final String internalDir;
public List<OsmNodeNamed> waypoints; public List<OsmNodeNamed> waypoints;
public List<OsmNodeNamed> nogopoints; public List<OsmNodeNamed> nogopoints;
public String basedir; public String basedir;
public String rootdir; public String rootdir;
public String tracksdir; public String tracksdir;
private boolean nogosOnly;
private Map<String, Map<String, OsmNodeNamed>> allpointsMap;
public List<OsmNodeNamed> allpoints; public List<OsmNodeNamed> allpoints;
private boolean nogosOnly;
private Map<String, Map<String, OsmNodeNamed>> allpointsMap;
private HashMap<String, OsmNodeNamed> pointmap; private HashMap<String, OsmNodeNamed> pointmap;
protected static String[] posnames
= new String[]{"from", "via1", "via2", "via3", "via4", "via5", "via6", "via7", "via8", "via9", "to"};
public CoordinateReader(String basedir) { public CoordinateReader(String basedir) {
this.basedir = basedir; this.basedir = basedir;
internalDir = basedir + "/brouter/import";
tracksdir = "/brouter/import/tracks";
rootdir = "/brouter/import";
} }
public abstract long getTimeStamp() throws Exception; public static CoordinateReader obtainValidReader(String basedir) throws IOException {
return obtainValidReader(basedir, false);
}
public abstract int getTurnInstructionMode(); public static CoordinateReader obtainValidReader(String basedir, boolean nogosOnly) throws IOException {
CoordinateReader cor = new CoordinateReader(basedir);
cor.nogosOnly = nogosOnly;
cor.readFromTo();
return cor;
}
public int getTurnInstructionMode() {
return 4; // comment style
}
/*
* read the from and to position from a gpx-file
* (with hardcoded name for now)
*/
public void readPointmap() throws IOException {
if (!_readPointmap(internalDir + "/favourites_bak.gpx")) {
_readPointmap(internalDir + "/favourites.gpx");
}
_readNogoLines(basedir + tracksdir);
}
private boolean _readPointmap(String filename) throws IOException {
BufferedReader br;
try {
br = new BufferedReader(
new InputStreamReader(
new FileInputStream(filename)));
} catch (FileNotFoundException e) {
// ignore until it's reading error
return false;
}
OsmNodeNamed n = null;
for (; ; ) {
String line = br.readLine();
if (line == null) break;
int idx0 = line.indexOf(" lat=\"");
int idx10 = line.indexOf("<name>");
if (idx0 >= 0) {
n = new OsmNodeNamed();
idx0 += 6;
int idx1 = line.indexOf('"', idx0);
n.ilat = (int) ((Double.parseDouble(line.substring(idx0, idx1)) + 90.) * 1000000. + 0.5);
int idx2 = line.indexOf(" lon=\"");
if (idx2 < 0) continue;
idx2 += 6;
int idx3 = line.indexOf('"', idx2);
n.ilon = (int) ((Double.parseDouble(line.substring(idx2, idx3)) + 180.) * 1000000. + 0.5);
if (idx3 < 0) continue;
}
if (n != null && idx10 >= 0) {
idx10 += 6;
int idx11 = line.indexOf("</name>", idx10);
if (idx11 >= 0) {
n.name = line.substring(idx10, idx11).trim();
checkAddPoint("(one-for-all)", n);
}
}
}
br.close();
return true;
}
private void _readNogoLines(String dirname) {
File dir = new File(dirname);
if (dir.exists() && dir.isDirectory()) {
for (final File file : dir.listFiles()) {
final String name = file.getName();
if (name.startsWith("nogo") && name.endsWith(".gpx")) {
try {
_readNogoLine(file);
} catch (Exception ignored) {
}
}
}
}
}
private void _readNogoLine(File file) throws Exception {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(false);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new FileReader(file));
List<Point> tmpPts = new ArrayList<>();
int eventType = xpp.getEventType();
int numSeg = 0;
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_TAG: {
if (xpp.getName().equals("trkpt") || xpp.getName().equals("rtept")) {
final String lon = xpp.getAttributeValue(null, "lon");
final String lat = xpp.getAttributeValue(null, "lat");
if (lon != null && lat != null) {
tmpPts.add(new Point(
(int) ((Double.parseDouble(lon) + 180.) * 1000000. + 0.5),
(int) ((Double.parseDouble(lat) + 90.) * 1000000. + 0.5)));
}
}
break;
}
case XmlPullParser.END_TAG: {
if (xpp.getName().equals("trkseg") || xpp.getName().equals("rte")) { // rte has no segment
OsmNogoPolygon nogo;
if (tmpPts.size() > 0) {
if (tmpPts.get(0).x == tmpPts.get(tmpPts.size() - 1).x &&
tmpPts.get(0).y == tmpPts.get(tmpPts.size() - 1).y) {
nogo = new OsmNogoPolygon(true);
} else {
nogo = new OsmNogoPolygon(false);
}
for (Point p : tmpPts) {
nogo.addVertex(p.x, p.y);
}
nogo.calcBoundingCircle();
final String name = file.getName();
nogo.name = name.substring(0, name.length() - 4);
if (numSeg > 0) {
nogo.name += Integer.toString(numSeg + 1);
}
numSeg++;
checkAddPoint("(one-for-all)", nogo);
}
tmpPts.clear();
}
break;
}
}
eventType = xpp.next();
}
}
public void readAllPoints() throws Exception { public void readAllPoints() throws Exception {
allpointsMap = new TreeMap<String, Map<String, OsmNodeNamed>>(); allpointsMap = new TreeMap<>();
readFromTo(); readFromTo();
allpoints = new ArrayList<OsmNodeNamed>(); allpoints = new ArrayList<>();
Set<String> names = new HashSet<String>(); Set<String> names = new HashSet<>();
for (String category : allpointsMap.keySet()) { for (String category : allpointsMap.keySet()) {
Map<String, OsmNodeNamed> cat = allpointsMap.get(category); Map<String, OsmNodeNamed> cat = allpointsMap.get(category);
if (cat.size() < 101) { if (cat != null && cat.size() < 101) {
for (OsmNodeNamed wp : cat.values()) { for (OsmNodeNamed wp : cat.values()) {
if (names.add(wp.name)) { if (names.add(wp.name)) {
allpoints.add(wp); allpoints.add(wp);
@ -67,14 +212,13 @@ public abstract class CoordinateReader {
/* /*
* read the from, to and via-positions from a gpx-file * read the from, to and via-positions from a gpx-file
*/ */
public void readFromTo() throws Exception { public void readFromTo() throws IOException {
pointmap = new HashMap<String, OsmNodeNamed>(); pointmap = new HashMap<>();
waypoints = new ArrayList<OsmNodeNamed>(); waypoints = new ArrayList<>();
nogopoints = new ArrayList<OsmNodeNamed>(); nogopoints = new ArrayList<>();
readPointmap(); readPointmap();
boolean fromToMissing = false; boolean fromToMissing = false;
for (int i = 0; i < posnames.length; i++) { for (String name : posnames) {
String name = posnames[i];
OsmNodeNamed n = pointmap.get(name); OsmNodeNamed n = pointmap.get(name);
if (n != null) { if (n != null) {
waypoints.add(n); waypoints.add(n);
@ -91,7 +235,7 @@ public abstract class CoordinateReader {
if (category == null) category = ""; if (category == null) category = "";
Map<String, OsmNodeNamed> cat = allpointsMap.get(category); Map<String, OsmNodeNamed> cat = allpointsMap.get(category);
if (cat == null) { if (cat == null) {
cat = new TreeMap<String, OsmNodeNamed>(); cat = new TreeMap<>();
allpointsMap.put(category, cat); allpointsMap.put(category, cat);
} }
if (cat.size() < 101) { if (cat.size() < 101) {
@ -101,8 +245,8 @@ public abstract class CoordinateReader {
} }
boolean isKnown = false; boolean isKnown = false;
for (int i = 0; i < posnames.length; i++) { for (String posname : posnames) {
if (posnames[i].equals(n.name)) { if (posname.equals(n.name)) {
isKnown = true; isKnown = true;
break; break;
} }
@ -121,74 +265,4 @@ public abstract class CoordinateReader {
} }
} }
protected abstract void readPointmap() throws Exception;
public static CoordinateReader obtainValidReader(String basedir, File segmentDir, boolean canAccessSdCard) throws Exception {
return obtainValidReader(basedir, segmentDir, canAccessSdCard, false);
}
public static CoordinateReader obtainValidReader(String basedir, File segmentDir, boolean canAccessSdCard, boolean nogosOnly) throws Exception {
CoordinateReader cor = null;
ArrayList<CoordinateReader> rl = new ArrayList<CoordinateReader>();
if (canAccessSdCard) {
AppLogger.log("adding standard maptool-base: " + basedir);
rl.add(new CoordinateReaderOsmAnd(basedir));
rl.add(new CoordinateReaderLocus(basedir));
rl.add(new CoordinateReaderOrux(basedir));
// eventually add standard-sd
File standardbase = Environment.getExternalStorageDirectory();
if (standardbase != null) {
String base2 = standardbase.getAbsolutePath();
if (!base2.equals(basedir)) {
AppLogger.log("adding internal sd maptool-base: " + base2);
rl.add(new CoordinateReaderOsmAnd(base2));
rl.add(new CoordinateReaderLocus(base2));
rl.add(new CoordinateReaderOrux(base2));
}
}
// eventually add explicit directory
File additional = RoutingHelper.getAdditionalMaptoolDir(segmentDir);
if (additional != null) {
String base3 = additional.getAbsolutePath();
AppLogger.log("adding maptool-base from storage-config: " + base3);
rl.add(new CoordinateReaderOsmAnd(base3));
rl.add(new CoordinateReaderOsmAnd(base3, true));
rl.add(new CoordinateReaderLocus(base3));
rl.add(new CoordinateReaderOrux(base3));
}
long tmax = 0;
for (CoordinateReader r : rl) {
if (AppLogger.isLogging()) {
AppLogger.log("reading timestamp at systime " + new Date());
}
long t = r.getTimeStamp();
if (t != 0) {
if (AppLogger.isLogging()) {
AppLogger.log("found coordinate source at " + r.basedir + r.rootdir + " with timestamp " + new Date(t));
}
}
if (t > tmax) {
tmax = t;
cor = r;
}
}
}
if (cor == null) {
cor = new CoordinateReaderInternal(basedir);
}
cor.nogosOnly = nogosOnly;
cor.readFromTo();
return cor;
}
} }

View file

@ -1,186 +0,0 @@
package btools.routingapp;
import android.graphics.Point;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import btools.router.OsmNodeNamed;
import btools.router.OsmNogoPolygon;
/**
* Read coordinates from a gpx-file
*/
public class CoordinateReaderInternal extends CoordinateReader {
private String internalDir;
public CoordinateReaderInternal(String basedir) {
this(basedir, false);
}
public CoordinateReaderInternal(String basedir, boolean shortPath) {
super(basedir);
if (shortPath) {
internalDir = basedir;
tracksdir = "/tracks";
rootdir = "";
} else {
internalDir = basedir + "/brouter/import";
tracksdir = "/brouter/import/tracks";
rootdir = "/brouter/import";
}
}
@Override
public long getTimeStamp() throws Exception {
long t1 = new File(internalDir + "/favourites_bak.gpx").lastModified();
long t2 = new File(internalDir + "/favourites.gpx").lastModified();
return t1 > t2 ? t1 : t2;
}
@Override
public int getTurnInstructionMode() {
return 4; // comment style
}
/*
* read the from and to position from a gpx-file
* (with hardcoded name for now)
*/
@Override
public void readPointmap() throws Exception {
if (!_readPointmap(internalDir + "/favourites_bak.gpx")) {
_readPointmap(internalDir + "/favourites.gpx");
}
try {
_readNogoLines(basedir + tracksdir);
} catch (IOException ioe) {
}
}
private boolean _readPointmap(String filename) throws Exception {
BufferedReader br = null;
try {
br = new BufferedReader(
new InputStreamReader(
new FileInputStream(filename)));
} catch (FileNotFoundException e) {
// ignore until it's reading error
return false;
}
OsmNodeNamed n = null;
for (; ; ) {
String line = br.readLine();
if (line == null) break;
int idx0 = line.indexOf(" lat=\"");
int idx10 = line.indexOf("<name>");
if (idx0 >= 0) {
n = new OsmNodeNamed();
idx0 += 6;
int idx1 = line.indexOf('"', idx0);
n.ilat = (int) ((Double.parseDouble(line.substring(idx0, idx1)) + 90.) * 1000000. + 0.5);
int idx2 = line.indexOf(" lon=\"");
if (idx2 < 0) continue;
idx2 += 6;
int idx3 = line.indexOf('"', idx2);
n.ilon = (int) ((Double.parseDouble(line.substring(idx2, idx3)) + 180.) * 1000000. + 0.5);
if (idx3 < 0) continue;
}
if (n != null && idx10 >= 0) {
idx10 += 6;
int idx11 = line.indexOf("</name>", idx10);
if (idx11 >= 0) {
n.name = line.substring(idx10, idx11).trim();
checkAddPoint("(one-for-all)", n);
}
}
}
br.close();
return true;
}
private void _readNogoLines(String dirname) throws IOException {
File dir = new File(dirname);
if (dir.exists() && dir.isDirectory()) {
for (final File file : dir.listFiles()) {
final String name = file.getName();
if (name.startsWith("nogo") && name.endsWith(".gpx")) {
try {
_readNogoLine(file);
} catch (Exception e) {
}
}
}
}
}
private void _readNogoLine(File file) throws Exception {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(false);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new FileReader(file));
List<Point> tmpPts = new ArrayList<Point>();
int eventType = xpp.getEventType();
int numSeg = 0;
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_TAG: {
if (xpp.getName().equals("trkpt") || xpp.getName().equals("rtept")) {
final String lon = xpp.getAttributeValue(null, "lon");
final String lat = xpp.getAttributeValue(null, "lat");
if (lon != null && lat != null) {
tmpPts.add(new Point(
(int) ((Double.parseDouble(lon) + 180.) * 1000000. + 0.5),
(int) ((Double.parseDouble(lat) + 90.) * 1000000. + 0.5)));
}
}
break;
}
case XmlPullParser.END_TAG: {
if (xpp.getName().equals("trkseg") || xpp.getName().equals("rte")) { // rte has no segment
OsmNogoPolygon nogo = null;
if (tmpPts.size() >= 0) {
if (tmpPts.get(0).x == tmpPts.get(tmpPts.size() - 1).x &&
tmpPts.get(0).y == tmpPts.get(tmpPts.size() - 1).y) {
nogo = new OsmNogoPolygon(true);
} else {
nogo = new OsmNogoPolygon(false);
}
for (Point p : tmpPts) {
nogo.addVertex(p.x, p.y);
}
nogo.calcBoundingCircle();
final String name = file.getName();
nogo.name = name.substring(0, name.length() - 4);
if (numSeg > 0) {
nogo.name += Integer.toString(numSeg + 1);
}
numSeg++;
checkAddPoint("(one-for-all)", nogo);
}
tmpPts.clear();
}
break;
}
}
eventType = xpp.next();
}
}
}

View file

@ -1,68 +0,0 @@
package btools.routingapp;
import java.io.File;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import btools.router.OsmNodeNamed;
/**
* Read coordinates from a gpx-file
*/
public class CoordinateReaderLocus extends CoordinateReader {
public CoordinateReaderLocus(String basedir) {
super(basedir);
tracksdir = "/Locus/mapItems";
rootdir = "/Locus";
}
@Override
public long getTimeStamp() throws Exception {
File f = new File(basedir + "/Locus/data/database/waypoints.db");
long t1 = f.lastModified();
// Android 10 delivers file size but can't read it
boolean canRead = f.canRead();
return canRead ? t1 : 0L;
}
@Override
public int getTurnInstructionMode() {
return 2; // locus style
}
/*
* read the from and to position from a ggx-file
* (with hardcoded name for now)
*/
@Override
public void readPointmap() throws Exception {
_readPointmap(basedir + "/Locus/data/database/waypoints.db");
}
private void _readPointmap(String filename) throws Exception {
SQLiteDatabase myDataBase = null;
try {
myDataBase = SQLiteDatabase.openDatabase(filename, null, SQLiteDatabase.OPEN_READONLY);
} catch (Exception e) {
// not open, do not produce an error
return;
}
Cursor c = myDataBase.rawQuery("SELECT c.name, w.name, w.longitude, w.latitude FROM waypoints w, categories c where w.parent_id = c._id", null);
if (c.getCount() == 0) {
c.close();
c = myDataBase.rawQuery("SELECT c.name, w.name, w.longitude, w.latitude FROM waypoints w, groups c where w.parent_id = c._id;", null);
}
while (c.moveToNext()) {
OsmNodeNamed n = new OsmNodeNamed();
String category = c.getString(0);
n.name = c.getString(1);
n.ilon = (int) ((c.getDouble(2) + 180.) * 1000000. + 0.5);
n.ilat = (int) ((c.getDouble(3) + 90.) * 1000000. + 0.5);
checkAddPoint(category, n);
}
c.close();
myDataBase.close();
}
}

View file

@ -1,63 +0,0 @@
package btools.routingapp;
import java.io.File;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import btools.router.OsmNodeNamed;
/**
* Read coordinates from a gpx-file
*/
public class CoordinateReaderOrux extends CoordinateReader {
public CoordinateReaderOrux(String basedir) {
super(basedir);
tracksdir = "/oruxmaps/tracklogs";
rootdir = "/oruxmaps";
}
@Override
public long getTimeStamp() throws Exception {
File f = new File(basedir + "/oruxmaps/tracklogs/oruxmapstracks.db");
long t1 = f.lastModified();
// Android 10 delivers file size but can't read it
boolean canRead = f.canRead();
return canRead ? t1 : 0L;
}
@Override
public int getTurnInstructionMode() {
return 0; // none
}
/*
* read the from and to position from a ggx-file
* (with hardcoded name for now)
*/
@Override
public void readPointmap() throws Exception {
_readPointmap(basedir + "/oruxmaps/tracklogs/oruxmapstracks.db");
}
private void _readPointmap(String filename) throws Exception {
SQLiteDatabase myDataBase = null;
try {
myDataBase = SQLiteDatabase.openDatabase(filename, null, SQLiteDatabase.OPEN_READONLY);
} catch (Exception e) {
// not open, do not produce an error
return;
}
Cursor c = myDataBase.rawQuery("SELECT poiname, poilon, poilat, poifolder FROM pois", null);
while (c.moveToNext()) {
OsmNodeNamed n = new OsmNodeNamed();
n.name = c.getString(0);
n.ilon = (int) ((c.getDouble(1) + 180.) * 1000000. + 0.5);
n.ilat = (int) ((c.getDouble(2) + 90.) * 1000000. + 0.5);
String category = c.getString(3);
checkAddPoint(category, n);
}
c.close();
myDataBase.close();
}
}

View file

@ -1,163 +0,0 @@
package btools.routingapp;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import btools.router.OsmNodeNamed;
import btools.router.OsmNogoPolygon;
/**
* Read coordinates from a gpx-file
*/
public class CoordinateReaderOsmAnd extends CoordinateReader {
private String osmandDir;
public CoordinateReaderOsmAnd(String basedir) {
this(basedir, false);
}
public CoordinateReaderOsmAnd(String basedir, boolean shortPath) {
super(basedir);
if (shortPath) {
osmandDir = basedir;
tracksdir = "/tracks";
rootdir = "";
} else {
osmandDir = basedir + "/osmand";
tracksdir = "/osmand/tracks";
rootdir = "/osmand";
}
}
@Override
public long getTimeStamp() throws Exception {
File f1 = new File(osmandDir + "/favourites_bak.gpx");
File f2 = new File(osmandDir + "/favourites.gpx");
long t1 = f1.canRead() ? f1.lastModified() : 0L;
long t2 = f2.canRead() ? f2.lastModified() : 0L;
return t1 > t2 ? t1 : t2;
}
@Override
public int getTurnInstructionMode() {
return 3; // osmand style
}
/*
* read the from and to position from a gpx-file
* (with hardcoded name for now)
*/
@Override
public void readPointmap() throws Exception {
try {
_readPointmap(osmandDir + "/favourites_bak.gpx");
} catch (Exception e) {
_readPointmap(osmandDir + "/favourites.gpx");
}
try {
_readNogoLines(basedir + tracksdir);
} catch (IOException ioe) {
}
}
private void _readPointmap(String filename) throws Exception {
BufferedReader br = new BufferedReader(
new InputStreamReader(
new FileInputStream(filename)));
OsmNodeNamed n = null;
for (; ; ) {
String line = br.readLine();
if (line == null) break;
int idx0 = line.indexOf("<wpt lat=\"");
int idx10 = line.indexOf("<name>");
if (idx0 >= 0) {
n = new OsmNodeNamed();
idx0 += 10;
int idx1 = line.indexOf('"', idx0);
n.ilat = (int) ((Double.parseDouble(line.substring(idx0, idx1)) + 90.) * 1000000. + 0.5);
int idx2 = line.indexOf(" lon=\"");
if (idx2 < 0) continue;
idx2 += 6;
int idx3 = line.indexOf('"', idx2);
n.ilon = (int) ((Double.parseDouble(line.substring(idx2, idx3)) + 180.) * 1000000. + 0.5);
continue;
}
if (n != null && idx10 >= 0) {
idx10 += 6;
int idx11 = line.indexOf("</name>", idx10);
if (idx11 >= 0) {
n.name = line.substring(idx10, idx11).trim();
checkAddPoint("(one-for-all)", n);
}
}
}
br.close();
}
private void _readNogoLines(String dirname) throws IOException {
File dir = new File(dirname);
if (dir.exists() && dir.isDirectory()) {
for (final File file : dir.listFiles()) {
final String name = file.getName();
if (name.startsWith("nogo") && name.endsWith(".gpx")) {
try {
_readNogoLine(file);
} catch (Exception e) {
}
}
}
}
}
private void _readNogoLine(File file) throws Exception {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(false);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new FileReader(file));
OsmNogoPolygon nogo = new OsmNogoPolygon(false);
int eventType = xpp.getEventType();
int numSeg = 0;
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_TAG: {
if (xpp.getName().equals("trkpt")) {
final String lon = xpp.getAttributeValue(null, "lon");
final String lat = xpp.getAttributeValue(null, "lat");
if (lon != null && lat != null) {
nogo.addVertex(
(int) ((Double.parseDouble(lon) + 180.) * 1000000. + 0.5),
(int) ((Double.parseDouble(lat) + 90.) * 1000000. + 0.5));
}
}
break;
}
case XmlPullParser.END_TAG: {
if (xpp.getName().equals("trkseg")) {
nogo.calcBoundingCircle();
final String name = file.getName();
nogo.name = name.substring(0, name.length() - 4);
if (numSeg > 0) {
nogo.name += Integer.toString(numSeg + 1);
}
numSeg++;
checkAddPoint("(one-for-all)", nogo);
}
break;
}
}
eventType = xpp.next();
}
}
}

View file

@ -1,107 +0,0 @@
package btools.routingapp;
import java.io.File;
public class WpDatabaseScanner extends Thread {
private String currentDir = "";
private String bestGuess = "";
private String lastError = "";
private Object currentDirSync = new Object();
private long maxtimestamp = 0;
public String getCurrentDir() {
synchronized (currentDirSync) {
return currentDir;
}
}
private void setCurrentDir(String dir) {
synchronized (currentDirSync) {
currentDir = dir;
}
}
public String getBestGuess() {
synchronized (currentDirSync) {
return bestGuess;
}
}
public String getLastError() {
synchronized (currentDirSync) {
return lastError;
}
}
private void setLastError(String msg) {
synchronized (currentDirSync) {
lastError = msg;
}
}
private static String[] vetos = new String[]{"dev", "sys", "system", "proc", "etc", "init", "d", "cache", "acct", "data"};
private void scan(File dir, int level) {
if (level > 8) {
return;
}
try {
if (dir.isDirectory()) {
if (level == 1) {
String name = dir.getName();
for (String veto : vetos) {
if (veto.equals(name)) {
return;
}
}
}
testPath(dir.getPath());
File[] childs = dir.listFiles();
if (childs == null) {
return;
}
for (File child : childs) {
scan(child, level + 1);
}
}
} catch (Exception e) {
setLastError(e.toString());
}
}
private void testPath(String path) throws Exception {
setCurrentDir(path);
testReader(new CoordinateReaderOsmAnd(path));
testReader(new CoordinateReaderOsmAnd(path, true));
testReader(new CoordinateReaderLocus(path));
testReader(new CoordinateReaderOrux(path));
}
private void testReader(CoordinateReader cor) throws Exception {
long ts = cor.getTimeStamp();
if (ts > maxtimestamp) {
maxtimestamp = ts;
synchronized (currentDirSync) {
bestGuess = cor.basedir;
}
} else if (ts > 0 && ts == maxtimestamp) {
synchronized (currentDirSync) {
if (cor.basedir.length() < bestGuess.length()) {
bestGuess = cor.basedir;
}
}
}
}
@Override
public void run() {
scan(new File("/"), 0);
setCurrentDir(null);
}
}

View file

@ -0,0 +1,5 @@
<paths>
<cache-path
name="cache"
path="." />
</paths>