From a80de15415ae57f8e6b9b1e07f855cbd33de23be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Wed, 10 Sep 2025 15:43:19 -0500 Subject: [PATCH 01/60] Increases version number to 71 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 8d4197b1d..3caf91def 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,7 +15,7 @@ android { multiDexEnabled true // Version code should be increased after each release - versionCode 69 + versionCode 71 versionName new Date().format('yyyy.MM.dd') testApplicationId "net.osmtracker.test" From c51ec9fafeb11aed67107e361c2c63f08d752508 Mon Sep 17 00:00:00 2001 From: Andy Porras Date: Wed, 10 Sep 2025 20:58:16 -0600 Subject: [PATCH 02/60] Add community and support section to README --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 335238300..91fc79ce7 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,15 @@ Here is a screenshot of the main screen with its default buttons. You can [custo - Contributions are welcome, please visit our [contributor guide](https://github.com/labexp/osmtracker-android/blob/master/CONTRIBUTING.md) - Translations can be done on [Transifex](https://explore.transifex.com/labexp/osmtracker-android/) +## Community & Support 🌐 + +Join our **Telegram group** to connect with users, developers, translators, and contributors: +👉 [https://t.me/OSMTracker](https://t.me/OSMTracker) + +Use this space for real-time discussions, guidance, and support. +For bug reports or feature requests, continue using the [GitHub Issues](https://github.com/labexp/osmtracker-android/issues) tracker. + + ## Note 📝 OSMTracker for Android™ official source code repository is [https://github.com/labexp/osmtracker-android](https://github.com/labexp/osmtracker-android). From 62aaa769250e63078d6c95ba192faec463ae2b4f Mon Sep 17 00:00:00 2001 From: Andy Porras Date: Wed, 8 Oct 2025 23:39:26 -0600 Subject: [PATCH 03/60] Clear the text fields in the track details editor The previous design used hints to label the name, description, and tags fields. These hints disappeared when the fields were filled in automatically, causing confusion for the user about the purpose of each field. This change introduces permanent text labels (TextView) above each input field. This ensures that the function of each field is always visible, significantly improving the usability of the screen. Fixes #609 --- .../main/res/layout/trackdetail_fields.xml | 51 +++++++++++++++---- app/src/main/res/values/strings.xml | 1 + 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/app/src/main/res/layout/trackdetail_fields.xml b/app/src/main/res/layout/trackdetail_fields.xml index 5272ede4f..c42734a2c 100644 --- a/app/src/main/res/layout/trackdetail_fields.xml +++ b/app/src/main/res/layout/trackdetail_fields.xml @@ -1,38 +1,67 @@ - + + + + + + + + android:layout_marginTop="8dp" + android:minHeight="48dp" /> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 01977f784..4b12833ab 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -68,6 +68,7 @@ (Not uploaded yet) Display Name + Name and title Description Tags (comma separated) You must enter a description From 204d9f5c6d7065501a4ddcb22ed7c01c735df1cb Mon Sep 17 00:00:00 2001 From: Dylan Date: Tue, 4 Nov 2025 11:06:06 -0600 Subject: [PATCH 04/60] DOCS: Improve the contributing.md file --- CONTRIBUTING.md | 137 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 123 insertions(+), 14 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 56151946f..0fb386315 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,30 +1,139 @@ -# Contributing -Everyone can contribute to the development of the app, and that's great!. Since we'll be using [gitflow](https://datasift.github.io/gitflow/IntroducingGitFlow.html), it's recommended to have feature branches that will eventually be merged back to the `develop` via pull requests, and later `develop` will be merged back to master when we're ready for a new release. - -## How to run the app -For running this project locally follow this steps: - - Clone the repository using git: - - `$ git clone https://github.com/labexp/osmtracker-android/` - - Install AndroidStudio - - [Here](https://developer.android.com/studio/install) is the official guide on how to install it on different operating systems - - Now open the IDE and click `open an existing Android Studio project`, then look for the folder where you cloned the repository - - Once it opens your project folder, click the top green hammer icon or press `Ctrl + F9` to make sure the project builds successfully - -## How to run the tests +# 🤝 Contributing to OSMTracker + +Thank you for your interest in contributing! 🎉 +Whether you're fixing a bug, adding a new feature, or improving documentation — all contributions are welcome. + +--- +## 📚 Table of Contents +1. 🔰 Before You Start +2. 🛠️ How to Run the App (Setup Guide) +3. 🧪 Running Tests +4. 🌍 Translations +5. 🧑‍💻 Git Workflow (GitFlow) +6. 👶 New Contributor Quick Guide (For Beginners) +7. 📜 Code Style & Commit Guidelines +8. 🚀 How to Submit a Pull Request +9. 💬 Community & Support + +--- + +## 🔰 1. Before You Start +- Make sure you have **Git** and **Android Studio** installed. +- Familiarity with **GitFlow** is recommended (see below). +- If you're new to open/free source, check out our **beginner section** ↓ + +--- + +## 🛠️ 2. How to Run the App Locally + +```bash +# Clone the repository +git clone https://github.com/labexp/osmtracker-android/ +cd osmtracker-android +``` + +1. Install Android Studio. - [Here](https://developer.android.com/studio/install) is the official guide on how to install it on different operating systems +2. Open the IDE and click `open an existing Android Studio project`, then look for the folder where you cloned the repository +3. Build the project (`Ctrl + F9` or the 🛠️ hammer button) + + + +## 🧪 3. Running Tests + This repository has an automated way to run the tests on branches but if you already have the project installed on you computer then you can also run them from a terminal. It's recommended to run the tests locally before making a new pull request to make sure the changes doesn't break any previous functionality. You can run the tests locally as follows: - Make sure you are at the *root directory of the project* - `$ cd YOUR_PATH/osmtracker-android` + +### 📱 Instrumentation Tests (Require Emulator or Device) - For running **instrumentation** tests it's needed to previously start up an emulator (or real device), you can do it from Android Studio but also without it using the command line. For that, you need to move to the Android SDK installation directory and look for a folder called `emulator` once there, start any already created emulator by typing: - `$ ./emulator -avd NAME` to start the emulator called *NAME* (run `$ ./emulator -list-avds` for a valid list of AVD names) - When it's up, go back to the root project folder and run the instrumentation tests with - `$ ./gradlew connectedAndroidTest` +### ✅ Unit Tests - For running the **unit tests** no emulator or device is needed, just run - `$ ./gradlew test` - Now just wait for gradle to run the tests for you, it'll show the results of which tests passed or failed when it's finished -## Translations + +## 🌍 4. Translations OSMTracker is translated using Transifex (see the [wiki](https://github.com/labexp/osmtracker-android/wiki/Translating)). Once translations are complete, they will be updated via automated Transifex PR. + + +## 🧑‍💻 5. Git Workflow (GitFlow) + +We use **GitFlow** branching model: + +| Branch | Purpose | +|--------|----------| +| `master` | Stable production releases | +| `develop` | Main development branch | +| `feature/*` | New features | +| `hotfix/*` | Quick fixes for production | + +- If you want more information, take a look [here](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) +--- + +## 👶 6. New Contributor Quick Guide (Beginner-Friendly) + +> ✨ If this is your first open-source contribution, start here! + +1. ⭐ **Fork the repository** + + After forking, make sure your fork includes **all the required branches** (especially `develop`, not only `master`). + + You can verify this by checking the branches tab in your fork on GitHub. + +2. 📥 **Clone your fork** + ```bash + git clone https://github.com/YOUR_USERNAME/osmtracker-android.git + ``` +3. 🔄 (Optional) Add upstream to stay updated + ```bash + git remote add upstream https://github.com/labexp/osmtracker-android.git + ``` +4. 🌱 Create a branch + ```bash + git checkout develop + git checkout -b feature/your-feature-name + ``` +5. ✍️ Make changes + commit (atomic commits) +6. 🚀 Push your branch +7. 📝 Open a Pull Request (PR) + +--- + +## 📜 7. Commit Message Convention +Use **clear and descriptive** commit messages. + +✅ Good: +``` +feat: add option to export GPX file +fix: resolve crash when no GPS signal +docs: update contributing guide +``` +❌ Bad: +``` +update stuff +fix bug +``` + +--- +## 🚀 8. How to Submit a Pull Request +1. Push your changes +2. Go to GitHub → Open PR +3. Fill the PR template fully +4. Wait for review ✅ + +⚠️ PRs without a complete template may be rejected. + +--- + +## 💬 9. Community & Support +- Have questions? Open a **Discussion** or an **Issue** +- (Optional): Join the contributors chat/[Telegram](https://t.me/OSMTracker). + +Let's build something awesome together! 🚀 \ No newline at end of file From c5e2960f7a120953f9485885bc41089c8b28fb20 Mon Sep 17 00:00:00 2001 From: Dylan Date: Wed, 12 Nov 2025 20:11:04 -0600 Subject: [PATCH 05/60] Docs: Update PR Template structure --- .github/PULL_REQUEST_TEMPLATE.md | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1d5c65751..accc4f88e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,28 +1,40 @@ [comment]: # (Thank you for your contribution! Please fill out the following details to help us review your pull request.) +# 📝 Pull Request Title -### Description +## 🛠️ Issue +- Closes #add-your-issue-ID + +[comment]: # (Link to the ISSUES related, if applicable) +[comment]: # (* Related to: ISSUE #number) +## 🛠️ Related issues (if applicable) +- ISSUES #add-ISSUE + + + +## 📖 Description [comment]: # (Provide a clear explanation of the changes in this PR) -[comment]: # (Include information about what problem it solves, how it is implemented, and if it affects UI/API) -### Related issues -[comment]: # (Link to the original bug report or related work in list format, if applicable) -[comment]: # (* Closes: #number) -[comment]: # (* Related to: #number) +## 🖼️ Screenshots (if applicable) +- Include any relevant screenshots or examples of the changes made. This helps reviewers visualize the updates -## -### Pull Request Checklist +## ✅ Pull Request Checklist [comment]: # (Please confirm the following before submitting your PR) [comment]: # (To check a task please put a "x" inside the `[]`) [comment]: # ([ ] : not done) [comment]: # ([x] : done) [comment]: # (Make sure how your PR looks clicking the "Preview" tab at the top of this editor) -- [ ] The PR is proposed to the proper branch. +- [ ] The PR is proposed to the DEVELOP branch. - [ ] The changes have been tested on the target Android API and minimum Android API. - [ ] Automated tests have been added (if applicable). - [ ] The feature is well documented. -- [ ] There is a reference to the original bug report and related work. +- [ ] There is a reference to the original ISSUE and related work. + + +## 📝 Additional Notes +- Any additional context, questions, or considerations for the reviewers. +- Take a look at our [Contributing Guide](https://github.com/labexp/osmtracker-android/blob/develop/CONTRIBUTING.md) before submitting your PR. From 707a601ead03ee5d68301ca97e2fbfc0edddeffc Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Sun, 19 Oct 2025 19:53:14 +0000 Subject: [PATCH 06/60] Translate strings.xml in nl 100% translated source file: 'strings.xml' on 'nl'. --- app/src/main/res/values-nl/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 3c786b6e6..f5fae0005 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -65,6 +65,7 @@ Selecteer het in de lijst om door te gaan. (Nog niet geüpload) Weergeven Naam + Naam en titel Beschrijving Tags (kommagescheiden) Een beschrijving is vereist From 3072c488bca0da0085da3e814094c71dfd3bbd1b Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Fri, 31 Oct 2025 18:26:51 +0000 Subject: [PATCH 07/60] Translate strings.xml in zh_TW 100% translated source file: 'strings.xml' on 'zh_TW'. --- app/src/main/res/values-zh-rTW/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 08732e854..36f6f1c17 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -64,6 +64,7 @@ (尚未上傳) 顯示 名稱 + 名稱與標題 描述 標籤 (以半形逗號分隔) 您必須填寫描述欄 From 772150c142f11db622306ad1aad6c074c943509a Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Fri, 7 Nov 2025 10:09:36 +0000 Subject: [PATCH 08/60] Translate strings.xml in sv 86% of minimum 80% translated source file: 'strings.xml' on 'sv'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format --- app/src/main/res/values-sv/strings.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index ea385a114..421662dfc 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -40,6 +40,7 @@ Exportera Dela Ladda upp till OpenStreetMap + Ladda upp till GitHub Visa spår på skärm Visa detaljer Spår #{0} @@ -63,6 +64,7 @@ (inte uppladdad än) Visa Namn + Namn och titel Beskrivning Etiketter (kommaseparerade) Du måste ange en beskrivning @@ -118,6 +120,7 @@ Kontrollera att minneskortet är korrekt isatt och fungerar. Röstinspelningen misslyckades Ett fel inträffade när layoutfilen lästes in. Återställ orginalfilen. + Fel vid skapande av PR Tillstånd krävs För att exportera GPX-spåret behöver vi skriva till enhetens filsystem. @@ -196,6 +199,22 @@ Github Repository giltigt Github Repository felaktigt + skapad framgångsrikt + Fel vid skapande + Databasfel + sparade framgångsrikt + Sparfel + Status på pull request + Fel med repository-information + Laddade upp framgångsrikt + Fel vid uppladdning + Fel vid läsnng av GPX-fil + GPX-fil hittades inte + Laddar upp fil + Privat: + Skapar repository + Du måste ange ett repository-namn + Du måste ange ett värde på detta fällt From 8845028c928925613fd78ea811c986ed3e3d74f3 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Sat, 8 Nov 2025 18:13:08 +0000 Subject: [PATCH 09/60] Translate strings.xml in sv 100% translated source file: 'strings.xml' on 'sv'. --- app/src/main/res/values-sv/strings.xml | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 421662dfc..e918f8f1f 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -120,6 +120,7 @@ Kontrollera att minneskortet är korrekt isatt och fungerar. Röstinspelningen misslyckades Ett fel inträffade när layoutfilen lästes in. Återställ orginalfilen. + Token måste vara 40 tecken lång Fel vid skapande av PR Tillstånd krävs @@ -211,14 +212,42 @@ Fel vid läsnng av GPX-fil GPX-fil hittades inte Laddar upp fil + Valt objekt: Privat: Skapar repository Du måste ange ett repository-namn Du måste ange ett värde på detta fällt + Hämtar arkiv... + Fel vid hämtning av arkiv + Lyckades hämta arkiven + Konfigurera + GitHub-token: + Hämta token + Så här får du en GitHub-token: + 1. Klicka på knappen för att öppna GitHub-webbplatsen och skapa en token. Logga in med ditt GitHub-konto om det behövs. + 2. Välj \"Tokens (Klassisk)\" och klicka på knappen \"Generera ny token\". + 3. Ge din token ett beskrivande namn. + 4. Välj ett utgångsdatum. Vi rekommenderar \"Inget utgångsdatum\" för att undvika att upprepa detta steg. + 5. Välj det omfång eller de behörigheter du vill bevilja för denna token (OSMTracker behöver bara repo-behörigheten). + 6. Klicka på knappen \"Generera token\". + 7. Kopiera den genererade token och klistra in den i fältet \"GitHub token\". + ⚠️ Du kan spara tomt för att radera dina inloggningsuppgifter. + Förbindelse medlande + Skapa\ngren + Öppna dra-förfrågan + Välj ett arkiv + Skapa arkiv + Förbinda + Konfigurera + Ursprungligt användarnamn för arkivet + Ursprungligt arkivnamn + Skapa + Titel för dra-förfrågan + Beskrivning av dra-förfrågan Introduktion till OSMTracker for Android™ @@ -229,4 +258,5 @@ Lycka till med spårningen 🗺😎 OSMTracker för Android kommer att använda din GPS-position för att spela in spårpunkter och vägpunkter, även när appen körs i bakgrunden. \nDina data används inte för annonsering. + Ingen app hittades för att öppna den här filen. From 585a493315e77e8e378d7b9e8774c75e2bf48cee Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:42:58 -0600 Subject: [PATCH 10/60] =?UTF-8?q?[Transifex]=20Updates=20for=20project=20O?= =?UTF-8?q?SMTracker=20for=20Android=E2=84=A2=20and=20language=20sr=20(#62?= =?UTF-8?q?7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Translate accessibility.xml in sr 100% translated source file: 'accessibility.xml' on 'sr'. * Translate strings-preferences.xml in sr 95% of minimum 80% translated source file: 'strings-preferences.xml' on 'sr'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * Translate accessibility.xml in sr 100% translated source file: 'accessibility.xml' on 'sr'. --------- Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> --- app/src/main/res/values-sr/accessibility.xml | 5 +++-- app/src/main/res/values-sr/strings-preferences.xml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-sr/accessibility.xml b/app/src/main/res/values-sr/accessibility.xml index 86b5cd100..381dcdb14 100644 --- a/app/src/main/res/values-sr/accessibility.xml +++ b/app/src/main/res/values-sr/accessibility.xml @@ -5,10 +5,11 @@ Увеличај Умањи + Центрирај - Показатељ јачине сигнала сателита + Показатељ сигнала сателита Показатељ напретка снимања Показатељ стања путање - Показатељ стања слања Отворене мапе + Показатељ слања на Отворене мапе diff --git a/app/src/main/res/values-sr/strings-preferences.xml b/app/src/main/res/values-sr/strings-preferences.xml index fa9a78027..7bce13928 100644 --- a/app/src/main/res/values-sr/strings-preferences.xml +++ b/app/src/main/res/values-sr/strings-preferences.xml @@ -64,7 +64,7 @@ Назив праћења Назив, почетни датум и време - Почетни датум и време, Назив + Почетни датум и време, назив Почетни датум и време Тачност у GPX фајлу From f556eb1774ff5360aa6168dc599b4339b9e9c956 Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 11:43:49 -0600 Subject: [PATCH 11/60] =?UTF-8?q?[Transifex]=20Updates=20for=20project=20O?= =?UTF-8?q?SMTracker=20for=20Android=E2=84=A2=20and=20language=20sk=20(#62?= =?UTF-8?q?6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Translate accessibility.xml in sk 100% translated source file: 'accessibility.xml' on 'sk'. * Translate strings-preferences.xml in sk 100% translated source file: 'strings-preferences.xml' on 'sk'. * Translate strings.xml in sk 87% of minimum 80% translated source file: 'strings.xml' on 'sk'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format --------- Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> --- app/src/main/res/values-sk/accessibility.xml | 1 + .../res/values-sk/strings-preferences.xml | 11 ++++ app/src/main/res/values-sk/strings.xml | 57 +++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/app/src/main/res/values-sk/accessibility.xml b/app/src/main/res/values-sk/accessibility.xml index 8a4a431e1..0c00b5737 100644 --- a/app/src/main/res/values-sk/accessibility.xml +++ b/app/src/main/res/values-sk/accessibility.xml @@ -5,6 +5,7 @@ Priblížiť Oddialiť + Priblížiť na stred Indikátor sily signálu satelitov Indikátor prebiehajúceho záznamu diff --git a/app/src/main/res/values-sk/strings-preferences.xml b/app/src/main/res/values-sk/strings-preferences.xml index 69fc993d9..319bb97f0 100644 --- a/app/src/main/res/values-sk/strings-preferences.xml +++ b/app/src/main/res/values-sk/strings-preferences.xml @@ -9,9 +9,14 @@ Skontrolovať, či je GPS vypnuté po spustení a navrhnúť jeho zapnutie Ignorovať čas GPS Ignorovať čas GPS a použiť čas Androidu pre časové značky + Zaznamenávať barometrický tlak [hPa] + Prepínač vyžaduje reštart stopy Interval logovania GPS Použite 0 pre najkratší možný (Ovplyvní výdrž batérie) sekundy + Vzdialenosť medzi záznamami GPS + Najmenšia vzdialenosť medzi bodmi stopy v metroch. Pre najhustejší záznam použite 0 + metrov Užívateľské rozhranie Predvolený zdroj fotografií Zachytiť fotografie fotoaparátom alebo vybrať z galérie? @@ -49,7 +54,9 @@ Obrazovka zostane zapnutá počas stopovania. Vypnite pre úsporu batérie OSM pozadie Zobraziť OpenStreetMap pod stopou. Potrebuje dátové pripojenie + Vždy zobrazovať na pozadí OpenStreetMap. Vyžaduje dátové pripojenie Výstup GPX súboru + Ukladať do priečinka pre dokumenty Použité až v ďalšej stope (nie v aktuálnej) Jeden adresár na stopu Uloží každú stopu a priradené súbory do jej vlastného adresára @@ -61,6 +68,8 @@ Dátum a čas spustenia, názov Dátum a čas spustenia + Štítok názvu súboru + Tento štítok bude pripojený na koniec názvu súboru Presnosť v GPX súbore Povoliť informácie o presnosti v GPX súbore, s názvom cestovného bodu alebo v oddelenom poli @@ -75,6 +84,7 @@ Vymazať autentifikáciu OSM Vymaže prihlasovacie údaje a oprávnenia OSM uložené v telefóne a prinúti OSMTracker, aby si ich opätovne vyžiadal Znova sa pokúšate autorizovať OSMTracker, aby mohol nahrávať záznamy stôp. Ste si istý? + Poskytovateľ mapových dlaždíc Mapnik @@ -86,5 +96,6 @@ V komentári V rozšírení + Exportovať aj smer kompasu Určiť, či a ako sa majú exportovať údaje kompasu do súboru GPX diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index c37a8fec4..c0f3f8ec5 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -31,13 +31,16 @@ Body trasy: Trasové body: Nemáte zaznamenané žiadne prejdené trasy. + Zapnúť záznam novej stopy. Nedá sa vytvoriť nový záznam trasy: {0} Práve zaznamenávate stopu #{0}\nPre pokračovanie ju zvoľte v zozname Zastaviť záznam Pokračovať v zázname Odstrániť Exportovať + Zdieľať Odoslať na OpenStreetMap + Nahrať na GitHub Zobraziť Podrobnosti Záznam #{0} @@ -47,6 +50,7 @@ Pripravuje sa export... Nedá sa exportovať stopa: {0} Všetky stop budú exportované, čo môže chvíľu trvať. Pokračovať? + Nepodarilo sa spracovať stopu: {0} Podrobnosti o stope Čas začatia: @@ -59,6 +63,8 @@ (Zatiaľ neexportovaná) (Zatiaľ neodovzdané) Zobraziť + Názov + Názov a hlavička Popis Tagy (oddelené čiarkou) Musíte zadať popis @@ -82,6 +88,16 @@ Zachytiť fotografiu Písomná poznámka + Názov prechodného bodu/text + Zadať názov prechodného bodu + Otvoriť súbor + Uložiť + Odstrániť + Zrušiť + Odstrániť prechodný bod + Vymazať tento prechodný bod? + Odstrániť + Zrušiť Nastavenia Cestovné body @@ -104,7 +120,15 @@ Prosím, skontrolujte, či je ext. úložisko správne vložené a pripojené. Hlasový záznam zlyhal Chyba počas analýzi XML súboru rozloženia. Prosím, vráťte sa k štandardnému rozloženiu. + Token musí mať 40 znakov + Vyžaduje sa oprávnenie + Pre export GPX stopy sa vyžaduje zápis na úložisko. + Na správne zobrazenie stopy sa vyžaduje prístup k úložisku. + Na správne zdieľanie stopy sa vyžaduje prístup k úložisku. + Na nahratie stopy do OSM sa vyžaduje prístup k úložisku. + Prijať + Bez povelenia GPS nemožno pokračovať Stopované s OSMTracker-om pre Android™ Varovanie: Hodnoty HDOP nie sú vrátené HDOP z GPS zariadenia. Sú odhadnuté pre presnosť umiestnenia v metroch, a nemali by byť vložené do účtu. @@ -137,6 +161,8 @@ Čaká sa na smerovanie... Nedá sa zistiť smerovanie + Proces exportovania prebehol úspešne + Poloha nie je dostupná {0} {1} / {2} {3} Zobrazenie OpenStreetMap stopy @@ -148,8 +174,10 @@ Rozloženie nebolo aktualizované, skúste inokedy Naozaj chcete vymazať rozloženie {0} ? Áno + Rozloženie bolo úspešne odstránené Priečinok piktogramov bol úspešne vymazaný Tento súbor nemal priradený žiadny priečinok pre priktogramy + Rozloženie sa nepodarilo odstrániť Chyba: nepodarilo sa pripojiť na Internet Chyba: nepodarilo sa pripojiť na predvolený repozitár s prisposobenými rozloženiami tlačidiel @@ -170,6 +198,35 @@ Názov vetvy: Platný názov Github repozitára Neplatný názov Github repozitára + + úspešne vytvorené + Chyba pri vytváraní + Chyba databázy + úspešne uložené + Chyba pri ukladaní + Chyba s infomáciami o repozitári + Úspešne nahraté + Chyba pri nahrávaní + Chyba pri načítaní GPX súboru + Nenašiel sa GPX súbor + Nahrávanie súboru: + Vybratá položka: + Súkromné: + Vytváranie repozitára + Musíte zadať názov repozitára + Musíte zadať hodnotu do tohto poľa + Získavam repozitáre... + Chyba pri získavaní repozitárov + Získavanie repozitárov prebehlo úspešne + + Nastaviť + Token GitHubu: + Získať token: + + Nastaviť + + + From 16412e1d5687cec39a2daf6c65a33fce58aead50 Mon Sep 17 00:00:00 2001 From: Alain Knaff Date: Wed, 27 Aug 2025 07:14:09 +0200 Subject: [PATCH 12/60] Allow again to chose map tile provider. CyclOSM and OpenTopo are now available in addition to the standard Mapnik map. --- .../osmtracker/activity/DisplayTrackMap.java | 35 ++++++++++++------- .../res/values-ar/strings-preferences.xml | 2 +- .../values-b+sr+Latn/strings-preferences.xml | 2 +- .../res/values-ca/strings-preferences.xml | 2 +- .../res/values-cs-rCZ/strings-preferences.xml | 2 +- .../res/values-da/strings-preferences.xml | 2 +- .../res/values-de/strings-preferences.xml | 2 +- .../res/values-el/strings-preferences.xml | 2 +- .../res/values-es/strings-preferences.xml | 2 +- .../res/values-fa-rIR/strings-preferences.xml | 2 +- .../res/values-fi/strings-preferences.xml | 2 +- .../res/values-fr/strings-preferences.xml | 2 +- .../res/values-gl/strings-preferences.xml | 2 +- .../res/values-he/strings-preferences.xml | 2 +- .../res/values-hr/strings-preferences.xml | 2 +- .../res/values-hu/strings-preferences.xml | 2 +- .../res/values-id/strings-preferences.xml | 2 +- .../res/values-it/strings-preferences.xml | 2 +- .../res/values-ja/strings-preferences.xml | 2 +- .../res/values-ko/strings-preferences.xml | 2 +- .../res/values-lt/strings-preferences.xml | 2 +- .../res/values-lv/strings-preferences.xml | 2 +- .../res/values-nb/strings-preferences.xml | 2 +- .../res/values-nl/strings-preferences.xml | 2 +- .../res/values-pl/strings-preferences.xml | 2 +- .../res/values-pt-rBR/strings-preferences.xml | 2 +- .../res/values-pt-rPT/strings-preferences.xml | 2 +- .../res/values-ru/strings-preferences.xml | 2 +- .../res/values-sk/strings-preferences.xml | 2 +- .../res/values-sl/strings-preferences.xml | 2 +- .../res/values-sr/strings-preferences.xml | 2 +- .../res/values-sv/strings-preferences.xml | 2 +- .../res/values-tr/strings-preferences.xml | 2 +- .../res/values-uk/strings-preferences.xml | 2 +- .../res/values-vi/strings-preferences.xml | 2 +- .../res/values-zh-rCN/strings-preferences.xml | 2 +- .../res/values-zh-rTW/strings-preferences.xml | 2 +- .../main/res/values/strings-preferences.xml | 2 +- .../main/res/values/values-preferences.xml | 6 ++-- app/src/main/res/xml/preferences.xml | 7 ++++ 40 files changed, 70 insertions(+), 52 deletions(-) diff --git a/app/src/main/java/net/osmtracker/activity/DisplayTrackMap.java b/app/src/main/java/net/osmtracker/activity/DisplayTrackMap.java index 707fefbc2..5475c20e5 100644 --- a/app/src/main/java/net/osmtracker/activity/DisplayTrackMap.java +++ b/app/src/main/java/net/osmtracker/activity/DisplayTrackMap.java @@ -26,6 +26,9 @@ import org.osmdroid.api.IMapController; import org.osmdroid.config.Configuration; import org.osmdroid.tileprovider.tilesource.TileSourceFactory; +import org.osmdroid.tileprovider.tilesource.ITileSource; +import org.osmdroid.tileprovider.tilesource.XYTileSource; + import org.osmdroid.util.GeoPoint; import org.osmdroid.views.CustomZoomButtonsController; import org.osmdroid.views.MapView; @@ -231,8 +234,7 @@ public void onChange(boolean selfChange) { public void selectTileSource() { String mapTile = prefs.getString(OSMTracker.Preferences.KEY_UI_MAP_TILE, OSMTracker.Preferences.VAL_UI_MAP_TILE_MAPNIK); Log.e("TileMapName active", mapTile); - //osmView.setTileSource(selectMapTile(mapTile)); - osmView.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE); + osmView.setTileSource(selectMapTile(mapTile)); } /** @@ -243,6 +245,16 @@ public void setTileDpiScaling() { } + static { + TileSourceFactory.addTileSource(new XYTileSource("CyclOSM", + 0, 18, 256, ".png", + new String[] { + "https://a.tile-cyclosm.openstreetmap.fr/cyclosm/", + "https://b.tile-cyclosm.openstreetmap.fr/cyclosm/", + "https://c.tile-cyclosm.openstreetmap.fr/cyclosm/"}, + "© OpenStreetMap contributors")); + } + // /** // * Returns a ITileSource for the map according to the selected mapTile // * String. The default is mapnik. @@ -250,16 +262,15 @@ public void setTileDpiScaling() { // * @param mapTile String that is the name of the tile provider // * @return ITileSource with the selected Tile-Source // */ -// private ITileSource selectMapTile(String mapTile) { -// try { -// Field f = TileSourceFactory.class.getField(mapTile); -// return (ITileSource) f.get(null); -// } catch (Exception e) { -// Log.e(TAG, "Invalid tile source '"+mapTile+"'", e); -// Log.e(TAG, "Default tile source selected: '" + TileSourceFactory.DEFAULT_TILE_SOURCE.name() +"'"); -// return TileSourceFactory.DEFAULT_TILE_SOURCE; -// } -// } + private ITileSource selectMapTile(String mapTile) { + try { + return TileSourceFactory.getTileSource(mapTile); + } catch (Exception e) { + Log.e(TAG, "Invalid tile source '"+mapTile+"'", e); + Log.e(TAG, "Default tile source selected: '" + TileSourceFactory.DEFAULT_TILE_SOURCE.name() +"'"); + return TileSourceFactory.DEFAULT_TILE_SOURCE; + } + } @Override diff --git a/app/src/main/res/values-ar/strings-preferences.xml b/app/src/main/res/values-ar/strings-preferences.xml index 3815e2e3e..74d6901d4 100644 --- a/app/src/main/res/values-ar/strings-preferences.xml +++ b/app/src/main/res/values-ar/strings-preferences.xml @@ -80,7 +80,7 @@ Mapnik خريطة الدراجات - MapQuest Open + OpenTopo لا شيء diff --git a/app/src/main/res/values-b+sr+Latn/strings-preferences.xml b/app/src/main/res/values-b+sr+Latn/strings-preferences.xml index 7c46fa0bd..04b4b66ab 100644 --- a/app/src/main/res/values-b+sr+Latn/strings-preferences.xml +++ b/app/src/main/res/values-b+sr+Latn/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Bez usmerenja diff --git a/app/src/main/res/values-ca/strings-preferences.xml b/app/src/main/res/values-ca/strings-preferences.xml index 405bdaa8e..bef7e0616 100644 --- a/app/src/main/res/values-ca/strings-preferences.xml +++ b/app/src/main/res/values-ca/strings-preferences.xml @@ -76,7 +76,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Cap diff --git a/app/src/main/res/values-cs-rCZ/strings-preferences.xml b/app/src/main/res/values-cs-rCZ/strings-preferences.xml index 60f507564..eda58cac3 100644 --- a/app/src/main/res/values-cs-rCZ/strings-preferences.xml +++ b/app/src/main/res/values-cs-rCZ/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Nikde diff --git a/app/src/main/res/values-da/strings-preferences.xml b/app/src/main/res/values-da/strings-preferences.xml index 65c88cbe9..aa8633314 100644 --- a/app/src/main/res/values-da/strings-preferences.xml +++ b/app/src/main/res/values-da/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Deaktiveret diff --git a/app/src/main/res/values-de/strings-preferences.xml b/app/src/main/res/values-de/strings-preferences.xml index 9a65f62c3..365cf5a08 100644 --- a/app/src/main/res/values-de/strings-preferences.xml +++ b/app/src/main/res/values-de/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo kein Export diff --git a/app/src/main/res/values-el/strings-preferences.xml b/app/src/main/res/values-el/strings-preferences.xml index 0ffcd40ca..548bd3d44 100644 --- a/app/src/main/res/values-el/strings-preferences.xml +++ b/app/src/main/res/values-el/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Κανένα diff --git a/app/src/main/res/values-es/strings-preferences.xml b/app/src/main/res/values-es/strings-preferences.xml index f973b7c0d..6108720f5 100644 --- a/app/src/main/res/values-es/strings-preferences.xml +++ b/app/src/main/res/values-es/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Ninguno diff --git a/app/src/main/res/values-fa-rIR/strings-preferences.xml b/app/src/main/res/values-fa-rIR/strings-preferences.xml index 7569146d4..3f1e66510 100644 --- a/app/src/main/res/values-fa-rIR/strings-preferences.xml +++ b/app/src/main/res/values-fa-rIR/strings-preferences.xml @@ -73,7 +73,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo خالی diff --git a/app/src/main/res/values-fi/strings-preferences.xml b/app/src/main/res/values-fi/strings-preferences.xml index 0f06e139b..c73d19f4f 100644 --- a/app/src/main/res/values-fi/strings-preferences.xml +++ b/app/src/main/res/values-fi/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Pyöräilykartta - MapQuest Open + OpenTopo Ei lainkaan diff --git a/app/src/main/res/values-fr/strings-preferences.xml b/app/src/main/res/values-fr/strings-preferences.xml index 126e9468a..d35520931 100644 --- a/app/src/main/res/values-fr/strings-preferences.xml +++ b/app/src/main/res/values-fr/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Aucun diff --git a/app/src/main/res/values-gl/strings-preferences.xml b/app/src/main/res/values-gl/strings-preferences.xml index fc949848c..2aab7430a 100644 --- a/app/src/main/res/values-gl/strings-preferences.xml +++ b/app/src/main/res/values-gl/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Cycle Map - Abrir MapQuest + Abrir yMapQuest Non diff --git a/app/src/main/res/values-he/strings-preferences.xml b/app/src/main/res/values-he/strings-preferences.xml index c5ea1e5e4..fa73df383 100644 --- a/app/src/main/res/values-he/strings-preferences.xml +++ b/app/src/main/res/values-he/strings-preferences.xml @@ -73,7 +73,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo ללא שמירה diff --git a/app/src/main/res/values-hr/strings-preferences.xml b/app/src/main/res/values-hr/strings-preferences.xml index b64dca958..f2c68d753 100644 --- a/app/src/main/res/values-hr/strings-preferences.xml +++ b/app/src/main/res/values-hr/strings-preferences.xml @@ -67,7 +67,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Ništa diff --git a/app/src/main/res/values-hu/strings-preferences.xml b/app/src/main/res/values-hu/strings-preferences.xml index 8558546c0..078864d40 100644 --- a/app/src/main/res/values-hu/strings-preferences.xml +++ b/app/src/main/res/values-hu/strings-preferences.xml @@ -88,7 +88,7 @@ Mapnik Biciklis térkép - MapQuest Open + OpenTopo Semmi diff --git a/app/src/main/res/values-id/strings-preferences.xml b/app/src/main/res/values-id/strings-preferences.xml index 6166faed5..aaf2fbf50 100644 --- a/app/src/main/res/values-id/strings-preferences.xml +++ b/app/src/main/res/values-id/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Nihil diff --git a/app/src/main/res/values-it/strings-preferences.xml b/app/src/main/res/values-it/strings-preferences.xml index ec55c4994..85ecd37aa 100644 --- a/app/src/main/res/values-it/strings-preferences.xml +++ b/app/src/main/res/values-it/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Nessuno diff --git a/app/src/main/res/values-ja/strings-preferences.xml b/app/src/main/res/values-ja/strings-preferences.xml index c4a2222fe..2896e29bf 100644 --- a/app/src/main/res/values-ja/strings-preferences.xml +++ b/app/src/main/res/values-ja/strings-preferences.xml @@ -86,7 +86,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo なし diff --git a/app/src/main/res/values-ko/strings-preferences.xml b/app/src/main/res/values-ko/strings-preferences.xml index 9acc551ae..6f0e22673 100644 --- a/app/src/main/res/values-ko/strings-preferences.xml +++ b/app/src/main/res/values-ko/strings-preferences.xml @@ -80,7 +80,7 @@ Mapnik 사이클 지도 - MapQuest Open + OpenTopo 없음 diff --git a/app/src/main/res/values-lt/strings-preferences.xml b/app/src/main/res/values-lt/strings-preferences.xml index 4cc8b5fec..ddd803428 100644 --- a/app/src/main/res/values-lt/strings-preferences.xml +++ b/app/src/main/res/values-lt/strings-preferences.xml @@ -18,6 +18,6 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo diff --git a/app/src/main/res/values-lv/strings-preferences.xml b/app/src/main/res/values-lv/strings-preferences.xml index ffbc89425..c0d7f9e7a 100644 --- a/app/src/main/res/values-lv/strings-preferences.xml +++ b/app/src/main/res/values-lv/strings-preferences.xml @@ -79,7 +79,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Nekur diff --git a/app/src/main/res/values-nb/strings-preferences.xml b/app/src/main/res/values-nb/strings-preferences.xml index 466744ec8..db0ce59f3 100644 --- a/app/src/main/res/values-nb/strings-preferences.xml +++ b/app/src/main/res/values-nb/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Ingen diff --git a/app/src/main/res/values-nl/strings-preferences.xml b/app/src/main/res/values-nl/strings-preferences.xml index 982e260fd..139df22fb 100644 --- a/app/src/main/res/values-nl/strings-preferences.xml +++ b/app/src/main/res/values-nl/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Geen diff --git a/app/src/main/res/values-pl/strings-preferences.xml b/app/src/main/res/values-pl/strings-preferences.xml index b79dd6d7a..a2fa81f30 100644 --- a/app/src/main/res/values-pl/strings-preferences.xml +++ b/app/src/main/res/values-pl/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Mapa rowerowa - MapQuest Open + OpenTopo Brak diff --git a/app/src/main/res/values-pt-rBR/strings-preferences.xml b/app/src/main/res/values-pt-rBR/strings-preferences.xml index 6b51c1316..f365ee399 100644 --- a/app/src/main/res/values-pt-rBR/strings-preferences.xml +++ b/app/src/main/res/values-pt-rBR/strings-preferences.xml @@ -84,7 +84,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Nenhum diff --git a/app/src/main/res/values-pt-rPT/strings-preferences.xml b/app/src/main/res/values-pt-rPT/strings-preferences.xml index f8ac2d6ee..1358ea47c 100644 --- a/app/src/main/res/values-pt-rPT/strings-preferences.xml +++ b/app/src/main/res/values-pt-rPT/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Não exportar diff --git a/app/src/main/res/values-ru/strings-preferences.xml b/app/src/main/res/values-ru/strings-preferences.xml index 6feaddc5e..e49fd7634 100644 --- a/app/src/main/res/values-ru/strings-preferences.xml +++ b/app/src/main/res/values-ru/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Нет diff --git a/app/src/main/res/values-sk/strings-preferences.xml b/app/src/main/res/values-sk/strings-preferences.xml index 319bb97f0..29c32d975 100644 --- a/app/src/main/res/values-sk/strings-preferences.xml +++ b/app/src/main/res/values-sk/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Žiadne diff --git a/app/src/main/res/values-sl/strings-preferences.xml b/app/src/main/res/values-sl/strings-preferences.xml index b73c6f14a..8e466b010 100644 --- a/app/src/main/res/values-sl/strings-preferences.xml +++ b/app/src/main/res/values-sl/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Brez diff --git a/app/src/main/res/values-sr/strings-preferences.xml b/app/src/main/res/values-sr/strings-preferences.xml index 7bce13928..267d449ee 100644 --- a/app/src/main/res/values-sr/strings-preferences.xml +++ b/app/src/main/res/values-sr/strings-preferences.xml @@ -86,7 +86,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Без усмерења diff --git a/app/src/main/res/values-sv/strings-preferences.xml b/app/src/main/res/values-sv/strings-preferences.xml index 2a098f7ff..730ab54bb 100644 --- a/app/src/main/res/values-sv/strings-preferences.xml +++ b/app/src/main/res/values-sv/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Ingen diff --git a/app/src/main/res/values-tr/strings-preferences.xml b/app/src/main/res/values-tr/strings-preferences.xml index 43e30d240..d736c3d47 100644 --- a/app/src/main/res/values-tr/strings-preferences.xml +++ b/app/src/main/res/values-tr/strings-preferences.xml @@ -86,7 +86,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Hiçbiri diff --git a/app/src/main/res/values-uk/strings-preferences.xml b/app/src/main/res/values-uk/strings-preferences.xml index e7133125d..47c70a0fb 100644 --- a/app/src/main/res/values-uk/strings-preferences.xml +++ b/app/src/main/res/values-uk/strings-preferences.xml @@ -79,7 +79,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo Ні diff --git a/app/src/main/res/values-vi/strings-preferences.xml b/app/src/main/res/values-vi/strings-preferences.xml index f6e8c5a93..469d1b92a 100644 --- a/app/src/main/res/values-vi/strings-preferences.xml +++ b/app/src/main/res/values-vi/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Bản đồ Xe đạp - MapQuest Mở + yMapQuest Mở Không xuất diff --git a/app/src/main/res/values-zh-rCN/strings-preferences.xml b/app/src/main/res/values-zh-rCN/strings-preferences.xml index d8a93299a..59b182043 100644 --- a/app/src/main/res/values-zh-rCN/strings-preferences.xml +++ b/app/src/main/res/values-zh-rCN/strings-preferences.xml @@ -73,7 +73,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo 不保存 diff --git a/app/src/main/res/values-zh-rTW/strings-preferences.xml b/app/src/main/res/values-zh-rTW/strings-preferences.xml index 89ef7b2d2..f3efa45b6 100644 --- a/app/src/main/res/values-zh-rTW/strings-preferences.xml +++ b/app/src/main/res/values-zh-rTW/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index 828793888..973e61b17 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -111,7 +111,7 @@ Mapnik Cycle Map - MapQuest Open + OpenTopo None diff --git a/app/src/main/res/values/values-preferences.xml b/app/src/main/res/values/values-preferences.xml index 6aae963a7..51c26b354 100644 --- a/app/src/main/res/values/values-preferences.xml +++ b/app/src/main/res/values/values-preferences.xml @@ -44,9 +44,9 @@ - MAPNIK - CYCLEMAP - MAPQUESTOSM + Mapnik + CyclOSM + OpenTopoMap none diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index dc1749d09..cbb191bbd 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -114,6 +114,13 @@ android:title="@string/prefs_displaytrack_osm" android:summary="@string/prefs_displaytrack_osm_summary" android:defaultValue="false" /> + Date: Wed, 27 Aug 2025 08:24:59 +0200 Subject: [PATCH 13/60] - Undo changes on translations - Use the proper name CyclOSM for the new cycle map in keys --- app/src/main/res/values-ar/strings-preferences.xml | 2 +- app/src/main/res/values-b+sr+Latn/strings-preferences.xml | 2 +- app/src/main/res/values-ca/strings-preferences.xml | 2 +- app/src/main/res/values-cs-rCZ/strings-preferences.xml | 2 +- app/src/main/res/values-da/strings-preferences.xml | 2 +- app/src/main/res/values-de/strings-preferences.xml | 2 +- app/src/main/res/values-el/strings-preferences.xml | 2 +- app/src/main/res/values-es/strings-preferences.xml | 2 +- app/src/main/res/values-fa-rIR/strings-preferences.xml | 2 +- app/src/main/res/values-fi/strings-preferences.xml | 2 +- app/src/main/res/values-fr/strings-preferences.xml | 2 +- app/src/main/res/values-gl/strings-preferences.xml | 2 +- app/src/main/res/values-he/strings-preferences.xml | 2 +- app/src/main/res/values-hr/strings-preferences.xml | 2 +- app/src/main/res/values-hu/strings-preferences.xml | 2 +- app/src/main/res/values-id/strings-preferences.xml | 2 +- app/src/main/res/values-it/strings-preferences.xml | 2 +- app/src/main/res/values-ja/strings-preferences.xml | 2 +- app/src/main/res/values-ko/strings-preferences.xml | 2 +- app/src/main/res/values-lt/strings-preferences.xml | 2 +- app/src/main/res/values-lv/strings-preferences.xml | 2 +- app/src/main/res/values-nb/strings-preferences.xml | 2 +- app/src/main/res/values-nl/strings-preferences.xml | 2 +- app/src/main/res/values-pl/strings-preferences.xml | 2 +- app/src/main/res/values-pt-rBR/strings-preferences.xml | 2 +- app/src/main/res/values-pt-rPT/strings-preferences.xml | 2 +- app/src/main/res/values-ru/strings-preferences.xml | 2 +- app/src/main/res/values-sk/strings-preferences.xml | 2 +- app/src/main/res/values-sl/strings-preferences.xml | 2 +- app/src/main/res/values-sr/strings-preferences.xml | 2 +- app/src/main/res/values-sv/strings-preferences.xml | 2 +- app/src/main/res/values-tr/strings-preferences.xml | 2 +- app/src/main/res/values-uk/strings-preferences.xml | 2 +- app/src/main/res/values-vi/strings-preferences.xml | 2 +- app/src/main/res/values-zh-rCN/strings-preferences.xml | 2 +- app/src/main/res/values-zh-rTW/strings-preferences.xml | 2 +- app/src/main/res/values/strings-preferences.xml | 2 +- 37 files changed, 37 insertions(+), 37 deletions(-) diff --git a/app/src/main/res/values-ar/strings-preferences.xml b/app/src/main/res/values-ar/strings-preferences.xml index 74d6901d4..3815e2e3e 100644 --- a/app/src/main/res/values-ar/strings-preferences.xml +++ b/app/src/main/res/values-ar/strings-preferences.xml @@ -80,7 +80,7 @@ Mapnik خريطة الدراجات - OpenTopo + MapQuest Open لا شيء diff --git a/app/src/main/res/values-b+sr+Latn/strings-preferences.xml b/app/src/main/res/values-b+sr+Latn/strings-preferences.xml index 04b4b66ab..7c46fa0bd 100644 --- a/app/src/main/res/values-b+sr+Latn/strings-preferences.xml +++ b/app/src/main/res/values-b+sr+Latn/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Bez usmerenja diff --git a/app/src/main/res/values-ca/strings-preferences.xml b/app/src/main/res/values-ca/strings-preferences.xml index bef7e0616..405bdaa8e 100644 --- a/app/src/main/res/values-ca/strings-preferences.xml +++ b/app/src/main/res/values-ca/strings-preferences.xml @@ -76,7 +76,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Cap diff --git a/app/src/main/res/values-cs-rCZ/strings-preferences.xml b/app/src/main/res/values-cs-rCZ/strings-preferences.xml index eda58cac3..60f507564 100644 --- a/app/src/main/res/values-cs-rCZ/strings-preferences.xml +++ b/app/src/main/res/values-cs-rCZ/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Nikde diff --git a/app/src/main/res/values-da/strings-preferences.xml b/app/src/main/res/values-da/strings-preferences.xml index aa8633314..65c88cbe9 100644 --- a/app/src/main/res/values-da/strings-preferences.xml +++ b/app/src/main/res/values-da/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Deaktiveret diff --git a/app/src/main/res/values-de/strings-preferences.xml b/app/src/main/res/values-de/strings-preferences.xml index 365cf5a08..9a65f62c3 100644 --- a/app/src/main/res/values-de/strings-preferences.xml +++ b/app/src/main/res/values-de/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open kein Export diff --git a/app/src/main/res/values-el/strings-preferences.xml b/app/src/main/res/values-el/strings-preferences.xml index 548bd3d44..0ffcd40ca 100644 --- a/app/src/main/res/values-el/strings-preferences.xml +++ b/app/src/main/res/values-el/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Κανένα diff --git a/app/src/main/res/values-es/strings-preferences.xml b/app/src/main/res/values-es/strings-preferences.xml index 6108720f5..f973b7c0d 100644 --- a/app/src/main/res/values-es/strings-preferences.xml +++ b/app/src/main/res/values-es/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Ninguno diff --git a/app/src/main/res/values-fa-rIR/strings-preferences.xml b/app/src/main/res/values-fa-rIR/strings-preferences.xml index 3f1e66510..7569146d4 100644 --- a/app/src/main/res/values-fa-rIR/strings-preferences.xml +++ b/app/src/main/res/values-fa-rIR/strings-preferences.xml @@ -73,7 +73,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open خالی diff --git a/app/src/main/res/values-fi/strings-preferences.xml b/app/src/main/res/values-fi/strings-preferences.xml index c73d19f4f..0f06e139b 100644 --- a/app/src/main/res/values-fi/strings-preferences.xml +++ b/app/src/main/res/values-fi/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Pyöräilykartta - OpenTopo + MapQuest Open Ei lainkaan diff --git a/app/src/main/res/values-fr/strings-preferences.xml b/app/src/main/res/values-fr/strings-preferences.xml index d35520931..126e9468a 100644 --- a/app/src/main/res/values-fr/strings-preferences.xml +++ b/app/src/main/res/values-fr/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Aucun diff --git a/app/src/main/res/values-gl/strings-preferences.xml b/app/src/main/res/values-gl/strings-preferences.xml index 2aab7430a..fc949848c 100644 --- a/app/src/main/res/values-gl/strings-preferences.xml +++ b/app/src/main/res/values-gl/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Cycle Map - Abrir yMapQuest + Abrir MapQuest Non diff --git a/app/src/main/res/values-he/strings-preferences.xml b/app/src/main/res/values-he/strings-preferences.xml index fa73df383..c5ea1e5e4 100644 --- a/app/src/main/res/values-he/strings-preferences.xml +++ b/app/src/main/res/values-he/strings-preferences.xml @@ -73,7 +73,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open ללא שמירה diff --git a/app/src/main/res/values-hr/strings-preferences.xml b/app/src/main/res/values-hr/strings-preferences.xml index f2c68d753..b64dca958 100644 --- a/app/src/main/res/values-hr/strings-preferences.xml +++ b/app/src/main/res/values-hr/strings-preferences.xml @@ -67,7 +67,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Ništa diff --git a/app/src/main/res/values-hu/strings-preferences.xml b/app/src/main/res/values-hu/strings-preferences.xml index 078864d40..8558546c0 100644 --- a/app/src/main/res/values-hu/strings-preferences.xml +++ b/app/src/main/res/values-hu/strings-preferences.xml @@ -88,7 +88,7 @@ Mapnik Biciklis térkép - OpenTopo + MapQuest Open Semmi diff --git a/app/src/main/res/values-id/strings-preferences.xml b/app/src/main/res/values-id/strings-preferences.xml index aaf2fbf50..6166faed5 100644 --- a/app/src/main/res/values-id/strings-preferences.xml +++ b/app/src/main/res/values-id/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Nihil diff --git a/app/src/main/res/values-it/strings-preferences.xml b/app/src/main/res/values-it/strings-preferences.xml index 85ecd37aa..ec55c4994 100644 --- a/app/src/main/res/values-it/strings-preferences.xml +++ b/app/src/main/res/values-it/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Nessuno diff --git a/app/src/main/res/values-ja/strings-preferences.xml b/app/src/main/res/values-ja/strings-preferences.xml index 2896e29bf..c4a2222fe 100644 --- a/app/src/main/res/values-ja/strings-preferences.xml +++ b/app/src/main/res/values-ja/strings-preferences.xml @@ -86,7 +86,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open なし diff --git a/app/src/main/res/values-ko/strings-preferences.xml b/app/src/main/res/values-ko/strings-preferences.xml index 6f0e22673..9acc551ae 100644 --- a/app/src/main/res/values-ko/strings-preferences.xml +++ b/app/src/main/res/values-ko/strings-preferences.xml @@ -80,7 +80,7 @@ Mapnik 사이클 지도 - OpenTopo + MapQuest Open 없음 diff --git a/app/src/main/res/values-lt/strings-preferences.xml b/app/src/main/res/values-lt/strings-preferences.xml index ddd803428..4cc8b5fec 100644 --- a/app/src/main/res/values-lt/strings-preferences.xml +++ b/app/src/main/res/values-lt/strings-preferences.xml @@ -18,6 +18,6 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open diff --git a/app/src/main/res/values-lv/strings-preferences.xml b/app/src/main/res/values-lv/strings-preferences.xml index c0d7f9e7a..ffbc89425 100644 --- a/app/src/main/res/values-lv/strings-preferences.xml +++ b/app/src/main/res/values-lv/strings-preferences.xml @@ -79,7 +79,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Nekur diff --git a/app/src/main/res/values-nb/strings-preferences.xml b/app/src/main/res/values-nb/strings-preferences.xml index db0ce59f3..466744ec8 100644 --- a/app/src/main/res/values-nb/strings-preferences.xml +++ b/app/src/main/res/values-nb/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Ingen diff --git a/app/src/main/res/values-nl/strings-preferences.xml b/app/src/main/res/values-nl/strings-preferences.xml index 139df22fb..982e260fd 100644 --- a/app/src/main/res/values-nl/strings-preferences.xml +++ b/app/src/main/res/values-nl/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Geen diff --git a/app/src/main/res/values-pl/strings-preferences.xml b/app/src/main/res/values-pl/strings-preferences.xml index a2fa81f30..b79dd6d7a 100644 --- a/app/src/main/res/values-pl/strings-preferences.xml +++ b/app/src/main/res/values-pl/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Mapa rowerowa - OpenTopo + MapQuest Open Brak diff --git a/app/src/main/res/values-pt-rBR/strings-preferences.xml b/app/src/main/res/values-pt-rBR/strings-preferences.xml index f365ee399..6b51c1316 100644 --- a/app/src/main/res/values-pt-rBR/strings-preferences.xml +++ b/app/src/main/res/values-pt-rBR/strings-preferences.xml @@ -84,7 +84,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Nenhum diff --git a/app/src/main/res/values-pt-rPT/strings-preferences.xml b/app/src/main/res/values-pt-rPT/strings-preferences.xml index 1358ea47c..f8ac2d6ee 100644 --- a/app/src/main/res/values-pt-rPT/strings-preferences.xml +++ b/app/src/main/res/values-pt-rPT/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Não exportar diff --git a/app/src/main/res/values-ru/strings-preferences.xml b/app/src/main/res/values-ru/strings-preferences.xml index e49fd7634..6feaddc5e 100644 --- a/app/src/main/res/values-ru/strings-preferences.xml +++ b/app/src/main/res/values-ru/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Нет diff --git a/app/src/main/res/values-sk/strings-preferences.xml b/app/src/main/res/values-sk/strings-preferences.xml index 29c32d975..319bb97f0 100644 --- a/app/src/main/res/values-sk/strings-preferences.xml +++ b/app/src/main/res/values-sk/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Žiadne diff --git a/app/src/main/res/values-sl/strings-preferences.xml b/app/src/main/res/values-sl/strings-preferences.xml index 8e466b010..b73c6f14a 100644 --- a/app/src/main/res/values-sl/strings-preferences.xml +++ b/app/src/main/res/values-sl/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Brez diff --git a/app/src/main/res/values-sr/strings-preferences.xml b/app/src/main/res/values-sr/strings-preferences.xml index 267d449ee..7bce13928 100644 --- a/app/src/main/res/values-sr/strings-preferences.xml +++ b/app/src/main/res/values-sr/strings-preferences.xml @@ -86,7 +86,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Без усмерења diff --git a/app/src/main/res/values-sv/strings-preferences.xml b/app/src/main/res/values-sv/strings-preferences.xml index 730ab54bb..2a098f7ff 100644 --- a/app/src/main/res/values-sv/strings-preferences.xml +++ b/app/src/main/res/values-sv/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Ingen diff --git a/app/src/main/res/values-tr/strings-preferences.xml b/app/src/main/res/values-tr/strings-preferences.xml index d736c3d47..43e30d240 100644 --- a/app/src/main/res/values-tr/strings-preferences.xml +++ b/app/src/main/res/values-tr/strings-preferences.xml @@ -86,7 +86,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Hiçbiri diff --git a/app/src/main/res/values-uk/strings-preferences.xml b/app/src/main/res/values-uk/strings-preferences.xml index 47c70a0fb..e7133125d 100644 --- a/app/src/main/res/values-uk/strings-preferences.xml +++ b/app/src/main/res/values-uk/strings-preferences.xml @@ -79,7 +79,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open Ні diff --git a/app/src/main/res/values-vi/strings-preferences.xml b/app/src/main/res/values-vi/strings-preferences.xml index 469d1b92a..f6e8c5a93 100644 --- a/app/src/main/res/values-vi/strings-preferences.xml +++ b/app/src/main/res/values-vi/strings-preferences.xml @@ -74,7 +74,7 @@ Mapnik Bản đồ Xe đạp - yMapQuest Mở + MapQuest Mở Không xuất diff --git a/app/src/main/res/values-zh-rCN/strings-preferences.xml b/app/src/main/res/values-zh-rCN/strings-preferences.xml index 59b182043..d8a93299a 100644 --- a/app/src/main/res/values-zh-rCN/strings-preferences.xml +++ b/app/src/main/res/values-zh-rCN/strings-preferences.xml @@ -73,7 +73,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open 不保存 diff --git a/app/src/main/res/values-zh-rTW/strings-preferences.xml b/app/src/main/res/values-zh-rTW/strings-preferences.xml index f3efa45b6..89ef7b2d2 100644 --- a/app/src/main/res/values-zh-rTW/strings-preferences.xml +++ b/app/src/main/res/values-zh-rTW/strings-preferences.xml @@ -89,7 +89,7 @@ Mapnik Cycle Map - OpenTopo + MapQuest Open diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index 973e61b17..9207da626 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -110,7 +110,7 @@ Mapnik - Cycle Map + CyclOSM OpenTopo From 2c0c43162201994c2a85e6b79283183f7171683f Mon Sep 17 00:00:00 2001 From: JoseAndresVargas Date: Wed, 12 Nov 2025 19:26:59 -0600 Subject: [PATCH 14/60] fix: resolve text overlap in osm_upload layout --- app/src/main/res/layout/osm_upload.xml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/layout/osm_upload.xml b/app/src/main/res/layout/osm_upload.xml index be17e6725..0b3278074 100644 --- a/app/src/main/res/layout/osm_upload.xml +++ b/app/src/main/res/layout/osm_upload.xml @@ -32,9 +32,16 @@ android:text="@string/tracklogger_btnBack" /> - + + + + \ No newline at end of file From e134b03be2984d48898e8b4e451d8ece80c395dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Sun, 14 Dec 2025 14:39:48 -0600 Subject: [PATCH 15/60] Add map tiles summary text and set tile options to non-translatable. Code format improvements. --- .../net/osmtracker/activity/DisplayTrackMap.java | 14 +++++++------- app/src/main/res/values/strings-preferences.xml | 10 +++++----- app/src/main/res/values/values-preferences.xml | 7 ++++--- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/net/osmtracker/activity/DisplayTrackMap.java b/app/src/main/java/net/osmtracker/activity/DisplayTrackMap.java index 5475c20e5..1b56a6855 100644 --- a/app/src/main/java/net/osmtracker/activity/DisplayTrackMap.java +++ b/app/src/main/java/net/osmtracker/activity/DisplayTrackMap.java @@ -255,13 +255,13 @@ public void setTileDpiScaling() { "© OpenStreetMap contributors")); } -// /** -// * Returns a ITileSource for the map according to the selected mapTile -// * String. The default is mapnik. -// * -// * @param mapTile String that is the name of the tile provider -// * @return ITileSource with the selected Tile-Source -// */ + /** + * Returns a ITileSource for the map according to the selected mapTile + * String. The default is mapnik. + * + * @param mapTile String that is the name of the tile provider + * @return ITileSource with the selected Tile-Source + */ private ITileSource selectMapTile(String mapTile) { try { return TileSourceFactory.getTileSource(mapTile); diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index 9207da626..32f528bf6 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -107,16 +107,16 @@ You\'ll have to authorize OSMTracker to upload tracks again. Are you sure? Map tile provider - - + Select the tile provider for rendering the map + Mapnik CyclOSM OpenTopo - None - in comment - in extension + None + in comment + in extension Export compass heading Defines if and how the compass data should be exported to the GPX file diff --git a/app/src/main/res/values/values-preferences.xml b/app/src/main/res/values/values-preferences.xml index 51c26b354..16d5e4960 100644 --- a/app/src/main/res/values/values-preferences.xml +++ b/app/src/main/res/values/values-preferences.xml @@ -48,10 +48,11 @@ CyclOSM OpenTopoMap + - none - comment - extension + none + comment + extension From 93c802808320b21b53d68ccebc9b2f238bee8305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Mon, 15 Dec 2025 11:43:56 -0600 Subject: [PATCH 16/60] refactor: Clean tile provider names from translation files. --- app/src/main/res/values-ar/strings-preferences.xml | 5 ----- app/src/main/res/values-cs-rCZ/strings-preferences.xml | 5 ----- app/src/main/res/values-da/strings-preferences.xml | 5 ----- app/src/main/res/values-de/strings-preferences.xml | 5 ----- app/src/main/res/values-el/strings-preferences.xml | 5 ----- app/src/main/res/values-es/strings-preferences.xml | 5 ----- app/src/main/res/values-fa-rIR/strings-preferences.xml | 5 ----- app/src/main/res/values-fr/strings-preferences.xml | 5 ----- app/src/main/res/values-hu/strings-preferences.xml | 5 ----- app/src/main/res/values-it/strings-preferences.xml | 5 ----- app/src/main/res/values-ja/strings-preferences.xml | 5 ----- app/src/main/res/values-ko/strings-preferences.xml | 5 ----- app/src/main/res/values-lv/strings-preferences.xml | 5 ----- app/src/main/res/values-nl/strings-preferences.xml | 5 ----- app/src/main/res/values-pl/strings-preferences.xml | 5 ----- app/src/main/res/values-pt-rBR/strings-preferences.xml | 5 ----- app/src/main/res/values-pt-rPT/strings-preferences.xml | 5 ----- app/src/main/res/values-ru/strings-preferences.xml | 5 ----- app/src/main/res/values-sk/strings-preferences.xml | 5 ----- app/src/main/res/values-sr/strings-preferences.xml | 5 ----- app/src/main/res/values-tr/strings-preferences.xml | 5 ----- app/src/main/res/values-uk/strings-preferences.xml | 5 ----- app/src/main/res/values-zh-rCN/strings-preferences.xml | 5 ----- app/src/main/res/values-zh-rTW/strings-preferences.xml | 5 ----- 24 files changed, 120 deletions(-) diff --git a/app/src/main/res/values-ar/strings-preferences.xml b/app/src/main/res/values-ar/strings-preferences.xml index 3815e2e3e..23bba852b 100644 --- a/app/src/main/res/values-ar/strings-preferences.xml +++ b/app/src/main/res/values-ar/strings-preferences.xml @@ -77,11 +77,6 @@ لابد من السماح لـOSMTracker برفع المسارات مرة أخرى. هل أنت متأكد؟ مزود الصور المتجانبة للخريطة - - Mapnik - خريطة الدراجات - MapQuest Open - لا شيء في التعليق diff --git a/app/src/main/res/values-cs-rCZ/strings-preferences.xml b/app/src/main/res/values-cs-rCZ/strings-preferences.xml index 60f507564..92300bf0d 100644 --- a/app/src/main/res/values-cs-rCZ/strings-preferences.xml +++ b/app/src/main/res/values-cs-rCZ/strings-preferences.xml @@ -86,11 +86,6 @@ Je třeba autorizace OSMTrackeru pro opakované nahrání. Jste si jisti? Poskytovatel mapových dlaždic - - Mapnik - Cycle Map - MapQuest Open - Nikde V komentáři diff --git a/app/src/main/res/values-da/strings-preferences.xml b/app/src/main/res/values-da/strings-preferences.xml index 65c88cbe9..a1e53bc57 100644 --- a/app/src/main/res/values-da/strings-preferences.xml +++ b/app/src/main/res/values-da/strings-preferences.xml @@ -86,11 +86,6 @@ Dette betyder at du vil skulle autorisere OSMTracker for at kunne uploade igen. Er du sikker? Leverandør af kortfliser - - Mapnik - Cycle Map - MapQuest Open - Deaktiveret til kommentar diff --git a/app/src/main/res/values-de/strings-preferences.xml b/app/src/main/res/values-de/strings-preferences.xml index 9a65f62c3..ae1086a7f 100644 --- a/app/src/main/res/values-de/strings-preferences.xml +++ b/app/src/main/res/values-de/strings-preferences.xml @@ -86,11 +86,6 @@ Sie müssen OSMTracker erneut zum Hochladen von Routen autorisieren. Sind Sie sicher? Anbieter von Kartenkacheln - - Mapnik - Cycle Map - MapQuest Open - kein Export im Kommentar diff --git a/app/src/main/res/values-el/strings-preferences.xml b/app/src/main/res/values-el/strings-preferences.xml index 0ffcd40ca..f763763fa 100644 --- a/app/src/main/res/values-el/strings-preferences.xml +++ b/app/src/main/res/values-el/strings-preferences.xml @@ -86,11 +86,6 @@ Θα πρέπει να εξουσιοδοτήσετε το OSMTracker να στείλει τα ίχνη ξανά. Είστε σίγουρος; Πάροχος πλακιδίων χάρτη - - Mapnik - Cycle Map - MapQuest Open - Κανένα σε σχόλιο diff --git a/app/src/main/res/values-es/strings-preferences.xml b/app/src/main/res/values-es/strings-preferences.xml index f973b7c0d..c0c3b7295 100644 --- a/app/src/main/res/values-es/strings-preferences.xml +++ b/app/src/main/res/values-es/strings-preferences.xml @@ -86,11 +86,6 @@ Deberá autorizar a OSMTracker para volver a subir las pistas. ¿Está seguro? Proveedor de mosaicos de mapas - - Mapnik - Cycle Map - MapQuest Open - Ninguno en comentario diff --git a/app/src/main/res/values-fa-rIR/strings-preferences.xml b/app/src/main/res/values-fa-rIR/strings-preferences.xml index 7569146d4..df69ffae8 100644 --- a/app/src/main/res/values-fa-rIR/strings-preferences.xml +++ b/app/src/main/res/values-fa-rIR/strings-preferences.xml @@ -70,11 +70,6 @@ اعتبارنامه‌ها و مجوزهای OSM را فراموش کن و OSMTracker را مجبور به درخواست دوبارهٔ آن‌ها کن باید به OSMTracker مجوز بدهید تا دوباره بتوانید ردها را بارگذاری کنید. مطمئن هستید؟ - - Mapnik - Cycle Map - MapQuest Open - خالی در توضیحات diff --git a/app/src/main/res/values-fr/strings-preferences.xml b/app/src/main/res/values-fr/strings-preferences.xml index 126e9468a..3d506e89c 100644 --- a/app/src/main/res/values-fr/strings-preferences.xml +++ b/app/src/main/res/values-fr/strings-preferences.xml @@ -86,11 +86,6 @@ Vous devrez vous reconnecter à OpenStreetMap. Êtes-vous sûr ? Fournisseur de tuiles de carte - - Mapnik - Cycle Map - MapQuest Open - Aucun En commentaire diff --git a/app/src/main/res/values-hu/strings-preferences.xml b/app/src/main/res/values-hu/strings-preferences.xml index 8558546c0..d85086bc8 100644 --- a/app/src/main/res/values-hu/strings-preferences.xml +++ b/app/src/main/res/values-hu/strings-preferences.xml @@ -85,11 +85,6 @@ Az OSMTrackert majd újból azonosítani kell a nyomvonalak feltöltéséhez. Biztosan ezt szeretné? Térképcsempe-szolgáltató - - Mapnik - Biciklis térkép - MapQuest Open - Semmi megjegyzésben diff --git a/app/src/main/res/values-it/strings-preferences.xml b/app/src/main/res/values-it/strings-preferences.xml index ec55c4994..53477d9e3 100644 --- a/app/src/main/res/values-it/strings-preferences.xml +++ b/app/src/main/res/values-it/strings-preferences.xml @@ -86,11 +86,6 @@ Devi autorizzare nuovamente OSMTracker a caricare i tracciati. Sei sicuro? Fornitore dei tasselli della mappa - - Mapnik - Cycle Map - MapQuest Open - Nessuno come commento diff --git a/app/src/main/res/values-ja/strings-preferences.xml b/app/src/main/res/values-ja/strings-preferences.xml index c4a2222fe..f96b08e02 100644 --- a/app/src/main/res/values-ja/strings-preferences.xml +++ b/app/src/main/res/values-ja/strings-preferences.xml @@ -83,11 +83,6 @@ 再びトラックをアップロードするには、OSMTrackerの認証が必要です。続けますか? 地図タイルプロバイダー - - Mapnik - Cycle Map - MapQuest Open - なし コメント内 diff --git a/app/src/main/res/values-ko/strings-preferences.xml b/app/src/main/res/values-ko/strings-preferences.xml index 9acc551ae..e346f66ea 100644 --- a/app/src/main/res/values-ko/strings-preferences.xml +++ b/app/src/main/res/values-ko/strings-preferences.xml @@ -77,11 +77,6 @@ 트랙을 올리려면 OSMTracker를 다시 인증해야 합니다. 지우겠습니까? 지도 타일 제공자 - - Mapnik - 사이클 지도 - MapQuest Open - 없음 주석에서 diff --git a/app/src/main/res/values-lv/strings-preferences.xml b/app/src/main/res/values-lv/strings-preferences.xml index ffbc89425..c91fa526d 100644 --- a/app/src/main/res/values-lv/strings-preferences.xml +++ b/app/src/main/res/values-lv/strings-preferences.xml @@ -76,11 +76,6 @@ Aizmirst OSM konta informāciju un atļaujas, un pieprasīt OSMTracker tās pieprasīt atkārtoti Tev būs atkārtoti jāautorizē OSMTracker lai augšupielādētu ierakstus. Vai esi pārliecināts? - - Mapnik - Cycle Map - MapQuest Open - Nekur komentārā diff --git a/app/src/main/res/values-nl/strings-preferences.xml b/app/src/main/res/values-nl/strings-preferences.xml index 982e260fd..719d5bf3e 100644 --- a/app/src/main/res/values-nl/strings-preferences.xml +++ b/app/src/main/res/values-nl/strings-preferences.xml @@ -86,11 +86,6 @@ U zal OSMTracker terug moeten autoriseren om trajecten te uploaden. Bent u zeker? Kaartvak-provider - - Mapnik - Cycle Map - MapQuest Open - Geen in opmerking diff --git a/app/src/main/res/values-pl/strings-preferences.xml b/app/src/main/res/values-pl/strings-preferences.xml index b79dd6d7a..a5e2fdf43 100644 --- a/app/src/main/res/values-pl/strings-preferences.xml +++ b/app/src/main/res/values-pl/strings-preferences.xml @@ -86,11 +86,6 @@ Będziesz musiał ponownie autoryzować OSMTracker by wysyłać ślady. Czy jesteś pewien? Dostawca kafelków mapy - - Mapnik - Mapa rowerowa - MapQuest Open - Brak w komentarzu diff --git a/app/src/main/res/values-pt-rBR/strings-preferences.xml b/app/src/main/res/values-pt-rBR/strings-preferences.xml index 6b51c1316..89f513cab 100644 --- a/app/src/main/res/values-pt-rBR/strings-preferences.xml +++ b/app/src/main/res/values-pt-rBR/strings-preferences.xml @@ -81,11 +81,6 @@ Você vai ter que autorizar OSMTracker para carregar trilhas novamente. Tem certeza? Provedor de blocos de mapas - - Mapnik - Cycle Map - MapQuest Open - Nenhum em comentário diff --git a/app/src/main/res/values-pt-rPT/strings-preferences.xml b/app/src/main/res/values-pt-rPT/strings-preferences.xml index f8ac2d6ee..7f69248d4 100644 --- a/app/src/main/res/values-pt-rPT/strings-preferences.xml +++ b/app/src/main/res/values-pt-rPT/strings-preferences.xml @@ -86,11 +86,6 @@ Terá de autorizar novamente o OSMTracker para poder enviar trilhos para o OpenStreetMap. Quer continuar? Fornecedor de mosaicos de mapas - - Mapnik - Cycle Map - MapQuest Open - Não exportar No comentário diff --git a/app/src/main/res/values-ru/strings-preferences.xml b/app/src/main/res/values-ru/strings-preferences.xml index 6feaddc5e..0723a6ad7 100644 --- a/app/src/main/res/values-ru/strings-preferences.xml +++ b/app/src/main/res/values-ru/strings-preferences.xml @@ -86,11 +86,6 @@ Нужно будет заново авторизовать OSMTracker, чтобы закачивать треки. Вы уверены? Поставщик тайлов карт - - Mapnik - Cycle Map - MapQuest Open - Нет в комментарии diff --git a/app/src/main/res/values-sk/strings-preferences.xml b/app/src/main/res/values-sk/strings-preferences.xml index 319bb97f0..caaa2f11b 100644 --- a/app/src/main/res/values-sk/strings-preferences.xml +++ b/app/src/main/res/values-sk/strings-preferences.xml @@ -86,11 +86,6 @@ Znova sa pokúšate autorizovať OSMTracker, aby mohol nahrávať záznamy stôp. Ste si istý? Poskytovateľ mapových dlaždíc - - Mapnik - Cycle Map - MapQuest Open - Žiadne V komentári diff --git a/app/src/main/res/values-sr/strings-preferences.xml b/app/src/main/res/values-sr/strings-preferences.xml index 7bce13928..e46d3c401 100644 --- a/app/src/main/res/values-sr/strings-preferences.xml +++ b/app/src/main/res/values-sr/strings-preferences.xml @@ -83,11 +83,6 @@ Мораћете поново да овластите OSM пратиоца да шаље праћења. Сигурни сте? Добављач поља мапе - - Mapnik - Cycle Map - MapQuest Open - Без усмерења У коментару diff --git a/app/src/main/res/values-tr/strings-preferences.xml b/app/src/main/res/values-tr/strings-preferences.xml index 43e30d240..6695eb0b5 100644 --- a/app/src/main/res/values-tr/strings-preferences.xml +++ b/app/src/main/res/values-tr/strings-preferences.xml @@ -83,11 +83,6 @@ İzleme yüklemek için OSMTracker\'a tekrardan yetki vermeniz gerekecek. Emin misiniz? Harita kutucuğu sağlayıcısı - - Mapnik - Cycle Map - MapQuest Open - Hiçbiri yorumda diff --git a/app/src/main/res/values-uk/strings-preferences.xml b/app/src/main/res/values-uk/strings-preferences.xml index e7133125d..6ae8fb570 100644 --- a/app/src/main/res/values-uk/strings-preferences.xml +++ b/app/src/main/res/values-uk/strings-preferences.xml @@ -76,11 +76,6 @@ Видалити облікові дані доступу до OSM і примусити OSMTracker запросити їх знову. Потрібно буде заново авторизувати OSMTracker, щоб завантажувати шляхи. Ви впевнені? - - Mapnik - Cycle Map - MapQuest Open - Ні у коментарі diff --git a/app/src/main/res/values-zh-rCN/strings-preferences.xml b/app/src/main/res/values-zh-rCN/strings-preferences.xml index d8a93299a..d5e5425e5 100644 --- a/app/src/main/res/values-zh-rCN/strings-preferences.xml +++ b/app/src/main/res/values-zh-rCN/strings-preferences.xml @@ -70,11 +70,6 @@ 清除本地OSM账户以及权限信息。OSMTracker将要求用户重新输入这些信息 你将要再次授权 OSMTracker 来上传轨迹。确定吗? - - Mapnik - Cycle Map - MapQuest Open - 不保存 保存于注释 diff --git a/app/src/main/res/values-zh-rTW/strings-preferences.xml b/app/src/main/res/values-zh-rTW/strings-preferences.xml index 89ef7b2d2..1c656f1b6 100644 --- a/app/src/main/res/values-zh-rTW/strings-preferences.xml +++ b/app/src/main/res/values-zh-rTW/strings-preferences.xml @@ -86,11 +86,6 @@ 您必須重新認證 OSMTracker 方能繼續上傳軌跡資料,確定嗎? 地圖圖磚提供者 - - Mapnik - Cycle Map - MapQuest Open - 於註解 From 7c9621b978c94641c36930b69232570390a53581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Mon, 15 Dec 2025 13:33:16 -0600 Subject: [PATCH 17/60] refactor: Clean tile provider names from translation files (x2). --- app/src/main/res/values-he/strings-preferences.xml | 6 ------ app/src/main/res/values-sv/strings-preferences.xml | 6 ------ 2 files changed, 12 deletions(-) diff --git a/app/src/main/res/values-he/strings-preferences.xml b/app/src/main/res/values-he/strings-preferences.xml index c5ea1e5e4..6a29c3928 100644 --- a/app/src/main/res/values-he/strings-preferences.xml +++ b/app/src/main/res/values-he/strings-preferences.xml @@ -69,12 +69,6 @@ איפוס אימות פרטי משתמש OSM מחק את אימות פרטי משתמש OSM ואלץ את הכנסתם מחדש ידרש אימות מחדש כדי לשוב ולהעלות מסלולים. את/ה בטוח/ה? - - - Mapnik - Cycle Map - MapQuest Open - ללא שמירה כהערה diff --git a/app/src/main/res/values-sv/strings-preferences.xml b/app/src/main/res/values-sv/strings-preferences.xml index 2a098f7ff..b6608f84e 100644 --- a/app/src/main/res/values-sv/strings-preferences.xml +++ b/app/src/main/res/values-sv/strings-preferences.xml @@ -85,12 +85,6 @@ Glöm bort inloggning och tillstånd och tvinga OSMTracker att fråga om detta igen Du måste godkänna OSMTracker för att kunna ladda upp spår igen. Är du säker? Tillhandahållare av kartrutor - - - Mapnik - Cycle Map - MapQuest Open - Ingen i kommentar From 0278ff50d89ff163af2209f50bb75640bc762087 Mon Sep 17 00:00:00 2001 From: Andy Porras Date: Sat, 20 Dec 2025 23:54:21 -0600 Subject: [PATCH 18/60] Fix: Remove trackdetail_name_and_title string to clarify filename configuration --- app/src/main/res/layout/trackdetail_fields.xml | 2 +- app/src/main/res/values/strings.xml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/res/layout/trackdetail_fields.xml b/app/src/main/res/layout/trackdetail_fields.xml index c42734a2c..db20f151b 100644 --- a/app/src/main/res/layout/trackdetail_fields.xml +++ b/app/src/main/res/layout/trackdetail_fields.xml @@ -8,7 +8,7 @@ android:layout_height="wrap_content" android:layout_marginStart="5dp" android:layout_marginTop="8dp" - android:text="@string/trackdetail_name_and_title" /> + android:text="@string/trackdetail_name" /> (Not uploaded yet) Display Name - Name and title Description Tags (comma separated) You must enter a description From 26bb1aecc1341c26371b2156d8b048b5b3e3ef3a Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Mon, 22 Dec 2025 10:59:28 -0600 Subject: [PATCH 19/60] =?UTF-8?q?[Transifex]=20Updates=20for=20project=20O?= =?UTF-8?q?SMTracker=20for=20Android=E2=84=A2=20(#655)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Translate strings-preferences.xml in es 100% translated source file: 'strings-preferences.xml' on 'es'. * Translate strings-preferences.xml in pt_BR 100% translated source file: 'strings-preferences.xml' on 'pt_BR'. * Translate strings.xml in sr 80% of minimum 80% translated source file: 'strings.xml' on 'sr'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * Translate strings-preferences.xml in sv 100% translated source file: 'strings-preferences.xml' on 'sv'. * Translate strings-preferences.xml in nl 100% translated source file: 'strings-preferences.xml' on 'nl'. --------- Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> Co-authored-by: Jaime Gutiérrez Alfaro <593829+jamescr@users.noreply.github.com> --- .../res/values-es/strings-preferences.xml | 2 +- .../res/values-nl/strings-preferences.xml | 2 +- .../res/values-pt-rBR/strings-preferences.xml | 2 +- app/src/main/res/values-sr/strings.xml | 42 +++++++++++++++++++ .../res/values-sv/strings-preferences.xml | 1 + 5 files changed, 46 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-es/strings-preferences.xml b/app/src/main/res/values-es/strings-preferences.xml index c0c3b7295..d90514037 100644 --- a/app/src/main/res/values-es/strings-preferences.xml +++ b/app/src/main/res/values-es/strings-preferences.xml @@ -85,7 +85,7 @@ Olvidar las credenciales y permisos de OSM, y forzar a que OSMTracker los vuelva a solicitar Deberá autorizar a OSMTracker para volver a subir las pistas. ¿Está seguro? Proveedor de mosaicos de mapas - + Escoja el proveedor de mosaicos para mostrar el mapa Ninguno en comentario diff --git a/app/src/main/res/values-nl/strings-preferences.xml b/app/src/main/res/values-nl/strings-preferences.xml index 719d5bf3e..a49eeb8f5 100644 --- a/app/src/main/res/values-nl/strings-preferences.xml +++ b/app/src/main/res/values-nl/strings-preferences.xml @@ -85,7 +85,7 @@ OSM-inloggegevens en toestemming vergeten en OSMTracker forceren om ze nogmaals op te vragen. U zal OSMTracker terug moeten autoriseren om trajecten te uploaden. Bent u zeker? Kaartvak-provider - + Selecteer de provider voor tegels om de kaart te renderen Geen in opmerking diff --git a/app/src/main/res/values-pt-rBR/strings-preferences.xml b/app/src/main/res/values-pt-rBR/strings-preferences.xml index 89f513cab..59c2a8999 100644 --- a/app/src/main/res/values-pt-rBR/strings-preferences.xml +++ b/app/src/main/res/values-pt-rBR/strings-preferences.xml @@ -80,7 +80,7 @@ Esquecer as credenciais e permissões OSM e forçar o OSMTracker a perguntar isso novamente Você vai ter que autorizar OSMTracker para carregar trilhas novamente. Tem certeza? Provedor de blocos de mapas - + Escolha o provedor do blocos para renderizar o mapa. Nenhum em comentário diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 5fb286ae0..0cc95259c 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -37,7 +37,10 @@ Заустави праћење Настави праћење Обриши + Извези + Подели Пошаљи на OpenStreetMap + Отпреми на GitHub Приказ Детаљи Праћење #{0} @@ -59,6 +62,8 @@ (још није извезено) (још није послато) Приказ + Назив + Назив и наслов Опис Ознаке (раздвој запетом) Морате унети опис @@ -82,6 +87,12 @@ Сликај Белешка + Отвори датотеку + Сачувај + Обриши + Откажи + Обриши + Откажи Поставке Пролазне тачке @@ -104,7 +115,9 @@ Проверите да ли је спољно складиште убачено и монтирано. Гласовна белешка није успела Грешка при читању XML фајла распореда. Вратите на подразумевани распоред. + Потребно је да токен има 40 знакова + Потребна су права Испраћено са OSM пратиоцем за Андроид Пажња: HDOP вредности нису са GPS уређаја већ процењене на основу прецизности локације у метрима. @@ -137,6 +150,8 @@ Чекам правац... Правац се не може одредити + Успешно је завршен поступак извоза + Позиција није доступна {0} {1} / {2} {3} OpenStreetMap приказ праћења @@ -148,8 +163,10 @@ Распоред није послат. Покушајте касније Заиста желите да обришете распоред {0} ? Да + Распоред успешно уклоњен Директоријум са иконама успешно обрисан Овај фајл није имао придружени директоријум са иконама + Распоред није могуће уклонити Грешка: не могу да се повежем на интернет Грешка: не могу да се повежем на ризницу подразумеваних посебних распореда @@ -170,7 +187,32 @@ Назив гране: Гитхаб ризница исправна Гитхаб ризница неисправна + + успешно направљено + Грешка приликом прављења + Грешка базе података + успешно сачувано + Грешка приликом чувања + Статус захтева за спајање: + Грешка у вези са информацијама спремишта + Учитавање је било успешно + Грешка приликом отпремања + Грешка приликом читања GPX датотеке + Није пронађена GPX датотека + Отпремање датотеке: + Одабрана ставка: + Приватно: + Прављење спремишта + + ⚠️ Можете да сачувате „размак” како бисте уклонили своје акредитиве. + + + + + Упутство за коришћење апликације OSMTracker за Android™ + Добро дошли у OSMTracker за Android™ 👋 + Срећан пут и успешно праћење 🗺 😎 diff --git a/app/src/main/res/values-sv/strings-preferences.xml b/app/src/main/res/values-sv/strings-preferences.xml index b6608f84e..8ad147578 100644 --- a/app/src/main/res/values-sv/strings-preferences.xml +++ b/app/src/main/res/values-sv/strings-preferences.xml @@ -85,6 +85,7 @@ Glöm bort inloggning och tillstånd och tvinga OSMTracker att fråga om detta igen Du måste godkänna OSMTracker för att kunna ladda upp spår igen. Är du säker? Tillhandahållare av kartrutor + Välj rut-leverantör för att rendera kartan Ingen i kommentar From 0ce70517d647eeefeb32975e537e3c168a6e11db Mon Sep 17 00:00:00 2001 From: Binnette Date: Wed, 4 Dec 2024 09:25:27 +0100 Subject: [PATCH 20/60] Replace deprecated ActivityTestRule --- .../osmtracker/layouts/DeleteLayoutTest.java | 162 ++++++------- .../layouts/DownloadLayoutTest.java | 217 +++++++++--------- .../layouts/RepositorySettingsDialogTest.java | 182 ++++++++------- 3 files changed, 296 insertions(+), 265 deletions(-) diff --git a/app/src/androidTest/java/net/osmtracker/layouts/DeleteLayoutTest.java b/app/src/androidTest/java/net/osmtracker/layouts/DeleteLayoutTest.java index 63fd0a464..339caaccb 100644 --- a/app/src/androidTest/java/net/osmtracker/layouts/DeleteLayoutTest.java +++ b/app/src/androidTest/java/net/osmtracker/layouts/DeleteLayoutTest.java @@ -1,21 +1,5 @@ package net.osmtracker.layouts; -import android.Manifest; -import androidx.test.rule.ActivityTestRule; -import androidx.test.rule.GrantPermissionRule; - -import net.osmtracker.R; -import net.osmtracker.activity.ButtonsPresets; -import net.osmtracker.activity.Preferences; -import net.osmtracker.util.CustomLayoutsUtils; -import net.osmtracker.util.TestUtils; - -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; -import java.util.ArrayList; - import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.action.ViewActions.longClick; @@ -26,72 +10,94 @@ import static net.osmtracker.util.TestUtils.getStringResource; import static net.osmtracker.util.TestUtils.injectMockLayout; import static net.osmtracker.util.TestUtils.listFiles; +import static org.apache.commons.io.FileUtils.deleteDirectory; import static org.hamcrest.Matchers.equalToIgnoringCase; import static org.junit.Assert.assertFalse; -import static org.apache.commons.io.FileUtils.deleteDirectory; +import android.Manifest; + +import androidx.lifecycle.Lifecycle; +import androidx.test.core.app.ActivityScenario; +import androidx.test.rule.GrantPermissionRule; + +import net.osmtracker.R; +import net.osmtracker.activity.ButtonsPresets; +import net.osmtracker.activity.Preferences; +import net.osmtracker.util.CustomLayoutsUtils; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayList; public class DeleteLayoutTest { - @Rule - public GrantPermissionRule storagePermission = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE); - - @Rule - public ActivityTestRule mRule = new ActivityTestRule(ButtonsPresets.class) { - @Override - protected void beforeActivityLaunched() { - //Makes sure that only the mock layout exists - try { - deleteDirectory(getLayoutsDirectory()); - injectMockLayout(layoutName, ISOLanguageCode); - - } catch (IOException e) { - e.printStackTrace(); - } - } - }; - - private static String layoutName = "mock"; - private static String ISOLanguageCode = "es"; - - /** - * Assumes being in the ButtonsPresets activity - * Deletes the layout with the received name - */ - private void deleteLayout(String layoutName){ - onView(withText(layoutName)).perform(longClick()); - onView(withText(getStringResource(R.string.buttons_presets_context_menu_delete))).perform(click()); - String textToMatch = getStringResource(R.string.buttons_presets_delete_positive_confirmation); - onView(withText(equalToIgnoringCase(textToMatch))).perform(click()); - } - - /** - * Deletes the mock layout and then checks that: - * - The UI option doesn't appear anymore - * - The XML file is deleted - * - A Toast is shown to inform about what happened - * - The icons directory is deleted - */ - @Test - public void layoutDeletionTest(){ - - deleteLayout(layoutName); - - // Check the informative Toast is shown - checkToastIsShownWith(getStringResource(R.string.buttons_presets_successful_delete)); - - // Check the layout doesn't appear anymore - onView(withText(layoutName)).check(doesNotExist()); - - // List files after the deletion - ArrayList filesAfterDeletion = listFiles(getLayoutsDirectory()); - - // Check the xml file was deleted - String layoutFileName = CustomLayoutsUtils.createFileName(layoutName, ISOLanguageCode); - assertFalse(filesAfterDeletion.contains(layoutFileName)); - - // Check the icons folder was deleted - assertFalse(filesAfterDeletion.contains(layoutName+ Preferences.ICONS_DIR_SUFFIX)); - - } + @Rule + public GrantPermissionRule storagePermission = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE); + + public ActivityScenario activity; + + private static final String layoutName = "mock"; + private static final String ISOLanguageCode = "es"; + + @Before + public void setUp() { + // Makes sure that only the mock layout exists + try { + deleteDirectory(getLayoutsDirectory()); + injectMockLayout(layoutName, ISOLanguageCode); + } catch (IOException e) { + e.printStackTrace(); + } + // Launch activity + activity = ActivityScenario.launch(ButtonsPresets.class); + activity.moveToState(Lifecycle.State.RESUMED); + } + + @After + public void tearDown() { + activity.close(); + } + + /** + * Assumes being in the ButtonsPresets activity + * Deletes the layout with the received name + */ + private void deleteLayout() { + onView(withText(layoutName)).perform(longClick()); + onView(withText(getStringResource(R.string.buttons_presets_context_menu_delete))).perform(click()); + String textToMatch = getStringResource(R.string.buttons_presets_delete_positive_confirmation); + onView(withText(equalToIgnoringCase(textToMatch))).perform(click()); + } + + /** + * Deletes the mock layout and then checks that: + * - The UI option doesn't appear anymore + * - The XML file is deleted + * - A Toast is shown to inform about what happened + * - The icons directory is deleted + */ + @Test + public void layoutDeletionTest() { + deleteLayout(); + + // Check the informative Toast is shown + checkToastIsShownWith(getStringResource(R.string.buttons_presets_successful_delete)); + + // Check the layout doesn't appear anymore + onView(withText(layoutName)).check(doesNotExist()); + + // List files after the deletion + ArrayList filesAfterDeletion = listFiles(getLayoutsDirectory()); + + // Check the xml file was deleted + String layoutFileName = CustomLayoutsUtils.createFileName(layoutName, ISOLanguageCode); + assertFalse(filesAfterDeletion.contains(layoutFileName)); + + // Check the icons folder was deleted + assertFalse(filesAfterDeletion.contains(layoutName + Preferences.ICONS_DIR_SUFFIX)); + } } diff --git a/app/src/androidTest/java/net/osmtracker/layouts/DownloadLayoutTest.java b/app/src/androidTest/java/net/osmtracker/layouts/DownloadLayoutTest.java index 1c20d9c7e..7882dbea6 100644 --- a/app/src/androidTest/java/net/osmtracker/layouts/DownloadLayoutTest.java +++ b/app/src/androidTest/java/net/osmtracker/layouts/DownloadLayoutTest.java @@ -19,8 +19,9 @@ import android.content.SharedPreferences; import android.preference.PreferenceManager; +import androidx.lifecycle.Lifecycle; +import androidx.test.core.app.ActivityScenario; import androidx.test.espresso.Espresso; -import androidx.test.rule.ActivityTestRule; import androidx.test.rule.GrantPermissionRule; import net.osmtracker.OSMTracker; @@ -29,6 +30,8 @@ import net.osmtracker.util.TestUtils; import org.apache.commons.io.FileUtils; +import org.junit.After; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -36,107 +39,115 @@ public class DownloadLayoutTest { - private final int WAIT_VIEW_TIMEOUT = 5000; + private final int WAIT_VIEW_TIMEOUT = 5000; - @Rule - public GrantPermissionRule fineLocationPermission = GrantPermissionRule.grant(Manifest.permission.ACCESS_FINE_LOCATION); - @Rule - public GrantPermissionRule coarseLocationPermission = GrantPermissionRule.grant(Manifest.permission.ACCESS_COARSE_LOCATION); - @Rule - public GrantPermissionRule writeStoragePermission = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE); - - @Rule - public ActivityTestRule mRule = new ActivityTestRule(TrackManager.class) { - @Override - protected void beforeActivityLaunched() { - // Skip cool intro - SharedPreferences dtPrefs = PreferenceManager - .getDefaultSharedPreferences(getInstrumentation().getTargetContext()); - dtPrefs.edit().putBoolean(OSMTracker.Preferences.KEY_DISPLAY_APP_INTRO, false).apply(); - } - }; - - @Test - public void downloadLayoutTest() { - deleteLayoutsDirectory(); - - TestUtils.setLayoutsTestingRepository(); - - String layoutName = "abc"; - - navigateToAvailableLayouts(); - - clickButtonsToDownloadLayout(layoutName); - - makePostDownloadAssertions(layoutName); - } - - - public void deleteLayoutsDirectory(){ - try { - FileUtils.deleteDirectory(TestUtils.getLayoutsDirectory()); - }catch (Exception e){ - e.printStackTrace(); - fail(); - } - } - - - /** - * Assuming being in TrackManager - */ - public void navigateToAvailableLayouts() { - // Open options menu in the Action Bar - openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); - // Click on "Settings" in this menu - onView(withText(TestUtils.getStringResource(R.string.menu_settings))).perform(click()); - // Click on "Buttons presets" settings - onData(withTitleText(TestUtils.getStringResource(R.string.prefs_ui_buttons_layout))).perform(scrollTo(), click()); - // Wait for "+" to be visible - onView(isRoot()).perform(waitForView(R.id.launch_available, WAIT_VIEW_TIMEOUT)); - // Perform a click action on the "+" button - onView(withId(R.id.launch_available)).perform(click()); - } - - - /** - * Check the new layouts appears as a new option - * Select the layout and check its buttons are shown when tracking - * @param layoutName - */ - private void makePostDownloadAssertions(String layoutName) { - Espresso.pressBack(); - - // Check the layout appears as a new option in AvailableLayouts - onView(withText(layoutName.toLowerCase())).check(matches(isDisplayed())); - - // Select the layout - onView(withText(layoutName.toLowerCase())).perform(click()); - - // Go to TrackLogger - Espresso.pressBack(); - Espresso.pressBack(); - onView(withId(R.id.trackmgr_fab)).perform(click()); - - // Check the buttons are loaded correctly - String expectedButtonsLabels[] = new String[]{"A", "B", "C"}; - for(String label : expectedButtonsLabels) - onView(withText(label)).check(matches(isDisplayed())); - - } - - - private void clickButtonsToDownloadLayout(String layoutName) { - onView(withText(layoutName)).perform(click()); - - // Catch languages available dialog that shows up when the cell phone is not in English - if (! Locale.getDefault().getLanguage().equalsIgnoreCase("en")) { - onView(withText("English")).perform(click()); - } - - onView(withText(TestUtils.getStringResource(R.string.available_layouts_description_dialog_positive_confirmation))). - perform(click()); - - TestUtils.checkToastIsShownWith(TestUtils.getStringResource(R.string.available_layouts_successful_download)); - } + @Rule + public GrantPermissionRule fineLocationPermission = GrantPermissionRule.grant(Manifest.permission.ACCESS_FINE_LOCATION); + @Rule + public GrantPermissionRule coarseLocationPermission = GrantPermissionRule.grant(Manifest.permission.ACCESS_COARSE_LOCATION); + @Rule + public GrantPermissionRule writeStoragePermission = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE); + + public ActivityScenario activity; + + @Before + public void setUp() { + // Skip cool intro + SharedPreferences dtPrefs = PreferenceManager + .getDefaultSharedPreferences(getInstrumentation().getTargetContext()); + dtPrefs.edit().putBoolean(OSMTracker.Preferences.KEY_DISPLAY_APP_INTRO, false).apply(); + // Launch activity + activity = ActivityScenario.launch(TrackManager.class); + activity.moveToState(Lifecycle.State.RESUMED); + } + + @After + public void tearDown() { + activity.close(); + } + + @Test + public void downloadLayoutTest() { + deleteLayoutsDirectory(); + + TestUtils.setLayoutsTestingRepository(); + + String layoutName = "abc"; + + navigateToAvailableLayouts(); + + clickButtonsToDownloadLayout(layoutName); + + makePostDownloadAssertions(layoutName); + } + + + public void deleteLayoutsDirectory() { + try { + FileUtils.deleteDirectory(TestUtils.getLayoutsDirectory()); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + } + + + /** + * Assuming being in TrackManager + */ + public void navigateToAvailableLayouts() { + // Open options menu in the Action Bar + openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); + // Click on "Settings" in this menu + onView(withText(TestUtils.getStringResource(R.string.menu_settings))).perform(click()); + // Click on "Buttons presets" settings + onData(withTitleText(TestUtils.getStringResource(R.string.prefs_ui_buttons_layout))).perform(scrollTo(), click()); + // Wait for "+" to be visible + onView(isRoot()).perform(waitForView(R.id.launch_available, WAIT_VIEW_TIMEOUT)); + // Perform a click action on the "+" button + onView(withId(R.id.launch_available)).perform(click()); + } + + + /** + * Check the new layouts appears as a new option + * Select the layout and check its buttons are shown when tracking + * + * @param layoutName layout name + */ + private void makePostDownloadAssertions(String layoutName) { + Espresso.pressBack(); + + // Check the layout appears as a new option in AvailableLayouts + onView(withText(layoutName.toLowerCase())).check(matches(isDisplayed())); + + // Select the layout + onView(withText(layoutName.toLowerCase())).perform(click()); + + // Go to TrackLogger + Espresso.pressBack(); + Espresso.pressBack(); + onView(withId(R.id.trackmgr_fab)).perform(click()); + + // Check the buttons are loaded correctly + String[] expectedButtonsLabels = new String[]{"A", "B", "C"}; + for (String label : expectedButtonsLabels) + onView(withText(label)).check(matches(isDisplayed())); + + } + + + private void clickButtonsToDownloadLayout(String layoutName) { + onView(withText(layoutName)).perform(click()); + + // Catch languages available dialog that shows up when the cell phone is not in English + if (!Locale.getDefault().getLanguage().equalsIgnoreCase("en")) { + onView(withText("English")).perform(click()); + } + + onView(withText(TestUtils.getStringResource(R.string.available_layouts_description_dialog_positive_confirmation))). + perform(click()); + + TestUtils.checkToastIsShownWith(TestUtils.getStringResource(R.string.available_layouts_successful_download)); + } } \ No newline at end of file diff --git a/app/src/androidTest/java/net/osmtracker/layouts/RepositorySettingsDialogTest.java b/app/src/androidTest/java/net/osmtracker/layouts/RepositorySettingsDialogTest.java index 607587fc0..bac3b7d7c 100644 --- a/app/src/androidTest/java/net/osmtracker/layouts/RepositorySettingsDialogTest.java +++ b/app/src/androidTest/java/net/osmtracker/layouts/RepositorySettingsDialogTest.java @@ -16,101 +16,115 @@ import static net.osmtracker.util.TestUtils.getStringResource; import static org.hamcrest.core.IsNot.not; +import android.view.View; + +import androidx.lifecycle.Lifecycle; +import androidx.test.core.app.ActivityScenario; import androidx.test.espresso.ViewAssertion; -import androidx.test.rule.ActivityTestRule; import net.osmtracker.OSMTracker; import net.osmtracker.R; import net.osmtracker.activity.AvailableLayouts; import org.hamcrest.Matcher; -import org.junit.Rule; +import org.junit.After; +import org.junit.Before; import org.junit.Test; public class RepositorySettingsDialogTest { - @Rule - public ActivityTestRule mRule = new ActivityTestRule<>(AvailableLayouts.class); - - - @Test - public void testToggleBehaviour(){ - onView(withId(R.id.github_config)).perform(click()); - - onView(withId(R.id.default_server)).perform(click(), closeSoftKeyboard()); - checkStateAfterToggle(R.id.default_server, R.id.custom_server); - checkTextFieldsState(not(isEnabled())); - checkTextFieldsDefaultValues(); - - onView(withId(R.id.custom_server)).perform(click(), closeSoftKeyboard()); - checkStateAfterToggle(R.id.custom_server, R.id.default_server); - checkTextFieldsState(isEnabled()); - } - - @Test - public void testRepositoryValidation(){ - String validUser = OSMTracker.Preferences.VAL_GITHUB_USERNAME; - String validRepository = OSMTracker.Preferences.VAL_REPOSITORY_NAME; - String validBranch = OSMTracker.Preferences.VAL_BRANCH_NAME; - String invalidBranch = "NONE"; - - checkRepositoryValidity(validUser,validRepository,validBranch, true); - checkRepositoryValidity(validUser,validRepository,invalidBranch, false); - } - - - public void checkStateAfterToggle(int expectedActiveId, int expectedInactiveId){ - onView(withId(expectedActiveId)).check(matches(not(isEnabled()))); - onView(withId(expectedActiveId)).check(matches(isChecked())); - onView(withId(expectedInactiveId)).check(matches(not(isChecked()))); - onView(withId(expectedInactiveId)).check(matches(isEnabled())); - } - - public void checkRepositoryValidity(String user, String repo, String branch, boolean isValid) { - onView(withId(R.id.github_config)).perform(click()); - - onView(withId(R.id.custom_server)).perform(click(), closeSoftKeyboard()); - - onView(withId(R.id.github_username)).perform(clearText(), typeText(user), closeSoftKeyboard()); - onView(withId(R.id.repository_name)).perform(clearText(), typeText(repo), closeSoftKeyboard()); - onView(withId(R.id.branch_name)).perform(clearText(), typeText(branch), closeSoftKeyboard()); - - onView(withText(getStringResource(R.string.menu_save))).perform(click()); - - String expectedMessage = (isValid) ? getStringResource(R.string.github_repository_settings_valid_server) : - getStringResource(R.string.github_repository_settings_invalid_server); - - checkToastIsShownWith(expectedMessage); - - ViewAssertion expectedDialogState = (isValid) ? doesNotExist() : matches(isDisplayed()); - checkDialogState(expectedDialogState); - } - - /** - * Check if the dialog is shown by looking for its title on the screen - */ - private void checkDialogState(ViewAssertion assertion) { - onView(withText(getStringResource(R.string.prefs_ui_github_repository_settings))).check(assertion); - } - - /** - * Check that the text fields values match the expected default ones - */ - private void checkTextFieldsDefaultValues() { - onView(withId(R.id.repository_name)).check(matches(withText(OSMTracker.Preferences.VAL_REPOSITORY_NAME))); - onView(withId(R.id.branch_name)).check(matches(withText(OSMTracker.Preferences.VAL_BRANCH_NAME))); - onView(withId(R.id.github_username)).check(matches(withText(OSMTracker.Preferences.VAL_GITHUB_USERNAME))); - } - - /** - * @param matcher can be isEnabled or not(isEnabled()) or any matcher - */ - public void checkTextFieldsState(Matcher matcher){ - - onView(withId(R.id.github_username)).check(matches(matcher)); - onView(withId(R.id.repository_name)).check(matches(matcher)); - onView(withId(R.id.branch_name)).check(matches(matcher)); - } + public ActivityScenario activity; + + @Before + public void setUp() { + // Launch activity + activity = ActivityScenario.launch(AvailableLayouts.class); + activity.moveToState(Lifecycle.State.RESUMED); + } + + @After + public void tearDown() { + activity.close(); + } + + @Test + public void testToggleBehaviour() { + onView(withId(R.id.github_config)).perform(click()); + + onView(withId(R.id.default_server)).perform(click(), closeSoftKeyboard()); + checkStateAfterToggle(R.id.default_server, R.id.custom_server); + checkTextFieldsState(not(isEnabled())); + checkTextFieldsDefaultValues(); + + onView(withId(R.id.custom_server)).perform(click(), closeSoftKeyboard()); + checkStateAfterToggle(R.id.custom_server, R.id.default_server); + checkTextFieldsState(isEnabled()); + } + + @Test + public void testRepositoryValidation() { + String validUser = OSMTracker.Preferences.VAL_GITHUB_USERNAME; + String validRepository = OSMTracker.Preferences.VAL_REPOSITORY_NAME; + String validBranch = OSMTracker.Preferences.VAL_BRANCH_NAME; + String invalidBranch = "NONE"; + + checkRepositoryValidity(validUser, validRepository, validBranch, true); + checkRepositoryValidity(validUser, validRepository, invalidBranch, false); + } + + + public void checkStateAfterToggle(int expectedActiveId, int expectedInactiveId) { + onView(withId(expectedActiveId)).check(matches(not(isEnabled()))); + onView(withId(expectedActiveId)).check(matches(isChecked())); + onView(withId(expectedInactiveId)).check(matches(not(isChecked()))); + onView(withId(expectedInactiveId)).check(matches(isEnabled())); + } + + public void checkRepositoryValidity(String user, String repo, String branch, boolean isValid) { + onView(withId(R.id.github_config)).perform(click()); + + onView(withId(R.id.custom_server)).perform(click(), closeSoftKeyboard()); + + onView(withId(R.id.github_username)).perform(clearText(), typeText(user), closeSoftKeyboard()); + onView(withId(R.id.repository_name)).perform(clearText(), typeText(repo), closeSoftKeyboard()); + onView(withId(R.id.branch_name)).perform(clearText(), typeText(branch), closeSoftKeyboard()); + + onView(withText(getStringResource(R.string.menu_save))).perform(click()); + + String expectedMessage = (isValid) ? getStringResource(R.string.github_repository_settings_valid_server) : + getStringResource(R.string.github_repository_settings_invalid_server); + + checkToastIsShownWith(expectedMessage); + + ViewAssertion expectedDialogState = (isValid) ? doesNotExist() : matches(isDisplayed()); + checkDialogState(expectedDialogState); + } + + /** + * Check if the dialog is shown by looking for its title on the screen + */ + private void checkDialogState(ViewAssertion assertion) { + onView(withText(getStringResource(R.string.prefs_ui_github_repository_settings))).check(assertion); + } + + /** + * Check that the text fields values match the expected default ones + */ + private void checkTextFieldsDefaultValues() { + onView(withId(R.id.repository_name)).check(matches(withText(OSMTracker.Preferences.VAL_REPOSITORY_NAME))); + onView(withId(R.id.branch_name)).check(matches(withText(OSMTracker.Preferences.VAL_BRANCH_NAME))); + onView(withId(R.id.github_username)).check(matches(withText(OSMTracker.Preferences.VAL_GITHUB_USERNAME))); + } + + /** + * @param matcher can be isEnabled or not(isEnabled()) or any matcher + */ + public void checkTextFieldsState(Matcher matcher) { + + onView(withId(R.id.github_username)).check(matches(matcher)); + onView(withId(R.id.repository_name)).check(matches(matcher)); + onView(withId(R.id.branch_name)).check(matches(matcher)); + } } From 91036df722de5700fa2037451214e90edc62c39d Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Tue, 23 Dec 2025 08:52:34 -0600 Subject: [PATCH 21/60] =?UTF-8?q?[Transifex]=20Updates=20for=20project=20O?= =?UTF-8?q?SMTracker=20for=20Android=E2=84=A2=20(#656)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Updating app/src/main/res/values/strings.xml source file: 'app/src/main/res/values/strings.xml' updated. * Translate strings.xml in nl 100% translated source file: 'strings.xml' on 'nl'. * Translate strings.xml in zh_TW 100% translated source file: 'strings.xml' on 'zh_TW'. * Translate strings.xml in sv 100% translated source file: 'strings.xml' on 'sv'. * Translate strings.xml in sr 80% of minimum 80% translated source file: 'strings.xml' on 'sr'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format * Translate strings.xml in sk 87% of minimum 80% translated source file: 'strings.xml' on 'sk'. Sync of partially translated files: untranslated content is included with an empty translation or source language content depending on file format --------- Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com> Co-authored-by: Jaime Gutiérrez Alfaro <593829+jamescr@users.noreply.github.com> --- app/src/main/res/values-nl/strings.xml | 1 - app/src/main/res/values-sk/strings.xml | 1 - app/src/main/res/values-sr/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values-zh-rTW/strings.xml | 1 - app/src/main/res/values/strings.xml | 535 ++++++++++----------- 6 files changed, 258 insertions(+), 282 deletions(-) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index f5fae0005..3c786b6e6 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -65,7 +65,6 @@ Selecteer het in de lijst om door te gaan. (Nog niet geüpload) Weergeven Naam - Naam en titel Beschrijving Tags (kommagescheiden) Een beschrijving is vereist diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index c0f3f8ec5..6d856b0d7 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -64,7 +64,6 @@ (Zatiaľ neodovzdané) Zobraziť Názov - Názov a hlavička Popis Tagy (oddelené čiarkou) Musíte zadať popis diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 0cc95259c..2f2dc374d 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -63,7 +63,6 @@ (још није послато) Приказ Назив - Назив и наслов Опис Ознаке (раздвој запетом) Морате унети опис diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index e918f8f1f..21e4e703f 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -64,7 +64,6 @@ (inte uppladdad än) Visa Namn - Namn och titel Beskrivning Etiketter (kommaseparerade) Du måste ange en beskrivning diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 36f6f1c17..08732e854 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -64,7 +64,6 @@ (尚未上傳) 顯示 名稱 - 名稱與標題 描述 標籤 (以半形逗號分隔) 您必須填寫描述欄 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 01977f784..d8a4fd12c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,280 +1,261 @@ - + - - OSMTracker for Android™ - OSMTracker - Inspired by OSMTracker on Windows Mobile, it allows you to track your journeys, mark significant way points (Voice recording, photos), export them in GPX format for later use with Open Street Map tools like JOSM. - - - Track logger - Waiting for GPS fix to enable buttons… - Voice recording - Recording a {0}s audio clip. - Stop - Back - Tracked: - GPS disabled - GPS is disabled. Do you want to enable it? - Gallery or camera? - Take photo with camera - Select photo from gallery - - - Waypoint list - Lat: - Long: - Ele: - Accur: - Comp. head.: - Comp. accur.: - - - Track manager - Track list: - Waypoints: - Trackpoints: - You don\'t have any tracks. - Press to record a new track. - Unable to create a new track: {0} - You are currently recording track #{0}\nChoose it in the list to continue - Stop tracking - Resume tracking - Delete - Export - Share - Upload to OpenStreetMap - Upload to GitHub - Display - Details - Track #{0} - Track #{0} will be deleted - All tracks will be deleted. Are you sure? - Exporting track #{0}… - Preparing export… - Unable to export track: {0} - All tracks will be exported, which could take a long time. Are you sure? - Unable to process the track: {0} - - - Track Details - Start time: - End time: - Starts at: - Ends at: - Exported: - Uploaded to OpenStreetMap: - Export as GPX - (Not exported yet) - (Not uploaded yet) - Display - Name - Description - Tags (comma separated) - You must enter a description - Private - Public - Trackable - Identifiable - - - OpenStreetMap upload - Save and upload - Unable to export the track to a temporary file - Unable to authenticate to OSM - Sending track #{0}… - Waiting for OpenStreetMap server response… - Error while uploading track - The OSM server returned an error: ({0}) message {1} - Authorization error. Would you like to clear the saved OpenStreetMap credentials? - OpenStreetMap upload succeeded - - - Voice record - Take photo - Text note - - - Waypoint Name/text - Enter waypoint name - Open file - Save - Delete - Cancel - Delete waypoint - Delete this waypoint? - Delete - Cancel - - - Settings - Waypoints - About - Display track - Stop & save - New track - Delete all tracks - Continue track - Stop current track - Save - Cancel - Export as GPX - OpenStreetMap upload - Center to GPS - Export all as GPX - - - Unable to write to external storage. - Unable to create track folder %s - Please check if ext. storage is correctly inserted and mounted. - Voice recording has failed - Error while parsing XML layout file. Please revert to default layout. - Token must be 40 characters - Error while creating the PR" - - - Permission required - To export the GPX trace we need to write on the storage. - To display the track properly we need access to the storage. - To share the track properly we need access to the storage. - To upload the track to OSM we need access to the storage. - Accept - Can\'t continue without GPS permission - - - Tracked with OSMTracker for Android™ - Warning: HDOP values aren\'t the HDOP as returned by the GPS device. They\'re approximated from the location accuracy in meters. - - - About - For more information, docs and issue report, please visit the project home page: - Help translating OSMTracker: - Debug info - Export database - Exporting database… - Database export result: %s - - - OSMTracker is tracking - OSMTracker is tracking (#{0}) - Tap here to display main screen - - - Display track - Display background map - N - - - Save - - - m - Accuracy - Accuracy {0}{1} ({2}/{3}) - Waiting for GPS fix… ({0}/{1}) - {0}° - Wait for heading… - Heading can\'t be determined - Export process finished successfully - Position not available - {0} {1} / {2} {3} - - - OpenStreetMap track display - - - Update & Install - Delete - Updating… - Layout was updated successfully - Layout was not updated, try again later - Are you sure to delete the {0} layout? - Yes - The layout was deleted successfully - The icon directory was deleted successfully - This file didn\'t have any icon directory associated - The layout could not be deleted - - - Error: unable to connect to the Internet - Error: unable to connect to the default custom layouts repository - (Connecting…) - Download - Your language is not available select one from the list - Available Languages - Checking local language versions - Downloading… - The layout was downloaded successfully - The layout can\'t be downloaded, try again later - Error retrieving data from server - - - Default - Custom - Github username: - Repository name: - Branch name: - Github Repository valid - Github Repository invalid - - - successfully created - Error creating - Database error - successfully saved - Saving error - Pull request status: - Error with repository information - Successfully uploaded" - Error uploading - Error reading the GPX file - GPX file not found - Uploading file: - Item Selected: - Private: - Creating repository - You must specify a repository name - You must specify a value for this field - Retrieving repositories... - Error retrieving repositories - Successfully retrieved repositories - - Configure - GitHub token: - Get token - How to get a GitHub Token: - 1. Click the button to open the GitHub website and create a token. Sign In with your GitHub account if needed. - 2. Select \"Tokens (Classic)\" and click \"Generate new token\" button. - 3. Assign a descriptive name to your token. - 4. Select an expiration date. We recommend \"No expiration\" to avoid repeating this step." - 5. Select the scope or permissions you want to grant for this token (OSMTracker just need the repo permission). - 6. Click the \"Generate token\" button. - 7. Copy the generated token and paste it in the field \"GitHub token\". - ⚠️ You can save blank to delete your credentials. - - Commit message: - Create\nfork - Open pull request - Select a repository - Create repository - Commit - Configure - - Original Repository Username - Original Repository Name - Create - - Pull Request Title - Pull Request Description - - - - OSMTracker for Android™ Introduction - - Welcome to OSMTracker for Android™ 👋 - This App is free software that respects your freedom! - - Happy tracking 🗺 😎 - OSMTracker for Android will use your GPS location to record trackpoints and waypoints, even when the App is running in background. + + OSMTracker for Android™ + OSMTracker + Inspired by OSMTracker on Windows Mobile, it allows you to track your journeys, mark significant way points (Voice recording, photos), export them in GPX format for later use with Open Street Map tools like JOSM. + + Track logger + Waiting for GPS fix to enable buttons… + Voice recording + Recording a {0}s audio clip. + Stop + Back + Tracked: + GPS disabled + GPS is disabled. Do you want to enable it? + Gallery or camera? + Take photo with camera + Select photo from gallery + + Waypoint list + Lat: + Long: + Ele: + Accur: + Comp. head.: + Comp. accur.: + + Track manager + Track list: + Waypoints: + Trackpoints: + You don\'t have any tracks. + Press to record a new track. + Unable to create a new track: {0} + You are currently recording track #{0}\nChoose it in the list to continue + Stop tracking + Resume tracking + Delete + Export + Share + Upload to OpenStreetMap + Upload to GitHub + Display + Details + Track #{0} + Track #{0} will be deleted + All tracks will be deleted. Are you sure? + Exporting track #{0}… + Preparing export… + Unable to export track: {0} + All tracks will be exported, which could take a long time. Are you sure? + Unable to process the track: {0} + + Track Details + Start time: + End time: + Starts at: + Ends at: + Exported: + Uploaded to OpenStreetMap: + Export as GPX + (Not exported yet) + (Not uploaded yet) + Display + Name + Description + Tags (comma separated) + You must enter a description + Private + Public + Trackable + Identifiable + + OpenStreetMap upload + Save and upload + Unable to export the track to a temporary file + Unable to authenticate to OSM + Sending track #{0}… + Waiting for OpenStreetMap server response… + Error while uploading track + The OSM server returned an error: ({0}) message {1} + Authorization error. Would you like to clear the saved OpenStreetMap credentials? + OpenStreetMap upload succeeded + + Voice record + Take photo + Text note + + Waypoint Name/text + Enter waypoint name + Open file + Save + Delete + Cancel + Delete waypoint + Delete this waypoint? + Delete + Cancel + + Settings + Waypoints + About + Display track + Stop & save + New track + Delete all tracks + Continue track + Stop current track + Save + Cancel + Export as GPX + OpenStreetMap upload + Center to GPS + Export all as GPX + + Unable to write to external storage. + Unable to create track folder %s + Please check if ext. storage is correctly inserted and mounted. + Voice recording has failed + Error while parsing XML layout file. Please revert to default layout. + Token must be 40 characters + Error while creating the PR + + Permission required + To export the GPX trace we need to write on the storage. + To display the track properly we need access to the storage. + To share the track properly we need access to the storage. + To upload the track to OSM we need access to the storage. + Accept + Can\'t continue without GPS permission + + Tracked with OSMTracker for Android™ + Warning: HDOP values aren\'t the HDOP as returned by the GPS device. They\'re approximated from the location accuracy in meters. + + About + For more information, docs and issue report, please visit the project home page: + Help translating OSMTracker: + Debug info + Export database + Exporting database… + Database export result: %s + + OSMTracker is tracking + OSMTracker is tracking (#{0}) + Tap here to display main screen + + Display track + Display background map + N + + Save + + m + Accuracy + Accuracy {0}{1} ({2}/{3}) + + Waiting for GPS fix… ({0}/{1}) + + {0}° + + Wait for heading… + Heading can\'t be determined + Export process finished successfully + Position not available + {0} {1} / {2} {3} + + OpenStreetMap track display + + Update & Install + Delete + Updating… + Layout was updated successfully + Layout was not updated, try again later + Are you sure to delete the {0} layout? + Yes + The layout was deleted successfully + The icon directory was deleted successfully + This file didn\'t have any icon directory associated + The layout could not be deleted + + Error: unable to connect to the Internet + Error: unable to connect to the default custom layouts repository + (Connecting…) + Download + Your language is not available select one from the list + Available Languages + Checking local language versions + Downloading… + The layout was downloaded successfully + The layout can\'t be downloaded, try again later + Error retrieving data from server + + Default + Custom + Github username: + Repository name: + Branch name: + Github Repository valid + Github Repository invalid + + successfully created + Error creating + Database error + successfully saved + Saving error + Pull request status: + Error with repository information + Successfully uploaded + Error uploading + Error reading the GPX file + GPX file not found + Uploading file: + Item Selected: + Private: + Creating repository + You must specify a repository name + You must specify a value for this field + Retrieving repositories... + Error retrieving repositories + Successfully retrieved repositories + + Configure + GitHub token: + Get token + How to get a GitHub Token: + 1. Click the button to open the GitHub website and create a token. Sign In with your GitHub account if needed. + 2. Select \"Tokens (Classic)\" and click \"Generate new token\" button. + 3. Assign a descriptive name to your token. + 4. Select an expiration date. We recommend \"No expiration\" to avoid repeating this step. + 5. Select the scope or permissions you want to grant for this token (OSMTracker just need the repo permission). + 6. Click the \"Generate token\" button. + 7. Copy the generated token and paste it in the field \"GitHub token\". + ⚠️ You can save blank to delete your credentials. + + Commit message: + Create\nfork + Open pull request + Select a repository + Create repository + Commit + Configure + + Original Repository Username + Original Repository Name + Create + + Pull Request Title + Pull Request Description + + + OSMTracker for Android™ Introduction + + Welcome to OSMTracker for Android™ 👋 + This App is free software that respects your freedom! + + Happy tracking 🗺 😎 + OSMTracker for Android will use your GPS location to record trackpoints and waypoints, even when the App is running in background. \nYour data is not used to support ads. - No application was found to open this file. + No application was found to open this file. From 96cf84a597d173411bed53f80b711a17418256e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Sat, 27 Dec 2025 12:23:15 -0600 Subject: [PATCH 22/60] Migrate preferences to AndroidX --- app/build.gradle | 2 + .../osmtracker/layouts/DeleteLayoutTest.java | 4 +- .../layouts/DownloadLayoutTest.java | 13 +- .../java/net/osmtracker/util/TestUtils.java | 8 +- app/src/main/AndroidManifest.xml | 4 +- .../java/net/osmtracker/activity/About.java | 4 +- .../osmtracker/activity/AvailableLayouts.java | 3 +- .../osmtracker/activity/ButtonsPresets.java | 16 +- .../net/osmtracker/activity/DisplayTrack.java | 3 +- .../osmtracker/activity/DisplayTrackMap.java | 3 +- .../java/net/osmtracker/activity/Intro.kt | 10 +- .../activity/OpenStreetMapUpload.java | 3 +- .../net/osmtracker/activity/Preferences.java | 393 ++++++++---------- .../net/osmtracker/activity/TrackDetail.java | 3 +- .../net/osmtracker/activity/TrackLogger.java | 4 +- .../net/osmtracker/activity/TrackManager.java | 6 +- .../java/net/osmtracker/db/DataHelper.java | 23 +- .../osmtracker/gpx/ExportToStorageTask.java | 3 +- .../osmtracker/gpx/ExportToTempFileTask.java | 3 +- .../net/osmtracker/gpx/ExportTrackTask.java | 3 +- .../layout/DownloadCustomLayoutTask.java | 9 +- .../osmtracker/layout/GpsStatusRecord.java | 3 +- .../osm/UploadToOpenStreetMapTask.java | 3 +- .../net/osmtracker/service/gps/GPSLogger.java | 2 +- .../osmtracker/util/CustomLayoutsUtils.java | 9 +- .../java/net/osmtracker/util/URLCreator.java | 8 +- .../net/osmtracker/view/VoiceRecDialog.java | 3 +- app/src/main/res/layout/settings_activity.xml | 9 + .../main/res/values/strings-preferences.xml | 1 + app/src/main/res/xml/preferences.xml | 269 ++++++------ .../activity/ButtonsPresetsTest.java | 3 +- .../gpx/ExportToStorageTaskTest.java | 3 +- .../layout/DownloadCustomLayoutTaskTest.java | 7 +- .../util/CustomLayoutsUtilsTest.java | 3 +- .../osmtracker/util/ThemeValidatorTest.java | 3 +- .../net/osmtracker/util/URLCreatorTest.java | 3 +- 36 files changed, 441 insertions(+), 408 deletions(-) create mode 100644 app/src/main/res/layout/settings_activity.xml diff --git a/app/build.gradle b/app/build.gradle index 3caf91def..cd692d859 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -95,6 +95,7 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.2.0' implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.7.0' + implementation 'androidx.preference:preference:1.2.0' // Required -- JUnit 4 framework testImplementation 'junit:junit:4.13.2' @@ -111,6 +112,7 @@ dependencies { // Required for instrumented tests androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' + androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.7.0' androidTestImplementation 'androidx.test.ext:junit:1.2.1' androidTestImplementation 'androidx.test:rules:1.6.1' } diff --git a/app/src/androidTest/java/net/osmtracker/layouts/DeleteLayoutTest.java b/app/src/androidTest/java/net/osmtracker/layouts/DeleteLayoutTest.java index 339caaccb..c1bc2cdbb 100644 --- a/app/src/androidTest/java/net/osmtracker/layouts/DeleteLayoutTest.java +++ b/app/src/androidTest/java/net/osmtracker/layouts/DeleteLayoutTest.java @@ -22,7 +22,7 @@ import net.osmtracker.R; import net.osmtracker.activity.ButtonsPresets; -import net.osmtracker.activity.Preferences; +import net.osmtracker.db.DataHelper; import net.osmtracker.util.CustomLayoutsUtils; import org.junit.After; @@ -98,6 +98,6 @@ public void layoutDeletionTest() { assertFalse(filesAfterDeletion.contains(layoutFileName)); // Check the icons folder was deleted - assertFalse(filesAfterDeletion.contains(layoutName + Preferences.ICONS_DIR_SUFFIX)); + assertFalse(filesAfterDeletion.contains(layoutName + DataHelper.LAYOUTS_ICONS_DIR_SUFFIX)); } } diff --git a/app/src/androidTest/java/net/osmtracker/layouts/DownloadLayoutTest.java b/app/src/androidTest/java/net/osmtracker/layouts/DownloadLayoutTest.java index 7882dbea6..5d7c99d24 100644 --- a/app/src/androidTest/java/net/osmtracker/layouts/DownloadLayoutTest.java +++ b/app/src/androidTest/java/net/osmtracker/layouts/DownloadLayoutTest.java @@ -1,12 +1,9 @@ package net.osmtracker.layouts; -import static androidx.test.espresso.Espresso.onData; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu; import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.scrollTo; import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.PreferenceMatchers.withTitleText; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.isRoot; import static androidx.test.espresso.matcher.ViewMatchers.withId; @@ -17,11 +14,13 @@ import android.Manifest; import android.content.SharedPreferences; -import android.preference.PreferenceManager; import androidx.lifecycle.Lifecycle; +import androidx.preference.PreferenceManager; import androidx.test.core.app.ActivityScenario; import androidx.test.espresso.Espresso; +import androidx.test.espresso.contrib.RecyclerViewActions; +import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.rule.GrantPermissionRule; import net.osmtracker.OSMTracker; @@ -101,7 +100,11 @@ public void navigateToAvailableLayouts() { // Click on "Settings" in this menu onView(withText(TestUtils.getStringResource(R.string.menu_settings))).perform(click()); // Click on "Buttons presets" settings - onData(withTitleText(TestUtils.getStringResource(R.string.prefs_ui_buttons_layout))).perform(scrollTo(), click()); + onView(ViewMatchers.withId(androidx.preference.R.id.recycler_view)) + .perform(RecyclerViewActions.actionOnItem( + ViewMatchers.hasDescendant(withText(R.string.prefs_ui_buttons_layout)), + click() + )); // Wait for "+" to be visible onView(isRoot()).perform(waitForView(R.id.launch_available, WAIT_VIEW_TIMEOUT)); // Perform a click action on the "+" button diff --git a/app/src/androidTest/java/net/osmtracker/util/TestUtils.java b/app/src/androidTest/java/net/osmtracker/util/TestUtils.java index 2c733c75f..18d94d3a2 100644 --- a/app/src/androidTest/java/net/osmtracker/util/TestUtils.java +++ b/app/src/androidTest/java/net/osmtracker/util/TestUtils.java @@ -4,13 +4,13 @@ import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; +import androidx.preference.PreferenceManager; import androidx.test.platform.app.InstrumentationRegistry; import net.osmtracker.OSMTracker; -import net.osmtracker.activity.Preferences; import net.osmtracker.data.Mocks; +import net.osmtracker.db.DataHelper; import java.io.File; import java.io.FileWriter; @@ -66,7 +66,7 @@ public static void injectMockLayout(String layoutName, String ISOLangCode) { writeToFile(newLayout, Mocks.MOCK_LAYOUT_CONTENT); // Create the icons directory - File iconsDir = createDirectory(layoutsDir, layoutName + Preferences.ICONS_DIR_SUFFIX); + File iconsDir = createDirectory(layoutsDir, layoutName + DataHelper.LAYOUTS_ICONS_DIR_SUFFIX); // And put some mock files inside int pngsToCreate = 4; @@ -109,7 +109,7 @@ public static File getAppDirectory(){ */ public static File getLayoutsDirectory(){ String appDirectory = getAppDirectory().getAbsolutePath(); - File layoutsDirectory = new File(appDirectory + File.separator + Preferences.LAYOUTS_SUBDIR); + File layoutsDirectory = new File(appDirectory + File.separator + DataHelper.LAYOUTS_SUBDIR); layoutsDirectory.mkdirs(); return layoutsDirectory; } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4dc8627d4..15271702c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -52,7 +52,9 @@ android:launchMode="singleTop" /> + android:exported="false" + android:label="@string/prefs" + android:theme="@style/AppTheme" /> diff --git a/app/src/main/java/net/osmtracker/activity/About.java b/app/src/main/java/net/osmtracker/activity/About.java index 84aa7804c..9ab141da0 100644 --- a/app/src/main/java/net/osmtracker/activity/About.java +++ b/app/src/main/java/net/osmtracker/activity/About.java @@ -15,12 +15,12 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.os.Environment; -import android.preference.PreferenceManager; import android.view.View; import android.view.View.OnClickListener; -import android.widget.Button; import android.widget.TextView; +import androidx.preference.PreferenceManager; + import java.io.File; /** diff --git a/app/src/main/java/net/osmtracker/activity/AvailableLayouts.java b/app/src/main/java/net/osmtracker/activity/AvailableLayouts.java index eb215767c..c4ad46b18 100644 --- a/app/src/main/java/net/osmtracker/activity/AvailableLayouts.java +++ b/app/src/main/java/net/osmtracker/activity/AvailableLayouts.java @@ -13,7 +13,6 @@ import android.net.NetworkInfo; import android.os.Build; import android.os.Bundle; -import android.preference.PreferenceManager; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -26,6 +25,8 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.preference.PreferenceManager; + import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; diff --git a/app/src/main/java/net/osmtracker/activity/ButtonsPresets.java b/app/src/main/java/net/osmtracker/activity/ButtonsPresets.java index 2d5f864dd..50438c96a 100644 --- a/app/src/main/java/net/osmtracker/activity/ButtonsPresets.java +++ b/app/src/main/java/net/osmtracker/activity/ButtonsPresets.java @@ -11,9 +11,10 @@ import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; -import android.preference.PreferenceManager; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; +import androidx.preference.PreferenceManager; + import android.util.Log; import android.view.ContextMenu; import android.view.Menu; @@ -26,6 +27,7 @@ import net.osmtracker.OSMTracker; import net.osmtracker.R; +import net.osmtracker.db.DataHelper; import net.osmtracker.layout.DownloadCustomLayoutTask; import net.osmtracker.util.CustomLayoutsUtils; import net.osmtracker.util.FileSystemUtils; @@ -41,7 +43,7 @@ public class ButtonsPresets extends Activity { @SuppressWarnings("unused") - private static final String TAG = Preferences.class.getSimpleName(); + private static final String TAG = ButtonsPresets.class.getSimpleName(); final private int RC_WRITE_PERMISSION = 1; @@ -108,7 +110,7 @@ private void initializeAttributes(){ private void listLayouts(LinearLayout rootLayout){ File layoutsDir = new File(this.getExternalFilesDir(null), storageDir + - File.separator + Preferences.LAYOUTS_SUBDIR + File.separator); + File.separator + DataHelper.LAYOUTS_SUBDIR + File.separator); int AT_START = 0; //the position to insert the view at int fontSize = 20; if (layoutsDir.exists() && layoutsDir.canRead()) { @@ -116,7 +118,7 @@ private void listLayouts(LinearLayout rootLayout){ String[] layoutFiles = layoutsDir.list(new FilenameFilter() { @Override public boolean accept(File dir, String filename) { - return filename.endsWith(Preferences.LAYOUT_FILE_EXTENSION); + return filename.endsWith(DataHelper.LAYOUT_FILE_EXTENSION); } }); //Remove all the layouts @@ -272,10 +274,10 @@ protected void onPostExecute(Boolean status){ @Override public void onClick(DialogInterface dialog, int which) { String fileName = layoutsFileNames.get(checkboxHeld.getText()); - String rootDir = storageDir + File.separator + Preferences.LAYOUTS_SUBDIR + File.separator; + String rootDir = storageDir + File.separator + DataHelper.LAYOUTS_SUBDIR + File.separator; File fileToDelete = new File(externalFilesDir, rootDir + fileName); String iconDirName = fileName.substring(0, fileName.length() - CustomLayoutsUtils.LAYOUT_EXTENSION_ISO.length()) - + Preferences.ICONS_DIR_SUFFIX; + + DataHelper.LAYOUTS_ICONS_DIR_SUFFIX; File iconDirToDelete = new File(externalFilesDir, rootDir + iconDirName); boolean successfulDeletion = FileSystemUtils.delete(fileToDelete, false); @@ -312,7 +314,7 @@ public void onClick(DialogInterface dialog, int which) { * Example: given "foo_es.xml" return only "es" */ private String getIso(String layoutName){ - String tmp = layoutName.substring(0, layoutName.length() - Preferences.LAYOUT_FILE_EXTENSION.length()); + String tmp = layoutName.substring(0, layoutName.length() - DataHelper.LAYOUT_FILE_EXTENSION.length()); String iso = ""; for (int i=tmp.length() - AvailableLayouts.ISO_CHARACTER_LENGTH; i { - Intent intent = new Intent(this, ButtonsPresets.class); - startActivity(intent); - return true; - }); + setContentView(R.layout.settings_activity); + if (savedInstanceState == null) { + getSupportFragmentManager() + .beginTransaction() + .replace(R.id.settings, new SettingsFragment()) + .commit(); } + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } + } - // External storage directory - EditTextPreference storageDirPref = (EditTextPreference) findPreference(OSMTracker.Preferences.KEY_STORAGE_DIR); - storageDirPref.setSummary(prefs.getString(OSMTracker.Preferences.KEY_STORAGE_DIR, OSMTracker.Preferences.VAL_STORAGE_DIR)); - storageDirPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // Ensure there is always a leading slash - if (! ((String) newValue).startsWith(File.separator)) { - newValue = File.separator + (String) newValue; + public static class SettingsFragment extends PreferenceFragmentCompat { + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + setPreferencesFromResource(R.xml.preferences, rootKey); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext()); + Preference preference; + + // Voice record duration: set a custom SummaryProvider + preference = findPreference(OSMTracker.Preferences.KEY_VOICEREC_DURATION); + preference.setSummaryProvider(new Preference.SummaryProvider() { + @Override + public CharSequence provideSummary(@NonNull ListPreference preference) { + String currentValue = preference.getEntry().toString(); + // Return your combined string + return currentValue+ " " + + getResources().getString(R.string.prefs_voicerec_duration_seconds); } + }); + + // Clear OSM data: Disable if there's no OSM data stored + preference = findPreference(OSMTracker.Preferences.KEY_OSM_OAUTH_CLEAR_DATA); + preference.setEnabled(prefs.contains(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN)); + // Set a Click Listener to show the confirmation dialog + preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(@NonNull Preference preference) { + new androidx.appcompat.app.AlertDialog.Builder(requireContext()) + .setTitle(preference.getTitle()) + .setMessage(R.string.prefs_osm_clear_oauth_data_dialog) + .setIcon(preference.getIcon()) + .setPositiveButton(android.R.string.ok, (dialog, which) -> { + // User clicked OK: Clear the data + SharedPreferences.Editor editor = prefs.edit(); + editor.remove(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN); + editor.apply(); + + // Disable the button now that data is gone + preference.setEnabled(false); + }) + .setNegativeButton(android.R.string.cancel, null) + .show(); + return true; + } + }); - // Set summary with the directory value - preference.setSummary((String) newValue); - - return true; - } - }); - - // Voice record duration - Preference pref = findPreference(OSMTracker.Preferences.KEY_VOICEREC_DURATION); - pref.setSummary(prefs.getString(OSMTracker.Preferences.KEY_VOICEREC_DURATION, OSMTracker.Preferences.VAL_VOICEREC_DURATION) + " " + getResources().getString(R.string.prefs_voicerec_duration_seconds)); - pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // Set summary with the number of seconds, following by "seconds" - preference.setSummary(newValue+ " " + getResources().getString(R.string.prefs_voicerec_duration_seconds)); - return true; - } - }); - - // Use barometer yes/no - pref = findPreference(OSMTracker.Preferences.KEY_USE_BAROMETER); - pref.setSummary(getResources().getString(R.string.prefs_use_barometer_summary)); - - - // Update GPS logging interval summary to the current value - pref = findPreference(OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL); - pref.setSummary( - prefs.getString(OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL, OSMTracker.Preferences.VAL_GPS_LOGGING_INTERVAL) - + " " + getResources().getString(R.string.prefs_gps_logging_interval_seconds) - + ". " + getResources().getString(R.string.prefs_gps_logging_interval_summary)); - pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // Set summary with the interval and "seconds" - preference.setSummary(newValue - + " " + getResources().getString(R.string.prefs_gps_logging_interval_seconds) - + ". " + getResources().getString(R.string.prefs_gps_logging_interval_summary)); - return true; - } - }); - - // Update GPS min. distance summary to the current value - pref = findPreference(OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE); - pref.setSummary( - prefs.getString(OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE, OSMTracker.Preferences.VAL_GPS_LOGGING_MIN_DISTANCE) - + " " + getResources().getString(R.string.prefs_gps_logging_min_distance_meters) - + ". " + getResources().getString(R.string.prefs_gps_logging_min_distance_summary)); - pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // Set summary with the interval and "seconds" - preference.setSummary(newValue - + " " + getResources().getString(R.string.prefs_gps_logging_min_distance_meters) - + ". " + getResources().getString(R.string.prefs_gps_logging_min_distance_summary)); - return true; - } - }); - - // don't allow the logging_min_distance to be empty - final EditText et = ((EditTextPreference)pref).getEditText(); - final EditTextPreference etp = (EditTextPreference)pref; - et.addTextChangedListener( - new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - if (s.length() >= 0) { - try { - Button bt_ok = ((AlertDialog) etp.getDialog()).getButton(AlertDialog.BUTTON_POSITIVE); - if (s.length() == 0) { - bt_ok.setEnabled(false); - } else { - ((AlertDialog) etp.getDialog()).getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true); - } - } catch (Exception ex) { - } - } + // GPS Settings + + preference = findPreference(OSMTracker.Preferences.KEY_GPS_OSSETTINGS); + preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(@NonNull Preference preference) { + startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); + return true; + } + }); + + // Update GPS logging interval summary to the current value + preference = findPreference(OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL); + preference.setSummary( + prefs.getString(OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL, OSMTracker.Preferences.VAL_GPS_LOGGING_INTERVAL) + + " " + getResources().getString(R.string.prefs_gps_logging_interval_seconds) + + ". " + getResources().getString(R.string.prefs_gps_logging_interval_summary)); + preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { + String val = (String) newValue; + // don't allow the logging_min_distance to be empty + if (TextUtils.isEmpty(val)) { + Toast.makeText(requireContext(), R.string.prefs_gps_logging_interval_empty, Toast.LENGTH_SHORT).show(); + return false; // Don't save + } else { + // Set summary with the interval and "seconds" + preference.setSummary(newValue + + " " + getResources().getString(R.string.prefs_gps_logging_interval_seconds) + + ". " + getResources().getString(R.string.prefs_gps_logging_interval_summary)); + return true; } + } + }); + + // Update GPS min. distance summary to the current value + preference = findPreference(OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE); + preference.setSummary( + prefs.getString(OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE, OSMTracker.Preferences.VAL_GPS_LOGGING_MIN_DISTANCE) + + " " + getResources().getString(R.string.prefs_gps_logging_min_distance_meters) + + ". " + getResources().getString(R.string.prefs_gps_logging_min_distance_summary)); + preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { + // Set summary with the interval and "seconds" + preference.setSummary(newValue + + " " + getResources().getString(R.string.prefs_gps_logging_min_distance_meters) + + ". " + getResources().getString(R.string.prefs_gps_logging_min_distance_summary)); + return true; + } + }); + + - @Override - public void afterTextChanged(Editable s) { + //GPX Settings + + // External storage directory + EditTextPreference storageDirPref = (EditTextPreference) findPreference(OSMTracker.Preferences.KEY_STORAGE_DIR); + storageDirPref.setSummary(prefs.getString(OSMTracker.Preferences.KEY_STORAGE_DIR, OSMTracker.Preferences.VAL_STORAGE_DIR)); + storageDirPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { + // Ensure there is always a leading slash + if (! ((String) newValue).startsWith(File.separator)) { + newValue = File.separator + (String) newValue; } + + // Set summary with the directory value + preference.setSummary((String) newValue); + + return true; + }}); + + // Explicit execution of buttons presets window + preference = findPreference(OSMTracker.Preferences.KEY_UI_BUTTONS_LAYOUT); + preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener(){ + @Override + public boolean onPreferenceClick(@NonNull Preference preference) { + startActivity(new Intent(requireContext(), ButtonsPresets.class)); + return true; } - ); - - pref = findPreference(OSMTracker.Preferences.KEY_GPS_OSSETTINGS); - pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); - return true; - } - }); - - // Button screen orientation option - pref = findPreference(OSMTracker.Preferences.KEY_UI_ORIENTATION); - ListPreference orientationListPreference = (ListPreference) pref; - String displayValueKey = prefs.getString(OSMTracker.Preferences.KEY_UI_ORIENTATION, OSMTracker.Preferences.VAL_UI_ORIENTATION); - int displayValueIndex = orientationListPreference.findIndexOfValue(displayValueKey); - String displayValue = orientationListPreference.getEntries()[displayValueIndex].toString(); - orientationListPreference.setSummary(displayValue + ".\n" - + getResources().getString(R.string.prefs_ui_orientation_summary)); - - // Set a listener to update the preference display after a change is made - pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // Set summary with the display text of the item and a description of the preference - ListPreference orientationListPreference = (ListPreference)preference; - // Pull the display string from the list preference rather than simply using the key value - int newValueIndex = orientationListPreference.findIndexOfValue((String)newValue); - String newPreferenceDisplayValue = orientationListPreference.getEntries()[newValueIndex].toString(); - - preference.setSummary(newPreferenceDisplayValue - + ".\n" + getResources().getString(R.string.prefs_ui_orientation_summary)); - return true; - } - }); - - // Clear OSM data: Disable if there's no OSM data stored - pref = findPreference(OSMTracker.Preferences.KEY_OSM_OAUTH_CLEAR_DATA); - if (prefs.contains(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN)) { - pref.setEnabled(true); - } else { - pref.setEnabled(false); - } - pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // Clear data - Editor editor = prefs.edit(); - editor.remove(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN); - editor.commit(); - - preference.setEnabled(false); - return false; - } - }); + }); + + // Button screen orientation option + preference = findPreference(OSMTracker.Preferences.KEY_UI_ORIENTATION); + ListPreference orientationListPreference = (ListPreference) preference; + String displayValueKey = prefs.getString(OSMTracker.Preferences.KEY_UI_ORIENTATION, OSMTracker.Preferences.VAL_UI_ORIENTATION); + int displayValueIndex = orientationListPreference.findIndexOfValue(displayValueKey); + String displayValue = orientationListPreference.getEntries()[displayValueIndex].toString(); + orientationListPreference.setSummary(displayValue + ".\n" + + getResources().getString(R.string.prefs_ui_orientation_summary)); + // Set a listener to update the preference display after a change is made + preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { + // Set summary with the display text of the item and a description of the preference + ListPreference orientationListPreference = (ListPreference) preference; + // Pull the display string from the list preference rather than simply using the key value + int newValueIndex = orientationListPreference.findIndexOfValue((String)newValue); + String newPreferenceDisplayValue = orientationListPreference.getEntries()[newValueIndex].toString(); + + preference.setSummary(newPreferenceDisplayValue + + ".\n" + getResources().getString(R.string.prefs_ui_orientation_summary)); + return true; + }}); + + } } - -} +} \ No newline at end of file diff --git a/app/src/main/java/net/osmtracker/activity/TrackDetail.java b/app/src/main/java/net/osmtracker/activity/TrackDetail.java index 5cb640f0c..d73a40949 100644 --- a/app/src/main/java/net/osmtracker/activity/TrackDetail.java +++ b/app/src/main/java/net/osmtracker/activity/TrackDetail.java @@ -24,9 +24,10 @@ import android.graphics.Paint; import android.os.Build; import android.os.Bundle; -import android.preference.PreferenceManager; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; +import androidx.preference.PreferenceManager; + import android.util.Log; import android.view.Menu; import android.view.MenuInflater; diff --git a/app/src/main/java/net/osmtracker/activity/TrackLogger.java b/app/src/main/java/net/osmtracker/activity/TrackLogger.java index 0cbb5f405..45c4a1f34 100644 --- a/app/src/main/java/net/osmtracker/activity/TrackLogger.java +++ b/app/src/main/java/net/osmtracker/activity/TrackLogger.java @@ -20,7 +20,6 @@ import android.net.Uri; import android.os.Bundle; import android.os.StrictMode; -import android.preference.PreferenceManager; import android.provider.MediaStore; import android.provider.Settings; import android.util.Log; @@ -36,6 +35,7 @@ import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; +import androidx.preference.PreferenceManager; import net.osmtracker.OSMTracker; import net.osmtracker.R; @@ -313,7 +313,7 @@ protected void onResume() { File layoutFile = new File( this.getExternalFilesDir(null), OSMTracker.Preferences.VAL_STORAGE_DIR - + File.separator + Preferences.LAYOUTS_SUBDIR + + File.separator + DataHelper.LAYOUTS_SUBDIR + File.separator + userLayout); mainLayout = new UserDefinedLayout(this, currentTrackId, layoutFile); } diff --git a/app/src/main/java/net/osmtracker/activity/TrackManager.java b/app/src/main/java/net/osmtracker/activity/TrackManager.java index f4d6ca9e6..10a7b40e9 100644 --- a/app/src/main/java/net/osmtracker/activity/TrackManager.java +++ b/app/src/main/java/net/osmtracker/activity/TrackManager.java @@ -1,11 +1,11 @@ package net.osmtracker.activity; -import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; +import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -17,13 +17,11 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.preference.PreferenceManager; import android.util.Base64OutputStream; import android.util.Log; import android.view.ContextMenu; @@ -53,8 +51,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.file.Files; -import java.util.Base64; import java.util.Date; /** diff --git a/app/src/main/java/net/osmtracker/db/DataHelper.java b/app/src/main/java/net/osmtracker/db/DataHelper.java index aafdbb751..fa50d8a56 100644 --- a/app/src/main/java/net/osmtracker/db/DataHelper.java +++ b/app/src/main/java/net/osmtracker/db/DataHelper.java @@ -8,10 +8,10 @@ import android.database.Cursor; import android.location.Location; import android.net.Uri; -import android.os.Environment; -import android.preference.PreferenceManager; import android.util.Log; +import androidx.preference.PreferenceManager; + import net.osmtracker.OSMTracker; import net.osmtracker.db.model.Track; import net.osmtracker.db.model.TrackPoint; @@ -53,6 +53,12 @@ public class DataHelper { */ public static final String EXTENSION_ZIP = ".zip"; + /** + * File extension for layout files + */ + + public static final String LAYOUT_FILE_EXTENSION = ".xml"; + /** * GPX Files MIME standard for sharing */ @@ -68,6 +74,19 @@ public class DataHelper { */ public static final String MIME_TYPE_IMAGE = "image/*"; + /** + * Directory containing user layouts, relative to storage dir. + */ + public static final String LAYOUTS_SUBDIR = "layouts"; + + /** + * The suffix that must be added to the layout's name for getting its icons directory + * Example: water_supply <- layout name + * water_supply_icons <- icon directory + */ + + public static final String LAYOUTS_ICONS_DIR_SUFFIX = "_icons"; + /** * APP sign plus FileProvider = authority */ diff --git a/app/src/main/java/net/osmtracker/gpx/ExportToStorageTask.java b/app/src/main/java/net/osmtracker/gpx/ExportToStorageTask.java index 855929f85..347bf3467 100644 --- a/app/src/main/java/net/osmtracker/gpx/ExportToStorageTask.java +++ b/app/src/main/java/net/osmtracker/gpx/ExportToStorageTask.java @@ -5,9 +5,10 @@ import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; -import android.preference.PreferenceManager; import android.util.Log; +import androidx.preference.PreferenceManager; + import net.osmtracker.OSMTracker; import net.osmtracker.R; import net.osmtracker.db.DataHelper; diff --git a/app/src/main/java/net/osmtracker/gpx/ExportToTempFileTask.java b/app/src/main/java/net/osmtracker/gpx/ExportToTempFileTask.java index fdc971180..61369fca4 100644 --- a/app/src/main/java/net/osmtracker/gpx/ExportToTempFileTask.java +++ b/app/src/main/java/net/osmtracker/gpx/ExportToTempFileTask.java @@ -2,9 +2,10 @@ import android.content.Context; import android.database.Cursor; -import android.preference.PreferenceManager; import android.util.Log; +import androidx.preference.PreferenceManager; + import net.osmtracker.OSMTracker; import net.osmtracker.db.DataHelper; import net.osmtracker.exception.ExportTrackException; diff --git a/app/src/main/java/net/osmtracker/gpx/ExportTrackTask.java b/app/src/main/java/net/osmtracker/gpx/ExportTrackTask.java index a9dec64da..c54faa2a3 100644 --- a/app/src/main/java/net/osmtracker/gpx/ExportTrackTask.java +++ b/app/src/main/java/net/osmtracker/gpx/ExportTrackTask.java @@ -10,7 +10,6 @@ import android.database.Cursor; import android.media.MediaScannerConnection; import android.os.AsyncTask; -import android.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; @@ -36,6 +35,8 @@ import static net.osmtracker.db.DataHelper.EXTENSION_GPX; import static net.osmtracker.util.FileSystemUtils.getUniqueChildNameFor; +import androidx.preference.PreferenceManager; + /** * Base class to writes a GPX file and export * track media (Photos, Sounds) diff --git a/app/src/main/java/net/osmtracker/layout/DownloadCustomLayoutTask.java b/app/src/main/java/net/osmtracker/layout/DownloadCustomLayoutTask.java index 2c4048aa5..525c34447 100644 --- a/app/src/main/java/net/osmtracker/layout/DownloadCustomLayoutTask.java +++ b/app/src/main/java/net/osmtracker/layout/DownloadCustomLayoutTask.java @@ -4,9 +4,10 @@ import android.content.SharedPreferences; import android.os.AsyncTask; import android.os.Environment; -import android.preference.PreferenceManager; import android.util.Log; +import androidx.preference.PreferenceManager; + import org.json.JSONArray; import org.json.JSONObject; import net.osmtracker.OSMTracker; @@ -21,7 +22,7 @@ import java.util.Set; import net.osmtracker.R; -import net.osmtracker.activity.Preferences; +import net.osmtracker.db.DataHelper; import net.osmtracker.util.CustomLayoutsUtils; import net.osmtracker.util.URLCreator; @@ -55,11 +56,11 @@ public boolean downloadLayout(String layoutName, String iso){ String layoutURL = URLCreator.createLayoutFileURL(context, layoutFolderName, iso); String layoutPath = context.getExternalFilesDir(null) + storageDir + File.separator + - Preferences.LAYOUTS_SUBDIR + File.separator; + DataHelper.LAYOUTS_SUBDIR + File.separator; //TODO: change "_icons" for Preferences.ICONS_DIR_SUFFIX String iconsPath = context.getExternalFilesDir(null) + storageDir + File.separator + - Preferences.LAYOUTS_SUBDIR + File.separator + layoutFolderName+"_icons" + + DataHelper.LAYOUTS_SUBDIR + File.separator + layoutFolderName+"_icons" + File.separator; Boolean status = false; diff --git a/app/src/main/java/net/osmtracker/layout/GpsStatusRecord.java b/app/src/main/java/net/osmtracker/layout/GpsStatusRecord.java index f2b264d9d..3afd60bc5 100644 --- a/app/src/main/java/net/osmtracker/layout/GpsStatusRecord.java +++ b/app/src/main/java/net/osmtracker/layout/GpsStatusRecord.java @@ -16,10 +16,11 @@ import android.location.LocationManager; import android.location.LocationProvider; import android.os.Bundle; -import android.preference.PreferenceManager; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; +import androidx.preference.PreferenceManager; + import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; diff --git a/app/src/main/java/net/osmtracker/osm/UploadToOpenStreetMapTask.java b/app/src/main/java/net/osmtracker/osm/UploadToOpenStreetMapTask.java index f78c80b9f..46d2c4a63 100644 --- a/app/src/main/java/net/osmtracker/osm/UploadToOpenStreetMapTask.java +++ b/app/src/main/java/net/osmtracker/osm/UploadToOpenStreetMapTask.java @@ -6,9 +6,10 @@ import android.content.DialogInterface; import android.content.SharedPreferences.Editor; import android.os.AsyncTask; -import android.preference.PreferenceManager; import android.util.Log; +import androidx.preference.PreferenceManager; + import net.osmtracker.OSMTracker; import net.osmtracker.R; import net.osmtracker.db.DataHelper; diff --git a/app/src/main/java/net/osmtracker/service/gps/GPSLogger.java b/app/src/main/java/net/osmtracker/service/gps/GPSLogger.java index fb785d279..a6a735fb2 100644 --- a/app/src/main/java/net/osmtracker/service/gps/GPSLogger.java +++ b/app/src/main/java/net/osmtracker/service/gps/GPSLogger.java @@ -18,11 +18,11 @@ import android.os.Build; import android.os.Bundle; import android.os.IBinder; -import android.preference.PreferenceManager; import android.util.Log; import androidx.core.app.NotificationCompat; import androidx.core.content.ContextCompat; +import androidx.preference.PreferenceManager; import net.osmtracker.OSMTracker; import net.osmtracker.R; diff --git a/app/src/main/java/net/osmtracker/util/CustomLayoutsUtils.java b/app/src/main/java/net/osmtracker/util/CustomLayoutsUtils.java index b07f7884f..6e27b27ce 100644 --- a/app/src/main/java/net/osmtracker/util/CustomLayoutsUtils.java +++ b/app/src/main/java/net/osmtracker/util/CustomLayoutsUtils.java @@ -2,11 +2,12 @@ import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; + +import androidx.preference.PreferenceManager; import net.osmtracker.OSMTracker; import net.osmtracker.activity.AvailableLayouts; -import net.osmtracker.activity.Preferences; +import net.osmtracker.db.DataHelper; import net.osmtracker.layout.GetStringResponseTask; import java.io.BufferedReader; @@ -32,7 +33,7 @@ public class CustomLayoutsUtils { */ public static String convertFileName(String fileName) { //Remove de file extension - String subname = fileName.replace(Preferences.LAYOUT_FILE_EXTENSION,""); + String subname = fileName.replace(DataHelper.LAYOUT_FILE_EXTENSION,""); //Check if it has iso: if(subname.matches("\\w+_..")){ @@ -49,7 +50,7 @@ public static String convertFileName(String fileName) { * @return Layout filename. */ public static String unconvertFileName(String representation){ - return representation.replace(" ","_") + Preferences.LAYOUT_FILE_EXTENSION; + return representation.replace(" ","_") + DataHelper.LAYOUT_FILE_EXTENSION; } /** diff --git a/app/src/main/java/net/osmtracker/util/URLCreator.java b/app/src/main/java/net/osmtracker/util/URLCreator.java index e87f5d81e..d50ee82e7 100644 --- a/app/src/main/java/net/osmtracker/util/URLCreator.java +++ b/app/src/main/java/net/osmtracker/util/URLCreator.java @@ -2,9 +2,11 @@ import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; + +import androidx.preference.PreferenceManager; + import net.osmtracker.OSMTracker; -import net.osmtracker.activity.Preferences; +import net.osmtracker.db.DataHelper; /** * Created by labexp on 13/12/17. @@ -66,7 +68,7 @@ public static String createLayoutFileURL(Context context, String layoutFolderNam String[] ghParams = getGithubParams(context); String url = RAW_CONTENT + ghParams[USERNAME] + "/" + ghParams[REPO] + "/" + ghParams[BRANCH] - + "/layouts/" + layoutFolderName + "/" + iso + Preferences.LAYOUT_FILE_EXTENSION; + + "/layouts/" + layoutFolderName + "/" + iso + DataHelper.LAYOUT_FILE_EXTENSION; return url; } diff --git a/app/src/main/java/net/osmtracker/view/VoiceRecDialog.java b/app/src/main/java/net/osmtracker/view/VoiceRecDialog.java index 97018ffc0..f50e8f373 100644 --- a/app/src/main/java/net/osmtracker/view/VoiceRecDialog.java +++ b/app/src/main/java/net/osmtracker/view/VoiceRecDialog.java @@ -10,11 +10,12 @@ import android.media.MediaRecorder; import android.media.MediaRecorder.OnInfoListener; import android.os.SystemClock; -import android.preference.PreferenceManager; import android.util.Log; import android.view.KeyEvent; import android.widget.Toast; +import androidx.preference.PreferenceManager; + import net.osmtracker.OSMTracker; import net.osmtracker.R; import net.osmtracker.db.DataHelper; diff --git a/app/src/main/res/layout/settings_activity.xml b/app/src/main/res/layout/settings_activity.xml new file mode 100644 index 000000000..de6591a20 --- /dev/null +++ b/app/src/main/res/layout/settings_activity.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index 32f528bf6..580b3d717 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -21,6 +21,7 @@ GPS logging interval Use 0 for the shortest possible (affects battery life) seconds + GPS logging interval cannot be empty GPS logging distance Min. distance between track points in meters, use 0 for the shortest possible diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index cbb191bbd..12b32f2e2 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -1,133 +1,146 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/test/java/net/osmtracker/activity/ButtonsPresetsTest.java b/app/src/test/java/net/osmtracker/activity/ButtonsPresetsTest.java index 07c7b5f6b..0786ac9d5 100644 --- a/app/src/test/java/net/osmtracker/activity/ButtonsPresetsTest.java +++ b/app/src/test/java/net/osmtracker/activity/ButtonsPresetsTest.java @@ -5,7 +5,6 @@ import android.content.Context; import android.content.res.Resources; import android.os.Environment; -import android.preference.PreferenceManager; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; @@ -33,6 +32,8 @@ import static org.powermock.api.mockito.PowerMockito.verifyPrivate; import static org.powermock.api.mockito.PowerMockito.when; +import androidx.preference.PreferenceManager; + @RunWith(PowerMockRunner.class) @PowerMockIgnore("jdk.internal.reflect.*") public class ButtonsPresetsTest { diff --git a/app/src/test/java/net/osmtracker/gpx/ExportToStorageTaskTest.java b/app/src/test/java/net/osmtracker/gpx/ExportToStorageTaskTest.java index 2bd6f8775..59b5b8013 100644 --- a/app/src/test/java/net/osmtracker/gpx/ExportToStorageTaskTest.java +++ b/app/src/test/java/net/osmtracker/gpx/ExportToStorageTaskTest.java @@ -21,7 +21,8 @@ import android.content.res.Resources; import android.database.Cursor; import android.os.Environment; -import android.preference.PreferenceManager; + +import androidx.preference.PreferenceManager; import net.osmtracker.OSMTracker; import net.osmtracker.R; diff --git a/app/src/test/java/net/osmtracker/layout/DownloadCustomLayoutTaskTest.java b/app/src/test/java/net/osmtracker/layout/DownloadCustomLayoutTaskTest.java index f0f3334c1..9410e7c21 100644 --- a/app/src/test/java/net/osmtracker/layout/DownloadCustomLayoutTaskTest.java +++ b/app/src/test/java/net/osmtracker/layout/DownloadCustomLayoutTaskTest.java @@ -3,11 +3,10 @@ import android.content.Context; import android.content.SharedPreferences; import android.os.Environment; -import android.preference.PreferenceManager; import android.util.Log; import net.osmtracker.OSMTracker; -import net.osmtracker.activity.Preferences; +import net.osmtracker.db.DataHelper; import net.osmtracker.util.UnitTestUtils; import org.junit.Test; @@ -24,6 +23,8 @@ import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; +import androidx.preference.PreferenceManager; + @RunWith(PowerMockRunner.class) @PrepareForTest({PreferenceManager.class, Environment.class, Log.class}) @PowerMockIgnore("jdk.internal.reflect.*") @@ -68,7 +69,7 @@ public void downloadLayoutWithoutIconsTest() { // Check if layout was downloaded at .../osmtracker/layouts/abc_en.xml String expectedLayoutFilePath = mockContext.getExternalFilesDir(null) + OSMTracker.Preferences.VAL_STORAGE_DIR + File.separator - + Preferences.LAYOUTS_SUBDIR + File.separator + + DataHelper.LAYOUTS_SUBDIR + File.separator + expectedLayoutFilename; System.out.println(expectedLayoutFilePath); diff --git a/app/src/test/java/net/osmtracker/util/CustomLayoutsUtilsTest.java b/app/src/test/java/net/osmtracker/util/CustomLayoutsUtilsTest.java index 0d0a2efaa..05faea75e 100644 --- a/app/src/test/java/net/osmtracker/util/CustomLayoutsUtilsTest.java +++ b/app/src/test/java/net/osmtracker/util/CustomLayoutsUtilsTest.java @@ -3,7 +3,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.AssetManager; -import android.preference.PreferenceManager; import net.osmtracker.OSMTracker; @@ -26,6 +25,8 @@ import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; +import androidx.preference.PreferenceManager; + @RunWith(PowerMockRunner.class) @PrepareForTest(PreferenceManager.class) @PowerMockIgnore("jdk.internal.reflect.*") diff --git a/app/src/test/java/net/osmtracker/util/ThemeValidatorTest.java b/app/src/test/java/net/osmtracker/util/ThemeValidatorTest.java index 7072e3966..8eeedd0a8 100644 --- a/app/src/test/java/net/osmtracker/util/ThemeValidatorTest.java +++ b/app/src/test/java/net/osmtracker/util/ThemeValidatorTest.java @@ -2,7 +2,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.Resources; -import android.preference.PreferenceManager; import android.content.SharedPreferences.Editor; import net.osmtracker.OSMTracker; @@ -21,6 +20,8 @@ import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; +import androidx.preference.PreferenceManager; + @RunWith(PowerMockRunner.class) @PrepareForTest(PreferenceManager.class) diff --git a/app/src/test/java/net/osmtracker/util/URLCreatorTest.java b/app/src/test/java/net/osmtracker/util/URLCreatorTest.java index 001366bea..4b4888f9a 100644 --- a/app/src/test/java/net/osmtracker/util/URLCreatorTest.java +++ b/app/src/test/java/net/osmtracker/util/URLCreatorTest.java @@ -2,7 +2,6 @@ import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; import org.junit.Test; import org.junit.runner.RunWith; @@ -15,6 +14,8 @@ import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; +import androidx.preference.PreferenceManager; + @RunWith(PowerMockRunner.class) @PrepareForTest(PreferenceManager.class) From e7d63266cc9ff70482820081846be9a74e0d04f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Sun, 28 Dec 2025 09:01:47 -0600 Subject: [PATCH 23/60] Fix: Add validation in GPS logging interval and GPS logging distance --- .../net/osmtracker/activity/Preferences.java | 97 ++++++++++++------- .../main/res/values/strings-preferences.xml | 1 + 2 files changed, 64 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/net/osmtracker/activity/Preferences.java b/app/src/main/java/net/osmtracker/activity/Preferences.java index b77d18005..6e5b31005 100644 --- a/app/src/main/java/net/osmtracker/activity/Preferences.java +++ b/app/src/main/java/net/osmtracker/activity/Preferences.java @@ -100,45 +100,74 @@ public boolean onPreferenceClick(@NonNull Preference preference) { }); // Update GPS logging interval summary to the current value - preference = findPreference(OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL); - preference.setSummary( - prefs.getString(OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL, OSMTracker.Preferences.VAL_GPS_LOGGING_INTERVAL) - + " " + getResources().getString(R.string.prefs_gps_logging_interval_seconds) - + ". " + getResources().getString(R.string.prefs_gps_logging_interval_summary)); - preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { - String val = (String) newValue; - // don't allow the logging_min_distance to be empty - if (TextUtils.isEmpty(val)) { - Toast.makeText(requireContext(), R.string.prefs_gps_logging_interval_empty, Toast.LENGTH_SHORT).show(); - return false; // Don't save - } else { - // Set summary with the interval and "seconds" - preference.setSummary(newValue + EditTextPreference GPSLoggingInterval = findPreference(OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL); + if (GPSLoggingInterval != null) { + + GPSLoggingInterval.setSummary( + prefs.getString( + OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL, OSMTracker.Preferences.VAL_GPS_LOGGING_INTERVAL) + " " + getResources().getString(R.string.prefs_gps_logging_interval_seconds) + ". " + getResources().getString(R.string.prefs_gps_logging_interval_summary)); - return true; + + GPSLoggingInterval.setOnBindEditTextListener(editText -> { + // forces the dialog to only accept numbers + editText.setInputType(android.text.InputType.TYPE_CLASS_NUMBER); + // move cursor to the end of the text + editText.setSelection(editText.getText().length()); + }); + + GPSLoggingInterval.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { + String val = (String) newValue; + // don't allow the logging_min_distance to be empty + if (TextUtils.isEmpty(val)) { + Toast.makeText(requireContext(), R.string.prefs_gps_logging_interval_empty, Toast.LENGTH_SHORT).show(); + return false; // Don't save + } else { + // Set summary with the interval and "seconds" + preference.setSummary(newValue + + " " + getResources().getString(R.string.prefs_gps_logging_interval_seconds) + + ". " + getResources().getString(R.string.prefs_gps_logging_interval_summary)); + return true; + } } - } - }); + }); + } // Update GPS min. distance summary to the current value - preference = findPreference(OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE); - preference.setSummary( - prefs.getString(OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE, OSMTracker.Preferences.VAL_GPS_LOGGING_MIN_DISTANCE) - + " " + getResources().getString(R.string.prefs_gps_logging_min_distance_meters) - + ". " + getResources().getString(R.string.prefs_gps_logging_min_distance_summary)); - preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { - // Set summary with the interval and "seconds" - preference.setSummary(newValue - + " " + getResources().getString(R.string.prefs_gps_logging_min_distance_meters) - + ". " + getResources().getString(R.string.prefs_gps_logging_min_distance_summary)); - return true; - } - }); + EditTextPreference GPSLoggingMinDistance = findPreference(OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE); + if (GPSLoggingMinDistance != null) { + GPSLoggingMinDistance.setSummary( + prefs.getString(OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE, OSMTracker.Preferences.VAL_GPS_LOGGING_MIN_DISTANCE) + + " " + getResources().getString(R.string.prefs_gps_logging_min_distance_meters) + + ". " + getResources().getString(R.string.prefs_gps_logging_min_distance_summary)); + + GPSLoggingMinDistance.setOnBindEditTextListener(editText -> { + // forces the dialog to only accept numbers + editText.setInputType(android.text.InputType.TYPE_CLASS_NUMBER); + // move cursor to the end of the text + editText.setSelection(editText.getText().length()); + }); + + GPSLoggingMinDistance.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { + String val = (String) newValue; + // don't allow the logging_min_distance to be empty + if (TextUtils.isEmpty(val)) { + Toast.makeText(requireContext(), R.string.prefs_gps_logging_min_distance_meters_empty, Toast.LENGTH_SHORT).show(); + return false; // Don't save + } else { + // Set summary with the interval and "seconds" + preference.setSummary(newValue + + " " + getResources().getString(R.string.prefs_gps_logging_min_distance_meters) + + ". " + getResources().getString(R.string.prefs_gps_logging_min_distance_summary)); + return true; + } + } + }); + } diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index 580b3d717..427d9565c 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -26,6 +26,7 @@ GPS logging distance Min. distance between track points in meters, use 0 for the shortest possible meters + Min. distance between track points cannot be empty User interface From b5676fcb33b8745bf3027934db299385c5cd22c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Mon, 29 Dec 2025 08:08:30 -0600 Subject: [PATCH 24/60] Refactor: Improve code formatting and readability in Preferences.java --- .../net/osmtracker/activity/Preferences.java | 346 ++++++++++-------- .../main/res/values/strings-preferences.xml | 3 +- 2 files changed, 187 insertions(+), 162 deletions(-) diff --git a/app/src/main/java/net/osmtracker/activity/Preferences.java b/app/src/main/java/net/osmtracker/activity/Preferences.java index 6e5b31005..08107acbd 100644 --- a/app/src/main/java/net/osmtracker/activity/Preferences.java +++ b/app/src/main/java/net/osmtracker/activity/Preferences.java @@ -6,7 +6,6 @@ import android.text.TextUtils; import android.widget.Toast; -import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.preference.EditTextPreference; @@ -19,6 +18,7 @@ import net.osmtracker.R; import java.io.File; +import java.util.Objects; /** * Manages preferences screen @@ -45,185 +45,209 @@ public static class SettingsFragment extends PreferenceFragmentCompat { @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.preferences, rootKey); + SharedPreferences prefs = + PreferenceManager.getDefaultSharedPreferences(requireContext()); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext()); - Preference preference; - - // Voice record duration: set a custom SummaryProvider - preference = findPreference(OSMTracker.Preferences.KEY_VOICEREC_DURATION); - preference.setSummaryProvider(new Preference.SummaryProvider() { - @Override - public CharSequence provideSummary(@NonNull ListPreference preference) { - String currentValue = preference.getEntry().toString(); - // Return your combined string - return currentValue+ " " - + getResources().getString(R.string.prefs_voicerec_duration_seconds); + setupVoiceRecDuration(); + setupOSMAuthClearData(prefs); + + + // GPS Settings + setupGPSOSSettings(); + // GPSLogging Interval + setupEditTextNum( + OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL, + getString(R.string.prefs_gps_logging_interval_seconds), + getString(R.string.prefs_gps_logging_interval_summary), + getString(R.string.prefs_gps_logging_interval_empty) + ); + //GPS Logging Min Distance + setupEditTextNum( + OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE, + getString(R.string.prefs_gps_logging_min_distance_meters), + getString(R.string.prefs_gps_logging_min_distance_summary), + getString(R.string.prefs_gps_logging_min_distance_empty) + ); + + + //GPX Settings + setupStorageDirectory(); + setupButtonsLayout(); + setupButtonScreenOrientation(); + + } + + /** + * Explicit execution of buttons presets window + */ + private void setupButtonsLayout() { + + Preference UIButtonsLayout = findPreference( + OSMTracker.Preferences.KEY_UI_BUTTONS_LAYOUT); + if (UIButtonsLayout == null) return; + UIButtonsLayout.setOnPreferenceClickListener(preference -> { + startActivity(new Intent(requireContext(), ButtonsPresets.class)); + return true; + }); + } + + /** + * + */ + private void setupStorageDirectory() { + // External storage directory + EditTextPreference storageDirPref = findPreference( + OSMTracker.Preferences.KEY_STORAGE_DIR); + + if (storageDirPref == null) return; + + // Set summary provider + storageDirPref.setSummaryProvider(preference -> { + String val = storageDirPref.getText(); + if (TextUtils.isEmpty(val)) { + return OSMTracker.Preferences.VAL_STORAGE_DIR; } + return val; }); - // Clear OSM data: Disable if there's no OSM data stored - preference = findPreference(OSMTracker.Preferences.KEY_OSM_OAUTH_CLEAR_DATA); - preference.setEnabled(prefs.contains(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN)); - // Set a Click Listener to show the confirmation dialog - preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(@NonNull Preference preference) { - new androidx.appcompat.app.AlertDialog.Builder(requireContext()) - .setTitle(preference.getTitle()) - .setMessage(R.string.prefs_osm_clear_oauth_data_dialog) - .setIcon(preference.getIcon()) - .setPositiveButton(android.R.string.ok, (dialog, which) -> { - // User clicked OK: Clear the data - SharedPreferences.Editor editor = prefs.edit(); - editor.remove(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN); - editor.apply(); - - // Disable the button now that data is gone - preference.setEnabled(false); - }) - .setNegativeButton(android.R.string.cancel, null) - .show(); - return true; + // Enforce the leading slash + storageDirPref.setOnPreferenceChangeListener((preference, newValue) -> { + String val = newValue.toString().trim(); + // Empty + if (TextUtils.isEmpty(val)) { + Toast.makeText(requireContext(), + R.string.prefs_storage_dir_empty, + Toast.LENGTH_SHORT).show(); + return false; } + + // Ensure there is always a leading slash + if (!val.startsWith(File.separator)) { + String fixedVal = File.separator + val; + ((EditTextPreference) preference).setText(fixedVal); + return false; //ignores the user input + } + + return true; }); + } + /** + * Open Android GPS Settings screen + */ + private void setupGPSOSSettings() { + Preference GPSOSSettings = findPreference(OSMTracker.Preferences.KEY_GPS_OSSETTINGS); - // GPS Settings + if (GPSOSSettings == null) return; - preference = findPreference(OSMTracker.Preferences.KEY_GPS_OSSETTINGS); - preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(@NonNull Preference preference) { - startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); - return true; - } + GPSOSSettings.setOnPreferenceClickListener(preference -> { + startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); + return true; }); + } - // Update GPS logging interval summary to the current value - EditTextPreference GPSLoggingInterval = findPreference(OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL); - if (GPSLoggingInterval != null) { - - GPSLoggingInterval.setSummary( - prefs.getString( - OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL, OSMTracker.Preferences.VAL_GPS_LOGGING_INTERVAL) - + " " + getResources().getString(R.string.prefs_gps_logging_interval_seconds) - + ". " + getResources().getString(R.string.prefs_gps_logging_interval_summary)); - - GPSLoggingInterval.setOnBindEditTextListener(editText -> { - // forces the dialog to only accept numbers - editText.setInputType(android.text.InputType.TYPE_CLASS_NUMBER); - // move cursor to the end of the text - editText.setSelection(editText.getText().length()); - }); - - GPSLoggingInterval.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { - String val = (String) newValue; - // don't allow the logging_min_distance to be empty - if (TextUtils.isEmpty(val)) { - Toast.makeText(requireContext(), R.string.prefs_gps_logging_interval_empty, Toast.LENGTH_SHORT).show(); - return false; // Don't save - } else { - // Set summary with the interval and "seconds" - preference.setSummary(newValue - + " " + getResources().getString(R.string.prefs_gps_logging_interval_seconds) - + ". " + getResources().getString(R.string.prefs_gps_logging_interval_summary)); - return true; - } - } - }); - } - - // Update GPS min. distance summary to the current value - EditTextPreference GPSLoggingMinDistance = findPreference(OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE); - if (GPSLoggingMinDistance != null) { - GPSLoggingMinDistance.setSummary( - prefs.getString(OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE, OSMTracker.Preferences.VAL_GPS_LOGGING_MIN_DISTANCE) - + " " + getResources().getString(R.string.prefs_gps_logging_min_distance_meters) - + ". " + getResources().getString(R.string.prefs_gps_logging_min_distance_summary)); - - GPSLoggingMinDistance.setOnBindEditTextListener(editText -> { - // forces the dialog to only accept numbers - editText.setInputType(android.text.InputType.TYPE_CLASS_NUMBER); - // move cursor to the end of the text - editText.setSelection(editText.getText().length()); - }); - - GPSLoggingMinDistance.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { - String val = (String) newValue; - // don't allow the logging_min_distance to be empty - if (TextUtils.isEmpty(val)) { - Toast.makeText(requireContext(), R.string.prefs_gps_logging_min_distance_meters_empty, Toast.LENGTH_SHORT).show(); - return false; // Don't save - } else { - // Set summary with the interval and "seconds" - preference.setSummary(newValue - + " " + getResources().getString(R.string.prefs_gps_logging_min_distance_meters) - + ". " + getResources().getString(R.string.prefs_gps_logging_min_distance_summary)); - return true; - } - } - }); - } + /** + * Voice record duration: set a custom SummaryProvider + */ + private void setupVoiceRecDuration() { + Preference voiceRec = findPreference(OSMTracker.Preferences.KEY_VOICEREC_DURATION); + if (voiceRec == null) return; + voiceRec.setSummaryProvider( + (Preference.SummaryProvider) preference -> { + // Return your combined string + return preference.getEntry() + " " + + getString(R.string.prefs_voicerec_duration_seconds); + }); + } - //GPX Settings + /** + * Clear OSM data: Disable if there's no OSM data stored + * + * @param prefs SharedPreferences + */ + private void setupOSMAuthClearData(SharedPreferences prefs) { - // External storage directory - EditTextPreference storageDirPref = (EditTextPreference) findPreference(OSMTracker.Preferences.KEY_STORAGE_DIR); - storageDirPref.setSummary(prefs.getString(OSMTracker.Preferences.KEY_STORAGE_DIR, OSMTracker.Preferences.VAL_STORAGE_DIR)); - storageDirPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { - // Ensure there is always a leading slash - if (! ((String) newValue).startsWith(File.separator)) { - newValue = File.separator + (String) newValue; - } - - // Set summary with the directory value - preference.setSummary((String) newValue); - - return true; - }}); - - // Explicit execution of buttons presets window - preference = findPreference(OSMTracker.Preferences.KEY_UI_BUTTONS_LAYOUT); - preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener(){ - @Override - public boolean onPreferenceClick(@NonNull Preference preference) { - startActivity(new Intent(requireContext(), ButtonsPresets.class)); - return true; - } + Preference OSMAuthClearData = findPreference( + OSMTracker.Preferences.KEY_OSM_OAUTH_CLEAR_DATA); + + if (OSMAuthClearData == null) return; + String tokenKey = OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN; + OSMAuthClearData.setEnabled(prefs.contains(tokenKey)); + // Set a Click Listener to show the confirmation dialog + OSMAuthClearData.setOnPreferenceClickListener(preference -> { + new androidx.appcompat.app.AlertDialog.Builder(requireContext()) + .setTitle(preference.getTitle()) + .setMessage(R.string.prefs_osm_clear_oauth_data_dialog) + .setIcon(preference.getIcon()) + .setPositiveButton(android.R.string.ok, (dialog, which) -> { + // User clicked OK: Clear the data + prefs.edit().remove(tokenKey).apply(); + // Disable the button now that data is gone + preference.setEnabled(false); + }) + .setNegativeButton(android.R.string.cancel, null) + .show(); + return true; }); - // Button screen orientation option - preference = findPreference(OSMTracker.Preferences.KEY_UI_ORIENTATION); - ListPreference orientationListPreference = (ListPreference) preference; - String displayValueKey = prefs.getString(OSMTracker.Preferences.KEY_UI_ORIENTATION, OSMTracker.Preferences.VAL_UI_ORIENTATION); - int displayValueIndex = orientationListPreference.findIndexOfValue(displayValueKey); - String displayValue = orientationListPreference.getEntries()[displayValueIndex].toString(); - orientationListPreference.setSummary(displayValue + ".\n" - + getResources().getString(R.string.prefs_ui_orientation_summary)); - // Set a listener to update the preference display after a change is made - preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { - // Set summary with the display text of the item and a description of the preference - ListPreference orientationListPreference = (ListPreference) preference; - // Pull the display string from the list preference rather than simply using the key value - int newValueIndex = orientationListPreference.findIndexOfValue((String)newValue); - String newPreferenceDisplayValue = orientationListPreference.getEntries()[newValueIndex].toString(); - - preference.setSummary(newPreferenceDisplayValue - + ".\n" + getResources().getString(R.string.prefs_ui_orientation_summary)); - return true; - }}); + } + /** + * + * @param preferenceKey from OSMTracker.Preferences + * @param valueSuffix appended to the end of the value, shown in the summary + * @param summary static summary to be appended to the end of the summary + * @param validationError in case of empty value + */ + private void setupEditTextNum(String preferenceKey, String valueSuffix, String summary, + String validationError) { + EditTextPreference numInputPref = findPreference(preferenceKey); + if (numInputPref == null) return; + + // Set input type to number and move cursor to the end + numInputPref.setOnBindEditTextListener(editText -> { + editText.setInputType(android.text.InputType.TYPE_CLASS_NUMBER); + editText.setSelection(editText.getText().length()); + }); + + // Set summary provider + numInputPref.setSummaryProvider(preference -> { + EditTextPreference editTextPreference = (EditTextPreference) preference; + return editTextPreference.getText() + " " + valueSuffix + ". " + summary; + }); + + numInputPref.setOnPreferenceChangeListener((preference, newValue) -> { + String val = (String) newValue; + if (TextUtils.isEmpty(val)) { + Toast.makeText(requireContext(), validationError, Toast.LENGTH_SHORT).show(); + return false; + } + return true; + }); + } + + /** + * Button screen orientation option + */ + private void setupButtonScreenOrientation() { + ListPreference uiOrientationPref = findPreference( + OSMTracker.Preferences.KEY_UI_ORIENTATION); + + if (uiOrientationPref == null) return; + + String summary = getString(R.string.prefs_ui_orientation_summary); + + uiOrientationPref.setSummaryProvider(preference -> { + ListPreference listPref = (ListPreference) preference; + CharSequence entry = listPref.getEntry(); + // Null check: entry might be null if no value is selected + String displayValue = Objects.requireNonNull(entry).toString(); + return displayValue + ".\n" + summary; + }); } + } } \ No newline at end of file diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index 427d9565c..729d97e93 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -26,7 +26,7 @@ GPS logging distance Min. distance between track points in meters, use 0 for the shortest possible meters - Min. distance between track points cannot be empty + Min. distance between track points cannot be empty User interface @@ -77,6 +77,7 @@ GPX settings Storage folder in documents Effective for the next track (not the current one) + Storage folder value cannot be empty One directory per track Save each track and associated files to its own directory Filename for named tracks From 1ab25649f8f4f593637c155b9ced8aed0afa601d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Mon, 29 Dec 2025 09:30:55 -0600 Subject: [PATCH 25/60] Feature: Add default values for List Preferences. --- app/src/main/res/xml/preferences.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 12b32f2e2..fa928bea4 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -91,6 +91,7 @@ app:summary="@string/prefs_output_gpx_hdop_approximation_summary" app:title="@string/prefs_output_gpx_hdop_approximation" /> Date: Mon, 29 Dec 2025 09:46:03 -0600 Subject: [PATCH 26/60] Refactor: replace redundant methods with generic implementations --- .../net/osmtracker/activity/Preferences.java | 83 +++++++++---------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/net/osmtracker/activity/Preferences.java b/app/src/main/java/net/osmtracker/activity/Preferences.java index 08107acbd..403755bc7 100644 --- a/app/src/main/java/net/osmtracker/activity/Preferences.java +++ b/app/src/main/java/net/osmtracker/activity/Preferences.java @@ -53,7 +53,10 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { // GPS Settings - setupGPSOSSettings(); + // Open Android GPS Settings screen + setupPreferenceNavigation( + OSMTracker.Preferences.KEY_GPS_OSSETTINGS, + new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); // GPSLogging Interval setupEditTextNum( OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL, @@ -72,25 +75,18 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { //GPX Settings setupStorageDirectory(); - setupButtonsLayout(); - setupButtonScreenOrientation(); + //Explicit execution of buttons presets window + setupPreferenceNavigation( + OSMTracker.Preferences.KEY_UI_BUTTONS_LAYOUT, + new Intent(requireContext(), ButtonsPresets.class)); + // Screen Orientation + setupListPreference( + OSMTracker.Preferences.KEY_UI_ORIENTATION, + getString(R.string.prefs_ui_orientation_summary) + ); } - /** - * Explicit execution of buttons presets window - */ - private void setupButtonsLayout() { - - Preference UIButtonsLayout = findPreference( - OSMTracker.Preferences.KEY_UI_BUTTONS_LAYOUT); - if (UIButtonsLayout == null) return; - UIButtonsLayout.setOnPreferenceClickListener(preference -> { - startActivity(new Intent(requireContext(), ButtonsPresets.class)); - return true; - }); - } - /** * */ @@ -132,20 +128,6 @@ private void setupStorageDirectory() { }); } - /** - * Open Android GPS Settings screen - */ - private void setupGPSOSSettings() { - Preference GPSOSSettings = findPreference(OSMTracker.Preferences.KEY_GPS_OSSETTINGS); - - if (GPSOSSettings == null) return; - - GPSOSSettings.setOnPreferenceClickListener(preference -> { - startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); - return true; - }); - } - /** * Voice record duration: set a custom SummaryProvider */ @@ -195,6 +177,22 @@ private void setupOSMAuthClearData(SharedPreferences prefs) { } + /** + * Setup a preference that launches an activity via Intent + * @param preferenceKey The preference key + * @param intent The intent to launch + */ + private void setupPreferenceNavigation(String preferenceKey, Intent intent) { + Preference preference = findPreference(preferenceKey); + + if (preference == null) return; + + preference.setOnPreferenceClickListener(p -> { + startActivity(intent); + return true; + }); + } + /** * * @param preferenceKey from OSMTracker.Preferences @@ -230,22 +228,23 @@ private void setupEditTextNum(String preferenceKey, String valueSuffix, String s } /** - * Button screen orientation option + * Setup a ListPreference with a custom two lines summary, displays the selected entry + * on the first line, and the static summary on the second line. + * + * @param preferenceKey preference identifier + * @param staticSummary text to show on the second line */ - private void setupButtonScreenOrientation() { - ListPreference uiOrientationPref = findPreference( - OSMTracker.Preferences.KEY_UI_ORIENTATION); - - if (uiOrientationPref == null) return; + private void setupListPreference(String preferenceKey, String staticSummary) { + ListPreference listPref = findPreference(preferenceKey); - String summary = getString(R.string.prefs_ui_orientation_summary); + if (listPref == null) return; - uiOrientationPref.setSummaryProvider(preference -> { - ListPreference listPref = (ListPreference) preference; - CharSequence entry = listPref.getEntry(); + listPref.setSummaryProvider(preference -> { + ListPreference lp = (ListPreference) preference; + CharSequence entry = lp.getEntry(); // Null check: entry might be null if no value is selected String displayValue = Objects.requireNonNull(entry).toString(); - return displayValue + ".\n" + summary; + return displayValue + ".\n" + staticSummary; }); } From bf174e33a7a0cf68fb225c1c96a84f26dd456ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Mon, 29 Dec 2025 10:04:58 -0600 Subject: [PATCH 27/60] Feature: Display current preference value in ListPreferences summaries for better UX. --- .../net/osmtracker/activity/Preferences.java | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/osmtracker/activity/Preferences.java b/app/src/main/java/net/osmtracker/activity/Preferences.java index 403755bc7..2b9fab0d1 100644 --- a/app/src/main/java/net/osmtracker/activity/Preferences.java +++ b/app/src/main/java/net/osmtracker/activity/Preferences.java @@ -48,16 +48,16 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext()); + // General settings setupVoiceRecDuration(); setupOSMAuthClearData(prefs); - // GPS Settings - // Open Android GPS Settings screen + //Open Android GPS Settings screen setupPreferenceNavigation( OSMTracker.Preferences.KEY_GPS_OSSETTINGS, new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); - // GPSLogging Interval + //GPSLogging Interval setupEditTextNum( OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL, getString(R.string.prefs_gps_logging_interval_seconds), @@ -73,12 +73,44 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { ); - //GPX Settings + // GPX Settings setupStorageDirectory(); + //Filename + setupListPreference( + OSMTracker.Preferences.KEY_OUTPUT_FILENAME, + getString(R.string.prefs_output_filename_summary) + ); + //Accuracy + setupListPreference( + OSMTracker.Preferences.KEY_OUTPUT_ACCURACY, + getString(R.string.prefs_output_accuracy_summary) + ); + //Compas Heading + setupListPreference( + OSMTracker.Preferences.KEY_OUTPUT_COMPASS, + getString(R.string.prefs_compass_heading_summary) + ); + + // User Interface Settings + // Camera + setupListPreference( + OSMTracker.Preferences.KEY_UI_PICTURE_SOURCE, + getString(R.string.prefs_ui_picture_source_summary) + ); + // App Theme + setupListPreference( + OSMTracker.Preferences.KEY_UI_THEME, + getString(R.string.prefs_theme_summary) + ); //Explicit execution of buttons presets window setupPreferenceNavigation( OSMTracker.Preferences.KEY_UI_BUTTONS_LAYOUT, new Intent(requireContext(), ButtonsPresets.class)); + //Map tile provider + setupListPreference( + OSMTracker.Preferences.KEY_UI_MAP_TILE, + getString(R.string.prefs_map_tile_summary) + ); // Screen Orientation setupListPreference( OSMTracker.Preferences.KEY_UI_ORIENTATION, From 721fb64b6c992639885f0b0bf6058d61868d39c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Tue, 30 Dec 2025 13:36:31 -0600 Subject: [PATCH 28/60] Add Preferences Test --- .../osmtracker/activity/PreferencesTest.java | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 app/src/androidTest/java/net/osmtracker/activity/PreferencesTest.java diff --git a/app/src/androidTest/java/net/osmtracker/activity/PreferencesTest.java b/app/src/androidTest/java/net/osmtracker/activity/PreferencesTest.java new file mode 100644 index 000000000..796ace41d --- /dev/null +++ b/app/src/androidTest/java/net/osmtracker/activity/PreferencesTest.java @@ -0,0 +1,185 @@ +package net.osmtracker.activity; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.clearText; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.typeText; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static org.hamcrest.Matchers.stringContainsInOrder; + +import android.content.Context; +import android.content.SharedPreferences; + +import androidx.preference.PreferenceManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.test.core.app.ActivityScenario; +import androidx.test.espresso.contrib.RecyclerViewActions; +import androidx.test.espresso.matcher.ViewMatchers; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; + +import net.osmtracker.OSMTracker; +import net.osmtracker.R; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.Arrays; + + +@RunWith(AndroidJUnit4.class) +public class PreferencesTest { + + private Context context; + private ActivityScenario activity; + + @Before + public void setup() { + context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + // Reset preferences to default before each test to ensure a clean state + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + prefs.edit().clear().commit(); + + // Launch the activity + activity = ActivityScenario.launch(Preferences.class); + } + + @After + public void tearDown() { + activity.close(); + } + + /** + * Test that the Storage Directory preference logic works to rejects empty input. + */ + @Test + public void testStorageDirectoryValidatesNonEmpty() { + String keyTitle = context.getString(R.string.prefs_storage_dir); + String defaultValue = OSMTracker.Preferences.VAL_STORAGE_DIR; + + // Looks for storage directory preference + scrollToAndClick(keyTitle); + + // Try to save an empty value + onView(withId(android.R.id.edit)).perform(clearText()); + onView(withText(android.R.string.ok)).perform(click()); + + // Open the preference to verify the value in the list remains the default (unchanged) + onView(ViewMatchers.isAssignableFrom(RecyclerView.class)) + .check(matches(hasDescendant(withText(defaultValue)))); + } + + /** + * Test that the Storage Directory preference logic works to automatically append a leading + * slash separator if missing. + */ + @Test + public void testStorageDirectoryValidatesAppendLeadingSlash() { + String keyTitle = context.getString(R.string.prefs_storage_dir); + String expected = File.separator + "my_folder"; + + + // Looks for storage directory preference + scrollToAndClick(keyTitle); + + // Try to type a value without a slash + onView(withId(android.R.id.edit)).perform(clearText()); + onView(withId(android.R.id.edit)) + .perform(typeText("my_folder")); + onView(withText(android.R.string.ok)).perform(click()); + + // Open the preference to verify the value in the list is the expected + onView(ViewMatchers.isAssignableFrom(RecyclerView.class)) + .check(matches(hasDescendant(withText(expected)))); + } + + /** + * Test Numeric Input logic (GPS Logging Interval): update summary with suffix. + */ + @Test + public void testNumericInputLogic() { + String title = context.getString(R.string.prefs_gps_logging_interval); + String suffix = context.getString(R.string.prefs_gps_logging_interval_seconds); + + scrollToAndClick(title); + + // Enter a valid number + onView(withId(android.R.id.edit)) + .perform(clearText(), typeText("30")); + onView(withText(android.R.string.ok)).perform(click()); + + // Verify summary format: "30 seconds. " + onView(ViewMatchers.isAssignableFrom(RecyclerView.class)) + .check(matches(hasDescendant(withText(stringContainsInOrder(Arrays.asList("30", + suffix)))))); + } + + /** + * Test ListPreference custom summary logic (Screen Orientation) + * Should show "Selected Value. \n ..." (don't check for the 2nd line of the summary) + */ + @Test + public void testListPreferenceCustomSummary() { + String title = context.getString(R.string.prefs_ui_orientation); + + scrollToAndClick(title); + + // Select 1st option from array resource entries + String[] entries = context.getResources() + .getStringArray(R.array.prefs_ui_orientation_options_keys); + onView(withText(entries[0])).perform(click()); + + // Verify the two-line summary exists + onView(ViewMatchers.isAssignableFrom(RecyclerView.class)).check(matches(hasDescendant( + withText(stringContainsInOrder(Arrays.asList(entries[0], ".\n")))))); + } + + /** + * Test Clear OAuth Data logic. + */ + @Test + public void testClearOAuthData() { + String title = context.getString(R.string.prefs_osm_clear_oauth_data); + + // Inject a fake token to enable the button + SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context) + .edit(); + editor.putString(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN, "fake_token"); + editor.commit(); + + // Relaunch to refresh UI state + ActivityScenario.launch(Preferences.class); + + + scrollToAndClick(title); + + // Click OK on Confirmation Dialog + onView(withText(R.string.prefs_osm_clear_oauth_data_dialog)).check(matches(isDisplayed())); + onView(withText(android.R.string.ok)).perform(click()); + + // Verify token is gone in prefs + assert(!PreferenceManager.getDefaultSharedPreferences(context) + .contains(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN)); + } + + // --- Helper Methods --- + + /** + * Helper to scroll to a preference in the RecyclerView and click it. + */ + private void scrollToAndClick(String text) { + onView(ViewMatchers.isAssignableFrom(RecyclerView.class)) + .perform(RecyclerViewActions.actionOnItem( + hasDescendant(withText(text)), + click())); + } + +} From e52a24fff1f50c0d2e048a40d7f99ecf02074daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Fri, 2 Jan 2026 07:44:05 -0600 Subject: [PATCH 29/60] Feature: add button to restore default values for logging interval and logging distance (Closes #345) --- .../osmtracker/activity/PreferencesTest.java | 33 +++++++++ .../net/osmtracker/activity/Preferences.java | 71 ++++++++++++++++++- .../main/res/values/strings-preferences.xml | 1 + 3 files changed, 102 insertions(+), 3 deletions(-) diff --git a/app/src/androidTest/java/net/osmtracker/activity/PreferencesTest.java b/app/src/androidTest/java/net/osmtracker/activity/PreferencesTest.java index 796ace41d..bef2a78b8 100644 --- a/app/src/androidTest/java/net/osmtracker/activity/PreferencesTest.java +++ b/app/src/androidTest/java/net/osmtracker/activity/PreferencesTest.java @@ -122,6 +122,39 @@ public void testNumericInputLogic() { suffix)))))); } + /** + * Test that the Reset button in numeric preferences restores the default value. + */ + @Test + public void testResetButtonResetsValue() { + String title = context.getString(R.string.prefs_gps_logging_interval); + String suffix = context.getString(R.string.prefs_gps_logging_interval_seconds); + String defaultValue = OSMTracker.Preferences.VAL_GPS_LOGGING_INTERVAL; + + scrollToAndClick(title); + + // Set a custom value "50" + onView(withId(android.R.id.edit)).perform(clearText(), typeText("50")); + onView(withText(android.R.string.ok)).perform(click()); + + // Verify custom value is set + onView(ViewMatchers.isAssignableFrom(RecyclerView.class)) + .check(matches(hasDescendant(withText(stringContainsInOrder(Arrays.asList("50", + suffix)))))); + + // Reopen dialog + scrollToAndClick(title); + + // Click the Reset button (Neutral button) + onView(withText(R.string.prefs_reset_default_value)).perform(click()); + + // Verify value is back to default "0" + onView(ViewMatchers.isAssignableFrom(RecyclerView.class)) + .check(matches(hasDescendant(withText(stringContainsInOrder(Arrays.asList( + defaultValue, + suffix)))))); + } + /** * Test ListPreference custom summary logic (Screen Orientation) * Should show "Selected Value. \n ..." (don't check for the 2nd line of the summary) diff --git a/app/src/main/java/net/osmtracker/activity/Preferences.java b/app/src/main/java/net/osmtracker/activity/Preferences.java index 2b9fab0d1..8ede50828 100644 --- a/app/src/main/java/net/osmtracker/activity/Preferences.java +++ b/app/src/main/java/net/osmtracker/activity/Preferences.java @@ -4,11 +4,15 @@ import android.content.SharedPreferences; import android.os.Bundle; import android.text.TextUtils; +import android.widget.Button; import android.widget.Toast; import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.FragmentManager; import androidx.preference.EditTextPreference; +import androidx.preference.EditTextPreferenceDialogFragmentCompat; import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; @@ -42,6 +46,9 @@ protected void onCreate(Bundle savedInstanceState) { } public static class SettingsFragment extends PreferenceFragmentCompat { + + private static final String EXTRA_DEFAULT_VALUE = "DEFAULT_VALUE"; + @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.preferences, rootKey); @@ -62,14 +69,16 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { OSMTracker.Preferences.KEY_GPS_LOGGING_INTERVAL, getString(R.string.prefs_gps_logging_interval_seconds), getString(R.string.prefs_gps_logging_interval_summary), - getString(R.string.prefs_gps_logging_interval_empty) + getString(R.string.prefs_gps_logging_interval_empty), + OSMTracker.Preferences.VAL_GPS_LOGGING_INTERVAL ); //GPS Logging Min Distance setupEditTextNum( OSMTracker.Preferences.KEY_GPS_LOGGING_MIN_DISTANCE, getString(R.string.prefs_gps_logging_min_distance_meters), getString(R.string.prefs_gps_logging_min_distance_summary), - getString(R.string.prefs_gps_logging_min_distance_empty) + getString(R.string.prefs_gps_logging_min_distance_empty), + OSMTracker.Preferences.VAL_GPS_LOGGING_MIN_DISTANCE ); @@ -231,12 +240,16 @@ private void setupPreferenceNavigation(String preferenceKey, Intent intent) { * @param valueSuffix appended to the end of the value, shown in the summary * @param summary static summary to be appended to the end of the summary * @param validationError in case of empty value + * @param defaultValue value to be used for the reset button */ private void setupEditTextNum(String preferenceKey, String valueSuffix, String summary, - String validationError) { + String validationError, String defaultValue) { EditTextPreference numInputPref = findPreference(preferenceKey); if (numInputPref == null) return; + // Store default value in Extras so it can be retrieved by the Reset Dialog + numInputPref.getExtras().putString(EXTRA_DEFAULT_VALUE, defaultValue); + // Set input type to number and move cursor to the end numInputPref.setOnBindEditTextListener(editText -> { editText.setInputType(android.text.InputType.TYPE_CLASS_NUMBER); @@ -259,6 +272,58 @@ private void setupEditTextNum(String preferenceKey, String valueSuffix, String s }); } + @SuppressWarnings("deprecation") // Required to link the dialog to the fragment + @Override + public void onDisplayPreferenceDialog(Preference preference) { + + // Retrieve the default value defined in extras. + // If null, it means this preference doesn't support the reset feature. + // Fallback to the default dialog behavior. + String defaultValue = preference.getExtras().getString(EXTRA_DEFAULT_VALUE); + if (defaultValue == null) { + super.onDisplayPreferenceDialog(preference); + return; + } + + // Create the standard dialog fragment + final EditTextPreferenceDialogFragmentCompat dialogFragment = + EditTextPreferenceDialogFragmentCompat.newInstance(preference.getKey()); + dialogFragment.setTargetFragment(this, 0); + dialogFragment.show( + getParentFragmentManager(), + "androidx.preference.PreferenceFragment.DIALOG"); + + // Inject the button after the dialog is shown + getParentFragmentManager().registerFragmentLifecycleCallbacks( + new FragmentManager.FragmentLifecycleCallbacks() { + @Override + public void onFragmentStarted( + @androidx.annotation.NonNull FragmentManager fm, + @androidx.annotation.NonNull androidx.fragment.app.Fragment f) { + if (f == dialogFragment) { + android.app.Dialog dialog = dialogFragment.getDialog(); + if (dialog instanceof androidx.appcompat.app.AlertDialog alertDialog) { + + // Configure the Neutral Button for reset default value + Button btnReset = alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL); + btnReset.setText(R.string.prefs_reset_default_value); + btnReset.setVisibility(android.view.View.VISIBLE); + + btnReset.setOnClickListener(v -> { + if (preference instanceof EditTextPreference) { + ((EditTextPreference) preference).setText(defaultValue); + alertDialog.dismiss(); + } + }); + } + // Cleanup + getParentFragmentManager().unregisterFragmentLifecycleCallbacks(this); + } + } + }, false); + } + + /** * Setup a ListPreference with a custom two lines summary, displays the selected entry * on the first line, and the static summary on the second line. diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index 729d97e93..1f68f547f 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -124,4 +124,5 @@ Export compass heading Defines if and how the compass data should be exported to the GPX file + Reset default value From 77afd193feb5c37fa408e7e99424e40517168719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Fri, 2 Jan 2026 15:50:16 -0600 Subject: [PATCH 30/60] UI: add visibility label in track details --- app/src/main/res/layout/trackdetail_fields.xml | 10 +++++++++- app/src/main/res/values/strings.xml | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/layout/trackdetail_fields.xml b/app/src/main/res/layout/trackdetail_fields.xml index db20f151b..82a4df525 100644 --- a/app/src/main/res/layout/trackdetail_fields.xml +++ b/app/src/main/res/layout/trackdetail_fields.xml @@ -57,11 +57,19 @@ android:minHeight="48dp" android:singleLine="true" /> + + + android:minHeight="48dp" + style="@style/Widget.AppCompat.Spinner.Underlined" /> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d8a4fd12c..0f606f663 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -67,6 +67,7 @@ Description Tags (comma separated) You must enter a description + Visibility Private Public Trackable From ebdc4ce163e510f45edeeebbb902a2e81bf8f1b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Sat, 3 Jan 2026 07:46:09 -0600 Subject: [PATCH 31/60] Feature: add OSM track visibility to preferences --- app/src/main/java/net/osmtracker/OSMTracker.java | 2 ++ .../java/net/osmtracker/activity/Preferences.java | 5 +++++ app/src/main/res/values/strings-preferences.xml | 13 +++++++++++-- app/src/main/res/values/values-preferences.xml | 7 +++++++ app/src/main/res/xml/preferences.xml | 7 +++++++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/net/osmtracker/OSMTracker.java b/app/src/main/java/net/osmtracker/OSMTracker.java index 046a4d23a..993668682 100644 --- a/app/src/main/java/net/osmtracker/OSMTracker.java +++ b/app/src/main/java/net/osmtracker/OSMTracker.java @@ -40,6 +40,7 @@ public static final class Preferences { public final static String KEY_UI_MAP_TILE = "ui.map.tile"; public final static String KEY_SOUND_ENABLED = "sound_enabled"; public final static String KEY_UI_ORIENTATION = "ui.orientation"; + public final static String KEY_OSM_TRACK_VISIBILITY = "osm.track.visibility"; public final static String KEY_OSM_OAUTH2_ACCESSTOKEN = "osm.oauth2.accesstoken"; public final static String KEY_OSM_OAUTH_CLEAR_DATA = "osm.oauth.clear-data"; @@ -90,6 +91,7 @@ public static final class Preferences { public final static boolean VAL_UI_DISPLAYTRACK_OSM = false; public final static boolean VAL_UI_DISPLAY_KEEP_ON = true; public final static boolean VAL_SOUND_ENABLED = true; + public final static String VAL_OSM_TRACK_VISIBILITY = "identifiable"; public final static String VAL_UI_ORIENTATION_NONE = "none"; public final static String VAL_UI_ORIENTATION_PORTRAIT = "portrait"; public final static String VAL_UI_ORIENTATION_LANDSCAPE = "landscape"; diff --git a/app/src/main/java/net/osmtracker/activity/Preferences.java b/app/src/main/java/net/osmtracker/activity/Preferences.java index 8ede50828..4ea78206f 100644 --- a/app/src/main/java/net/osmtracker/activity/Preferences.java +++ b/app/src/main/java/net/osmtracker/activity/Preferences.java @@ -57,6 +57,11 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { // General settings setupVoiceRecDuration(); + // OSM track visibility + setupListPreference( + OSMTracker.Preferences.KEY_OSM_TRACK_VISIBILITY, + getString(R.string.prefs_osm_visibility_summary) + ); setupOSMAuthClearData(prefs); // GPS Settings diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index 1f68f547f..d46b52824 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -104,8 +104,17 @@ Enable sound Play sounds when voice recording starts and ends - - Reset OSM authentication + + Track Visibility + Preferred visibility of traces uploaded to openstreetmap.org + + Private + Trackable + Public + Identifiable + + + Reset OSM authentication Forget OSM credentials and permissions and force OSMTracker to ask them again You\'ll have to authorize OSMTracker to upload tracks again. Are you sure? diff --git a/app/src/main/res/values/values-preferences.xml b/app/src/main/res/values/values-preferences.xml index 16d5e4960..9487b78ef 100644 --- a/app/src/main/res/values/values-preferences.xml +++ b/app/src/main/res/values/values-preferences.xml @@ -55,4 +55,11 @@ extension + + private + trackable + public + identifiable + + diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index fa928bea4..47143430b 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -20,6 +20,13 @@ app:key="gpx.use_barometer" app:summary="@string/prefs_use_barometer_summary" app:title="@string/prefs_use_barometer" /> + Date: Sat, 3 Jan 2026 13:46:43 -0600 Subject: [PATCH 32/60] Feature: get OSM track visibility from preferences --- app/src/main/java/net/osmtracker/OSMTracker.java | 5 ++++- .../java/net/osmtracker/activity/TrackManager.java | 8 ++++++++ app/src/main/res/layout/trackdetail_fields.xml | 1 + app/src/main/res/values/values-preferences.xml | 10 +++++----- app/src/main/res/xml/preferences.xml | 2 +- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/net/osmtracker/OSMTracker.java b/app/src/main/java/net/osmtracker/OSMTracker.java index 993668682..ffac68d4f 100644 --- a/app/src/main/java/net/osmtracker/OSMTracker.java +++ b/app/src/main/java/net/osmtracker/OSMTracker.java @@ -1,6 +1,8 @@ package net.osmtracker; +import net.osmtracker.db.model.Track; + /** * Constants & app-wide variables. * @@ -91,7 +93,8 @@ public static final class Preferences { public final static boolean VAL_UI_DISPLAYTRACK_OSM = false; public final static boolean VAL_UI_DISPLAY_KEEP_ON = true; public final static boolean VAL_SOUND_ENABLED = true; - public final static String VAL_OSM_TRACK_VISIBILITY = "identifiable"; + // Matches Track.OSMVisibility.Identifiable; + public final static String VAL_OSM_TRACK_VISIBILITY = "Identifiable"; public final static String VAL_UI_ORIENTATION_NONE = "none"; public final static String VAL_UI_ORIENTATION_PORTRAIT = "portrait"; public final static String VAL_UI_ORIENTATION_LANDSCAPE = "landscape"; diff --git a/app/src/main/java/net/osmtracker/activity/TrackManager.java b/app/src/main/java/net/osmtracker/activity/TrackManager.java index 10a7b40e9..4f9f23189 100644 --- a/app/src/main/java/net/osmtracker/activity/TrackManager.java +++ b/app/src/main/java/net/osmtracker/activity/TrackManager.java @@ -17,6 +17,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; @@ -635,6 +636,7 @@ public void onClick(long trackId) { * @throws CreateTrackException */ private long createNewTrack() throws CreateTrackException { + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); Date startDate = new Date(); // Create entry in TRACK table @@ -644,6 +646,12 @@ private long createNewTrack() throws CreateTrackException { values.put(TrackContentProvider.Schema.COL_START_DATE, startDate.getTime()); values.put(TrackContentProvider.Schema.COL_ACTIVE, TrackContentProvider.Schema.VAL_TRACK_ACTIVE); + String visibility = preferences.getString( + OSMTracker.Preferences.KEY_OSM_TRACK_VISIBILITY, + OSMTracker.Preferences.VAL_OSM_TRACK_VISIBILITY + ); + Log.d(TAG, "Visibility: " + visibility); + values.put(TrackContentProvider.Schema.COL_OSM_VISIBILITY, visibility); Uri trackUri = getContentResolver().insert(TrackContentProvider.CONTENT_URI_TRACK, values); long trackId = ContentUris.parseId(trackUri); diff --git a/app/src/main/res/layout/trackdetail_fields.xml b/app/src/main/res/layout/trackdetail_fields.xml index 82a4df525..c7397218a 100644 --- a/app/src/main/res/layout/trackdetail_fields.xml +++ b/app/src/main/res/layout/trackdetail_fields.xml @@ -70,6 +70,7 @@ android:layout_height="wrap_content" android:layout_marginTop="8dp" android:minHeight="48dp" + android:entries="@array/prefs_osm_visibility_keys" style="@style/Widget.AppCompat.Spinner.Underlined" /> \ No newline at end of file diff --git a/app/src/main/res/values/values-preferences.xml b/app/src/main/res/values/values-preferences.xml index 9487b78ef..eb85f7f2e 100644 --- a/app/src/main/res/values/values-preferences.xml +++ b/app/src/main/res/values/values-preferences.xml @@ -55,11 +55,11 @@ extension - - private - trackable - public - identifiable + + Private + Trackable + Public + Identifiable diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 47143430b..a73c72a16 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -21,7 +21,7 @@ app:summary="@string/prefs_use_barometer_summary" app:title="@string/prefs_use_barometer" /> Date: Mon, 12 Jan 2026 12:48:00 -0600 Subject: [PATCH 33/60] Refactor: delete unused import --- app/src/main/java/net/osmtracker/OSMTracker.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/net/osmtracker/OSMTracker.java b/app/src/main/java/net/osmtracker/OSMTracker.java index ffac68d4f..1d5da5e78 100644 --- a/app/src/main/java/net/osmtracker/OSMTracker.java +++ b/app/src/main/java/net/osmtracker/OSMTracker.java @@ -1,8 +1,6 @@ package net.osmtracker; -import net.osmtracker.db.model.Track; - /** * Constants & app-wide variables. * From b52014e4b39873aa6b04275f9f6dd55d46844984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Mon, 12 Jan 2026 20:20:11 -0600 Subject: [PATCH 34/60] Add Tests for OSM Visibility --- app/build.gradle | 6 +- .../activity/TrackDetailEditorTest.java | 70 +++++++++++++++++++ .../test/db/model/OSMVisibilityTest.java | 65 +++++++++++++++++ 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 app/src/test/java/net/osmtracker/activity/TrackDetailEditorTest.java create mode 100644 app/src/test/java/net/osmtracker/test/db/model/OSMVisibilityTest.java diff --git a/app/build.gradle b/app/build.gradle index cd692d859..7c11d2a1b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -61,6 +61,8 @@ android { } testOptions { unitTests.returnDefaultValues = true + // This flag is required for Robolectric to find XML resources + unitTests.includeAndroidResources = true unitTests.all { it.jvmArgs = [ '--add-opens', 'java.base/java.io=ALL-UNNAMED', @@ -99,7 +101,9 @@ dependencies { // Required -- JUnit 4 framework testImplementation 'junit:junit:4.13.2' - // Robolectric environment + // Robolectric + testImplementation 'org.robolectric:robolectric:4.11.1' + // AndroidX Test core for Robolectric testImplementation "androidx.test:core:1.6.1" // Mockito framework testImplementation "org.mockito:mockito-core:3.12.4" diff --git a/app/src/test/java/net/osmtracker/activity/TrackDetailEditorTest.java b/app/src/test/java/net/osmtracker/activity/TrackDetailEditorTest.java new file mode 100644 index 000000000..2fb14016c --- /dev/null +++ b/app/src/test/java/net/osmtracker/activity/TrackDetailEditorTest.java @@ -0,0 +1,70 @@ +package net.osmtracker.activity; + +import static org.robolectric.Robolectric.buildActivity; + +import android.os.Bundle; +import android.widget.ArrayAdapter; + +import net.osmtracker.R; +import net.osmtracker.db.model.Track; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +@RunWith(RobolectricTestRunner.class) +//Min SDK of the App +@Config(sdk = 25) +public class TrackDetailEditorTest { + private TrackDetailEditor activity; + + /** + * Concrete implementation of the abstract TrackDetailEditor for testing purposes. + */ + public static class TrackDetailEditorActivity extends TrackDetailEditor { + @Override + protected void onCreate(Bundle savedInstanceState) { + // Pass a dummy layout and ID to satisfy the base class + super.onCreate(savedInstanceState, R.layout.trackdetail, 1L); + } + } + @Before + public void setup() { + activity = buildActivity(TrackDetailEditorActivity.class).create().get(); + + // Ensure Spinner is populated as it would be from XML + ArrayAdapter adapter = ArrayAdapter.createFromResource( + activity, + R.array.prefs_osm_visibility_keys, + android.R.layout.simple_spinner_item); + activity.spVisibility.setAdapter(adapter); + } + + @Test + public void testBindTrackSetsCorrectSpinnerPosition() { + Track t = new Track(); + t.setVisibility(Track.OSMVisibility.Trackable); + + activity.bindTrack(t); + + // Verify that position 2 - Trackable is selected in the UI + Assert.assertEquals(Track.OSMVisibility.Trackable.position, + activity.spVisibility.getSelectedItemPosition()); + } + + @Test + public void testSaveCapturesCorrectEnumValue() { + // Simulate user selecting "Public" (Index 1) + activity.spVisibility.setSelection(Track.OSMVisibility.Public.position); + + // Verify that save logic correctly converts position to "Public" + Track.OSMVisibility result = Track.OSMVisibility.fromPosition( + activity.spVisibility.getSelectedItemPosition()); + + Assert.assertEquals(Track.OSMVisibility.Public, result); + Assert.assertEquals(Track.OSMVisibility.Public.name(), result.name()); + } +} diff --git a/app/src/test/java/net/osmtracker/test/db/model/OSMVisibilityTest.java b/app/src/test/java/net/osmtracker/test/db/model/OSMVisibilityTest.java new file mode 100644 index 000000000..36e2fdde4 --- /dev/null +++ b/app/src/test/java/net/osmtracker/test/db/model/OSMVisibilityTest.java @@ -0,0 +1,65 @@ +package net.osmtracker.test.db.model; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import net.osmtracker.R; +import net.osmtracker.db.model.Track; + +@RunWith(RobolectricTestRunner.class) +//Min SDK of the App +@Config(sdk = 25) +public class OSMVisibilityTest { + + private Context context; + + @Before + public void setUp() { + context = ApplicationProvider.getApplicationContext(); + } + + + @Test + public void testEnumMappingToName() { + // Database stores the .name() of the enum + Assert.assertEquals("Private" , Track.OSMVisibility.Private.name()); + Assert.assertEquals("Public" , Track.OSMVisibility.Public.name()); + Assert.assertEquals("Trackable" , Track.OSMVisibility.Trackable.name()); + Assert.assertEquals("Identifiable", Track.OSMVisibility.Identifiable.name()); + } + + @Test + public void testFromPosition() { + // Verifies the Spinner index mapping (0 -> Private, 3 -> Identifiable) + Assert.assertEquals(Track.OSMVisibility.Private, Track.OSMVisibility.fromPosition(0)); + Assert.assertEquals(Track.OSMVisibility.Public, Track.OSMVisibility.fromPosition(1)); + Assert.assertEquals(Track.OSMVisibility.Trackable, Track.OSMVisibility.fromPosition(2)); + Assert.assertEquals(Track.OSMVisibility.Identifiable, Track.OSMVisibility.fromPosition(3)); + } + + @Test + public void testResourceIdsMapToCorrectStrings() { + Assert.assertEquals(context.getString(R.string.osm_visibility_private), + context.getString(Track.OSMVisibility.Private.resId)); + Assert.assertEquals(context.getString(R.string.osm_visibility_public), + context.getString(Track.OSMVisibility.Public.resId)); + Assert.assertEquals(context.getString(R.string.osm_visibility_trackable), + context.getString(Track.OSMVisibility.Trackable.resId)); + Assert.assertEquals(context.getString(R.string.osm_visibility_identifiable), + context.getString(Track.OSMVisibility.Identifiable.resId)); + } + + @Test(expected = IllegalArgumentException.class) + public void testFromPosition_Invalid() { + // Verifies that an invalid index throws the expected exception + Track.OSMVisibility.fromPosition(99); + } +} From 990db5acfdc5702c14b6a52e95b3e5f5538c4df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Guti=C3=A9rrez=20Alfaro?= Date: Wed, 14 Jan 2026 10:02:38 -0600 Subject: [PATCH 35/60] =?UTF-8?q?[Transifex]=20Updates=20for=20project=20O?= =?UTF-8?q?SMTracker=20for=20Android=E2=84=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../res/values-ar/strings-preferences.xml | 1 - .../res/values-cs-rCZ/strings-preferences.xml | 1 - .../res/values-da/strings-preferences.xml | 1 - .../res/values-de/strings-preferences.xml | 1 - .../res/values-el/strings-preferences.xml | 1 - .../res/values-es/strings-preferences.xml | 14 +- .../res/values-fr/strings-preferences.xml | 1 - .../res/values-hu/strings-preferences.xml | 1 - .../res/values-it/strings-preferences.xml | 1 - .../res/values-ja/strings-preferences.xml | 1 - .../res/values-nl/strings-preferences.xml | 3 + .../res/values-pl/strings-preferences.xml | 1 - .../res/values-pt-rPT/strings-preferences.xml | 1 - .../res/values-ru/strings-preferences.xml | 1 - .../res/values-sk/strings-preferences.xml | 1 - .../res/values-sr/strings-preferences.xml | 1 - .../res/values-sv/strings-preferences.xml | 3 + .../res/values-tr/strings-preferences.xml | 1 - .../res/values-zh-rTW/strings-preferences.xml | 6 +- app/src/main/res/values/accessibility.xml | 33 +-- .../main/res/values/strings-preferences.xml | 247 ++++++++---------- app/src/main/res/values/strings-tags.xml | 204 +++++++-------- app/src/main/res/values/strings.xml | 2 +- app/src/main/res/values/waypoints.xml | 6 +- 24 files changed, 255 insertions(+), 278 deletions(-) diff --git a/app/src/main/res/values-ar/strings-preferences.xml b/app/src/main/res/values-ar/strings-preferences.xml index 23bba852b..73cb2812d 100644 --- a/app/src/main/res/values-ar/strings-preferences.xml +++ b/app/src/main/res/values-ar/strings-preferences.xml @@ -76,7 +76,6 @@ ننسى بيانات اعتماد OSM والأذونات وأجبر OSMTracker على طلبها مرة أخرى لابد من السماح لـOSMTracker برفع المسارات مرة أخرى. هل أنت متأكد؟ مزود الصور المتجانبة للخريطة - لا شيء في التعليق diff --git a/app/src/main/res/values-cs-rCZ/strings-preferences.xml b/app/src/main/res/values-cs-rCZ/strings-preferences.xml index 92300bf0d..b5c9ab09d 100644 --- a/app/src/main/res/values-cs-rCZ/strings-preferences.xml +++ b/app/src/main/res/values-cs-rCZ/strings-preferences.xml @@ -85,7 +85,6 @@ Zapomenout OSM údaje pro přihlášení a pověření a přiměj OSMTracker, aby se znovu zeptal Je třeba autorizace OSMTrackeru pro opakované nahrání. Jste si jisti? Poskytovatel mapových dlaždic - Nikde V komentáři diff --git a/app/src/main/res/values-da/strings-preferences.xml b/app/src/main/res/values-da/strings-preferences.xml index a1e53bc57..3dc658a20 100644 --- a/app/src/main/res/values-da/strings-preferences.xml +++ b/app/src/main/res/values-da/strings-preferences.xml @@ -85,7 +85,6 @@ Glem OSM-brugernavn og -tilladelser og tving OSMTracker til at spørge om dem igen Dette betyder at du vil skulle autorisere OSMTracker for at kunne uploade igen. Er du sikker? Leverandør af kortfliser - Deaktiveret til kommentar diff --git a/app/src/main/res/values-de/strings-preferences.xml b/app/src/main/res/values-de/strings-preferences.xml index ae1086a7f..6147760e8 100644 --- a/app/src/main/res/values-de/strings-preferences.xml +++ b/app/src/main/res/values-de/strings-preferences.xml @@ -85,7 +85,6 @@ OSM-Anmeldedaten und -berechtigungen vergessen und OSMTracker neu danach fragen lassen Sie müssen OSMTracker erneut zum Hochladen von Routen autorisieren. Sind Sie sicher? Anbieter von Kartenkacheln - kein Export im Kommentar diff --git a/app/src/main/res/values-el/strings-preferences.xml b/app/src/main/res/values-el/strings-preferences.xml index f763763fa..d39d1d33d 100644 --- a/app/src/main/res/values-el/strings-preferences.xml +++ b/app/src/main/res/values-el/strings-preferences.xml @@ -85,7 +85,6 @@ Αγνόηση των διαπιστευτηρίων και των αδειών του OSM και εξαναγκασμός του OSMTracker να τα ζητήσει ξανά Θα πρέπει να εξουσιοδοτήσετε το OSMTracker να στείλει τα ίχνη ξανά. Είστε σίγουρος; Πάροχος πλακιδίων χάρτη - Κανένα σε σχόλιο diff --git a/app/src/main/res/values-es/strings-preferences.xml b/app/src/main/res/values-es/strings-preferences.xml index d90514037..e0cce69d9 100644 --- a/app/src/main/res/values-es/strings-preferences.xml +++ b/app/src/main/res/values-es/strings-preferences.xml @@ -14,9 +14,11 @@ Intervalo de registro de GPS Utilice 0 para el más breve posible (afecta a la vida de la batería) segundos + La distancia de registro GPS no puede estar vacía Distancia de registro GPS Distancia min. entre puntos de traza en metros, utilice 0 para la menor distancia posible metros + La distancia mínima entre puntos de traza no puede estar vacía Interfaz de usuario Fuente de fotos predeterminada ¿Tomar fotos desde la cámara o la galería? @@ -38,7 +40,7 @@ Automático Vertical - Apaisado + Horizontal Duración de la grabación de voz segundos @@ -58,6 +60,7 @@ Configuraciones GPX Carpeta de almacenamiento en Documentos Se hará efectivo en la traza siguiente (no la actual) + El valor de la carpeta de almacenamiento no puede estar vacía Una carpeta por cada traza Guarda cada rastro y los archivos asociados en su propia carpeta Nombre del archivo para las trazas con nombre @@ -81,6 +84,14 @@ Rellenar el HDOP en el GPX con un valor de aproximación de la precisión Habilitar el sonido Reproducir sonidos cuando la grabación de voz comienza y termina + Visibilidad de la traza + Visibilidad preferida para las trazas al subirlas a openstreetmap.org + + Privado + Trazable + Público + Identificable + Restablecer la autenticación OSM Olvidar las credenciales y permisos de OSM, y forzar a que OSMTracker los vuelva a solicitar Deberá autorizar a OSMTracker para volver a subir las pistas. ¿Está seguro? @@ -93,4 +104,5 @@ Exportar rumbo de la brújula Define el si y cómo los datos de brújula deben ser exportados al archivo GPX + Reestablecer valor predeterminado diff --git a/app/src/main/res/values-fr/strings-preferences.xml b/app/src/main/res/values-fr/strings-preferences.xml index 3d506e89c..178780b0e 100644 --- a/app/src/main/res/values-fr/strings-preferences.xml +++ b/app/src/main/res/values-fr/strings-preferences.xml @@ -85,7 +85,6 @@ Force OSMTracker à se ré-authentifier sur OpenStreetMap Vous devrez vous reconnecter à OpenStreetMap. Êtes-vous sûr ? Fournisseur de tuiles de carte - Aucun En commentaire diff --git a/app/src/main/res/values-hu/strings-preferences.xml b/app/src/main/res/values-hu/strings-preferences.xml index d85086bc8..fa3b4f459 100644 --- a/app/src/main/res/values-hu/strings-preferences.xml +++ b/app/src/main/res/values-hu/strings-preferences.xml @@ -84,7 +84,6 @@ Az OSM belépési adatok és jogosultságok elfelejtése és az OSMTracker kényszerítése, hogy megkérdezze újra azokat Az OSMTrackert majd újból azonosítani kell a nyomvonalak feltöltéséhez. Biztosan ezt szeretné? Térképcsempe-szolgáltató - Semmi megjegyzésben diff --git a/app/src/main/res/values-it/strings-preferences.xml b/app/src/main/res/values-it/strings-preferences.xml index 53477d9e3..38ae1ce9b 100644 --- a/app/src/main/res/values-it/strings-preferences.xml +++ b/app/src/main/res/values-it/strings-preferences.xml @@ -85,7 +85,6 @@ Dimentica le credenziali e le autorizzazioni di OSM e forza OSMTracker a chiederle di nuovo Devi autorizzare nuovamente OSMTracker a caricare i tracciati. Sei sicuro? Fornitore dei tasselli della mappa - Nessuno come commento diff --git a/app/src/main/res/values-ja/strings-preferences.xml b/app/src/main/res/values-ja/strings-preferences.xml index f96b08e02..11d1d30ea 100644 --- a/app/src/main/res/values-ja/strings-preferences.xml +++ b/app/src/main/res/values-ja/strings-preferences.xml @@ -82,7 +82,6 @@ OSMの認証と許可を消去し、強制的にOSMTrackerが再び確認するようにする 再びトラックをアップロードするには、OSMTrackerの認証が必要です。続けますか? 地図タイルプロバイダー - なし コメント内 diff --git a/app/src/main/res/values-nl/strings-preferences.xml b/app/src/main/res/values-nl/strings-preferences.xml index a49eeb8f5..287708a5b 100644 --- a/app/src/main/res/values-nl/strings-preferences.xml +++ b/app/src/main/res/values-nl/strings-preferences.xml @@ -14,9 +14,11 @@ Gps-loginterval Gebruik 0 voor de kortst mogelijke (beïnvloedt levensduur van de batterij) seconden + Gps-loginterval mag niet leeg zijn Gps-logafstand Minimale afstand tussen trajectpunten in meter. Gebruik 0 voor de kortst mogelijke afstand meter + Minimale afstand tussen trajectpunten in mag niet leeg zijn Gebruikersinterface Standaard fotobron Foto\'s nemen van camera of galerij? @@ -58,6 +60,7 @@ GPX-instellingen Opslagmap in documenten Effectief voor het volgende traject (niet het huidige) + Opslagmap-waarde mag niet leeg zijn Een map per traject Elk traject en bijbehorende bestanden in eigen map opslaan Bestandsnaam voor trajecten diff --git a/app/src/main/res/values-pl/strings-preferences.xml b/app/src/main/res/values-pl/strings-preferences.xml index a5e2fdf43..945d8ec44 100644 --- a/app/src/main/res/values-pl/strings-preferences.xml +++ b/app/src/main/res/values-pl/strings-preferences.xml @@ -85,7 +85,6 @@ Usuń uwierzytelnienia i zezwolenia dla OSM, OSMTracker zapyta o nie ponownie. Będziesz musiał ponownie autoryzować OSMTracker by wysyłać ślady. Czy jesteś pewien? Dostawca kafelków mapy - Brak w komentarzu diff --git a/app/src/main/res/values-pt-rPT/strings-preferences.xml b/app/src/main/res/values-pt-rPT/strings-preferences.xml index 7f69248d4..4c13383bc 100644 --- a/app/src/main/res/values-pt-rPT/strings-preferences.xml +++ b/app/src/main/res/values-pt-rPT/strings-preferences.xml @@ -85,7 +85,6 @@ Esquecer as credenciais e permissões do OpenStreetMap e forçar o OSMTracker a requisitá-las novamente Terá de autorizar novamente o OSMTracker para poder enviar trilhos para o OpenStreetMap. Quer continuar? Fornecedor de mosaicos de mapas - Não exportar No comentário diff --git a/app/src/main/res/values-ru/strings-preferences.xml b/app/src/main/res/values-ru/strings-preferences.xml index 0723a6ad7..4c6c5a519 100644 --- a/app/src/main/res/values-ru/strings-preferences.xml +++ b/app/src/main/res/values-ru/strings-preferences.xml @@ -85,7 +85,6 @@ Удалить учетные данные доступа к OSM и задать OSMTracker запросить их снова. Нужно будет заново авторизовать OSMTracker, чтобы закачивать треки. Вы уверены? Поставщик тайлов карт - Нет в комментарии diff --git a/app/src/main/res/values-sk/strings-preferences.xml b/app/src/main/res/values-sk/strings-preferences.xml index caaa2f11b..99dac170f 100644 --- a/app/src/main/res/values-sk/strings-preferences.xml +++ b/app/src/main/res/values-sk/strings-preferences.xml @@ -85,7 +85,6 @@ Vymaže prihlasovacie údaje a oprávnenia OSM uložené v telefóne a prinúti OSMTracker, aby si ich opätovne vyžiadal Znova sa pokúšate autorizovať OSMTracker, aby mohol nahrávať záznamy stôp. Ste si istý? Poskytovateľ mapových dlaždíc - Žiadne V komentári diff --git a/app/src/main/res/values-sr/strings-preferences.xml b/app/src/main/res/values-sr/strings-preferences.xml index e46d3c401..bb87b8c5f 100644 --- a/app/src/main/res/values-sr/strings-preferences.xml +++ b/app/src/main/res/values-sr/strings-preferences.xml @@ -82,7 +82,6 @@ Заборави OSM акредитиве и дозволе и присили OSM пратиоца да их затражи поново Мораћете поново да овластите OSM пратиоца да шаље праћења. Сигурни сте? Добављач поља мапе - Без усмерења У коментару diff --git a/app/src/main/res/values-sv/strings-preferences.xml b/app/src/main/res/values-sv/strings-preferences.xml index 8ad147578..d3a081ba7 100644 --- a/app/src/main/res/values-sv/strings-preferences.xml +++ b/app/src/main/res/values-sv/strings-preferences.xml @@ -14,9 +14,11 @@ GPS logg-intervall Använd 0 för kortast möjliga intervall (påverkar batteriets livslängd). sekunder + GPS-loggningsintervallet får inte vara tomt GPS-loggningsavstånd Minsta avstånd mellan spårpunkter i meter, använd 0 för kortast möjliga meter + Minsta avstånd mellan spårpunkter kan inte vara tomt Användargränssnitt Vald bildkälla Välj bild från kamera eller galleri? @@ -58,6 +60,7 @@ GPX-fil Lagringsmapp i dokument Gäller för nästa och kommande spår, inte aktuellt spår. + Värdet för lagringsmappen får inte vara tomt En mapp per spår Spara varje spår och relaterade filer i en egen mapp Spårens namn diff --git a/app/src/main/res/values-tr/strings-preferences.xml b/app/src/main/res/values-tr/strings-preferences.xml index 6695eb0b5..892bbeb94 100644 --- a/app/src/main/res/values-tr/strings-preferences.xml +++ b/app/src/main/res/values-tr/strings-preferences.xml @@ -82,7 +82,6 @@ OSM bilgilerini ve izinlerini unut ve OSMTracker\'ı bunları tekrar sormaya zorla İzleme yüklemek için OSMTracker\'a tekrardan yetki vermeniz gerekecek. Emin misiniz? Harita kutucuğu sağlayıcısı - Hiçbiri yorumda diff --git a/app/src/main/res/values-zh-rTW/strings-preferences.xml b/app/src/main/res/values-zh-rTW/strings-preferences.xml index 1c656f1b6..513d07a5c 100644 --- a/app/src/main/res/values-zh-rTW/strings-preferences.xml +++ b/app/src/main/res/values-zh-rTW/strings-preferences.xml @@ -14,9 +14,11 @@ GPS 記錄頻率 使用 0 會盡可能的記錄資料 (會影響電池續航力) + GPS 記錄頻率不能是空白的 GPS 記錄距離 以公尺尺度的航點之間最小距離,設為 0 則是最小的可能 公尺 + 軌跡點之間最短距離不能是空白的 使用者介面 預設照片來源 拍張照或從相簿挑選? @@ -58,6 +60,7 @@ GPX 相關設定 文件當中的儲存資料夾 設定值將在記錄下一筆軌跡資料時生效 (不是目前這筆) + 儲存目標不能是空白的 給每筆軌跡各配置一個專屬資料夾 將每筆軌跡以及相關的檔案一起放在專屬的資料夾當中 軌跡資料檔命名 @@ -85,7 +88,7 @@ 捨棄現存的 OSM 認證與權限資訊,強制 OSMTracker 重新取得它們 您必須重新認證 OSMTracker 方能繼續上傳軌跡資料,確定嗎? 地圖圖磚提供者 - + 選擇渲染地圖的圖磚提供者 於註解 @@ -93,4 +96,5 @@ 匯出羅盤方位 定義羅盤資料要如何匯出到 GPX 檔案 + 重設預設值 diff --git a/app/src/main/res/values/accessibility.xml b/app/src/main/res/values/accessibility.xml index 8b6f1e6c3..a5f171e2b 100644 --- a/app/src/main/res/values/accessibility.xml +++ b/app/src/main/res/values/accessibility.xml @@ -1,20 +1,15 @@ - + - - - OSMTracker logo - - - Zoom in - Zoom out - Zoom center - - - Satellite signal strength indicator - Record in progress indicator - - - Track status indicator - OpenStreetMap upload status indicator - - \ No newline at end of file + + OSMTracker logo + + Zoom in + Zoom out + Zoom center + + Satellite signal strength indicator + Record in progress indicator + + Track status indicator + OpenStreetMap upload status indicator + diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index d46b52824..2d73889ac 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -1,137 +1,114 @@ - + - - - Settings - - GPS - - GPS settings - Display system GPS settings screen - - Check GPS at startup - Check if GPS is disabled at startup, and offer to enable it - - Ignore GPS clock - Ignore GPS clock and use Android clock for timestamps - - Log barometric pressure [hPa] - Toggling requires track restart - - GPS logging interval - Use 0 for the shortest possible (affects battery life) - seconds - GPS logging interval cannot be empty - - GPS logging distance - Min. distance between track points in meters, use 0 for the shortest possible - meters - Min. distance between track points cannot be empty - - User interface - - Default photo source - Take photos from camera or gallery? - - Camera - Gallery - Always ask - - - Buttons presets - Choose a custom set of buttons (see docs) - DEFAULT LAYOUT - Default - DOWNLOADED LAYOUT - You don\'t have downloaded layout files - Available Layouts - Github Repository Settings - Orientation - Preferred orientation for the button screen - - Automatic - Portrait - Landscape - - - - Voice record duration - seconds - - Main screen graphic theme - Application restart required for change to take effect - - OS default - OS default (dark) - OS default (light) - High contrast - - - Screen always on - Screen will stay on while tracking. Disable to save battery - - Background map - Display OpenStreetMap map under track. Needs a data connection - Always display OpenStreetMap background? Requires a data connection - - GPX settings - Storage folder in documents - Effective for the next track (not the current one) - Storage folder value cannot be empty - One directory per track - Save each track and associated files to its own directory - Filename for named tracks - Pattern for filename if the track has a name - - Track name - Name, start date and time - Start date and time, name - Start date and time - - Filename label - This label will be appended at the end of filename - - Accuracy in GPX file - Add accuracy info in the GPX file, with waypoint name or in waypoint comment - - None - With waypoint name - In waypoint comment - - - Use HDOP approximation - Fill HDOP in GPX with an approximation value from accuracy - - Enable sound - Play sounds when voice recording starts and ends - - Track Visibility - Preferred visibility of traces uploaded to openstreetmap.org - - Private - Trackable - Public - Identifiable - - - Reset OSM authentication - Forget OSM credentials and permissions and force OSMTracker to ask them again - You\'ll have to authorize OSMTracker to upload tracks again. Are you sure? - - Map tile provider - Select the tile provider for rendering the map - - Mapnik - CyclOSM - OpenTopo - - - None - in comment - in extension - - Export compass heading - Defines if and how the compass data should be exported to the GPX file - - Reset default value + + + Settings + GPS + GPS settings + Display system GPS settings screen + Check GPS at startup + Check if GPS is disabled at startup, and offer to enable it + Ignore GPS clock + Ignore GPS clock and use Android clock for timestamps + Log barometric pressure [hPa] + Toggling requires track restart + GPS logging interval + Use 0 for the shortest possible (affects battery life) + seconds + GPS logging interval cannot be empty + GPS logging distance + Min. distance between track points in meters, use 0 for the shortest possible + meters + Min. distance between track points cannot be empty + User interface + Default photo source + Take photos from camera or gallery? + + Camera + Gallery + Always ask + + Buttons presets + Choose a custom set of buttons (see docs) + DEFAULT LAYOUT + Default + DOWNLOADED LAYOUT + You don\'t have downloaded layout files + Available Layouts + Github Repository Settings + Orientation + Preferred orientation for the button screen + + Automatic + Portrait + Landscape + + Voice record duration + seconds + Main screen graphic theme + Application restart required for change to take effect + + OS default + OS default (dark) + OS default (light) + High contrast + + Screen always on + Screen will stay on while tracking. Disable to save battery + Background map + Display OpenStreetMap map under track. Needs a data connection + Always display OpenStreetMap background? Requires a data connection + GPX settings + Storage folder in documents + Effective for the next track (not the current one) + Storage folder value cannot be empty + One directory per track + Save each track and associated files to its own directory + Filename for named tracks + Pattern for filename if the track has a name + + Track name + Name, start date and time + Start date and time, name + Start date and time + + Filename label + This label will be appended at the end of filename + Accuracy in GPX file + Add accuracy info in the GPX file, with waypoint name or in waypoint comment + + None + With waypoint name + In waypoint comment + + Use HDOP approximation + Fill HDOP in GPX with an approximation value from accuracy + Enable sound + Play sounds when voice recording starts and ends + Track Visibility + Preferred visibility of traces uploaded to openstreetmap.org + + Private + Trackable + Public + Identifiable + + Reset OSM authentication + Forget OSM credentials and permissions and force OSMTracker to ask them again + You\'ll have to authorize OSMTracker to upload tracks again. Are you sure? + Map tile provider + Select the tile provider for rendering the map + + Mapnik + CyclOSM + OpenTopo + + + None + in comment + in extension + + Export compass heading + Defines if and how the compass data should be exported to the GPX file + Reset default value diff --git a/app/src/main/res/values/strings-tags.xml b/app/src/main/res/values/strings-tags.xml index af2078cc5..398f84770 100644 --- a/app/src/main/res/values/strings-tags.xml +++ b/app/src/main/res/values/strings-tags.xml @@ -1,105 +1,103 @@ - + - - Misc - Restriction - Car - Tourism - Amenity - Amenity (+) - Way - Track - Landuse - Bus stop - Railway - Telephone - Post box - ATM - Bollard - Toilets - Shelter - Surveillance - Max 20 - Max 30 - Max 40 - Max 50 - Max 60 - Max 70 - Max 80 - Max 90 - Max 100 - Max 110 - Max 120 - Max 130 - No exit - Traffic light - One way - Fuel station - Parking - Emergency Phone - Turning circle - Speed camera - View point - Information - Picnic site - Attraction - Theme park - Castle - Monument - Museum - Cinema - Bench - Water - Pharmacy - Shop - Marina - Sport - Taxi - Hospital,\nDoctors - Recycling - Place of\nworship - Post office - Library - School - Police - Fire station - Bank - Playground - Pub - Hotel - Motel - Hostel - Restaurant - Fast food - Camp site - Bridge - Zebra crossing - Motorway - Trunk - Primary - Secondary - Tertiary - Residential - Service - Track - Cycleway - Footway - Bridleway - Steps - Living street - Pedestrian - Grade 1 - Grade 2 - Grade 3 - Grade 4 - Grade 5 - Farm - Landfill - Basin - Reservoir - Forest - Allotments - Cemetery - Recreation\nground - + Misc + Restriction + Car + Tourism + Amenity + Amenity (+) + Way + Track + Landuse + Bus stop + Railway + Telephone + Post box + ATM + Bollard + Toilets + Shelter + Surveillance + Max 20 + Max 30 + Max 40 + Max 50 + Max 60 + Max 70 + Max 80 + Max 90 + Max 100 + Max 110 + Max 120 + Max 130 + No exit + Traffic light + One way + Fuel station + Parking + Emergency Phone + Turning circle + Speed camera + View point + Information + Picnic site + Attraction + Theme park + Castle + Monument + Museum + Cinema + Bench + Water + Pharmacy + Shop + Marina + Sport + Taxi + Hospital,\nDoctors + Recycling + Place of\nworship + Post office + Library + School + Police + Fire station + Bank + Playground + Pub + Hotel + Motel + Hostel + Restaurant + Fast food + Camp site + Bridge + Zebra crossing + Motorway + Trunk + Primary + Secondary + Tertiary + Residential + Service + Track + Cycleway + Footway + Bridleway + Steps + Living street + Pedestrian + Grade 1 + Grade 2 + Grade 3 + Grade 4 + Grade 5 + Farm + Landfill + Basin + Reservoir + Forest + Allotments + Cemetery + Recreation\nground diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0f606f663..91dbf116b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -67,7 +67,7 @@ Description Tags (comma separated) You must enter a description - Visibility + Visibility Private Public Trackable diff --git a/app/src/main/res/values/waypoints.xml b/app/src/main/res/values/waypoints.xml index cb2db928e..63cdecbb5 100644 --- a/app/src/main/res/values/waypoints.xml +++ b/app/src/main/res/values/waypoints.xml @@ -1,5 +1,5 @@ - + - Voice recording - Photo + Voice recording + Photo From ee89228bd1266a49e43e7540f6ab9d95789d896a Mon Sep 17 00:00:00 2001 From: JoseAndresVargas Date: Fri, 21 Nov 2025 15:09:41 -0600 Subject: [PATCH 36/60] scope and client_id change for notes auth --- .../main/java/net/osmtracker/osm/OpenStreetMapConstants.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/net/osmtracker/osm/OpenStreetMapConstants.java b/app/src/main/java/net/osmtracker/osm/OpenStreetMapConstants.java index f51469320..2db037506 100644 --- a/app/src/main/java/net/osmtracker/osm/OpenStreetMapConstants.java +++ b/app/src/main/java/net/osmtracker/osm/OpenStreetMapConstants.java @@ -14,12 +14,13 @@ public static class Api { } public static class OAuth2 { - public static final String CLIENT_ID_PROD = "6s8TuIQoPeq89ZWUFOXU7EZ-ZaCUVtUoNZFIKCMdU-E"; + // Client ID prod was changed to test notes uploading with new scope, must be changed back + public static final String CLIENT_ID_PROD = "2gBvqUryethglDBRXIZvXA-ijLMp--r6NUHV19NyRz4"; public static final String CLIENT_ID_DEV = "94Ht-oVBJ2spydzfk18s1RV2z7NS98SBwMfzSCqLQLE"; // DEV public static final String CLIENT_ID = (DEV_MODE) ? CLIENT_ID_DEV : CLIENT_ID_PROD; - public static final String SCOPE = "write_gpx"; + public static final String SCOPE = "write_gpx write_notes"; public static final String USER_AGENT = "OSMTracker for Android™"; public static class Urls { From 349bf38ce3601da23c6500dd4b41ae29bd482171 Mon Sep 17 00:00:00 2001 From: JoseAndresVargas Date: Fri, 21 Nov 2025 15:11:15 -0600 Subject: [PATCH 37/60] Implemented notes upload using osmapi --- app/build.gradle | 6 + app/src/main/AndroidManifest.xml | 1 + .../activity/OpenStreetMapNotesUpload.java | 204 ++++++++++++++++++ .../osm/UploadToOpenStreetMapNotesTask.java | 178 +++++++++++++++ 4 files changed, 389 insertions(+) create mode 100644 app/src/main/java/net/osmtracker/activity/OpenStreetMapNotesUpload.java create mode 100644 app/src/main/java/net/osmtracker/osm/UploadToOpenStreetMapNotesTask.java diff --git a/app/build.gradle b/app/build.gradle index 7c11d2a1b..0d1a11d90 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -87,6 +87,12 @@ dependencies { exclude group: 'net.sf.kxml', module: 'kxml2' exclude group: 'xmlpull', module: 'xmlpull' } + // For upload notes to osm server + implementation ('de.westnordost:osmapi-notes:3.1'){ + // Already included in Android + exclude group: 'net.sf.kxml', module: 'kxml2' + exclude group: 'xmlpull', module: 'xmlpull' + } // App intro implementation 'com.github.AppIntro:AppIntro:6.3.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 15271702c..f1307ea79 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -110,6 +110,7 @@ + Uploads a note on OSM using the API and + * OAuth authentication.

+ * + *

This activity may be called twice during a single + * upload cycle: First to start the upload, then a second + * time when the user has authenticated using the browser.

+ * + * @author Most of the code was made by Nicolas Guillaumin, adapted by Jose Andrés Vargas Serrano + */ +public class OpenStreetMapNotesUpload extends Activity { + + private static final String TAG = OpenStreetMapNotesUpload.class.getSimpleName(); + + private double latitude; + private double longitude; + + private TextView noteContentView; + private TextView noteFooterView; + + /** URL that the browser will call once the user is authenticated */ + public final static String OAUTH2_CALLBACK_URL = "osmtracker://osm-upload/oath2-completed/"; + public final static int RC_AUTH = 7; + + private AuthorizationService authService; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View uploadNoteView = getLayoutInflater().inflate(R.layout.osm_note_upload, null); + setContentView(uploadNoteView); + setTitle(R.string.osm_note_upload); + + noteContentView = uploadNoteView.findViewById(R.id.wplist_item_name); + noteFooterView = uploadNoteView.findViewById(R.id.osm_note_footer); + + // Read and cache extras + Bundle extras = getIntent().getExtras(); + if (extras == null) { + Log.e(TAG, "Missing extras for note upload."); + finish(); + return; + } + + String initialNoteText = extras.getString("noteContent", ""); + String appName = extras.getString("appName", getString(R.string.app_name)); + String version = extras.getString("version", ""); + + if (extras.containsKey("latitude")) latitude = extras.getDouble("latitude"); + if (extras.containsKey("longitude")) longitude = extras.getDouble("longitude"); + + // fill UI with note content and note footer + noteContentView.setText(initialNoteText); + noteFooterView.setText(getString(R.string.osm_note_footer, appName, version)); + + final Button btnOk = (Button) findViewById(R.id.osm_note_upload_button_ok); + btnOk.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + startUpload(); + } + }); + final Button btnCancel = (Button) findViewById(R.id.osm_note_upload_button_cancel); + btnCancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + } + + + /** + * Either starts uploading directly if we are authenticated against OpenStreetMap, + * or ask the user to authenticate via the browser. + */ + private void startUpload() { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + if ( prefs.contains(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN) ) { + // Re-use saved token + uploadToOsm(prefs.getString(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN, "")); + } else { + // Open browser and request token + requestOsmAuth(); + } + } + /* + * Init Authorization request workflow. + */ + public void requestOsmAuth() { + // Authorization service configuration + AuthorizationServiceConfiguration serviceConfig = + new AuthorizationServiceConfiguration( + Uri.parse(OpenStreetMapConstants.OAuth2.Urls.AUTHORIZATION_ENDPOINT), + Uri.parse(OpenStreetMapConstants.OAuth2.Urls.TOKEN_ENDPOINT)); + + // Obtaining an authorization code + Uri redirectURI = Uri.parse(OAUTH2_CALLBACK_URL); + AuthorizationRequest.Builder authRequestBuilder = + new AuthorizationRequest.Builder( + serviceConfig, OpenStreetMapConstants.OAuth2.CLIENT_ID, + ResponseTypeValues.CODE, redirectURI); + AuthorizationRequest authRequest = authRequestBuilder + .setScope(OpenStreetMapConstants.OAuth2.SCOPE) + .build(); + + // Start activity. + authService = new AuthorizationService(this); + Intent authIntent = authService.getAuthorizationRequestIntent(authRequest); + startActivityForResult(authIntent, RC_AUTH); //when done onActivityResult will be called. + } + + + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + // User is returning from authentication + if (requestCode == RC_AUTH) { + // Handling the authorization response + AuthorizationResponse resp = AuthorizationResponse.fromIntent(data); + AuthorizationException ex = AuthorizationException.fromIntent(data); + // ... process the response or exception ... + if (ex != null) { + Log.e(TAG, "Authorization Error. Exception received from server."); + Log.e(TAG, ex.getMessage()); + } else if (resp == null) { + Log.e(TAG, "Authorization Error. Null response from server."); + } else { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + + //Exchanging the authorization code + authService.performTokenRequest( + resp.createTokenExchangeRequest(), + new AuthorizationService.TokenResponseCallback() { + @Override public void onTokenRequestCompleted( + TokenResponse resp, AuthorizationException ex) { + if (resp != null) { + // exchange succeeded + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN, resp.accessToken); + editor.apply(); + //continue with the note Upload. + uploadToOsm(resp.accessToken); + } else { + // authorization failed, check ex for more details + Log.e(TAG, "OAuth failed."); + } + } + }); + } + } else { + Log.e(TAG, "Unexpected requestCode:" + requestCode + "."); + } + } + + /** + * Uploads notes to OSM. + */ + public void uploadToOsm(String accessToken) { + String noteText = noteContentView.getText().toString(); + String footer = noteFooterView.getText().toString(); + if (!footer.isEmpty()) { + noteText = noteText + "\n\n" + footer; + } + new UploadToOpenStreetMapNotesTask( + OpenStreetMapNotesUpload.this, + accessToken, + noteText, + latitude, + longitude + ).execute(); + } + + +} diff --git a/app/src/main/java/net/osmtracker/osm/UploadToOpenStreetMapNotesTask.java b/app/src/main/java/net/osmtracker/osm/UploadToOpenStreetMapNotesTask.java new file mode 100644 index 000000000..21e676312 --- /dev/null +++ b/app/src/main/java/net/osmtracker/osm/UploadToOpenStreetMapNotesTask.java @@ -0,0 +1,178 @@ +package net.osmtracker.osm; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.SharedPreferences.Editor; +import android.os.AsyncTask; +import android.preference.PreferenceManager; +import android.util.Log; + +import net.osmtracker.OSMTracker; +import net.osmtracker.R; +import net.osmtracker.util.DialogUtils; + +import de.westnordost.osmapi.OsmConnection; +import de.westnordost.osmapi.common.errors.OsmAuthorizationException; +import de.westnordost.osmapi.common.errors.OsmBadUserInputException; +import de.westnordost.osmapi.map.data.OsmLatLon; +import de.westnordost.osmapi.notes.Note; // Note object +import de.westnordost.osmapi.notes.NotesApi; // Api for uploading notes to OSM +import de.westnordost.osmapi.map.data.LatLon; // Data type for location points, maybe I'll put it in the dialog file + +/** + * Uploads a note to OpenStreetMap + * + * @author Most of the code was made by Nicolas Guillaumin, adapted by Jose Andrés Vargas Serrano + */ +public class UploadToOpenStreetMapNotesTask extends AsyncTask { + + private static final String TAG = UploadToOpenStreetMapNotesTask.class.getSimpleName(); + + /** Upload progress dialog */ + private ProgressDialog dialog; + + private final Activity activity; + private final String accessToken; + + /** Note text */ + private final String noteText; + + /** Note longitude */ + private final double longitude; + + /** Note latitude */ + private final double latitude; + + /** + * Error message, or text of the response returned by OSM + * if the request completed + */ + private String errorMsg; + + /** + * Either the HTTP result code, or -1 for an internal error + */ + private int resultCode = -1; + private final int authorizationErrorResultCode = -2; + private final int anotherErrorResultCode = -3; + private final int okResultCode = 1; + + // Not using an activity yet + public UploadToOpenStreetMapNotesTask(Activity activity, String accessToken, String noteText, + double latitude, double longitude) { + this.activity = activity; + this.accessToken = accessToken; + this.noteText = noteText; + this.longitude = longitude; + this.latitude = latitude; + } + + @Override + protected void onPreExecute() { + try { + // Display progress dialog + dialog = new ProgressDialog(activity); + dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + dialog.setIndeterminate(true); + dialog.setTitle(R.string.osm_note_upload); + + dialog.setCancelable(false); + dialog.show(); + + } catch (Exception e) { + Log.e(TAG, "onPreExecute() failed", e); + errorMsg = e.getLocalizedMessage(); + cancel(true); + } + } + + @Override + protected void onPostExecute(Void result) { + switch (resultCode) { + case -1: + dialog.dismiss(); + // Internal error, the request didn't start at all + DialogUtils.showErrorDialog(activity, + activity.getResources().getString(R.string.osm_note_upload_error) + + ": " + errorMsg); + break; + case okResultCode: + dialog.dismiss(); + + new AlertDialog.Builder(activity) + .setTitle(android.R.string.dialog_alert_title) + .setIcon(android.R.drawable.ic_dialog_info) + .setMessage(R.string.osm_upload_sucess) + .setCancelable(true) + .setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + activity.finish(); + } + }).create().show(); + + break; + case authorizationErrorResultCode: + dialog.dismiss(); + Log.e(TAG, "onPostExecute() authorization failed: " + errorMsg + " (" + resultCode + ")"); + // Authorization issue. Provide a way to clear credentials + new AlertDialog.Builder(activity) + .setTitle(android.R.string.dialog_alert_title) + .setIcon(android.R.drawable.ic_dialog_alert) + .setMessage(R.string.osm_note_upload_unauthorized) + .setCancelable(true) + .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }) + .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Editor editor = PreferenceManager.getDefaultSharedPreferences(activity).edit(); + editor.remove(OSMTracker.Preferences.KEY_OSM_OAUTH2_ACCESSTOKEN); + editor.commit(); + + dialog.dismiss(); + } + }).create().show(); + break; + + default: + // Another error. Display OSM response + dialog.dismiss(); + // Internal error, the request didn't start at all + Log.e(TAG, "onPostExecute() default failed: " + errorMsg + " (" + resultCode + ")"); + DialogUtils.showErrorDialog(activity, + activity.getResources().getString(R.string.osm_note_upload_error) + + ": " + errorMsg); + } + } + + @Override + protected Void doInBackground(Void... params) { + OsmConnection osm = new OsmConnection(OpenStreetMapConstants.Api.OSM_API_URL_PATH, + OpenStreetMapConstants.OAuth2.USER_AGENT, accessToken); + + try { + LatLon point = new OsmLatLon(latitude, longitude); + Note note = new NotesApi(osm).create(point, noteText); + resultCode = okResultCode; + } catch (/*IOException |*/ IllegalArgumentException | OsmBadUserInputException e) { + Log.d(TAG, e.getMessage()); + resultCode = -1; //internal error. + } catch (OsmAuthorizationException oae) { + Log.d(TAG, "OsmAuthorizationException"); + resultCode = authorizationErrorResultCode; + } catch (Exception e) { + Log.e(TAG, e.getMessage()); + resultCode = anotherErrorResultCode; + } + return null; + } + +} From bea2013b221e0a4881fbe491a19bcbec474c41ff Mon Sep 17 00:00:00 2001 From: JoseAndresVargas Date: Fri, 21 Nov 2025 15:12:10 -0600 Subject: [PATCH 38/60] Notes upload UI text added --- app/src/main/res/layout/osm_note_upload.xml | 65 +++++++++++++++++++++ app/src/main/res/values/strings.xml | 9 +++ 2 files changed, 74 insertions(+) create mode 100644 app/src/main/res/layout/osm_note_upload.xml diff --git a/app/src/main/res/layout/osm_note_upload.xml b/app/src/main/res/layout/osm_note_upload.xml new file mode 100644 index 000000000..268319633 --- /dev/null +++ b/app/src/main/res/layout/osm_note_upload.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + +