Merge pull request #318 from afischerdev/test-and11

Update for Android 11 part 1
This commit is contained in:
afischerdev 2021-07-24 12:01:21 +02:00 committed by GitHub
commit 1886ef1f17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 716 additions and 172 deletions

1
.gitignore vendored
View file

@ -19,5 +19,4 @@ misc/customprofiles
*.BAK
.classpath
.project
*.iml
!/.idea/runConfigurations

View file

@ -123,6 +123,15 @@ public final class RoutingContext
{
BExpressionContext expctxGlobal = expctxWay; // just one of them...
if (keyValues != null) {
// add parameter to context
for (Map.Entry<String, String> e : keyValues.entrySet()) {
float f = Float.parseFloat(e.getValue());
expctxWay.setVariableValue(e.getKey(), f, false );
expctxNode.setVariableValue(e.getKey(), f, false );
}
}
setModel( expctxGlobal._modelClass );
downhillcostdiv = (int)expctxGlobal.getVariableValue( "downhillcost", 0.f );

View file

@ -798,6 +798,13 @@ public abstract class BExpressionContext implements IByteArrayUnifier
return result;
}
public void setVariableValue(String name, float value, boolean create ) {
Integer num = variableNumbers.get( name );
if ( num != null )
{
variableData[num.intValue()] = value;
}
}
public float getVariableValue( String name, float defaultValue )
{

View file

@ -1,12 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="btools.routingapp">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="btools.routingapp">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application android:icon="@drawable/icon" android:label="@string/app_name" android:allowBackup="true">
<application
android:icon="@drawable/icon"
android:label="@string/app_name"
android:allowBackup="true">
<activity android:name=".BRouterActivity"
android:label="@string/app_name"
android:screenOrientation="portrait" android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
@ -17,13 +23,14 @@
</activity>
<activity android:name=".BInstallerActivity"
android:label="@string/app_name"
android:screenOrientation="landscape" android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
</activity>
<service
android:exported="true"
android:name=".BRouterService"
android:enabled="true"
android:process=":brouter_service">
</service>
android:process=":brouter_service" />
</application>
</manifest>

View file

@ -6,10 +6,10 @@ interface IBRouterService {
//param params--> Map of params:
// "pathToFileResult"-->String with the path to where the result must be saved, including file name and extension
// -->if null, the track is passed via the return argument
// -->if null, the track is passed via the return argument, this should be default when Android Q or later
// "maxRunningTime"-->String with a number of seconds for the routing timeout, default = 60
// "turnInstructionFormat"-->String selecting the format for turn-instructions values: osmand, locus
// "trackFormat"-->[kml|gpx] default = gpx
// "trackFormat"-->[kml|gpx|json] default = gpx
// "lats"-->double[] array of latitudes; 2 values at least.
// "lons"-->double[] array of longitudes; 2 values at least.
// "nogoLats"-->double[] array of nogo latitudes; may be null.
@ -18,7 +18,20 @@ interface IBRouterService {
// "fast"-->[0|1]
// "v"-->[motorcar|bicycle|foot]
// "remoteProfile"--> (String), net-content of a profile. If remoteProfile != null, v+fast are ignored
//
// "lonlats" = lon,lat|... (unlimited list of lon,lat waypoints separated by |)
// "nogos" = lon,lat,radius|... (optional, radius in meters)
// "polylines" = lon,lat,weight|... (unlimited list of lon,lat and weight (optional) separated by |)
// "polygons" = lon,lat,weight|... (unlimited list of lon,lat and weight (optional) separated by |)
// "profile" = profile file name without .brf
// "alternativeidx" = [0|1|2|3] (optional, default 0)
// "exportWaypoints" = 1 to export them (optional, default is no export)
// "pois" = lon,lat,name|... (optional)
// "extraParams" = Bundle key=value list for a profile setup (like "profile:")
// "timode" = turnInstructionMode [0=none, 1=auto-choose, 2=locus-style, 3=osmand-style, 4=comment-style, 5=gpsies-style, 6=orux-style] default 0
// return null if all ok and no path given, the track if ok and path given, an error message if it was wrong
// the resultas string when 'pathToFileResult' is null, this should be default when Android Q or later
// call in a background thread, heavy task!
String getTrackFromParams(in Bundle params);

View file

@ -25,7 +25,7 @@ public class AppLogger
// open logfile if existing
File sd = Environment.getExternalStorageDirectory();
if ( sd == null ) return;
File debugLog = new File( sd, "Android/data/btools.routingapp/files/brouterapp.txt" );
File debugLog = new File( sd, "Android/media/btools.routingapp/brouter/brouterapp.txt" );
if ( debugLog.exists() )
{
debugLogWriter = new FileWriter( debugLog, true );

View file

@ -7,6 +7,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Locale;
import android.app.Activity;
import android.content.Context;
@ -20,6 +21,7 @@ import android.graphics.Paint;
import android.os.AsyncTask;
import android.os.PowerManager;
import android.os.StatFs;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
@ -73,6 +75,10 @@ public class BInstallerView extends View
private long rd5Tiles = 0;
private long delTiles = 0;
Paint pnt_1 = new Paint();
Paint pnt_2 = new Paint();
Paint paint = new Paint();
protected String baseNameForTile( int tileIndex )
{
int lon = (tileIndex % 72 ) * 5 - 180;
@ -89,15 +95,15 @@ public class BInstallerView extends View
private int tileForBaseName( String basename )
{
String uname = basename.toUpperCase();
String uname = basename.toUpperCase(Locale.ROOT);
int idx = uname.indexOf( "_" );
if ( idx < 0 ) return -1;
String slon = uname.substring( 0, idx );
String slat = uname.substring( idx+1 );
int ilon = slon.charAt(0) == 'W' ? -Integer.valueOf( slon.substring(1) ) :
( slon.charAt(0) == 'E' ? Integer.valueOf( slon.substring(1) ) : -1 );
int ilat = slat.charAt(0) == 'S' ? -Integer.valueOf( slat.substring(1) ) :
( slat.charAt(0) == 'N' ? Integer.valueOf( slat.substring(1) ) : -1 );
int ilon = slon.charAt(0) == 'W' ? -Integer.parseInt( slon.substring(1) ) :
( slon.charAt(0) == 'E' ? Integer.parseInt( slon.substring(1) ) : -1 );
int ilat = slat.charAt(0) == 'S' ? -Integer.parseInt( slat.substring(1) ) :
( slat.charAt(0) == 'N' ? Integer.parseInt( slat.substring(1) ) : -1 );
if ( ilon < -180 || ilon >= 180 || ilon % 5 != 0 ) return -1;
if ( ilat < - 90 || ilat >= 90 || ilat % 5 != 0 ) return -1;
return (ilon+180) / 5 + 72*((ilat+90)/5);
@ -236,7 +242,7 @@ public class BInstallerView extends View
try
{
StatFs stat = new StatFs(baseDir.getAbsolutePath ());
availableSize = (long)stat.getAvailableBlocks()*stat.getBlockSize();
availableSize = (long)stat.getAvailableBlocksLong()*stat.getBlockSizeLong();
}
catch (Exception e) { /* ignore */ }
}
@ -339,7 +345,6 @@ public class BInstallerView extends View
if ( drawGrid )
{
Paint pnt_1 = new Paint();
pnt_1.setColor(Color.GREEN);
for( int ix=1; ix<72; ix++ )
@ -358,7 +363,7 @@ public class BInstallerView extends View
totalSize = 0;
int mask2 = MASK_SELECTED_RD5 | MASK_DELETED_RD5 | MASK_INSTALLED_RD5;
int mask3 = mask2 | MASK_CURRENT_RD5;
Paint pnt_2 = new Paint();
pnt_2.setColor(Color.GRAY);
pnt_2.setStrokeWidth(1);
drawSelectedTiles( canvas, pnt_2, fw, fh, MASK_INSTALLED_RD5, mask3, false, false, drawGrid );
@ -377,7 +382,6 @@ public class BInstallerView extends View
canvas.setMatrix( matText );
Paint paint = new Paint();
paint.setColor(Color.RED);
long mb = 1024*1024;
@ -408,6 +412,7 @@ public class BInstallerView extends View
if ( isDownloading ) btnText = "Cancel Download";
else if ( delTiles > 0 ) btnText = "Delete " + delTiles + " tiles";
else if ( rd5Tiles > 0 ) btnText = "Start Download";
else if ( tilesVisible && rd5Tiles == 0) btnText = "Update all";
if ( btnText != null )
{
@ -569,8 +574,23 @@ float tx, ty;
}
// download button?
if ( ( delTiles > 0 || rd5Tiles > 0 || isDownloading ) && event.getX() > imgwOrig - btnw*scaleOrig && event.getY() > imghOrig-btnh*scaleOrig )
if ( ( delTiles > 0 || rd5Tiles >= 0 || isDownloading ) && event.getX() > imgwOrig - btnw*scaleOrig && event.getY() > imghOrig-btnh*scaleOrig )
{
if (rd5Tiles == 0) {
for ( int ix = 0; ix < 72; ix++ )
{
for ( int iy = 0; iy < 36; iy++ )
{
int tidx = gridPos2Tileindex( ix, iy );
if (tidx != -1) {
if ( ( tileStatus[tidx] & MASK_INSTALLED_RD5 ) != 0 ) {
tileStatus[tidx] |= MASK_SELECTED_RD5;
}
}
}
}
}
toggleDownload();
invalidate();
break;
@ -731,7 +751,7 @@ float tx, ty;
tmp_file = new File( fname.getAbsolutePath() + ( delta ? "_diff" : "_tmp" ) );
output = new FileOutputStream( tmp_file );
byte data[] = new byte[4096];
byte[] data = new byte[4096];
long total = 0;
long t0 = System.currentTimeMillis();
int count;

View file

@ -23,6 +23,7 @@ import android.os.PowerManager.WakeLock;
import android.os.StatFs;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.EditText;
import androidx.core.app.ActivityCompat;
@ -81,10 +82,12 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
protected Dialog onCreateDialog( int id )
{
AlertDialog.Builder builder;
builder = new AlertDialog.Builder( this );
builder.setCancelable(false);
switch ( id )
{
case DIALOG_SELECTPROFILE_ID:
builder = new AlertDialog.Builder( this );
builder.setTitle( "Select a routing profile" );
builder.setItems( availableProfiles, new DialogInterface.OnClickListener()
{
@ -96,9 +99,9 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_MAINACTION_ID:
builder = new AlertDialog.Builder( this );
builder.setTitle( "Select Main Action" );
builder.setItems( new String[]
builder
.setItems( new String[]
{ "Download Manager", "BRouter App" }, new DialogInterface.OnClickListener()
{
public void onClick( DialogInterface dialog, int item )
@ -108,10 +111,18 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
else
showDialog( DIALOG_SELECTPROFILE_ID );
}
} );
}
)
.setNegativeButton( "Close", new DialogInterface.OnClickListener()
{
public void onClick( DialogInterface dialog, int id )
{
finish();
}
}
);
return builder.create();
case DIALOG_SHOW_DM_INFO_ID:
builder = new AlertDialog.Builder( this );
builder
.setTitle( "BRouter Download Manager" )
.setMessage(
@ -134,7 +145,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_SHOW_WP_HELP_ID:
builder = new AlertDialog.Builder( this );
builder
.setTitle( "No Waypoint Database found" )
.setMessage(
@ -160,7 +170,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_SHOW_API23_HELP_ID:
builder = new AlertDialog.Builder( this );
builder
.setTitle( "Android >=6 limitations" )
.setMessage(
@ -183,7 +192,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_SHOW_REPEAT_TIMEOUT_HELP_ID:
builder = new AlertDialog.Builder( this );
builder
.setTitle( "Successfully prepared a timeout-free calculation" )
.setMessage(
@ -199,7 +207,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_SHOW_WP_SCANRESULT_ID:
builder = new AlertDialog.Builder( this );
builder
.setTitle( "Waypoint Database " )
.setMessage( "Found Waypoint-Database(s) for maptool-dir: " + maptoolDirCandidate
@ -218,7 +225,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_OLDDATAHINT_ID:
builder = new AlertDialog.Builder( this );
builder
.setTitle( "Local setup needs reset" )
.setMessage(
@ -235,7 +241,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_ROUTINGMODES_ID:
builder = new AlertDialog.Builder( this );
builder.setTitle( message );
builder.setMultiChoiceItems( routingModes, routingModesChecked, new DialogInterface.OnMultiChoiceClickListener()
{
@ -254,7 +259,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_EXCEPTION_ID:
builder = new AlertDialog.Builder( this );
builder.setTitle( "An Error occured" ).setMessage( errorMessage ).setPositiveButton( "OK", new DialogInterface.OnClickListener()
{
public void onClick( DialogInterface dialog, int id )
@ -264,7 +268,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_TEXTENTRY_ID:
builder = new AlertDialog.Builder( this );
builder.setTitle( "Enter SDCARD base dir:" );
builder.setMessage( message );
final EditText input = new EditText( this );
@ -280,7 +283,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_SELECTBASEDIR_ID:
builder = new AlertDialog.Builder( this );
builder.setTitle( "Choose brouter data base dir:" );
// builder.setMessage( message );
builder.setSingleChoiceItems( basedirOptions, 0, new DialogInterface.OnClickListener()
@ -307,7 +309,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_VIASELECT_ID:
builder = new AlertDialog.Builder( this );
builder.setTitle( "Check VIA Selection:" );
builder.setMultiChoiceItems( availableVias, getCheckedBooleanArray( availableVias.length ), new DialogInterface.OnMultiChoiceClickListener()
{
@ -334,7 +335,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_NOGOSELECT_ID:
builder = new AlertDialog.Builder( this );
builder.setTitle( "Check NoGo Selection:" );
String[] nogoNames = new String[nogoList.size()];
for ( int i = 0; i < nogoList.size(); i++ )
@ -360,7 +360,7 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
case DIALOG_SHOWRESULT_ID:
String leftLabel = wpCount < 0 ? ( wpCount != -2 ? "Exit" : "Help") : ( wpCount == 0 ? "Select from" : "Select to/via" );
String rightLabel = wpCount < 2 ? ( wpCount == -3 ? "Help" : "Server-Mode" ) : "Calc Route";
builder = new AlertDialog.Builder( this );
builder.setTitle( title ).setMessage( errorMessage ).setPositiveButton( leftLabel, new DialogInterface.OnClickListener()
{
public void onClick( DialogInterface dialog, int id )
@ -399,7 +399,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_MODECONFIGOVERVIEW_ID:
builder = new AlertDialog.Builder( this );
builder.setTitle( "Success" ).setMessage( message ).setPositiveButton( "Exit", new DialogInterface.OnClickListener()
{
public void onClick( DialogInterface dialog, int id )
@ -409,7 +408,6 @@ public class BRouterActivity extends Activity implements OnInitListener, Activit
} );
return builder.create();
case DIALOG_PICKWAYPOINT_ID:
builder = new AlertDialog.Builder( this );
builder.setTitle( wpCount > 0 ? "Select to/via" : "Select from" );
builder.setItems( availableWaypoints, new DialogInterface.OnClickListener()
{

View file

@ -12,6 +12,7 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.zip.GZIPOutputStream;
import java.util.ArrayList;
@ -68,9 +69,24 @@ public class BRouterService extends Service
remoteProfile = checkForTestDummy( baseDir );
}
String errMsg = remoteProfile == null
? getConfigFromMode( worker, baseDir, params.getString( "v" ), params.getString( "fast" ) )
: getConfigForRemoteProfile( worker, baseDir, remoteProfile );
String errMsg = null;
if (remoteProfile != null ) {
errMsg = getConfigForRemoteProfile(worker, baseDir, remoteProfile);
} else if (params.containsKey("profile")) {
String profile = params.getString( "profile" );
worker.profileName = profile;
worker.profilePath = baseDir + "/brouter/profiles2/" + profile + ".brf";
worker.rawTrackPath = baseDir + "/brouter/modes/" + profile + "_rawtrack.dat";
if (!new File(worker.profilePath).exists()) errMsg = "Profile " + profile + " does not exists";
try {
readNogos(worker, baseDir);
} catch (Exception e) {
errMsg = e.getLocalizedMessage();
}
}
else {
errMsg = getConfigFromMode(worker, baseDir, params.getString("v"), params.getString("fast"));
}
if ( errMsg != null )
{
@ -131,24 +147,8 @@ public class BRouterService extends Service
worker.profilePath = baseDir + "/brouter/profiles2/" + smc.profile + ".brf";
worker.rawTrackPath = baseDir + "/brouter/modes/" + mode_key + "_rawtrack.dat";
worker.nogoList = new ArrayList<OsmNodeNamed>();
readNogos(worker, baseDir);
int deviceLevel = android.os.Build.VERSION.SDK_INT;
int targetSdkVersion = getApplicationInfo().targetSdkVersion;
boolean canAccessSdCard = deviceLevel < 23 || targetSdkVersion == 10;
AppLogger.log( "dev/target=" + deviceLevel + "/" + targetSdkVersion + " canAccessSdCard=" + canAccessSdCard );
if ( canAccessSdCard )
{
CoordinateReader cor = CoordinateReader.obtainValidReader( baseDir, worker.segmentDir, true );
// veto nogos by profiles veto list
for ( OsmNodeNamed nogo : cor.nogopoints )
{
if ( !smc.nogoVetos.contains( nogo.ilon + "," + nogo.ilat ) )
{
worker.nogoList.add( nogo );
}
}
}
return null;
}
}
@ -175,20 +175,7 @@ public class BRouterService extends Service
try
{
// add nogos from waypoint database
int deviceLevel = android.os.Build.VERSION.SDK_INT;
int targetSdkVersion = getApplicationInfo().targetSdkVersion;
boolean canAccessSdCard = deviceLevel < 23 || targetSdkVersion == 10;
AppLogger.log( "dev/target=" + deviceLevel + "/" + targetSdkVersion + " canAccessSdCard=" + canAccessSdCard );
if ( canAccessSdCard )
{
CoordinateReader cor = CoordinateReader.obtainValidReader( baseDir, worker.segmentDir, true );
worker.nogoList = new ArrayList<OsmNodeNamed>( cor.nogopoints );
}
else
{
worker.nogoList = new ArrayList<OsmNodeNamed>();
}
readNogos(worker, baseDir);
if ( !fileEqual( profileBytes, profileFile ) )
{
@ -211,6 +198,34 @@ public class BRouterService extends Service
return null;
}
private void readNogos(BRouterWorker worker, String baseDir) throws Exception {
// add nogos from waypoint database
int deviceLevel = android.os.Build.VERSION.SDK_INT;
int targetSdkVersion = getApplicationInfo().targetSdkVersion;
boolean canAccessSdCard = deviceLevel < 23 || targetSdkVersion == 10;
AppLogger.log( "dev/target=" + deviceLevel + "/" + targetSdkVersion + " canAccessSdCard=" + canAccessSdCard );
if ( canAccessSdCard )
{
CoordinateReader cor = CoordinateReader.obtainValidReader( baseDir, worker.segmentDir, true );
worker.nogoList = new ArrayList<OsmNodeNamed>( cor.nogopoints );
worker.nogoPolygonsList = new ArrayList<OsmNodeNamed>();
}
else if (deviceLevel >= android.os.Build.VERSION_CODES.Q) {
CoordinateReader cor = new CoordinateReaderInternal( baseDir );
cor.readFromTo();
worker.nogoList = new ArrayList<OsmNodeNamed>( cor.nogopoints );
worker.nogoPolygonsList = new ArrayList<OsmNodeNamed>();
}
else
{
worker.nogoList = new ArrayList<OsmNodeNamed>();
worker.nogoPolygonsList = new ArrayList<OsmNodeNamed>();
}
}
private boolean fileEqual( byte[] fileBytes, File file ) throws Exception
{
if ( !file.exists() )

View file

@ -28,6 +28,7 @@ import android.content.res.AssetManager;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.os.Environment;
import android.util.DisplayMetrics;
import android.util.Log;
@ -181,7 +182,7 @@ public class BRouterView extends View
String basedir = baseDir.getAbsolutePath();
AppLogger.log( "using basedir: " + basedir );
String version = "v1.6.1";
String version = "v" + getContext().getString(R.string.app_version);
// create missing directories
assertDirectoryExists( "project directory", new File (basedir, "brouter"), null, null );
@ -198,6 +199,9 @@ public class BRouterView extends View
assertDirectoryExists( "modes directory", modesDir, "modes.zip", version );
assertDirectoryExists( "readmes directory", new File (basedir, "brouter/readmes"), "readmes.zip", version );
File inputDir = new File (basedir, "/import");
assertDirectoryExists( "input directory", inputDir, null, version );
int deviceLevel = android.os.Build.VERSION.SDK_INT;
int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
canAccessSdCard = deviceLevel < 23 || targetSdkVersion == 10;
@ -207,7 +211,11 @@ public class BRouterView extends View
}
else
{
if (deviceLevel >= android.os.Build.VERSION_CODES.Q) {
cor = new CoordinateReaderInternal(basedir);
} else {
cor = new CoordinateReaderNone();
}
cor.readFromTo();
}
@ -342,7 +350,7 @@ public class BRouterView extends View
{
for ( int i = nogoList.size() - 1; i >= 0; i-- )
{
if ( !enabled[i] )
if ( enabled[i] )
{
nogoVetoList.add( nogoList.get( i ) );
nogoList.remove( i );
@ -830,7 +838,7 @@ public class BRouterView extends View
else
{
String memstat = memoryClass + "mb pathPeak " + ((cr.getPathPeak()+500)/1000) + "k";
String result = "version = BRouter-1.6.1\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()
+ " m\n" + "plain ascend = " + cr.getPlainAscend() + " m\n" + "estimated time = " + cr.getTime();
rawTrack = cr.getFoundRawTrack();
@ -1044,7 +1052,8 @@ public class BRouterView extends View
// no write new config
BufferedWriter bw = null;
StringBuilder msg = new StringBuilder( "Mode mapping is now:\n" );
msg.append( "( [..] counts nogo-vetos)\n" );
msg.append("( [");
msg.append(nogoVetoList.size()>0?nogoVetoList.size():"..").append( "] counts nogo-vetos)\n" );
try
{
bw = new BufferedWriter( new FileWriter( modesFile ) );
@ -1086,7 +1095,12 @@ public class BRouterView extends View
}
private ArrayList<File> getStorageDirectories () {
ArrayList<File> list = new ArrayList<File>(Arrays.asList(getContext().getExternalFilesDirs(null)));
ArrayList<File> list = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
list = new ArrayList<File>(Arrays.asList(getContext().getExternalMediaDirs()));
} else {
list = new ArrayList<File>(Arrays.asList(getContext().getExternalFilesDirs(null)));
}
ArrayList<File> res = new ArrayList<File>();
for (File f : list) {

View file

@ -10,8 +10,9 @@ import java.util.List;
import java.util.StringTokenizer;
import android.os.Bundle;
import btools.router.OsmNodeNamed;
import btools.router.OsmPathElement;
import btools.router.OsmNogoPolygon;
import btools.router.OsmTrack;
import btools.router.RoutingContext;
import btools.router.RoutingEngine;
@ -29,13 +30,12 @@ public class BRouterWorker
public String rawTrackPath;
public List<OsmNodeNamed> waypoints;
public List<OsmNodeNamed> nogoList;
public List<OsmNodeNamed> nogoPolygonsList;
public String getTrackFromParams(Bundle params)
{
public String getTrackFromParams(Bundle params) {
String pathToFileResult = params.getString("pathToFileResult");
if (pathToFileResult != null)
{
if (pathToFileResult != null) {
File f = new File(pathToFileResult);
File dir = f.getParentFile();
if (!dir.exists() || !dir.canWrite()) {
@ -45,8 +45,7 @@ public class BRouterWorker
long maxRunningTime = 60000;
String sMaxRunningTime = params.getString("maxRunningTime");
if ( sMaxRunningTime != null )
{
if (sMaxRunningTime != null) {
maxRunningTime = Integer.parseInt(sMaxRunningTime) * 1000;
}
@ -55,22 +54,52 @@ public class BRouterWorker
rc.localFunction = profilePath;
String tiFormat = params.getString("turnInstructionFormat");
if ( tiFormat != null )
{
if ( "osmand".equalsIgnoreCase( tiFormat ) )
{
if (tiFormat != null) {
if ("osmand".equalsIgnoreCase(tiFormat)) {
rc.turnInstructionMode = 3;
}
else if ( "locus".equalsIgnoreCase( tiFormat ) )
{
} else if ("locus".equalsIgnoreCase(tiFormat)) {
rc.turnInstructionMode = 2;
}
}
if (params.containsKey("timode")) {
rc.turnInstructionMode = params.getInt("timode");
}
if ( params.containsKey( "direction" ) )
{
rc.startDirection = Integer.valueOf( params.getInt( "direction" ) );
rc.startDirection = params.getInt( "direction" );
}
if ( params.containsKey( "alternativeidx" ) ) {
rc.alternativeIdx = params.getInt( "alternativeidx" );
}
readNogos( params ); // add interface provided nogos
if ( nogoList != null ) {
RoutingContext.prepareNogoPoints(nogoList);
if (rc.nogopoints == null) {
rc.nogopoints = nogoList;
} else {
rc.nogopoints.addAll(nogoList);
}
}
if (rc.nogopoints == null) {
rc.nogopoints = nogoPolygonsList;
} else if ( nogoPolygonsList != null ) {
rc.nogopoints.addAll(nogoPolygonsList);
}
List<OsmNodeNamed> poisList = readPoisList(params);
rc.poipoints = poisList;
if (params.containsKey("lats")) {
waypoints = readPositions(params);
}
if (params.containsKey("lonlats")) {
waypoints = readLonlats(params);
}
if (waypoints == null) return "no pts ";
if (params.containsKey( "extraParams" )) { // add user params
String extraParams = params.getString("extraParams");
if (rc.keyValues == null) rc.keyValues = new HashMap<String,String>();
@ -88,11 +117,6 @@ public class BRouterWorker
}
}
readNogos( params ); // add interface provided nogos
RoutingContext.prepareNogoPoints( nogoList );
rc.nogopoints = nogoList;
waypoints = readPositions(params);
try
{
@ -130,6 +154,9 @@ public class BRouterWorker
OsmTrack track = cr.getFoundTrack();
if ( track != null )
{
if (params.containsKey("exportWaypoints")) {
track.exportWaypoints = (params.getInt("exportWaypoints",0) == 1 );
}
if ( pathToFileResult == null )
{
switch ( writeFromat ) {
@ -183,16 +210,59 @@ public class BRouterWorker
return wplist;
}
private List<OsmNodeNamed> readLonlats(Bundle params )
{
List<OsmNodeNamed> wplist = new ArrayList<OsmNodeNamed>();
String lonLats = params.getString( "lonlats" );
if (lonLats == null) throw new IllegalArgumentException( "lonlats parameter not set" );
String[] coords = lonLats.split("\\|");
if (coords.length < 2)
throw new IllegalArgumentException( "we need two lat/lon points at least!" );
for (int i = 0; i < coords.length; i++)
{
String[] lonLat = coords[i].split(",");
if (lonLat.length < 2)
throw new IllegalArgumentException( "we need two lat/lon points at least!" );
wplist.add( readPosition( lonLat[0], lonLat[1], "via" + i ) );
}
wplist.get(0).name = "from";
wplist.get(wplist.size()-1).name = "to";
return wplist;
}
private static OsmNodeNamed readPosition( String vlon, String vlat, String name )
{
if ( vlon == null ) throw new IllegalArgumentException( "lon " + name + " not found in input" );
if ( vlat == null ) throw new IllegalArgumentException( "lat " + name + " not found in input" );
return readPosition(Double.parseDouble( vlon ), Double.parseDouble( vlat ), name);
}
private static OsmNodeNamed readPosition( double lon, double lat, String name )
{
OsmNodeNamed n = new OsmNodeNamed();
n.name = name;
n.ilon = (int)( ( lon + 180. ) *1000000. + 0.5);
n.ilat = (int)( ( lat + 90. ) *1000000. + 0.5);
return n;
}
private void readNogos( Bundle params )
{
if (params.containsKey("nogoLats")) {
double[] lats = params.getDoubleArray("nogoLats");
double[] lons = params.getDoubleArray("nogoLons");
double[] radi = params.getDoubleArray("nogoRadi");
if (lats == null || lons == null || radi == null) return;
for( int i=0; i<lats.length && i<lons.length && i<radi.length; i++ )
{
for (int i = 0; i < lats.length && i < lons.length && i < radi.length; i++) {
OsmNodeNamed n = new OsmNodeNamed();
n.name = "nogo" + (int) radi[i];
n.ilon = (int) ((lons[i] + 180.) * 1000000. + 0.5);
@ -203,6 +273,161 @@ public class BRouterWorker
nogoList.add(n);
}
}
if (params.containsKey("nogos")) {
nogoList = readNogoList(params);
}
if (params.containsKey("polylines") ||
params.containsKey("polygons")) {
nogoPolygonsList = readNogoPolygons(params);
}
}
private List<OsmNodeNamed> readNogoList(Bundle params)
{
// lon,lat,radius|...
String nogos = params.getString( "nogos" );
if ( nogos == null ) return null;
String[] lonLatRadList = nogos.split("\\|");
List<OsmNodeNamed> nogoList = new ArrayList<OsmNodeNamed>();
for (int i = 0; i < lonLatRadList.length; i++)
{
String[] lonLatRad = lonLatRadList[i].split(",");
String nogoWeight = "NaN";
if (lonLatRad.length > 3) {
nogoWeight = lonLatRad[3];
}
nogoList.add(readNogo(lonLatRad[0], lonLatRad[1], lonLatRad[2], nogoWeight));
}
return nogoList;
}
private static OsmNodeNamed readNogo( String lon, String lat, String radius, String nogoWeight )
{
double weight = "undefined".equals( nogoWeight ) ? Double.NaN : Double.parseDouble( nogoWeight );
return readNogo(Double.parseDouble( lon ), Double.parseDouble( lat ), Integer.parseInt( radius ), weight );
}
private static OsmNodeNamed readNogo( double lon, double lat, int radius, double nogoWeight )
{
OsmNodeNamed n = new OsmNodeNamed();
n.name = "nogo" + radius;
n.ilon = (int)( ( lon + 180. ) *1000000. + 0.5);
n.ilat = (int)( ( lat + 90. ) *1000000. + 0.5);
n.isNogo = true;
n.nogoWeight = nogoWeight;
return n;
}
private List<OsmNodeNamed> readNogoPolygons(Bundle params)
{
List<OsmNodeNamed> result = new ArrayList<OsmNodeNamed>();
parseNogoPolygons( params.getString("polylines"), result, false );
parseNogoPolygons( params.getString("polygons"), result, true );
return result.size() > 0 ? result : null;
}
private static void parseNogoPolygons(String polygons, List<OsmNodeNamed> result, boolean closed )
{
if ( polygons != null )
{
OsmNogoPolygon polygon = new OsmNogoPolygon(closed);
polygon.name = "nogopoly" ;
String nogoWeight = "NaN";
String[] polygonList = polygons.split("\\|");
for (int i = 0; i < polygonList.length; i++)
{
String[] lonLatList = polygonList[i].split(",");
if ( lonLatList.length > 1 )
{
int j;
for (j = 0; j < 2 * (lonLatList.length / 2) - 1;)
{
String slon = lonLatList[j++];
String slat = lonLatList[j++];
int lon = (int)( ( Double.parseDouble(slon) + 180. ) *1000000. + 0.5);
int lat = (int)( ( Double.parseDouble(slat) + 90. ) *1000000. + 0.5);
polygon.addVertex(lon, lat);
}
if (j < lonLatList.length) {
nogoWeight = lonLatList[j];
}
}
}
polygon.nogoWeight = Double.parseDouble( nogoWeight );
if ( polygon.points.size() > 0 )
{
polygon.calcBoundingCircle();
result.add(polygon);
}
}
}
private static void parseNogoPolygons_alt(String polygons, List<OsmNodeNamed> result, boolean closed )
{
if ( polygons != null )
{
String[] polygonList = polygons.split("\\|");
for (int i = 0; i < polygonList.length; i++)
{
String[] lonLatList = polygonList[i].split(",");
if ( lonLatList.length > 1 )
{
OsmNogoPolygon polygon = new OsmNogoPolygon(closed);
polygon.name = "nogo" + i;
int j;
for (j = 0; j < 2 * (lonLatList.length / 2) - 1;)
{
String slon = lonLatList[j++];
String slat = lonLatList[j++];
int lon = (int)( ( Double.parseDouble(slon) + 180. ) *1000000. + 0.5);
int lat = (int)( ( Double.parseDouble(slat) + 90. ) *1000000. + 0.5);
polygon.addVertex(lon, lat);
}
String nogoWeight = "NaN";
if (j < lonLatList.length) {
nogoWeight = lonLatList[j];
}
polygon.nogoWeight = Double.parseDouble( nogoWeight );
if ( polygon.points.size() > 0 )
{
polygon.calcBoundingCircle();
result.add(polygon);
}
}
}
}
}
private List<OsmNodeNamed> readPoisList(Bundle params )
{
// lon,lat,name|...
String pois = params.getString( "pois", null );
if ( pois == null ) return null;
String[] lonLatNameList = pois.split("\\|");
List<OsmNodeNamed> poisList = new ArrayList<OsmNodeNamed>();
for (int i = 0; i < lonLatNameList.length; i++)
{
String[] lonLatName = lonLatNameList[i].split(",");
OsmNodeNamed n = new OsmNodeNamed();
n.ilon = (int)( ( Double.parseDouble(lonLatName[0]) + 180. ) *1000000. + 0.5);
n.ilat = (int)( ( Double.parseDouble(lonLatName[1]) + 90. ) *1000000. + 0.5);
n.name = lonLatName[2];
poisList.add(n);
}
return poisList;
}
private void writeTimeoutData( RoutingContext rc ) throws Exception
{

View file

@ -0,0 +1,211 @@
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 + "/import";
tracksdir = "/import/tracks";
rootdir = "/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

@ -21,8 +21,11 @@ public class CoordinateReaderLocus extends CoordinateReader
@Override
public long getTimeStamp() throws Exception
{
long t1 = new File( basedir + "/Locus/data/database/waypoints.db" ).lastModified();
return t1;
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
@ -43,9 +46,19 @@ public class CoordinateReaderLocus extends CoordinateReader
private void _readPointmap( String filename ) throws Exception
{
SQLiteDatabase myDataBase = SQLiteDatabase.openDatabase( filename, null, SQLiteDatabase.OPEN_READONLY);
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();
@ -55,6 +68,7 @@ public class CoordinateReaderLocus extends CoordinateReader
n.ilat = (int)( ( c.getDouble(3) + 90. )*1000000. + 0.5);
checkAddPoint( category, n );
}
c.close();
myDataBase.close();
}
}

View file

@ -21,8 +21,11 @@ public class CoordinateReaderOrux extends CoordinateReader
@Override
public long getTimeStamp() throws Exception
{
long t1 = new File( basedir + "/oruxmaps/tracklogs/oruxmapstracks.db" ).lastModified();
return t1;
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
@ -43,7 +46,13 @@ public class CoordinateReaderOrux extends CoordinateReader
private void _readPointmap( String filename ) throws Exception
{
SQLiteDatabase myDataBase = SQLiteDatabase.openDatabase( filename, null, SQLiteDatabase.OPEN_READONLY);
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())
{
@ -54,6 +63,7 @@ public class CoordinateReaderOrux extends CoordinateReader
String category = c.getString(3);
checkAddPoint( category, n );
}
c.close();
myDataBase.close();
}
}

View file

@ -45,8 +45,10 @@ public class CoordinateReaderOsmAnd extends CoordinateReader
@Override
public long getTimeStamp() throws Exception
{
long t1 = new File( osmandDir + "/favourites_bak.gpx" ).lastModified();
long t2 = new File( osmandDir + "/favourites.gpx" ).lastModified();
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;
}