mirror of
https://github.com/russok/FitoTrack.git
synced 2025-10-29 00:32:11 -07:00
#24 Upload workouts to OpenStreetMap as GPS-Trace
This commit is contained in:
parent
7a61b94696
commit
d35c8a7428
@ -74,8 +74,14 @@ dependencies {
|
|||||||
implementation 'stax:stax-api:1.0.1'
|
implementation 'stax:stax-api:1.0.1'
|
||||||
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.8'
|
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.8'
|
||||||
|
|
||||||
|
implementation ('de.westnordost:osmapi-traces:1.0')
|
||||||
|
configurations {
|
||||||
|
compile.exclude group: 'net.sf.kxml', module: 'kxml2' // already included in Android
|
||||||
|
}
|
||||||
|
implementation 'oauth.signpost:signpost-commonshttp4:1.2.1.2'
|
||||||
|
|
||||||
// Android Room
|
// Android Room
|
||||||
def room_version = "2.2.0-beta01"
|
def room_version = "2.2.0"
|
||||||
annotationProcessor "androidx.room:room-compiler:$room_version"
|
annotationProcessor "androidx.room:room-compiler:$room_version"
|
||||||
implementation "androidx.room:room-runtime:$room_version"
|
implementation "androidx.room:room-runtime:$room_version"
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,8 @@
|
|||||||
package de.tadris.fitness.activity;
|
package de.tadris.fitness.activity;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -28,21 +30,31 @@ import android.util.TypedValue;
|
|||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.CheckBox;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import de.tadris.fitness.Instance;
|
import de.tadris.fitness.Instance;
|
||||||
import de.tadris.fitness.R;
|
import de.tadris.fitness.R;
|
||||||
|
import de.tadris.fitness.data.WorkoutSample;
|
||||||
|
import de.tadris.fitness.osm.OAuthAuthentication;
|
||||||
|
import de.tadris.fitness.osm.OsmTraceUploader;
|
||||||
import de.tadris.fitness.util.DialogUtils;
|
import de.tadris.fitness.util.DialogUtils;
|
||||||
import de.tadris.fitness.util.gpx.GpxExporter;
|
import de.tadris.fitness.util.gpx.GpxExporter;
|
||||||
import de.tadris.fitness.util.unit.UnitUtils;
|
import de.tadris.fitness.util.unit.UnitUtils;
|
||||||
import de.tadris.fitness.view.ProgressDialogController;
|
import de.tadris.fitness.view.ProgressDialogController;
|
||||||
|
import de.westnordost.osmapi.traces.GpsTraceDetails;
|
||||||
|
import oauth.signpost.OAuthConsumer;
|
||||||
|
|
||||||
public class ShowWorkoutActivity extends WorkoutActivity implements DialogUtils.WorkoutDeleter {
|
public class ShowWorkoutActivity extends WorkoutActivity implements DialogUtils.WorkoutDeleter {
|
||||||
|
|
||||||
@ -211,7 +223,55 @@ public class ShowWorkoutActivity extends WorkoutActivity implements DialogUtils.
|
|||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private OAuthConsumer oAuthConsumer= null;
|
||||||
|
private void prepareUpload(){
|
||||||
|
OAuthAuthentication authentication= new OAuthAuthentication(mHandler, this, new OAuthAuthentication.OAuthAuthenticationListener() {
|
||||||
|
@Override
|
||||||
|
public void authenticationFailed() {
|
||||||
|
new AlertDialog.Builder(ShowWorkoutActivity.this)
|
||||||
|
.setTitle(R.string.error)
|
||||||
|
.setMessage(R.string.authenticationFailed)
|
||||||
|
.setPositiveButton(R.string.okay, null)
|
||||||
|
.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void authenticationComplete(OAuthConsumer consumer) {
|
||||||
|
oAuthConsumer= consumer;
|
||||||
|
showUploadOptions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
authentication.authenticateIfNecessary();
|
||||||
|
}
|
||||||
|
|
||||||
|
AlertDialog dialog= null;
|
||||||
|
private void showUploadOptions(){
|
||||||
|
dialog= new AlertDialog.Builder(this)
|
||||||
|
.setTitle(R.string.actionUploadToOSM)
|
||||||
|
.setView(R.layout.dialog_upload_osm)
|
||||||
|
.setPositiveButton(R.string.upload, (dialogInterface, i) -> {
|
||||||
|
CheckBox checkBox= dialog.findViewById(R.id.uploadCutting);
|
||||||
|
Spinner spinner= dialog.findViewById(R.id.uploadVisibility);
|
||||||
|
EditText descriptionEdit= dialog.findViewById(R.id.uploadDescription);
|
||||||
|
String description= descriptionEdit.getText().toString().trim();
|
||||||
|
GpsTraceDetails.Visibility visibility;
|
||||||
|
switch (spinner.getSelectedItemPosition()){
|
||||||
|
case 0: visibility= GpsTraceDetails.Visibility.IDENTIFIABLE; break;
|
||||||
|
default:
|
||||||
|
case 1: visibility= GpsTraceDetails.Visibility.TRACKABLE; break;
|
||||||
|
case 2: visibility= GpsTraceDetails.Visibility.PRIVATE; break;
|
||||||
|
}
|
||||||
|
uploadToOsm(checkBox.isChecked(), visibility, description);
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadToOsm(boolean cut, GpsTraceDetails.Visibility visibility, String description){
|
||||||
|
List<WorkoutSample> samples = new ArrayList<>(this.samples);
|
||||||
|
new OsmTraceUploader(this, mHandler, workout, samples, visibility, oAuthConsumer, cut, description).upload();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
@ -223,6 +283,9 @@ public class ShowWorkoutActivity extends WorkoutActivity implements DialogUtils.
|
|||||||
case R.id.actionExportGpx:
|
case R.id.actionExportGpx:
|
||||||
exportToGpx();
|
exportToGpx();
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.actionUploadOSM:
|
||||||
|
prepareUpload();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,9 +80,13 @@ public class Workout{
|
|||||||
if(comment.length() > 2){
|
if(comment.length() > 2){
|
||||||
return comment;
|
return comment;
|
||||||
}else{
|
}else{
|
||||||
return SimpleDateFormat.getDateTimeInstance().format(new Date(start));
|
return getDateString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDateString(){
|
||||||
|
return SimpleDateFormat.getDateTimeInstance().format(new Date(start));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
29
app/src/main/java/de/tadris/fitness/osm/GpsTraceLatLong.java
Normal file
29
app/src/main/java/de/tadris/fitness/osm/GpsTraceLatLong.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package de.tadris.fitness.osm;
|
||||||
|
|
||||||
|
import de.tadris.fitness.data.WorkoutSample;
|
||||||
|
import de.westnordost.osmapi.map.data.LatLon;
|
||||||
|
|
||||||
|
public class GpsTraceLatLong implements LatLon {
|
||||||
|
|
||||||
|
private final double latitude;
|
||||||
|
private final double longitude;
|
||||||
|
|
||||||
|
public GpsTraceLatLong(double latitude, double longitude) {
|
||||||
|
this.latitude = latitude;
|
||||||
|
this.longitude = longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GpsTraceLatLong(WorkoutSample sample) {
|
||||||
|
this(sample.lat, sample.lon);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getLatitude() {
|
||||||
|
return latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getLongitude() {
|
||||||
|
return longitude;
|
||||||
|
}
|
||||||
|
}
|
||||||
132
app/src/main/java/de/tadris/fitness/osm/OAuthAuthentication.java
Normal file
132
app/src/main/java/de/tadris/fitness/osm/OAuthAuthentication.java
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
package de.tadris.fitness.osm;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.provider.Browser;
|
||||||
|
import android.text.InputType;
|
||||||
|
import android.widget.EditText;
|
||||||
|
|
||||||
|
import de.tadris.fitness.R;
|
||||||
|
import de.tadris.fitness.view.ProgressDialogController;
|
||||||
|
import oauth.signpost.OAuth;
|
||||||
|
import oauth.signpost.OAuthConsumer;
|
||||||
|
import oauth.signpost.OAuthProvider;
|
||||||
|
import oauth.signpost.exception.OAuthException;
|
||||||
|
|
||||||
|
public class OAuthAuthentication {
|
||||||
|
|
||||||
|
private OAuthConsumer oAuthConsumer= OAuthUrlProvider.getDefaultConsumer();
|
||||||
|
private OAuthProvider oAuthProvider= OAuthUrlProvider.getDefaultProvider();
|
||||||
|
|
||||||
|
private Handler handler;
|
||||||
|
private Activity activity;
|
||||||
|
private ProgressDialogController dialogController;
|
||||||
|
private SharedPreferences preferences;
|
||||||
|
private OAuthAuthenticationListener listener;
|
||||||
|
|
||||||
|
public OAuthAuthentication(Handler handler, Activity activity, OAuthAuthenticationListener listener) {
|
||||||
|
this.handler = handler;
|
||||||
|
this.activity = activity;
|
||||||
|
dialogController= new ProgressDialogController(activity, activity.getString(R.string.uploading));
|
||||||
|
this.preferences= activity.getSharedPreferences("osm_oauth", Context.MODE_PRIVATE);
|
||||||
|
this.listener= listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void authenticateIfNecessary(){
|
||||||
|
if(isAuthenticated()){
|
||||||
|
loadAccessToken();
|
||||||
|
listener.authenticationComplete(oAuthConsumer);
|
||||||
|
}else{
|
||||||
|
retrieveRequestToken();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAuthenticated(){
|
||||||
|
return preferences.getBoolean("authenticated", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void retrieveRequestToken(){
|
||||||
|
dialogController.show();
|
||||||
|
dialogController.setIndeterminate(true);
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
String authUrl = oAuthProvider.retrieveRequestToken(oAuthConsumer, OAuth.OUT_OF_BAND);
|
||||||
|
handler.post(() -> {
|
||||||
|
Intent intent= new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl));
|
||||||
|
intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName());
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
|
activity.startActivity(intent);
|
||||||
|
showEnterVerificationCodeDialog();
|
||||||
|
dialogController.cancel();
|
||||||
|
});
|
||||||
|
} catch (OAuthException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
handler.post(() -> {
|
||||||
|
dialogController.cancel();
|
||||||
|
listener.authenticationFailed();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showEnterVerificationCodeDialog(){
|
||||||
|
EditText editText= new EditText(activity);
|
||||||
|
editText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
|
||||||
|
editText.setSingleLine(true);
|
||||||
|
|
||||||
|
AlertDialog dialog= new AlertDialog.Builder(activity)
|
||||||
|
.setTitle(R.string.enterVerificationCode).setView(editText).setPositiveButton(R.string.okay, (dialogInterface, i) -> {
|
||||||
|
new Thread(() -> retrieveAccessToken(editText.getText().toString().trim())).start();
|
||||||
|
dialogInterface.cancel();
|
||||||
|
}).setNegativeButton(R.string.cancel, null).setCancelable(false).create();
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadAccessToken(){
|
||||||
|
oAuthConsumer.setTokenWithSecret(preferences.getString("accessToken", ""),
|
||||||
|
preferences.getString("tokenSecret", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveAccessToken(){
|
||||||
|
preferences.edit()
|
||||||
|
.putString("accessToken", oAuthConsumer.getToken())
|
||||||
|
.putString("tokenSecret", oAuthConsumer.getTokenSecret())
|
||||||
|
.putBoolean("authenticated", true).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearAccessToken(){
|
||||||
|
preferences.edit().putBoolean("authenticated", false).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void retrieveAccessToken(String verificationCode){
|
||||||
|
handler.post(() -> dialogController.show());
|
||||||
|
try{
|
||||||
|
oAuthProvider.retrieveAccessToken(oAuthConsumer, verificationCode);
|
||||||
|
handler.post(() -> {
|
||||||
|
dialogController.cancel();
|
||||||
|
saveAccessToken();
|
||||||
|
listener.authenticationComplete(oAuthConsumer);
|
||||||
|
});
|
||||||
|
}catch (OAuthException e){
|
||||||
|
handler.post(() -> {
|
||||||
|
dialogController.cancel();
|
||||||
|
listener.authenticationFailed();
|
||||||
|
});
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OAuthAuthenticationListener{
|
||||||
|
|
||||||
|
void authenticationFailed();
|
||||||
|
|
||||||
|
void authenticationComplete(OAuthConsumer consumer);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package de.tadris.fitness.osm;
|
||||||
|
|
||||||
|
import oauth.signpost.OAuthConsumer;
|
||||||
|
import oauth.signpost.OAuthProvider;
|
||||||
|
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
|
||||||
|
import oauth.signpost.commonshttp.CommonsHttpOAuthProvider;
|
||||||
|
|
||||||
|
public class OAuthUrlProvider {
|
||||||
|
|
||||||
|
static private final String CONSUMER_KEY= "jFL9grFmAo5ZS720YDDRXdSOb7F0IZQf9lnY1PHq";
|
||||||
|
static private final String CONSUMER_SECRET= "oH969vYW60fZLco6E09UQl3uFXqjl4siQbOL0q9q";
|
||||||
|
|
||||||
|
static OAuthConsumer getDefaultConsumer(){
|
||||||
|
return new CommonsHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
|
||||||
|
}
|
||||||
|
|
||||||
|
static OAuthProvider getDefaultProvider(){
|
||||||
|
return new CommonsHttpOAuthProvider(URL_TOKEN_REQUEST, URL_TOKEN_ACCESS, URL_AUTHORIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static private final String URL_TOKEN_REQUEST= "https://www.openstreetmap.org/oauth/request_token";
|
||||||
|
static private final String URL_TOKEN_ACCESS= "https://www.openstreetmap.org/oauth/access_token";
|
||||||
|
static private final String URL_AUTHORIZE= "https://www.openstreetmap.org/oauth/authorize";
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
116
app/src/main/java/de/tadris/fitness/osm/OsmTraceUploader.java
Normal file
116
app/src/main/java/de/tadris/fitness/osm/OsmTraceUploader.java
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package de.tadris.fitness.osm;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.tadris.fitness.R;
|
||||||
|
import de.tadris.fitness.data.Workout;
|
||||||
|
import de.tadris.fitness.data.WorkoutSample;
|
||||||
|
import de.tadris.fitness.view.ProgressDialogController;
|
||||||
|
import de.westnordost.osmapi.OsmConnection;
|
||||||
|
import de.westnordost.osmapi.traces.GpsTraceDetails;
|
||||||
|
import de.westnordost.osmapi.traces.GpsTracesDao;
|
||||||
|
import de.westnordost.osmapi.traces.GpsTrackpoint;
|
||||||
|
import oauth.signpost.OAuthConsumer;
|
||||||
|
|
||||||
|
public class OsmTraceUploader {
|
||||||
|
|
||||||
|
private static final int CUT_DISTANCE= 300;
|
||||||
|
|
||||||
|
private Activity activity;
|
||||||
|
private Handler handler;
|
||||||
|
private Workout workout;
|
||||||
|
private List<WorkoutSample> samples;
|
||||||
|
private GpsTraceDetails.Visibility visibility;
|
||||||
|
private OAuthConsumer consumer;
|
||||||
|
private boolean cut;
|
||||||
|
private ProgressDialogController dialogController;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
public OsmTraceUploader(Activity activity, Handler handler, Workout workout, List<WorkoutSample> samples, GpsTraceDetails.Visibility visibility, OAuthConsumer consumer, boolean cut, String description) {
|
||||||
|
this.activity = activity;
|
||||||
|
this.handler = handler;
|
||||||
|
this.workout = workout;
|
||||||
|
this.samples = samples;
|
||||||
|
this.visibility = visibility;
|
||||||
|
this.consumer = consumer;
|
||||||
|
this.cut = cut;
|
||||||
|
this.description= description;
|
||||||
|
this.dialogController= new ProgressDialogController(activity, activity.getString(R.string.uploading));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cut(){
|
||||||
|
cut(false);
|
||||||
|
cut(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cut(boolean last){
|
||||||
|
double distance= 0;
|
||||||
|
int count= 0;
|
||||||
|
WorkoutSample lastSample= samples.remove(last ? samples.size()-1 : 0);
|
||||||
|
while(distance < CUT_DISTANCE){
|
||||||
|
WorkoutSample currentSample= samples.remove(last ? samples.size()-1 : 0);
|
||||||
|
distance+= lastSample.toLatLong().sphericalDistance(currentSample.toLatLong());
|
||||||
|
count++;
|
||||||
|
lastSample= currentSample;
|
||||||
|
}
|
||||||
|
Log.d("Uploader", "Cutted " + (last ? "last" : "first") + " " + count + " Samples (" + distance + " meters)");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void upload(){
|
||||||
|
new Thread(() -> {
|
||||||
|
try{
|
||||||
|
executeTask();
|
||||||
|
}catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
handler.post(() -> {
|
||||||
|
Toast.makeText(activity, R.string.uploadFailed, Toast.LENGTH_LONG).show();
|
||||||
|
dialogController.cancel();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeTask(){
|
||||||
|
handler.post(() -> dialogController.show());
|
||||||
|
setProgress(0);
|
||||||
|
if(cut){ cut(); }
|
||||||
|
setProgress(20);
|
||||||
|
OsmConnection osm = new OsmConnection(
|
||||||
|
"https://api.openstreetmap.org/api/0.6/", "FitoTrack", consumer);
|
||||||
|
|
||||||
|
List<GpsTrackpoint> trackpoints= new ArrayList<>();
|
||||||
|
|
||||||
|
for(WorkoutSample sample : samples){
|
||||||
|
GpsTrackpoint trackpoint= new GpsTrackpoint(new GpsTraceLatLong(sample));
|
||||||
|
trackpoint.time= new Date(sample.absoluteTime);
|
||||||
|
trackpoint.elevation= (float)sample.elevation;
|
||||||
|
trackpoints.add(trackpoint);
|
||||||
|
}
|
||||||
|
setProgress(25);
|
||||||
|
new GpsTracesDao(osm).create(workout.getDateString(), visibility, description, Collections.singletonList("FitoTrack"), trackpoints);
|
||||||
|
setProgress(100);
|
||||||
|
handler.post(() -> {
|
||||||
|
Toast.makeText(activity, R.string.uploadSuccessful, Toast.LENGTH_LONG).show();
|
||||||
|
dialogController.cancel();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setProgress(int progress){
|
||||||
|
handler.post(() -> dialogController.setProgress(progress));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
64
app/src/main/res/layout/dialog_upload_osm.xml
Normal file
64
app/src/main/res/layout/dialog_upload_osm.xml
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TableLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/description" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/uploadDescription"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ems="10"
|
||||||
|
android:inputType="textShortMessage|textAutoComplete"
|
||||||
|
android:singleLine="true" />
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/trackVisibilityPref" />
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/uploadVisibility"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:dropDownWidth="match_parent"
|
||||||
|
android:entries="@array/osm_track_visibility"
|
||||||
|
android:spinnerMode="dropdown" />
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<TableRow
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</TableLayout>
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/uploadCutting"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/cut" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@ -23,6 +23,9 @@
|
|||||||
<item
|
<item
|
||||||
android:id="@+id/actionExportGpx"
|
android:id="@+id/actionExportGpx"
|
||||||
android:title="@string/exportAsGpxFile" />
|
android:title="@string/exportAsGpxFile" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/actionUploadOSM"
|
||||||
|
android:title="@string/actionUploadToOSM" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/actionDeleteWorkout"
|
android:id="@+id/actionDeleteWorkout"
|
||||||
android:title="@string/delete" />
|
android:title="@string/delete" />
|
||||||
|
|||||||
8
app/src/main/res/values/osm_track_visibility.xml
Normal file
8
app/src/main/res/values/osm_track_visibility.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string-array name="osm_track_visibility">
|
||||||
|
<item>Identifiable</item>
|
||||||
|
<item>Trackable</item>
|
||||||
|
<item>Private</item>
|
||||||
|
</string-array>
|
||||||
|
</resources>
|
||||||
@ -62,6 +62,12 @@
|
|||||||
<string name="workoutBurnedEnergy">Burned Energy</string>
|
<string name="workoutBurnedEnergy">Burned Energy</string>
|
||||||
<string name="workoutTotalEnergy">Total Energy</string>
|
<string name="workoutTotalEnergy">Total Energy</string>
|
||||||
<string name="workoutEnergyConsumption">Energy Consumption</string>
|
<string name="workoutEnergyConsumption">Energy Consumption</string>
|
||||||
|
<string name="uploading">Uploading</string>
|
||||||
|
<string name="enterVerificationCode">Enter Verification Code</string>
|
||||||
|
<string name="authenticationFailed">Authentication failed.</string>
|
||||||
|
<string name="upload">Upload</string>
|
||||||
|
<string name="uploadSuccessful">Upload Successful</string>
|
||||||
|
<string name="uploadFailed">Upload Failed</string>
|
||||||
|
|
||||||
<string name="workoutAscent">Ascent</string>
|
<string name="workoutAscent">Ascent</string>
|
||||||
<string name="workoutDescent">Descent</string>
|
<string name="workoutDescent">Descent</string>
|
||||||
@ -115,4 +121,8 @@
|
|||||||
<string name="data">Data</string>
|
<string name="data">Data</string>
|
||||||
<string name="mapStyle">Map Style</string>
|
<string name="mapStyle">Map Style</string>
|
||||||
<string name="waiting_gps">Waiting for GPS</string>
|
<string name="waiting_gps">Waiting for GPS</string>
|
||||||
|
<string name="actionUploadToOSM">Upload to OSM</string>
|
||||||
|
<string name="cut">Cut the first/last 300 Meters</string>
|
||||||
|
<string name="trackVisibilityPref">Track Visibility</string>
|
||||||
|
<string name="description">Description</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user