diff --git a/brouter-routing-app/src/main/java/btools/routingapp/AppLogger.java b/brouter-routing-app/src/main/java/btools/routingapp/AppLogger.java index 586d1f4..6d1eda8 100644 --- a/brouter-routing-app/src/main/java/btools/routingapp/AppLogger.java +++ b/brouter-routing-app/src/main/java/btools/routingapp/AppLogger.java @@ -25,7 +25,7 @@ public class AppLogger // open logfile if existing File sd = Environment.getExternalStorageDirectory(); if ( sd == null ) return; - File debugLog = new File( sd, "brouterapp.txt" ); + File debugLog = new File( sd, "Android/data/btools.routingapp/files/brouterapp.txt" ); if ( debugLog.exists() ) { debugLogWriter = new FileWriter( debugLog, true ); diff --git a/brouter-routing-app/src/main/java/btools/routingapp/BRouterActivity.java b/brouter-routing-app/src/main/java/btools/routingapp/BRouterActivity.java index fe5b036..4b9e393 100644 --- a/brouter-routing-app/src/main/java/btools/routingapp/BRouterActivity.java +++ b/brouter-routing-app/src/main/java/btools/routingapp/BRouterActivity.java @@ -40,6 +40,8 @@ public class BRouterActivity extends Activity implements OnInitListener 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_API23_HELP_ID = 17; + private BRouterView mBRouterView; private PowerManager mPowerManager; @@ -150,6 +152,29 @@ public class BRouterActivity extends Activity implements OnInitListener } } ); return builder.create(); + case DIALOG_SHOW_API23_HELP_ID: + builder = new AlertDialog.Builder( this ); + 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 funtions you need to start the BRouter App are 1) to initially define the base directory " + + "2) to dowload 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: builder = new AlertDialog.Builder( this ); builder @@ -529,7 +554,14 @@ public class BRouterActivity extends Activity implements OnInitListener @SuppressWarnings("deprecation") public void showWaypointDatabaseHelp() { - showNewDialog( DIALOG_SHOW_WP_HELP_ID ); + if ( mBRouterView.canAccessSdCard ) + { + showNewDialog( DIALOG_SHOW_WP_HELP_ID ); + } + else + { + showNewDialog( DIALOG_SHOW_API23_HELP_ID ); + } } @SuppressWarnings("deprecation") diff --git a/brouter-routing-app/src/main/java/btools/routingapp/BRouterService.java b/brouter-routing-app/src/main/java/btools/routingapp/BRouterService.java index 3bcc1fb..ad2b109 100644 --- a/brouter-routing-app/src/main/java/btools/routingapp/BRouterService.java +++ b/brouter-routing-app/src/main/java/btools/routingapp/BRouterService.java @@ -105,14 +105,22 @@ public class BRouterService extends Service worker.profilePath = baseDir + "/brouter/profiles2/" + smc.profile + ".brf"; worker.rawTrackPath = baseDir + "/brouter/modes/" + mode_key + "_rawtrack.dat"; - CoordinateReader cor = CoordinateReader.obtainValidReader( baseDir, worker.segmentDir, true ); worker.nogoList = new ArrayList(); - // veto nogos by profiles veto list - for ( OsmNodeNamed nogo : cor.nogopoints ) + + 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 ) { - if ( !smc.nogoVetos.contains( nogo.ilon + "," + nogo.ilat ) ) + CoordinateReader cor = CoordinateReader.obtainValidReader( baseDir, worker.segmentDir, true ); + // veto nogos by profiles veto list + for ( OsmNodeNamed nogo : cor.nogopoints ) { - worker.nogoList.add( nogo ); + if ( !smc.nogoVetos.contains( nogo.ilon + "," + nogo.ilat ) ) + { + worker.nogoList.add( nogo ); + } } } return null; @@ -142,8 +150,19 @@ public class BRouterService extends Service try { // add nogos from waypoint database - CoordinateReader cor = CoordinateReader.obtainValidReader( baseDir, worker.segmentDir, true ); - worker.nogoList = new ArrayList( cor.nogopoints ); + 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( cor.nogopoints ); + } + else + { + worker.nogoList = new ArrayList(); + } if ( !fileEqual( profileBytes, profileFile ) ) { diff --git a/brouter-routing-app/src/main/java/btools/routingapp/BRouterView.java b/brouter-routing-app/src/main/java/btools/routingapp/BRouterView.java index 41796ac..11a712c 100644 --- a/brouter-routing-app/src/main/java/btools/routingapp/BRouterView.java +++ b/brouter-routing-app/src/main/java/btools/routingapp/BRouterView.java @@ -10,6 +10,7 @@ import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -79,6 +80,8 @@ public class BRouterView extends View private int[] imgPixels; private int memoryClass; + + public boolean canAccessSdCard; public void stopRouting() { @@ -191,12 +194,24 @@ public class BRouterView extends View assertDirectoryExists( "modes directory", modesDir, "modes.zip", version ); assertDirectoryExists( "readmes directory", basedir + "/brouter/readmes", "readmes.zip", version ); - cor = CoordinateReader.obtainValidReader( basedir, segmentDir ); + int deviceLevel = android.os.Build.VERSION.SDK_INT; + int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; + canAccessSdCard = deviceLevel < 23 || targetSdkVersion == 10; + if ( canAccessSdCard ) + { + cor = CoordinateReader.obtainValidReader( basedir, segmentDir ); + } + else + { + cor = new CoordinateReaderNone(); + cor.readFromTo(); + } + wpList = cor.waypoints; nogoList = cor.nogopoints; nogoVetoList = new ArrayList(); - sourceHint = "(coordinate-source: " + cor.basedir + cor.rootdir + ")"; + sourceHint = "(dev/trgt=" + deviceLevel + "/" + targetSdkVersion + " coordinate-source: " + cor.basedir + cor.rootdir + ")"; needsViaSelection = wpList.size() > 2; needsNogoSelection = nogoList.size() > 0; @@ -284,7 +299,7 @@ public class BRouterView extends View AppLogger.log( msg ); AppLogger.log( AppLogger.formatThrowable( e ) ); - ( (BRouterActivity) getContext() ).showErrorMessage( msg ); + ( (BRouterActivity) getContext() ).showErrorMessage( msg + "\n" + AppLogger.formatThrowable( e ) ); } waitingForSelection = true; } @@ -1100,62 +1115,23 @@ public class BRouterView extends View } } - private static List getStorageDirectories() + private List getStorageDirectories() { ArrayList res = new ArrayList(); - res.add( Environment.getExternalStorageDirectory().getPath() ); - BufferedReader br = null; + try { - br = new BufferedReader( new FileReader( "/proc/mounts" ) ); - for ( ;; ) + Method method = Context.class.getDeclaredMethod("getExternalFilesDirs", new Class[]{ String.class } ); + File[] paths = (File[])method.invoke( getContext(), new Object[1] ); + for( File path : paths ) { - String line = br.readLine(); - if ( line == null ) - break; - if ( line.indexOf( "vfat" ) < 0 && line.indexOf( "/mnt" ) < 0 ) - continue; - StringTokenizer tokens = new StringTokenizer( line, " " ); - tokens.nextToken(); - String d = tokens.nextToken(); - boolean isExternalDir = false; - if ( line.contains( "/dev/block/vold" ) ) - { - isExternalDir = true; - String[] vetos = new String[] - { "/mnt/secure", "/mnt/asec", "/mnt/obb", "/dev/mapper", "tmpfs", "/mnt/media_rw" }; - for ( String v : vetos ) - { - if ( d.indexOf( v ) >= 0 ) - { - isExternalDir = false; - } - } - } - if ( isExternalDir ) - { - if ( !res.contains( d ) ) - { - res.add( d ); - } - } + res.add( path.getPath() ); } } - catch (Exception e) - { /* ignore */ - } - finally + catch( Exception e ) { - if ( br != null ) - { - try - { - br.close(); - } - catch (Exception e) - { /* ignore */ - } - } + res.add( e.toString() ); + res.add( Environment.getExternalStorageDirectory().getPath() ); } return res; }