From 9434d2ffa3829a4f7a74d20b41e7af38b645f682 Mon Sep 17 00:00:00 2001
From: Milton Barrera
Date: Tue, 11 Feb 2025 19:39:21 -0600
Subject: [PATCH 1/5] New GitHubUtils class to interact with GitHub API
---
.../java/net/osmtracker/util/Callback.java | 17 +++++
.../java/net/osmtracker/util/GitHubUtils.java | 75 +++++++++++++++++++
2 files changed, 92 insertions(+)
create mode 100644 app/src/main/java/net/osmtracker/util/Callback.java
create mode 100644 app/src/main/java/net/osmtracker/util/GitHubUtils.java
diff --git a/app/src/main/java/net/osmtracker/util/Callback.java b/app/src/main/java/net/osmtracker/util/Callback.java
new file mode 100644
index 00000000..78df7286
--- /dev/null
+++ b/app/src/main/java/net/osmtracker/util/Callback.java
@@ -0,0 +1,17 @@
+package net.osmtracker.util;
+
+/**
+ * A generic callback interface used for asynchronous operations.
+ * Implementations of this interface should define how to handle the result
+ * of an asynchronous task.
+ */
+public interface Callback {
+ /**
+ * Called when the asynchronous operation is completed.
+ * Implementations should handle the provided result accordingly.
+ *
+ * @param result The result of the operation, which may be {@code null} if an error occurs.
+ * @return A string value that may be used by the calling function, if applicable.
+ */
+ String onResult(String result);
+}
diff --git a/app/src/main/java/net/osmtracker/util/GitHubUtils.java b/app/src/main/java/net/osmtracker/util/GitHubUtils.java
new file mode 100644
index 00000000..27d5421a
--- /dev/null
+++ b/app/src/main/java/net/osmtracker/util/GitHubUtils.java
@@ -0,0 +1,75 @@
+package net.osmtracker.util;
+
+import android.os.AsyncTask;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+/**
+ * Utility class for interacting with the GitHub API.
+ * Provides methods to retrieve file information and manage file uploads.
+ *
+ * This class includes methods to:
+ *
+ * - Generate a unique filename within a GitHub repository.
+ * - Retrieve the SHA hash of a file stored in a GitHub repository.
+ *
+ *
+ *
+ * It requires a valid GitHub authentication token for API requests.
+ */
+public class GitHubUtils {
+ /**
+ * Retrieves the SHA hash of a file in a GitHub repository.
+ * If the file does not exist, it returns {@code null}.
+ *
+ * @param repoOwner The owner of the repository (user or organization).
+ * @param repoName The name of the GitHub repository.
+ * @param repoFilePath The file path in the repository.
+ * @param token The GitHub authentication token with appropriate permissions.
+ * @return The SHA hash of the file if it exists, or {@code null} if the file is not found.
+ * @throws IOException If an I/O error occurs while making the request.
+ * @throws JSONException If an error occurs while parsing the JSON response.
+ */
+ public static void getFileSHAAsync(String repoOwner, String repoName, String repoFilePath, String token, Callback callback) {
+ new AsyncTask() {
+ @Override
+ protected String doInBackground(Void... voids) {
+ try {
+ String apiUrl = "https://api.github.com/repos/" + repoOwner + "/" + repoName + "/contents/" + repoFilePath;
+ System.out.println("Fetching SHA: " + apiUrl);
+ HttpURLConnection connection = (HttpURLConnection) new URL(apiUrl).openConnection();
+ connection.setRequestMethod("GET");
+ connection.setRequestProperty("Authorization", "Bearer " + token);
+ connection.setRequestProperty("Accept", "application/vnd.github.v3+json");
+
+ if (connection.getResponseCode() == 200) {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ StringBuilder response = new StringBuilder();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ response.append(line);
+ }
+ reader.close();
+ JSONObject jsonResponse = new JSONObject(response.toString());
+ return jsonResponse.getString("sha");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(String sha) {
+ callback.onResult(sha); // Return result via callback
+ }
+ }.execute();
+ }
+}
From 4cd91ad674c9490e9dd4eb45e7f4c11bd7f0f89d Mon Sep 17 00:00:00 2001
From: Milton Barrera
Date: Tue, 11 Feb 2025 19:41:53 -0600
Subject: [PATCH 2/5] methods to get a unique name for a file in a GitHub
repository
---
.../java/net/osmtracker/util/GitHubUtils.java | 50 +++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/app/src/main/java/net/osmtracker/util/GitHubUtils.java b/app/src/main/java/net/osmtracker/util/GitHubUtils.java
index 27d5421a..460a3144 100644
--- a/app/src/main/java/net/osmtracker/util/GitHubUtils.java
+++ b/app/src/main/java/net/osmtracker/util/GitHubUtils.java
@@ -72,4 +72,54 @@ protected void onPostExecute(String sha) {
}
}.execute();
}
+
+ /**
+ * Asynchronously generates a unique filename in a GitHub repository.
+ * If the file already exists, a number is appended before the extension.
+ *
+ * @param repoOwner The owner of the repository.
+ * @param repoName The name of the GitHub repository.
+ * @param repoFilePath The initial file path in the repository.
+ * @param token The GitHub authentication token.
+ * @param callback Callback to return the generated filename.
+ */
+ public static void getGHFilenameAsync(String repoOwner, String repoName, final String repoFilePath, String token, Callback callback) {
+ String filename = repoFilePath.substring(0, repoFilePath.lastIndexOf("."));
+ String extension = repoFilePath.substring(repoFilePath.lastIndexOf("."));
+ checkFileExists(repoOwner, repoName, filename, extension, 0, token, callback);
+ }
+
+ /**
+ * Recursively checks if a file exists and generates a unique filename.
+ *
+ * @param repoOwner The owner of the repository.
+ * @param repoName The GitHub repository name.
+ * @param filename The base filename (without extension).
+ * @param extension The file extension.
+ * @param count The current attempt number for uniqueness.
+ * @param token The GitHub authentication token.
+ * @param callback Callback to return the final unique filename.
+ */
+ private static void checkFileExists(String repoOwner, String repoName, String filename, String extension, int count, String token, Callback callback) {
+ String newFilename;// (count == 0) ? filename + extension : filename + "(" + count + ")" + extension;
+ if (count == 0) {
+ newFilename = filename + extension;
+ } else {
+ newFilename = filename + "(" + count + ")" + extension;
+ }
+
+ getFileSHAAsync(repoOwner, repoName, newFilename, token, new Callback() {
+ @Override
+ public String onResult(String sha) {
+ if (sha == null) {
+ // File does not exist, return the new unique filename
+ callback.onResult(newFilename);
+ } else {
+ // File exists, recursively try with the next count
+ checkFileExists(repoOwner, repoName, filename, extension, count + 1, token, callback);
+ }
+ return null;
+ }
+ });
+ }
}
From 28cc6c7fe660f575a5d74d8159e02640097cf178 Mon Sep 17 00:00:00 2001
From: Milton Barrera
Date: Tue, 11 Feb 2025 19:45:25 -0600
Subject: [PATCH 3/5] Using unique name for the file on commit
---
.../net/osmtracker/activity/GitHubUpload.java | 20 +++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/net/osmtracker/activity/GitHubUpload.java b/app/src/main/java/net/osmtracker/activity/GitHubUpload.java
index d2265cf3..7b1a2ae9 100644
--- a/app/src/main/java/net/osmtracker/activity/GitHubUpload.java
+++ b/app/src/main/java/net/osmtracker/activity/GitHubUpload.java
@@ -31,7 +31,9 @@
import net.osmtracker.GitHubUser;
import net.osmtracker.R;
import net.osmtracker.db.DbGitHubUser;
+import net.osmtracker.util.Callback;
import net.osmtracker.util.DialogUtils;
+import net.osmtracker.util.GitHubUtils;
import org.json.JSONArray;
import org.json.JSONException;
@@ -102,7 +104,22 @@ private void uploadCommit() {
}
}
- startUploadGitHub(encondedFile.toString(), file.getName(), commitMsj);
+ String repoOwner = getRepoName().substring(0, getRepoName().indexOf("/")).replace(".base64", "");
+ String repoName = getRepoName().substring(getRepoName().indexOf("/") + 1);
+ String repoFilePath = file.getName().replace(".base64", "");
+ GitHubUtils.getGHFilenameAsync(repoOwner, repoName, repoFilePath, gitHubUser.getToken(),
+ new Callback() {
+ @Override
+ public String onResult(String result) {
+ if (result != null) {
+ System.out.println("uploading to GitHub: " + result);
+ startUploadGitHub(encondedFile.toString(), result, commitMsj);
+ } else {
+ System.out.println("Error while getting filename.");
+ }
+ return result;
+ }
+ });
} catch (IOException e) {
Toast.makeText(GitHubUpload.this, R.string.gpx_file_read_error, Toast.LENGTH_SHORT).show();
e.printStackTrace();
@@ -147,7 +164,6 @@ private void openActivityOnClick(int btnId, Class extends Activity> destinatio
* Either starts uploading directly if we are authenticated against GitHub
*/
private void startUploadGitHub(final String fileInBase64, String filename, String commitMsj){
- filename = filename.substring(0, filename.lastIndexOf("."));
String fullURL = getBaseURL()+"/repos/"+getRepoName()+"/contents/"+filename;
ProgressDialog progressDialog = new ProgressDialog(this);
From 832d812d79f60de0e91ac95ba8bc2840c910923d Mon Sep 17 00:00:00 2001
From: Milton Barrera
Date: Tue, 11 Feb 2025 19:53:42 -0600
Subject: [PATCH 4/5] Using R.string for progress dialog
---
app/src/main/java/net/osmtracker/activity/GitHubUpload.java | 2 +-
app/src/main/res/values-es/strings.xml | 1 +
app/src/main/res/values/strings.xml | 1 +
3 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/net/osmtracker/activity/GitHubUpload.java b/app/src/main/java/net/osmtracker/activity/GitHubUpload.java
index 7b1a2ae9..d815bdad 100644
--- a/app/src/main/java/net/osmtracker/activity/GitHubUpload.java
+++ b/app/src/main/java/net/osmtracker/activity/GitHubUpload.java
@@ -167,7 +167,7 @@ private void startUploadGitHub(final String fileInBase64, String filename, Strin
String fullURL = getBaseURL()+"/repos/"+getRepoName()+"/contents/"+filename;
ProgressDialog progressDialog = new ProgressDialog(this);
- progressDialog.setMessage("Subiendo el archivo " + filename + "...");
+ progressDialog.setMessage(R.string.uploading_file + filename);
progressDialog.setCancelable(true);
progressDialog.show();
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 05f78ac1..49294af6 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -185,6 +185,7 @@
Error al obtener información del repositorio
Subido exitosamente"
Error al subir
+ Subiendo:
Error al leer el archivo GPX
No se encontró el archivo GPX
Selecciono el elemento:
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fa17520a..c4534692 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -211,6 +211,7 @@
Error with repository information
Successfully uploaded"
Error uploading
+ Uploading file:
Error reading the GPX file
GPX file not found
Item Selected:
From 4fbab9c6126573a8e3d2172a95a43a8c9f525bcf Mon Sep 17 00:00:00 2001
From: Milton Barrera
Date: Wed, 7 May 2025 00:18:01 -0600
Subject: [PATCH 5/5] Manually performed translations are deleted
---
app/src/main/res/values-es/strings.xml | 50 +-------------------------
1 file changed, 1 insertion(+), 49 deletions(-)
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 49294af6..6baa11ac 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -40,7 +40,6 @@
Exportar como GPX
Compartir GPX
Subir a OpenStreetMap
- Subir a GitHub
Visualizar
Detalles
Traza #{0}
@@ -175,53 +174,6 @@
Repositorio de GitHub válido
Repositorio de GitHub inválido
-
- Creado exitosamente
- Error al crear
- Error en base de datos
- Guardado exitosamente
- Error al guardar
- Estado del pull request:
- Error al obtener información del repositorio
- Subido exitosamente"
- Error al subir
- Subiendo:
- Error al leer el archivo GPX
- No se encontró el archivo GPX
- Selecciono el elemento:
- Privado:
- Indique el nombre del repositorio
- Campo requerido
-
- Configurar
- Token de GitHub:
- Obtener token
- Cómo obtener un token de GitHub:
- 1. Haga clic en el botón para abrir el sitio web de GitHub y crear un token. Inicie sesión con su cuenta de GitHub si es necesario.
- 2. Seleccione \"Tokens (Clásicos)\" y haga clic en el botón \"Generar nuevo token\".
- 3. Asigne un nombre descriptivo a su token.
- 4. Seleccione una fecha de expiración. Recomendamos \"Sin expiración\" para evitar repetir este paso.
- 5. Seleccione los permisos que desee otorgar al token (OSMTracker solo necesita el permiso de repositorio).
- 6. Haga clic en el botón \"Generar token\".
- 7. Copie el token generado y péguelo en el campo \"Token de GitHub\".
- ⚠️ Puede guardar en blanco para borrar sus credenciales.
-
- Mensaje del commit:
- Crear\nfork
- Abrir pull request
- Seleccione un repositorio
- Crear repositorio
- Hacer commit
- Configurar
-
- Usuario del repositorio original
- Nombre del repositorio original
- Crear
-
- Título del Pull Request
- Descripción del Pull Request
-
-
Introducción a OSMTracker para Android ™
@@ -231,4 +183,4 @@
Feliz trazado 🗺 😎
OSMTracker para Android usará su ubicación GPS para registrar puntos de traza y puntos, incluso cuando la aplicación se está ejecutando en segundo plano.
Tus datos no se utilizan para respaldar anuncios.
-
+
\ No newline at end of file