listParams = new ArrayList<>();
+ * String file = "xyz.brf";
+ * InputStream fis = new FileInputStream(file); // could be also a stream from DocumentFile
+ * listParams = getParamsFromProfile(fis);
+ * fis.close();
+ *
+ * // call the BRouter param dialog
+ * ComponentName cn = new ComponentName("btools.routingapp", "btools.routingapp.RoutingParameterDialog");
+ * Intent i = new Intent();
+ * i.setComponent(cn);
+ *
+ * // fill some parameter for the dialog
+ * String profile_hash = String.format("X%X", file.hashCode()); // some identify code
+ * i.putExtra("PROFILE_HASH", profile_hash);
+ * i.putExtra("PROFILE", profile_name); // the profile name, only used for display
+ * i.putExtra("PARAMS", listParams); // the settings list
+ * i.putExtra("PARAMS_VALUES", saved_params); // your stored profile parameter or nothing
+ *
+ * startActivityForResult(i, ROUTE_SETTING_REQUEST);
+ *
+ * onActivityResult:
+ * if (requestCode == ROUTE_SETTING_REQUEST) {
+ * String profile = null;
+ * String profile_hash = null;
+ * String sparams = null;
+ * // get back the selected parameter (only PARAMS_VALUES is needed)
+ * if (data != null && data.hasExtra("PARAMS_VALUES")) {
+ * sparams = data.getExtras().getString("PARAMS_VALUES", "");
+ * Log.d(TAG, "result sparams " + sparams);
+ * }
+ * if (data != null && data.hasExtra("PROFILE")) {
+ * profile = data.getExtras().getString("PROFILE", "");
+ * Log.d(TAG, "result profile " + profile);
+ * }
+ * if (data != null && data.hasExtra("PROFILE_HASH")) {
+ * profile_hash = data.getExtras().getString("PROFILE_HASH", "");
+ * Log.d(TAG, "result profile_hash " + profile_hash);
+ * }
+ * }
+ */
+
+public class RoutingParameterDialog extends AppCompatActivity {
+
+ static String TAG = "RoutingParameterDialog";
+
+ static SharedPreferences sharedValues;
+ static ArrayList listParams;
+ static String profile;
+ static String profile_hash;
+
+ /**
+ * collect a list of parameter in a profile
+ *
+ * @param fis - inputstream from profile
+ * @return - list of variable params in this profile
+ * @throws IOException if not readable
+ */
+ static public List getParamsFromProfile(final InputStream fis) throws IOException {
+ List list = null;
+
+ if (fis != null) {
+ list = new ArrayList<>();
+
+ // prepare the file for reading
+ InputStreamReader chapterReader = new InputStreamReader(fis);
+ BufferedReader buffreader = new BufferedReader(chapterReader);
+
+ String line;
+
+ // read every line of the file into the line-variable, on line at the time
+ do {
+ line = buffreader.readLine();
+ // do something with the line
+ if (line != null &&
+ line.contains("#") &&
+ line.contains("%") &&
+ line.lastIndexOf("%") != line.indexOf("%")
+ ) {
+ String s = line.substring(line.indexOf("#") + 1);
+ String v = line.substring(0, line.indexOf("#"));
+ try {
+ String[] sa = s.split("\\|");
+ RoutingParam p = new RoutingParam();
+ p.name = sa[0].trim();
+ p.name = p.name.substring(1, p.name.length() - 1);
+ // turnInstructionMode may transfered from client direct, use only in web client
+ if (p.name.equals("turnInstructionMode")) continue;
+ p.description = sa[1].trim();
+ p.type = sa[2].trim();
+ String[] sav = v.trim().split(" +");
+ if (sav[1].equals(p.name)) {
+ if (sav[0].equals("assign")) {
+ if (sav[2].equals("=")) {
+ p.value = sav[3];
+ } else {
+ p.value = sav[2];
+ }
+ }
+ list.add(p);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ } while (line != null);
+
+ }
+
+ return list;
+ }
+
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getSupportFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
+
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT,
+ new OnBackInvokedCallback() {
+ @Override
+ public void onBackInvoked() {
+ StringBuilder sb = null;
+ if (sharedValues != null) {
+ // fill preference with used params
+ // for direct use in the BRouter interface "extraParams"
+ sb = new StringBuilder();
+ for (Map.Entry entry : sharedValues.getAll().entrySet()) {
+ if (!entry.getKey().equals("params")) {
+ sb.append(sb.length() > 0 ? "&" : "")
+ .append(entry.getKey())
+ .append("=");
+ String s = entry.getValue().toString();
+ if (s.equals("true")) s = "1";
+ else if (s.equals("false")) s = "0";
+ sb.append(s);
+ }
+ }
+ }
+ // and return the array
+ // one should be enough
+ Intent i = new Intent();
+ // i.putExtra("PARAMS", listParams);
+ i.putExtra("PROFILE", profile);
+ i.putExtra("PROFILE_HASH", profile_hash);
+ if (sb != null) i.putExtra("PARAMS_VALUES", sb.toString());
+
+ setResult(Activity.RESULT_OK, i);
+ finish();
+ }
+ }
+ );
+
+
+ }
+ }
+
+
+ public static class MyPreferenceFragment extends PreferenceFragmentCompat {
+
+ private Activity mActivity;
+
+ @Override
+ public void onAttach(@NonNull Context context) {
+ super.onAttach(context);
+ if (context instanceof Activity) {
+ mActivity = (Activity) context;
+ }
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mActivity = null;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mActivity.setTitle("Profile Settings");
+ listParams = new ArrayList<>();
+ String sparams = "";
+ try {
+ Intent i = mActivity.getIntent();
+ if (i == null) {
+ mActivity.finish();
+ return;
+ }
+
+ if (i.hasExtra("PROFILE")) {
+ profile = i.getStringExtra("PROFILE");
+ }
+ if (i.hasExtra("PROFILE_HASH")) {
+ profile_hash = i.getStringExtra("PROFILE_HASH");
+ }
+
+ if (i.hasExtra("PARAMS")) {
+ List> result;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ result = (List>) i.getExtras().getSerializable("PARAMS", ArrayList.class);
+ } else {
+ result = (List>) i.getExtras().getSerializable("PARAMS");
+ }
+ if (result instanceof ArrayList) {
+ for (Object o : result) {
+ if (o instanceof RoutingParam) listParams.add((RoutingParam) o);
+ }
+ }
+ }
+ if (i.hasExtra("PARAMS_VALUES")) {
+ sparams = i.getExtras().getString("PARAMS_VALUES", "");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ getPreferenceManager().setSharedPreferencesName("prefs_profile_" + profile_hash);
+ sharedValues = getPreferenceManager().getSharedPreferences();
+ // clear all
+ // sharedValues.edit().clear().commit();
+
+ setPreferenceScreen(createPreferenceHierarchy(sparams));
+
+ }
+
+ @Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+
+ }
+
+ private PreferenceScreen createPreferenceHierarchy(String sparams) {
+ // Root
+ Activity a = this.getActivity();
+ if (a == null) return null;
+
+ // fill incoming params
+ Map params = new HashMap<>();
+ if (sparams != null && sparams.length() > 0) {
+ String[] sa = sparams.split("&");
+ for (String sar : sa) {
+ String[] sa2 = sar.split("=");
+ if (sa2.length == 2) params.put(sa2[0], sa2[1]);
+
+ }
+ }
+
+ PreferenceScreen root = getPreferenceManager().createPreferenceScreen(a);
+
+ PreferenceCategory gpsPrefCat = new PreferenceCategory(this.getActivity());
+ if (profile.length() > 0) {
+ gpsPrefCat.setTitle(profile);
+ } else {
+ gpsPrefCat.setTitle("Profile Settings");
+ }
+ root.addPreference(gpsPrefCat);
+
+ if (listParams != null) {
+ for (RoutingParam p : listParams) {
+ if (p.type.equals("number")) {
+ EditTextPreference numberTextPref = new EditTextPreference(this.getActivity());
+ numberTextPref.setDialogTitle(p.name);
+ numberTextPref.setKey(p.name);
+ numberTextPref.setSummary(p.description);
+ String s = (params.get(p.name) != null ? params.get(p.name) : p.value);
+ if (p.value.equals(s)) sharedValues.edit().remove(p.name).apply();
+ numberTextPref.setTitle(p.name + ": " + s);
+ numberTextPref.setText(s);
+ //EditText speedEditText = (EditText) speedTextPref.getText();
+ //speedEditText.setKeyListener(DigitsKeyListener.getInstance(false, true));
+ numberTextPref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> {
+ p.value = (String) newValue;
+ numberTextPref.setTitle(p.name + ": " + p.value);
+ return true;
+ });
+
+ gpsPrefCat.addPreference(numberTextPref);
+
+ } else if (p.type.equals("boolean")) {
+ CheckBoxPreference boolPref = new CheckBoxPreference(this.getActivity());
+ boolPref.setKey(p.name);
+ boolPref.setTitle(p.name);
+ boolPref.setSummary(p.description);
+ boolean checked = false;
+ boolean vchecked = p.value != null && (p.value.equals("1") || p.value.equals("true"));
+
+ if (params.get(p.name) != null) {
+ checked = params.get(p.name).equals("1") || params.get(p.name).equals("true");
+ } else {
+ checked = vchecked;
+ }
+ if (vchecked == checked) sharedValues.edit().remove(p.name).apply();
+
+ boolPref.setChecked(checked);
+ //historyPref.setDefaultValue(sharedValues.getBoolean(p.name, p.value != null ? p.value.equals("1") || p.value.equals("true") : false));
+ boolPref.setDefaultValue(p.value != null && (p.value.equals("1") || p.value.equals("true")));
+ boolPref.setOnPreferenceClickListener((Preference preference) -> {
+ p.value = (((CheckBoxPreference) preference).isChecked() ? "1" : "0");
+ return true;
+
+ });
+ gpsPrefCat.addPreference(boolPref);
+
+ } else if (p.type.contains("[") && p.type.contains("]")) {
+ String[] sa = p.type.substring(p.type.indexOf("[") + 1, p.type.indexOf("]")).split(",");
+ String[] entryValues = new String[sa.length];
+ String[] entries = new String[sa.length];
+ int i = 0, ii = 0;
+ String s = (params.get(p.name) != null ? params.get(p.name) : p.value); //sharedValues.getString(p.name, p.value);
+ for (String tmp : sa) {
+ // Add the name and address to the ListPreference enties and entyValues
+ //L.v("AFTrack", "device: "+device.getName() + " -- " + device.getAddress());
+ entryValues[i] = "" + i;
+ entries[i] = tmp.trim();
+ if (entryValues[i].equals(s)) ii = i;
+ i++;
+ }
+ if (p.value.equals(s)) sharedValues.edit().remove(p.name).apply();
+
+ ListPreference listPref = new ListPreference(this.getActivity());
+ listPref.setEntries(entries);
+ listPref.setEntryValues(entryValues);
+ listPref.setDialogTitle(p.name);
+ listPref.setKey(p.name);
+ listPref.setValueIndex(ii);
+ listPref.setTitle(p.name + ": " + entries[ii]);
+ listPref.setSummary(p.description);
+ listPref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> {
+ p.value = (String) newValue;
+ int iii = Integer.decode(p.value);
+ listPref.setTitle(p.name + ": " + entries[iii]);
+
+ return true;
+
+ });
+
+ gpsPrefCat.addPreference(listPref);
+
+ }
+ }
+ }
+ return root;
+ }
+
+ }
+
+}
diff --git a/brouter-routing-app/src/main/java/btools/routingapp/ServerConfig.java b/brouter-routing-app/src/main/java/btools/routingapp/ServerConfig.java
index 658b13e..0d83d49 100644
--- a/brouter-routing-app/src/main/java/btools/routingapp/ServerConfig.java
+++ b/brouter-routing-app/src/main/java/btools/routingapp/ServerConfig.java
@@ -105,7 +105,10 @@ public class ServerConfig {
String name = ze.getName();
if (name.equals(mServerConfigName)) {
File outfile = new File(path, name + ".tmp");
- if (!outfile.exists() && outfile.getParentFile() != null) {
+ String canonicalPath = outfile.getCanonicalPath();
+ if (canonicalPath.startsWith(path.getCanonicalPath()) &&
+ !outfile.exists() &&
+ outfile.getParentFile() != null) {
outfile.getParentFile().mkdirs();
FileOutputStream fos = new FileOutputStream(outfile);
diff --git a/brouter-routing-app/src/main/java/btools/routingapp/ServiceModeConfig.java b/brouter-routing-app/src/main/java/btools/routingapp/ServiceModeConfig.java
index e66cda9..63f30ba 100644
--- a/brouter-routing-app/src/main/java/btools/routingapp/ServiceModeConfig.java
+++ b/brouter-routing-app/src/main/java/btools/routingapp/ServiceModeConfig.java
@@ -10,27 +10,32 @@ import java.util.TreeSet;
public class ServiceModeConfig {
public String mode;
public String profile;
+ public String params;
public TreeSet nogoVetos;
public ServiceModeConfig(String line) {
StringTokenizer tk = new StringTokenizer(line);
mode = tk.nextToken();
profile = tk.nextToken();
+ if (tk.hasMoreTokens()) params = tk.nextToken();
+ else params = "noparams";
nogoVetos = new TreeSet();
while (tk.hasMoreTokens()) {
nogoVetos.add(tk.nextToken());
}
}
- public ServiceModeConfig(String mode, String profile) {
+ public ServiceModeConfig(String mode, String profile, String params) {
this.mode = mode;
this.profile = profile;
+ this.params = params;
nogoVetos = new TreeSet();
}
public String toLine() {
StringBuilder sb = new StringBuilder(100);
sb.append(mode).append(' ').append(profile);
+ sb.append(' ').append(params);
for (String veto : nogoVetos) sb.append(' ').append(veto);
return sb.toString();
}
@@ -38,7 +43,7 @@ public class ServiceModeConfig {
public String toString() {
StringBuilder sb = new StringBuilder(100);
sb.append(mode).append("->").append(profile);
- sb.append(" [" + nogoVetos.size() + "]");
+ sb.append(" [" + nogoVetos.size() + "]" + (params.equals("noparams")?"":" +p"));
return sb.toString();
}
}
diff --git a/brouter-routing-app/src/main/res/layout/dialog_message.xml b/brouter-routing-app/src/main/res/layout/dialog_message.xml
new file mode 100644
index 0000000..ceca354
--- /dev/null
+++ b/brouter-routing-app/src/main/res/layout/dialog_message.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/build.gradle b/build.gradle
index 32b3748..a44f025 100644
--- a/build.gradle
+++ b/build.gradle
@@ -22,7 +22,7 @@ allprojects {
// app: build.gradle (versionCode only)
// OsmTrack (version and versionDate)
// docs revisions.md (version and versionDate)
- project.version "1.7.0"
+ project.version "1.7.1-beta-1"
group 'org.btools'
repositories {