got gpx export working - yay (#14)

master
y20k 2017-05-17 15:43:53 +02:00
parent 8c06c8c3ae
commit 9a14241915
19 changed files with 611 additions and 243 deletions

View File

@ -22,9 +22,9 @@ android {
dependencies { dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs') compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:25.1.1' compile 'com.android.support:appcompat-v7:25.2.0'
compile 'com.android.support:design:25.1.1' compile 'com.android.support:design:25.2.0'
compile 'com.android.support:cardview-v7:25.1.1' compile 'com.android.support:cardview-v7:25.2.0'
compile 'org.osmdroid:osmdroid-android:5.6.4' compile 'org.osmdroid:osmdroid-android:5.6.4'
compile 'com.google.code.gson:gson:2.8.0' compile 'com.google.code.gson:gson:2.8.0'
} }

View File

@ -25,6 +25,7 @@
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/TrackbookAppTheme.NoActionBar" android:theme="@style/TrackbookAppTheme.NoActionBar"
android:resizeableActivity="true"
android:launchMode="singleTop"> android:launchMode="singleTop">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -39,6 +40,7 @@
android:name=".InfosheetActivity" android:name=".InfosheetActivity"
android:label="@string/title_activity_infosheet" android:label="@string/title_activity_infosheet"
android:parentActivityName=".MainActivity" android:parentActivityName=".MainActivity"
android:resizeableActivity="true"
android:configChanges="keyboardHidden|orientation|screenSize|screenLayout"> android:configChanges="keyboardHidden|orientation|screenSize|screenLayout">

View File

@ -18,9 +18,9 @@ package org.y20k.trackbook;
import android.Manifest; import android.Manifest;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.Activity;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -34,12 +34,12 @@ import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton; import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout; import android.support.design.widget.TabLayout;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.util.SparseArray; import android.util.SparseArray;
@ -51,6 +51,7 @@ import android.widget.Button;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.Toast; import android.widget.Toast;
import org.y20k.trackbook.helpers.DialogHelper;
import org.y20k.trackbook.helpers.LogHelper; import org.y20k.trackbook.helpers.LogHelper;
import org.y20k.trackbook.helpers.NotificationHelper; import org.y20k.trackbook.helpers.NotificationHelper;
import org.y20k.trackbook.helpers.TrackbookKeys; import org.y20k.trackbook.helpers.TrackbookKeys;
@ -256,6 +257,64 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
} }
/* Handles FloatingActionButton dialog results */
public void onFloatingActionButtonResult(int requestCode, int resultCode) {
switch(requestCode) {
case RESULT_SAVE_DIALOG:
if (resultCode == Activity.RESULT_OK) {
// user chose SAVE
handleStateAfterSave();
} else if (resultCode == Activity.RESULT_CANCELED){
LogHelper.v(LOG_TAG, "Save dialog result: CANCEL");
}
break;
case RESULT_CLEAR_DIALOG:
if (resultCode == Activity.RESULT_OK) {
// user chose CLEAR
handleStateAfterClear();
} else if (resultCode == Activity.RESULT_CANCELED){
LogHelper.v(LOG_TAG, "Clear map: User chose CANCEL.");
}
break;
}
}
/* Handles the visual state after a save action */
private void handleStateAfterSave() {
// display and update track tab
mSelectedTab = FRAGMENT_ID_TRACK;
mViewPager.setCurrentItem(mSelectedTab);
// dismiss notification
NotificationHelper.stop();
// hide Floating Action Button sub menu
showFloatingActionButtonMenu(false);
// update Floating Action Button icon
mFloatingActionButtonState = FAB_STATE_DEFAULT;
setFloatingActionButtonState();
}
/* Handles the visual state after a save action */
private void handleStateAfterClear() {
// notify user
Toast.makeText(this, getString(R.string.toast_message_track_clear), Toast.LENGTH_LONG).show();
// dismiss notification
NotificationHelper.stop();
// hide Floating Action Button sub menu
showFloatingActionButtonMenu(false);
// update Floating Action Button icon
mFloatingActionButtonState = FAB_STATE_DEFAULT;
setFloatingActionButtonState();
}
/* Loads state of Floating Action Button from preferences */ /* Loads state of Floating Action Button from preferences */
private void loadFloatingActionButtonState(Context context) { private void loadFloatingActionButtonState(Context context) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
@ -348,7 +407,9 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
mFloatingActionButtonSubMenu1.setOnClickListener(new View.OnClickListener() { mFloatingActionButtonSubMenu1.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
handleButtonSaveAndClearClick(); MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP);
mainActivityMapFragment.onActivityResult(RESULT_SAVE_DIALOG, Activity.RESULT_OK, getIntent());
handleStateAfterSave();
} }
}); });
} }
@ -356,24 +417,16 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
mFloatingActionButtonSubMenu2.setOnClickListener(new View.OnClickListener() { mFloatingActionButtonSubMenu2.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
// ask user to confirm the clear action int dialogTitle = -1;
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); String dialogMessage = getString(R.string.dialog_clear_content);
builder.setMessage(R.string.dialog_clear_content); int dialogPositiveButton = R.string.dialog_clear_action_clear;
builder.setNegativeButton(R.string.dialog_default_action_cancel, new DialogInterface.OnClickListener() { int dialogNegativeButton = R.string.dialog_default_action_cancel;
@Override
public void onClick(DialogInterface dialogInterface, int i) { // show delete dialog - results are handles by onActivityResult
// do nothing MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP);
} DialogFragment dialogFragment = DialogHelper.newInstance(dialogTitle, dialogMessage, dialogPositiveButton, dialogNegativeButton);
}); dialogFragment.setTargetFragment(mainActivityMapFragment, RESULT_CLEAR_DIALOG);
builder.setPositiveButton(R.string.dialog_clear_action_clear, new DialogInterface.OnClickListener() { dialogFragment.show(getSupportFragmentManager(), "ClearDialog");
@Override
public void onClick(DialogInterface dialogInterface, int i) {
// clear current track
handleButtonClearClick();
}
});
AlertDialog dialog = builder.create();
dialog.show();
} }
}); });
} }
@ -465,46 +518,46 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
} }
/* Handles tap on the save and clear button */ // /* Handles tap on the save and clear button */
private void handleButtonSaveAndClearClick() { // private void handleButtonSaveAndClearClick() {
// clear map and save track // // clear map and save track
MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP); // MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP);
mainActivityMapFragment.clearMap(true); // mainActivityMapFragment.clearMap(true);
//
// display and update track tab // // display and update track tab
mSelectedTab = FRAGMENT_ID_TRACK; // mSelectedTab = FRAGMENT_ID_TRACK;
mViewPager.setCurrentItem(mSelectedTab); // mViewPager.setCurrentItem(mSelectedTab);
//
// dismiss notification // // dismiss notification
NotificationHelper.stop(); // NotificationHelper.stop();
//
// hide Floating Action Button sub menu // // hide Floating Action Button sub menu
showFloatingActionButtonMenu(false); // showFloatingActionButtonMenu(false);
//
// update Floating Action Button icon // // update Floating Action Button icon
mFloatingActionButtonState = FAB_STATE_DEFAULT; // mFloatingActionButtonState = FAB_STATE_DEFAULT;
setFloatingActionButtonState(); // setFloatingActionButtonState();
} // }
/* Handles tap on the clear button */ // /* Handles tap on the clear button */
private void handleButtonClearClick() { // private void handleButtonClearClick() {
// clear map, do not save track // // clear map, do not save track
MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP); // MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP);
mainActivityMapFragment.clearMap(false); // mainActivityMapFragment.clearMap(false);
//
// dismiss notification // // dismiss notification
NotificationHelper.stop(); // NotificationHelper.stop();
//
// hide Floating Action Button sub menu // // hide Floating Action Button sub menu
showFloatingActionButtonMenu(false); // showFloatingActionButtonMenu(false);
//
// update Floating Action Button icon // // update Floating Action Button icon
mFloatingActionButtonState = FAB_STATE_DEFAULT; // mFloatingActionButtonState = FAB_STATE_DEFAULT;
setFloatingActionButtonState(); // setFloatingActionButtonState();
//
Toast.makeText(this, getString(R.string.toast_message_track_clear), Toast.LENGTH_LONG).show(); // Toast.makeText(this, getString(R.string.toast_message_track_clear), Toast.LENGTH_LONG).show();
} // }
/* Set state of FloatingActionButton */ /* Set state of FloatingActionButton */

View File

@ -348,6 +348,35 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
} }
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case RESULT_SAVE_DIALOG:
if (resultCode == Activity.RESULT_OK) {
// user chose SAVE - clear map and save track
clearMap(true);
// FloatingActionButton state is already being handled in MainActivity
// ((MainActivity)mActivity).onFloatingActionButtonResult(requestCode, resultCode);
LogHelper.v(LOG_TAG, "Save dialog result: SAVE");
} else if (resultCode == Activity.RESULT_CANCELED){
LogHelper.v(LOG_TAG, "Save dialog result: CANCEL");
}
break;
case RESULT_CLEAR_DIALOG:
if (resultCode == Activity.RESULT_OK) {
// User chose CLEAR - clear map, do not save track
clearMap(false);
// handle FloatingActionButton state in MainActivity
((MainActivity)mActivity).onFloatingActionButtonResult(requestCode, resultCode);
} else if (resultCode == Activity.RESULT_CANCELED){
LogHelper.v(LOG_TAG, "Clear dialog result: CANCEL");
}
break;
}
}
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(INSTANCE_FIRST_START, mFirstStart); outState.putBoolean(INSTANCE_FIRST_START, mFirstStart);
@ -389,7 +418,7 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
/* Removes track crumbs from map */ /* Removes track crumbs from map */
public void clearMap(boolean saveTrack) { private void clearMap(boolean saveTrack) {
// clear map // clear map
if (mTrackOverlay != null) { if (mTrackOverlay != null) {

View File

@ -19,7 +19,6 @@ package org.y20k.trackbook;
import android.app.Activity; import android.app.Activity;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.location.Location; import android.location.Location;
@ -28,9 +27,10 @@ import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetBehavior; import android.support.design.widget.BottomSheetBehavior;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -48,7 +48,9 @@ import org.osmdroid.views.overlay.ItemizedIconOverlay;
import org.osmdroid.views.overlay.compass.CompassOverlay; import org.osmdroid.views.overlay.compass.CompassOverlay;
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider; import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider;
import org.y20k.trackbook.core.Track; import org.y20k.trackbook.core.Track;
import org.y20k.trackbook.helpers.DialogHelper;
import org.y20k.trackbook.helpers.DropdownAdapter; import org.y20k.trackbook.helpers.DropdownAdapter;
import org.y20k.trackbook.helpers.ExportHelper;
import org.y20k.trackbook.helpers.LogHelper; import org.y20k.trackbook.helpers.LogHelper;
import org.y20k.trackbook.helpers.MapHelper; import org.y20k.trackbook.helpers.MapHelper;
import org.y20k.trackbook.helpers.StorageHelper; import org.y20k.trackbook.helpers.StorageHelper;
@ -69,7 +71,7 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
/* Main class variables */ /* Main class variables */
private Activity mActivity; private FragmentActivity mActivity;
private View mRootView; private View mRootView;
private MapView mMapView; private MapView mMapView;
private LinearLayout mOnboardingView; private LinearLayout mOnboardingView;
@ -175,8 +177,10 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
mTrackManagementLayout = (LinearLayout) mRootView.findViewById(R.id.track_management_layout); mTrackManagementLayout = (LinearLayout) mRootView.findViewById(R.id.track_management_layout);
mDropdown = (Spinner) mRootView.findViewById(R.id.track_selector); mDropdown = (Spinner) mRootView.findViewById(R.id.track_selector);
// // attach listeners to export and delete buttons
ImageButton exportButton = (ImageButton) mRootView.findViewById(R.id.export_button);
ImageButton deleteButton = (ImageButton) mRootView.findViewById(R.id.delete_button); ImageButton deleteButton = (ImageButton) mRootView.findViewById(R.id.delete_button);
exportButton.setOnClickListener(getExportButtonListener());
deleteButton.setOnClickListener(getDeleteButtonListener()); deleteButton.setOnClickListener(getDeleteButtonListener());
// get views for statistics sheet // get views for statistics sheet
@ -291,6 +295,34 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
} }
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case RESULT_DELETE_DIALOG:
if (resultCode == Activity.RESULT_OK) {
LogHelper.v(LOG_TAG, "Delete dialog result: DELETE");
} else if (resultCode == Activity.RESULT_CANCELED){
LogHelper.v(LOG_TAG, "Delete dialog result: CANCEL");
}
break;
case RESULT_EXPORT_DIALOG:
if (resultCode == Activity.RESULT_OK) {
// User chose EXPORT
ExportHelper exportHelper = new ExportHelper(mActivity);
exportHelper.exportToGpx(mTrack);
} else if (resultCode == Activity.RESULT_CANCELED){
// User chose CANCEL
LogHelper.v(LOG_TAG, "Export to GPX: User chose CANCEL.");
}
break;
}
}
/* Displays map and statistics for track */ /* Displays map and statistics for track */
private void displayTrack() { private void displayTrack() {
GeoPoint position; GeoPoint position;
@ -360,9 +392,11 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
switch (newState) { switch (newState) {
case BottomSheetBehavior.STATE_EXPANDED: case BottomSheetBehavior.STATE_EXPANDED:
// statistics sheet expanded // statistics sheet expanded
mTrackManagementLayout.setVisibility(View.INVISIBLE);
break; break;
case BottomSheetBehavior.STATE_COLLAPSED: case BottomSheetBehavior.STATE_COLLAPSED:
// statistics sheet collapsed // statistics sheet collapsed
mTrackManagementLayout.setVisibility(View.VISIBLE);
mStatisticsSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); mStatisticsSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
break; break;
case BottomSheetBehavior.STATE_HIDDEN: case BottomSheetBehavior.STATE_HIDDEN:
@ -376,6 +410,12 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
@Override @Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) { public void onSlide(@NonNull View bottomSheet, float slideOffset) {
// react to dragging events // react to dragging events
if (slideOffset < 0.5f) {
mTrackManagementLayout.setVisibility(View.VISIBLE);
} else {
mTrackManagementLayout.setVisibility(View.INVISIBLE);
}
} }
}; };
} }
@ -386,26 +426,54 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
return new View.OnClickListener() { return new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
// ask user to confirm the delete action // get text elements for delete dialog
int dialogTitle = R.string.dialog_delete_title;
String dialogMessage = getString(R.string.dialog_delete_content) + " " + mTrack.getTrackDuration() + " | " + mTrack.getTrackDistance(); String dialogMessage = getString(R.string.dialog_delete_content) + " " + mTrack.getTrackDuration() + " | " + mTrack.getTrackDistance();
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity); int dialogPositiveButton = R.string.dialog_delete_action_delete;
builder.setTitle(R.string.dialog_delete_title); int dialogNegativeButton = R.string.dialog_default_action_cancel;
builder.setMessage(dialogMessage);
builder.setNegativeButton(R.string.dialog_default_action_cancel, new DialogInterface.OnClickListener() { // show delete dialog - results are handles by onActivityResult
@Override DialogFragment dialogFragment = DialogHelper.newInstance(dialogTitle, dialogMessage, dialogPositiveButton, dialogNegativeButton);
public void onClick(DialogInterface dialogInterface, int i) { dialogFragment.setTargetFragment(MainActivityTrackFragment.this, RESULT_DELETE_DIALOG);
// do nothing dialogFragment.show(mActivity.getSupportFragmentManager(), "DeleteDialog");
} }
}); };
builder.setPositiveButton(R.string.dialog_delete_action_delete, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
// delete current track
// TODO implement
} }
});
AlertDialog dialog = builder.create();
dialog.show(); /* Creates OnClickListener for the export button - needed in onCreateView */
private View.OnClickListener getExportButtonListener() {
return new View.OnClickListener() {
@Override
public void onClick(View view) {
// dialog text components
int dialogTitle;
String dialogMessage;
int dialogPositiveButton;
int dialogNegativeButton;
// create an ExportHelper
final ExportHelper exportHelper = new ExportHelper(mActivity);
// get text elements for delete dialog
if (exportHelper.gpxFileExists(mTrack)) {
// CASE: OVERWRITE - GPX file exists
dialogTitle = R.string.dialog_export_title_overwrite;
dialogMessage = getString(R.string.dialog_export_content_overwrite) + " (" + mTrack.getTrackDuration() + " | " + mTrack.getTrackDistance() + ")";
dialogPositiveButton = R.string.dialog_export_action_overwrite;
dialogNegativeButton = R.string.dialog_default_action_cancel;
} else {
// CASE: EXPORT - GPX file does NOT yet exits
dialogTitle = R.string.dialog_export_title_export;
dialogMessage = getString(R.string.dialog_export_content_export) + " (" + mTrack.getTrackDuration() + " | " + mTrack.getTrackDistance() + ")";
dialogPositiveButton = R.string.dialog_export_action_export;
dialogNegativeButton = R.string.dialog_default_action_cancel;
}
// show delete dialog - results are handles by onActivityResult
DialogFragment dialogFragment = DialogHelper.newInstance(dialogTitle, dialogMessage, dialogPositiveButton, dialogNegativeButton);
dialogFragment.setTargetFragment(MainActivityTrackFragment.this, RESULT_EXPORT_DIALOG);
dialogFragment.show(mActivity.getSupportFragmentManager(), "ExportDialog");
} }
}; };
} }

View File

@ -0,0 +1,80 @@
/**
* DialogHelper.java
* Implements the DialogHelper class
* A DialogHelper creates a customizable alert dialog
*
* This file is part of
* TRACKBOOK - Movement Recorder for Android
*
* Copyright (c) 2016-17 - Y20K.org
* Licensed under the MIT-License
* http://opensource.org/licenses/MIT
*
* Trackbook uses osmdroid - OpenStreetMap-Tools for Android
* https://github.com/osmdroid/osmdroid
*/
package org.y20k.trackbook.helpers;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
/**
* DialogHelper class
*/
public class DialogHelper extends DialogFragment implements TrackbookKeys {
/* Constructs a new instance */
public static DialogHelper newInstance(int title, String message, int positiveButton, int negativeButton) {
DialogHelper fragment = new DialogHelper();
Bundle args = new Bundle();
args.putInt(ARG_DIALOG_TITLE, title);
args.putString(ARG_DIALOG_MESSAGE, message);
args.putInt(ARG_DIALOG_BUTTON_POSITIVE, positiveButton);
args.putInt(ARG_DIALOG_BUTTON_NEGATIVE, negativeButton);
fragment.setArguments(args);
return fragment;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle args = getArguments();
// get text elements
int title = args.getInt(ARG_DIALOG_TITLE);
String message = args.getString(ARG_DIALOG_MESSAGE);
int positiveButton = args.getInt(ARG_DIALOG_BUTTON_POSITIVE);
int negativeButton = args.getInt(ARG_DIALOG_BUTTON_NEGATIVE);
// build dialog
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity());
if (title != -1) {
dialogBuilder.setTitle(title);
}
dialogBuilder.setTitle(message);
dialogBuilder.setPositiveButton(positiveButton,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, getActivity().getIntent());
}
}
);
dialogBuilder.setNegativeButton(negativeButton,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_CANCELED, getActivity().getIntent());
}
}
);
return dialogBuilder.create();
}
}

View File

@ -0,0 +1,186 @@
/**
* ExportHelper.java
* Implements the ExportHelper class
* A ExportHelper can convert Track object into a GPX string
*
* This file is part of
* TRACKBOOK - Movement Recorder for Android
*
* Copyright (c) 2016-17 - Y20K.org
* Licensed under the MIT-License
* http://opensource.org/licenses/MIT
*
* Trackbook uses osmdroid - OpenStreetMap-Tools for Android
* https://github.com/osmdroid/osmdroid
*/
package org.y20k.trackbook.helpers;
import android.content.Context;
import android.location.Location;
import android.os.Environment;
import android.widget.Toast;
import org.y20k.trackbook.R;
import org.y20k.trackbook.core.Track;
import org.y20k.trackbook.core.WayPoint;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* ExportHelper class
*/
public class ExportHelper implements TrackbookKeys {
/* Define log tag */
private static final String LOG_TAG = ExportHelper.class.getSimpleName();
/* Main class variables */
// private final Track mTrack;
private final Context mContext;
private File mFolder;
/* Constructor */
public ExportHelper(Context context) {
mContext = context;
mFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
}
/* Checks if a GPX file for given track is already present */
public boolean gpxFileExists(Track track) {
return createFile(track).exists();
}
/* Exports given track to GPX */
public boolean exportToGpx(Track track) {
// create "Download" folder if necessary
if (mFolder != null && !mFolder.exists()) {
LogHelper.v(LOG_TAG, "Creating new folder: " + mFolder.toString());
mFolder.mkdirs();
}
// get file for given track
File gpxFile = createFile(track);
// get GPX string representation for given track
String gpxString = createGpxString(track);
// write GPX file
if (writeGpxToFile(gpxString, gpxFile)) {
String toastMessage = mContext.getResources().getString(R.string.toast_message_export_success) + " " + gpxFile.toString();
Toast.makeText(mContext, toastMessage, Toast.LENGTH_LONG).show();
return true;
} else {
String toastMessage = mContext.getResources().getString(R.string.toast_message_export_fail) + " " + gpxFile.toString();
Toast.makeText(mContext, toastMessage, Toast.LENGTH_LONG).show();
return false;
}
}
/* Return a GPX filepath for a given track */
private File createFile(Track track) {
Date recordingStart = track.getRecordingStart();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US);
return new File(mFolder, dateFormat.format(recordingStart) + FILE_TYPE_GPX_EXTENSION);
}
/* Writes given GPX string to Download folder */
private boolean writeGpxToFile (String gpxString, File gpxFile) {
// write track
try (BufferedWriter bw = new BufferedWriter(new FileWriter(gpxFile))) {
LogHelper.v(LOG_TAG, "Saving track to external storage: " + gpxFile.toString());
bw.write(gpxString);
return true;
} catch (IOException e) {
LogHelper.e(LOG_TAG, "Unable to saving track to external storage (IOException): " + gpxFile.toString());
return false;
}
}
/* Creates GPX formatted string */
private String createGpxString(Track track) {
String gpxString;
// add header
gpxString = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n" +
"<gpx version=\"1.1\" creator=\"Transistor App (Android)\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n";
// add track
gpxString = gpxString + addTrack(track);
// add closing tag
gpxString = gpxString + "</gpx>\n";
return gpxString;
}
/* Creates Track */
private String addTrack(Track track) {
StringBuilder gpxTrack = new StringBuilder("");
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
// add opening track tag
gpxTrack.append("\t<trk>\n");
// add name to track
gpxTrack.append("\t\t<name>");
gpxTrack.append("test");
gpxTrack.append("</name>\n");
// add opening track segment tag
gpxTrack.append("\t\t<trkseg>\n");
// add route point
for (WayPoint wayPoint:track.getWayPoints()) {
// get location from waypoint
Location location = wayPoint.getLocation();
// add longitude and latitude
gpxTrack.append("\t\t\t<trkpt lat=\"");
gpxTrack.append(location.getLatitude());
gpxTrack.append("\" lon=\"");
gpxTrack.append(location.getLongitude());
gpxTrack.append("\">\n");
// add time
gpxTrack.append("\t\t\t\t<time>");
gpxTrack.append(dateFormat.format(new Date(location.getTime())));
gpxTrack.append("</time>\n");
// add altitude
gpxTrack.append("\t\t\t\t<ele>");
gpxTrack.append(location.getAltitude());
gpxTrack.append("</ele>\n");
// add closing tag
gpxTrack.append("\t\t\t</trkpt>\n");
}
// add closing track segment tag
gpxTrack.append("\t\t<trkseg>\n");
// add closing track tag
gpxTrack.append("\t</trk>\n");
return gpxTrack.toString();
}
}

View File

@ -1,110 +0,0 @@
/**
* GpxHelper.java
* Implements the GpxHelper class
* A GpxHelper can convert Track object into a GPX string
*
* This file is part of
* TRACKBOOK - Movement Recorder for Android
*
* Copyright (c) 2016-17 - Y20K.org
* Licensed under the MIT-License
* http://opensource.org/licenses/MIT
*
* Trackbook uses osmdroid - OpenStreetMap-Tools for Android
* https://github.com/osmdroid/osmdroid
*/
package org.y20k.trackbook.helpers;
import android.location.Location;
import org.y20k.trackbook.core.Track;
import org.y20k.trackbook.core.WayPoint;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* GpxHelper class
*/
public class GpxHelper {
/* Define log tag */
private static final String LOG_TAG = GpxHelper.class.getSimpleName();
/* Main class variables */
private final Track mTrack;
/* Constructor */
public GpxHelper(Track track) {
mTrack = track;
}
/* Creates GPX formatted string */
public String createGpxString() {
String gpxString;
// add header
gpxString = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n" +
"<gpx version=\"1.1\" creator=\"Transistor App (Android)\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n";
// add track
gpxString = gpxString + addTrack();
// add closing tag
gpxString = gpxString + "</gpx>\n";
// todo remove
LogHelper.v(LOG_TAG, "GPX output:\n" + gpxString);
return gpxString;
}
/* Creates Track */
private String addTrack() {
StringBuilder gpxTrack = new StringBuilder("");
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
// add opening route tag
gpxTrack.append("\t<rte>\n");
// add route point
for (WayPoint wayPoint:mTrack.getWayPoints()) {
// get location from waypoint
Location location = wayPoint.getLocation();
// add longitude and latitude
gpxTrack.append("\t\t<rtept lat=\"");
gpxTrack.append(location.getLatitude());
gpxTrack.append("\" lon=\"");
gpxTrack.append(location.getLongitude());
gpxTrack.append("\">\n");
// add time
gpxTrack.append("\t\t\t<time>");
gpxTrack.append(dateFormat.format(new Date(location.getTime())));
gpxTrack.append("</time>\n");
// add altitude
gpxTrack.append("\t\t\t<ele>");
gpxTrack.append(location.getAltitude());
gpxTrack.append("</ele>\n");
// add closing tag
gpxTrack.append("\t\t</rtept>\n");
}
// add closing route tag
gpxTrack.append("\t</rte>\n");
return gpxTrack.toString();
}
}

View File

@ -26,7 +26,7 @@ import android.util.Log;
*/ */
public final class LogHelper { public final class LogHelper {
private final static boolean mTesting = false; private final static boolean mTesting = true;
public static void d(final String tag, String message) { public static void d(final String tag, String message) {
// include logging only in debug versions // include logging only in debug versions

View File

@ -36,11 +36,9 @@ import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -64,17 +62,17 @@ public class StorageHelper implements TrackbookKeys {
mActivity = activity; mActivity = activity;
// get "tracks" folder // get "tracks" folder
mFolder = mActivity.getExternalFilesDir(DIRECTORY_NAME); mFolder = mActivity.getExternalFilesDir(TRACKS_DIRECTORY_NAME);
// mFolder = getTracksDirectory(); // mFolder = getTracksDirectory();
// create folder if necessary // create "tracks" folder if necessary
if (mFolder != null && !mFolder.exists()) { if (mFolder != null && !mFolder.exists()) {
LogHelper.v(LOG_TAG, "Creating new folder: " + mFolder.toString()); LogHelper.v(LOG_TAG, "Creating new folder: " + mFolder.toString());
mFolder.mkdir(); mFolder.mkdirs();
} }
// create temp file object // create temp file object
mTempFile = new File(mFolder.toString() + "/" + FILE_NAME_TEMP + FILE_TYPE_EXTENSION); mTempFile = new File(mFolder.toString() + "/" + FILE_NAME_TEMP + FILE_TYPE_TRACKBOOK_EXTENSION);
// delete old track - exclude temp file // delete old track - exclude temp file
deleteOldTracks(false); deleteOldTracks(false);
@ -96,9 +94,6 @@ public class StorageHelper implements TrackbookKeys {
/* Saves track object to file */ /* Saves track object to file */
public boolean saveTrack(@Nullable Track track, int fileType) { public boolean saveTrack(@Nullable Track track, int fileType) {
// get "tracks" folder
mFolder = mActivity.getExternalFilesDir(DIRECTORY_NAME);
Date recordingStart = null; Date recordingStart = null;
if (track != null) { if (track != null) {
recordingStart = track.getRecordingStart(); recordingStart = track.getRecordingStart();
@ -109,11 +104,11 @@ public class StorageHelper implements TrackbookKeys {
String fileName; String fileName;
if (fileType == FILE_TEMP_TRACK) { if (fileType == FILE_TEMP_TRACK) {
// case: temp file // case: temp file
fileName = FILE_NAME_TEMP + FILE_TYPE_EXTENSION; fileName = FILE_NAME_TEMP + FILE_TYPE_TRACKBOOK_EXTENSION;
} else { } else {
// case: regular file // case: regular file
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US);
fileName = dateFormat.format(recordingStart) + FILE_TYPE_EXTENSION; fileName = dateFormat.format(recordingStart) + FILE_TYPE_TRACKBOOK_EXTENSION;
} }
File file = new File(mFolder.toString() + "/" + fileName); File file = new File(mFolder.toString() + "/" + fileName);
@ -196,21 +191,21 @@ public class StorageHelper implements TrackbookKeys {
} }
/* Gets a list of tracks based on their file names */ // /* Gets a list of tracks based on their file names */
public List<String> getListOfTracks() { // public List<String> getListOfTracks() {
List<String> listOfTracks = new ArrayList<String>(); // List<String> listOfTracks = new ArrayList<String>();
//
// get files and sort them // // get files and sort them
File[] files = mFolder.listFiles(); // File[] files = mFolder.listFiles();
files = sortFiles(files); // files = sortFiles(files);
//
for (File file : files) { // for (File file : files) {
listOfTracks.add(file.getName()); // listOfTracks.add(file.getName());
} // }
//
// TODO HANDLE CASE: EMPTY FILE LIST // // TODO HANDLE CASE: EMPTY FILE LIST
return listOfTracks; // return listOfTracks;
} // }
// loads file and parses it into a track // loads file and parses it into a track
@ -252,14 +247,11 @@ public class StorageHelper implements TrackbookKeys {
/* Gets most current track from directory */ /* Gets most current track from directory */
private File getMostCurrentTrack() { private File getMostCurrentTrack() {
// get "tracks" folder
mFolder = mActivity.getExternalFilesDir(DIRECTORY_NAME);
if (mFolder != null && mFolder.isDirectory()) { if (mFolder != null && mFolder.isDirectory()) {
// get files and sort them // get files and sort them
File[] files = mFolder.listFiles(); File[] files = mFolder.listFiles();
files = sortFiles(files); files = sortFiles(files);
if (files.length > 0 && files[0].getName().endsWith(FILE_TYPE_EXTENSION) && !files[0].equals(mTempFile)){ if (files.length > 0 && files[0].getName().endsWith(FILE_TYPE_TRACKBOOK_EXTENSION) && !files[0].equals(mTempFile)){
// return latest track // return latest track
return files[0]; return files[0];
} }
@ -282,9 +274,6 @@ public class StorageHelper implements TrackbookKeys {
/* Gets the last track from directory */ /* Gets the last track from directory */
private void deleteOldTracks(boolean includeTempFile) { private void deleteOldTracks(boolean includeTempFile) {
// get "tracks" folder
mFolder = mActivity.getExternalFilesDir(DIRECTORY_NAME);
if (mFolder != null && mFolder.isDirectory()) { if (mFolder != null && mFolder.isDirectory()) {
LogHelper.v(LOG_TAG, "Deleting older recordings."); LogHelper.v(LOG_TAG, "Deleting older recordings.");
@ -298,7 +287,7 @@ public class StorageHelper implements TrackbookKeys {
// keep the latest ten (mMaxTrackFiles) track files // keep the latest ten (mMaxTrackFiles) track files
int index = MAXIMUM_TRACK_FILES; int index = MAXIMUM_TRACK_FILES;
// iterate through array // iterate through array
while (index < numberOfFiles && files[index].getName().endsWith(FILE_TYPE_EXTENSION) && !files[index].equals(mTempFile)) { while (index < numberOfFiles && files[index].getName().endsWith(FILE_TYPE_TRACKBOOK_EXTENSION) && !files[index].equals(mTempFile)) {
files[index].delete(); files[index].delete();
index++; index++;
} }
@ -321,8 +310,8 @@ public class StorageHelper implements TrackbookKeys {
public int compare(File file1, File file2) { public int compare(File file1, File file2) {
// discard temp file and files not ending with ".trackbook" // discard temp file and files not ending with ".trackbook"
boolean file1IsTrack = file1.getName().endsWith(FILE_TYPE_EXTENSION) && !file1.equals(mTempFile); boolean file1IsTrack = file1.getName().endsWith(FILE_TYPE_TRACKBOOK_EXTENSION) && !file1.equals(mTempFile);
boolean file2IsTrack = file2.getName().endsWith(FILE_TYPE_EXTENSION) && !file2.equals(mTempFile); boolean file2IsTrack = file2.getName().endsWith(FILE_TYPE_TRACKBOOK_EXTENSION) && !file2.equals(mTempFile);
// note: "greater" means higher index in array // note: "greater" means higher index in array
if (!file1IsTrack && file2IsTrack) { if (!file1IsTrack && file2IsTrack) {
@ -353,7 +342,7 @@ public class StorageHelper implements TrackbookKeys {
/* Return a write-able sub-directory from external storage */ /* Return a write-able sub-directory from external storage */
private File getTracksDirectory() { private File getTracksDirectory() {
File[] storage = mActivity.getExternalFilesDirs(DIRECTORY_NAME); File[] storage = mActivity.getExternalFilesDirs(TRACKS_DIRECTORY_NAME);
for (File file : storage) { for (File file : storage) {
if (file != null) { if (file != null) {
String state = EnvironmentCompat.getStorageState(file); String state = EnvironmentCompat.getStorageState(file);

View File

@ -1,7 +1,7 @@
/** /**
* TrackbookKeys.java * TrackbookKeys.java
* Implements the keys used throughout the app * Implements the keys used throughout the app
* This class hosts all keys used to control Trackbook's state * This interface hosts all keys used to control Trackbook's state
* *
* This file is part of * This file is part of
* TRACKBOOK - Movement Recorder for Android * TRACKBOOK - Movement Recorder for Android
@ -41,6 +41,11 @@ public interface TrackbookKeys {
String EXTRA_SAVE_FINISHED = "SAVE_FINISHED"; String EXTRA_SAVE_FINISHED = "SAVE_FINISHED";
/* ARGS */ /* ARGS */
String ARG_DIALOG_TITLE = "ArgDialogTitle";
String ARG_DIALOG_MESSAGE = "ArgDialogMessage";
String ARG_DIALOG_BUTTON_POSITIVE = "ArgDialogButtonPositive";
String ARG_DIALOG_BUTTON_NEGATIVE = "ArgDialogButtonNegative";
// String ARG_PERMISSIONS_GRANTED = "ArgPermissionsGranted"; // String ARG_PERMISSIONS_GRANTED = "ArgPermissionsGranted";
// String ARG_TRACKING_STATE = "ArgTrackingState"; // String ARG_TRACKING_STATE = "ArgTrackingState";
// String ARG_TRACK = "ArgTrack"; // String ARG_TRACK = "ArgTrack";
@ -94,8 +99,17 @@ public interface TrackbookKeys {
int FILE_MOST_CURRENT_TRACK = 1; int FILE_MOST_CURRENT_TRACK = 1;
int NEW_DROPDOWN_ITEM = -1; int NEW_DROPDOWN_ITEM = -1;
String DIRECTORY_NAME = "tracks"; int RESULT_SAVE_DIALOG = 1;
String FILE_TYPE_EXTENSION = ".trackbook"; int RESULT_CLEAR_DIALOG = 2;
int RESULT_DELETE_DIALOG = 3;
int RESULT_EXPORT_DIALOG = 4;
int STORAGE_TRACKS = 1;
int STORAGE_DOWNLOADS = 2;
String TRACKS_DIRECTORY_NAME = "tracks";
String FILE_TYPE_GPX_EXTENSION = ".gpx";
String FILE_TYPE_TRACKBOOK_EXTENSION = ".trackbook";
String FILE_NAME_TEMP = "temp"; String FILE_NAME_TEMP = "temp";

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M9,3L5,6.99h3L8,14h2L10,6.99h3L9,3zM16,17.01L16,10h-2v7.01h-3L15,21l4,-3.99h-3z"
android:fillColor="@color/trackbook_white" />
</vector>

View File

@ -38,12 +38,24 @@
android:gravity="start|center" android:gravity="start|center"
android:theme="@style/TrackbookAppTheme.PopupOverlay" android:theme="@style/TrackbookAppTheme.PopupOverlay"
android:contentDescription="@string/descr_track_selector" /> android:contentDescription="@string/descr_track_selector" />
<ImageButton
android:visibility="visible"
android:id="@+id/export_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:background="@drawable/ic_export_white_24dp"
android:contentDescription="@string/descr_export_button" />
<ImageButton <ImageButton
android:visibility="gone" android:visibility="gone"
android:id="@+id/delete_button" android:id="@+id/delete_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="end|center" android:layout_gravity="end|center"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:background="@drawable/ic_delete_forever_white_24dp" android:background="@drawable/ic_delete_forever_white_24dp"
android:contentDescription="@string/descr_delete_button" /> android:contentDescription="@string/descr_delete_button" />
</LinearLayout> </LinearLayout>

View File

@ -40,6 +40,12 @@
<string name="dialog_delete_title">Aufzeichnung löschen?</string> <string name="dialog_delete_title">Aufzeichnung löschen?</string>
<string name="dialog_delete_content">Diese Aufzeichnung löschen:</string> <string name="dialog_delete_content">Diese Aufzeichnung löschen:</string>
<string name="dialog_delete_action_delete">Löschen</string> <string name="dialog_delete_action_delete">Löschen</string>
<string name="dialog_export_title_export">Export Recording as GPX?</string>
<string name="dialog_export_content_export">Export this recording as GPX track.</string>
<string name="dialog_export_action_export">Export</string>
<string name="dialog_export_title_overwrite">Export and Overwrite?</string>
<string name="dialog_export_content_overwrite">File already exists. Export and overwrite this recording as GPX track.</string>
<string name="dialog_export_action_overwrite">Export and Overwrite</string>
<!-- toast messages --> <!-- toast messages -->
<string name="toast_message_permissions_granted">Berechtigungen erteilt.</string> <string name="toast_message_permissions_granted">Berechtigungen erteilt.</string>
@ -52,6 +58,8 @@
<string name="toast_message_save_track">Aufzeichnung wird gespeichert.</string> <string name="toast_message_save_track">Aufzeichnung wird gespeichert.</string>
<string name="toast_message_last_location_age_one_hour">über eine Stunde</string> <string name="toast_message_last_location_age_one_hour">über eine Stunde</string>
<string name="toast_message_track_clear">Aufzeichnung zurückgesetzt.</string> <string name="toast_message_track_clear">Aufzeichnung zurückgesetzt.</string>
<string name="toast_message_export_success">GPX export successful:</string>
<string name="toast_message_export_fail">GPX export failed:</string>
<!-- map markers --> <!-- map markers -->
<string name="marker_description_source">Quelle</string> <string name="marker_description_source">Quelle</string>
@ -81,8 +89,8 @@
<string name="layout_onboarding_button_okay">Alles klar!</string> <string name="layout_onboarding_button_okay">Alles klar!</string>
<!-- track tab onboarding --> <!-- track tab onboarding -->
<string name="track_tab_onboarding_h1_part_1">Your recorded tracks</string> <string name="track_tab_onboarding_h1_part_1">Bewegungsaufzeichnungen</string>
<string name="track_tab_onboarding_h1_part_2">… will show up here.</string> <string name="track_tab_onboarding_h1_part_2">… werden hier erscheinen.</string>
<!-- infosheet about --> <!-- infosheet about -->
<string name="infosheet_about_h1_about">Über Trackbook</string> <string name="infosheet_about_h1_about">Über Trackbook</string>
@ -126,6 +134,7 @@
<string name="descr_statistics_sheet_p_recording_start_value">Wert: Start der Aufzeichnung</string> <string name="descr_statistics_sheet_p_recording_start_value">Wert: Start der Aufzeichnung</string>
<string name="descr_statistics_sheet_p_recording_end_value">Wert: Ende der Aufzeichnung</string> <string name="descr_statistics_sheet_p_recording_end_value">Wert: Ende der Aufzeichnung</string>
<string name="descr_track_selector">Auswahl-Menü für weitere Aufzeichnungen</string> <string name="descr_track_selector">Auswahl-Menü für weitere Aufzeichnungen</string>
<string name="descr_export_button">Button Track Exportierem</string>
<string name="descr_delete_button">Button Track Löschen</string> <string name="descr_delete_button">Button Track Löschen</string>
</resources> </resources>

View File

@ -32,6 +32,12 @@
<string name="dialog_delete_title">記録を削除しますか?</string> <string name="dialog_delete_title">記録を削除しますか?</string>
<string name="dialog_delete_content">次の記録を削除:</string> <string name="dialog_delete_content">次の記録を削除:</string>
<string name="dialog_delete_action_delete">Delete</string> <string name="dialog_delete_action_delete">Delete</string>
<string name="dialog_export_title_export">Export Recording as GPX?</string>
<string name="dialog_export_content_export">Export this recording as GPX track.</string>
<string name="dialog_export_action_export">Export</string>
<string name="dialog_export_title_overwrite">Export and Overwrite?</string>
<string name="dialog_export_content_overwrite">File already exists. Export and overwrite this recording as GPX track.</string>
<string name="dialog_export_action_overwrite">Export and Overwrite</string>
<string name="toast_message_permissions_granted">アクセス許可を付与しました。</string> <string name="toast_message_permissions_granted">アクセス許可を付与しました。</string>
<string name="toast_message_unable_to_start_app">Trackbook を起動できません。</string> <string name="toast_message_unable_to_start_app">Trackbook を起動できません。</string>
@ -43,6 +49,8 @@
<string name="toast_message_save_track">現在のトレースを保存しています。</string> <string name="toast_message_save_track">現在のトレースを保存しています。</string>
<string name="toast_message_last_location_age_one_hour">1 時間以上</string> <string name="toast_message_last_location_age_one_hour">1 時間以上</string>
<string name="toast_message_track_clear">現在のトレース データを削除しました。</string> <string name="toast_message_track_clear">現在のトレース データを削除しました。</string>
<string name="toast_message_export_success">GPX export successful:</string>
<string name="toast_message_export_fail">GPX export failed:</string>
<string name="marker_description_source">ソース</string> <string name="marker_description_source">ソース</string>
<string name="marker_description_time">時間</string> <string name="marker_description_time">時間</string>
@ -111,6 +119,7 @@
<string name="descr_statistics_sheet_p_recording_start_value">値: 記録の開始</string> <string name="descr_statistics_sheet_p_recording_start_value">値: 記録の開始</string>
<string name="descr_statistics_sheet_p_recording_end_value">値: 記録の終了</string> <string name="descr_statistics_sheet_p_recording_end_value">値: 記録の終了</string>
<string name="descr_track_selector">ドロップダウン メニューでさらにトレース</string> <string name="descr_track_selector">ドロップダウン メニューでさらにトレース</string>
<string name="descr_export_button">Track export button</string>
<string name="descr_delete_button">トレース削除ボタン</string> <string name="descr_delete_button">トレース削除ボタン</string>
</resources> </resources>

View File

@ -30,6 +30,12 @@
<string name="dialog_delete_title">Delete Recording?</string> <string name="dialog_delete_title">Delete Recording?</string>
<string name="dialog_delete_content">Delete the following recording:</string> <string name="dialog_delete_content">Delete the following recording:</string>
<string name="dialog_delete_action_delete">Delete</string> <string name="dialog_delete_action_delete">Delete</string>
<string name="dialog_export_title_export">Export Recording as GPX?</string>
<string name="dialog_export_content_export">Export this recording as GPX track.</string>
<string name="dialog_export_action_export">Export</string>
<string name="dialog_export_title_overwrite">Export and Overwrite?</string>
<string name="dialog_export_content_overwrite">File already exists. Export and overwrite this recording as GPX track.</string>
<string name="dialog_export_action_overwrite">Export and Overwrite</string>
<string name="toast_message_permissions_granted">Rechten verleend.</string> <string name="toast_message_permissions_granted">Rechten verleend.</string>
<string name="toast_message_unable_to_start_app">Trackbook kan niet worden gestart.</string> <string name="toast_message_unable_to_start_app">Trackbook kan niet worden gestart.</string>
@ -41,6 +47,8 @@
<string name="toast_message_save_track">Bezig met opslaan van huidige baan.</string> <string name="toast_message_save_track">Bezig met opslaan van huidige baan.</string>
<string name="toast_message_last_location_age_one_hour">langer dan één uur</string> <string name="toast_message_last_location_age_one_hour">langer dan één uur</string>
<string name="toast_message_track_clear">Huidige baangegevens verwijderd.</string> <string name="toast_message_track_clear">Huidige baangegevens verwijderd.</string>
<string name="toast_message_export_success">GPX export successful:</string>
<string name="toast_message_export_fail">GPX export failed:</string>
<string name="marker_description_source">Bron</string> <string name="marker_description_source">Bron</string>
<string name="marker_description_time">Tijd</string> <string name="marker_description_time">Tijd</string>
@ -109,6 +117,7 @@
<string name="descr_statistics_sheet_p_recording_start_value">Waarde: beginnen met bijhouden</string> <string name="descr_statistics_sheet_p_recording_start_value">Waarde: beginnen met bijhouden</string>
<string name="descr_statistics_sheet_p_recording_end_value">Waarde: stoppen met bijhouden</string> <string name="descr_statistics_sheet_p_recording_end_value">Waarde: stoppen met bijhouden</string>
<string name="descr_track_selector">Uitrolmenu voor verdere banen</string> <string name="descr_track_selector">Uitrolmenu voor verdere banen</string>
<string name="descr_export_button">Track export button</string>
<string name="descr_delete_button">Baan - verwijderknop</string> <string name="descr_delete_button">Baan - verwijderknop</string>
</resources> </resources>

View File

@ -38,8 +38,14 @@
<string name="dialog_clear_content">Clear Recording?</string> <string name="dialog_clear_content">Clear Recording?</string>
<string name="dialog_clear_action_clear">Clear</string> <string name="dialog_clear_action_clear">Clear</string>
<string name="dialog_delete_title">Delete Recording?</string> <string name="dialog_delete_title">Delete Recording?</string>
<string name="dialog_delete_content">Delete the following recording:</string> <string name="dialog_delete_content">Delete this recording:</string>
<string name="dialog_delete_action_delete">Delete</string> <string name="dialog_delete_action_delete">Delete</string>
<string name="dialog_export_title_export">Export Recording as GPX?</string>
<string name="dialog_export_content_export">Export this recording as GPX track.</string>
<string name="dialog_export_action_export">Export</string>
<string name="dialog_export_title_overwrite">Export and Overwrite?</string>
<string name="dialog_export_content_overwrite">File already exists. Export and overwrite this recording as GPX track.</string>
<string name="dialog_export_action_overwrite">Export and Overwrite</string>
<!-- toast messages --> <!-- toast messages -->
<string name="toast_message_permissions_granted">Permissions granted.</string> <string name="toast_message_permissions_granted">Permissions granted.</string>
@ -52,6 +58,8 @@
<string name="toast_message_save_track">Saving current track.</string> <string name="toast_message_save_track">Saving current track.</string>
<string name="toast_message_last_location_age_one_hour">over one hour</string> <string name="toast_message_last_location_age_one_hour">over one hour</string>
<string name="toast_message_track_clear">Current track data removed.</string> <string name="toast_message_track_clear">Current track data removed.</string>
<string name="toast_message_export_success">GPX export successful:</string>
<string name="toast_message_export_fail">GPX export failed:</string>
<!-- map markers --> <!-- map markers -->
<string name="marker_description_source">Source</string> <string name="marker_description_source">Source</string>
@ -126,6 +134,7 @@
<string name="descr_statistics_sheet_p_recording_start_value">Value: start of recording</string> <string name="descr_statistics_sheet_p_recording_start_value">Value: start of recording</string>
<string name="descr_statistics_sheet_p_recording_end_value">Value: end of recording</string> <string name="descr_statistics_sheet_p_recording_end_value">Value: end of recording</string>
<string name="descr_track_selector">Dropdown menu for further tracks</string> <string name="descr_track_selector">Dropdown menu for further tracks</string>
<string name="descr_export_button">Track export button</string>
<string name="descr_delete_button">Track delete button</string> <string name="descr_delete_button">Track delete button</string>
</resources> </resources>

View File

@ -5,7 +5,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.2.3' classpath 'com.android.tools.build:gradle:2.3.2'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files

View File

@ -1,6 +1,6 @@
#Mon Aug 22 10:55:02 CEST 2016 #Fri Mar 03 15:35:49 CET 2017
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip