clean up, clear map now works

This commit is contained in:
y20k 2016-09-12 14:31:37 +02:00
parent 4859536b3a
commit 42ce5a3e76
11 changed files with 115 additions and 80 deletions

View file

@ -6,7 +6,7 @@ Trackbook - Movement Recorder for Android
**Version 0.1.x ("The Great Gig in the Sky")**
Trackbook is a bare bones app for recording your movements. Trackbook is great for hiking, vacation or workout. Once started it displays your movements on a map.
Trackbook is a bare bones app for recording your movements. Trackbook is great for hiking, vacation or workout. Once started it traces your movements on a map. The map data is provided by [OpenStreetMap (OSM)](https://www.openstreetmap.org/).
Trackbook is free software. It is published under the [MIT open source license](https://opensource.org/licenses/MIT). Trackbook uses [osmdroid](https://github.com/osmdroid/osmdroid) to display the map, which is also free software published under the [Apache License](https://github.com/osmdroid/osmdroid/blob/master/LICENSE). Want to help? Please check out the notes in [CONTRIBUTE.md](https://github.com/y20k/transistor/blob/master/CONTRIBUTE.md) first.
@ -24,14 +24,6 @@ Do not install Trackbook. Trackbook is not finished yet. See the Install Canary
|||
'|'
Developement screenshot(s)
--------------------------
[<img src="https://cloud.githubusercontent.com/assets/9103935/18307128/4ca8e8a8-74ef-11e6-9f47-33f31bdff36e.png" width="240">](https://cloud.githubusercontent.com/assets/9103935/18307128/4ca8e8a8-74ef-11e6-9f47-33f31bdff36e.png)
[<img src="https://cloud.githubusercontent.com/assets/9103935/18307129/4ca963be-74ef-11e6-8b5b-f4ea6793a1d1.png" width="240">](https://cloud.githubusercontent.com/assets/9103935/18307129/4ca963be-74ef-11e6-8b5b-f4ea6793a1d1.png)
[<img src="https://cloud.githubusercontent.com/assets/9103935/18307132/4cabc816-74ef-11e6-9752-237e3f1611fc.png" width="240">](https://cloud.githubusercontent.com/assets/9103935/18307132/4cabc816-74ef-11e6-9752-237e3f1611fc.png)
[<img src="https://cloud.githubusercontent.com/assets/9103935/18307131/4caa247a-74ef-11e6-8059-41abfe11f71c.png" width="240">](https://cloud.githubusercontent.com/assets/9103935/18307131/4caa247a-74ef-11e6-8059-41abfe11f71c.png)
[<img src="https://cloud.githubusercontent.com/assets/9103935/18307130/4ca9f270-74ef-11e6-96e7-d918e807e9a2.png" width="240">](https://cloud.githubusercontent.com/assets/9103935/18307130/4ca9f270-74ef-11e6-96e7-d918e807e9a2.png)
How to use Trackbook
--------------------
### Start recording movements
@ -59,3 +51,11 @@ Trackbook needs accurate GPS location data to be able to record your movements.
### Permission "WRITE_EXTERNAL_STORAGE"
Trackbook uses [osmdroid](https://github.com/osmdroid/osmdroid), which caches map tiles on Android's external storage. You can find the map cache in the `osmdroid` folder on the top level of the user-facing file system.
Developement screenshot(s)
--------------------------
[<img src="https://cloud.githubusercontent.com/assets/9103935/18307128/4ca8e8a8-74ef-11e6-9f47-33f31bdff36e.png" width="240">](https://cloud.githubusercontent.com/assets/9103935/18307128/4ca8e8a8-74ef-11e6-9f47-33f31bdff36e.png)
[<img src="https://cloud.githubusercontent.com/assets/9103935/18307129/4ca963be-74ef-11e6-8b5b-f4ea6793a1d1.png" width="240">](https://cloud.githubusercontent.com/assets/9103935/18307129/4ca963be-74ef-11e6-8b5b-f4ea6793a1d1.png)
[<img src="https://cloud.githubusercontent.com/assets/9103935/18307132/4cabc816-74ef-11e6-9752-237e3f1611fc.png" width="240">](https://cloud.githubusercontent.com/assets/9103935/18307132/4cabc816-74ef-11e6-9752-237e3f1611fc.png)
[<img src="https://cloud.githubusercontent.com/assets/9103935/18307131/4caa247a-74ef-11e6-8059-41abfe11f71c.png" width="240">](https://cloud.githubusercontent.com/assets/9103935/18307131/4caa247a-74ef-11e6-8059-41abfe11f71c.png)
[<img src="https://cloud.githubusercontent.com/assets/9103935/18307130/4ca9f270-74ef-11e6-96e7-d918e807e9a2.png" width="240">](https://cloud.githubusercontent.com/assets/9103935/18307130/4ca9f270-74ef-11e6-96e7-d918e807e9a2.png)

View file

@ -9,7 +9,7 @@ android {
minSdkVersion 22
targetSdkVersion 24
versionCode 1
versionName "0.1.0 (The Great Gig in the Sky)"
versionName "0.9.0 (The Great Gig in the Sky)"
vectorDrawables.useSupportLibrary = true
}
buildTypes {

View file

@ -26,6 +26,7 @@ import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
@ -38,6 +39,7 @@ import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import org.y20k.trackbook.helpers.LogHelper;
import org.y20k.trackbook.helpers.NotificationHelper;
import org.y20k.trackbook.helpers.TrackbookKeys;
@ -60,7 +62,6 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
private boolean mTrackerServiceRunning;
private boolean mPermissionsGranted;
private List<String> mMissingPermissions;
private View mRootView;
private FloatingActionButton mFloatingActionButton;
private MainActivityFragment mMainActivityFragment;
private BroadcastReceiver mTrackingStoppedReceiver;
@ -143,14 +144,8 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
protected void onResume() {
super.onResume();
Intent intent = getIntent();
String intentAction = intent.getAction();
if (intentAction != null && intentAction.contains(ACTION_SHOW_MAP) && intent.hasExtra(EXTRA_TRACKING_STATE)) {
mTrackerServiceRunning = intent.getBooleanExtra(EXTRA_TRACKING_STATE, false);
mMainActivityFragment.setTrackingState(mTrackerServiceRunning);
// prevent multiple reactions to intent
intent.setAction(ACTION_DEFAULT);
}
// handle new intents - onNewIntent does not seem to work
handleIncomingIntent();
// if not in onboarding mode: set state of FloatingActionButton
if (mFloatingActionButton != null) {
@ -169,7 +164,7 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
@ -219,16 +214,18 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
mFloatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// onClick: start / stop tracking
handleFloatingActionButtonClick(view);
}
});
mFloatingActionButton.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
if (mTrackerServiceRunning) {
// onLongClick: clear map
if (mTrackerServiceRunning || mMainActivityFragment == null) {
return false;
} else {
clearMap();
mMainActivityFragment.clearMap();
NotificationHelper.stop();
return true;
}
@ -305,10 +302,30 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
}
/* Handles new incoming intents */
private void handleIncomingIntent() {
Intent intent = getIntent();
String intentAction = intent.getAction();
/* Removes track crumbs from map */
private void clearMap() {
Toast.makeText(this, "Clearing map", Toast.LENGTH_LONG).show(); // TODO remove
switch (intentAction) {
case ACTION_SHOW_MAP:
if (intent.hasExtra(EXTRA_TRACKING_STATE) && mMainActivityFragment != null) {
mTrackerServiceRunning = intent.getBooleanExtra(EXTRA_TRACKING_STATE, false);
mMainActivityFragment.setTrackingState(mTrackerServiceRunning);
// prevent multiple reactions to intent
intent.setAction(ACTION_DEFAULT);
} else if (intent.hasExtra(EXTRA_CLEAR_MAP) && mMainActivityFragment != null) {
mMainActivityFragment.clearMap();
// prevent multiple reactions to intent
intent.setAction(ACTION_DEFAULT);
}
break;
default:
// log
LogHelper.v(LOG_TAG, "Intent received. Doing nothing. Type of ACTION: " + intentAction);
break;
}
}

View file

@ -30,7 +30,6 @@ import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
@ -77,6 +76,7 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
private Location mCurrentBestLocation;
private boolean mTrackerServiceRunning;
private boolean mLocalTrackerRunning;
private boolean mFragmentVisible;
/* Constructor (default) */
@ -144,9 +144,6 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
// create basic map
mMapView = new MapView(inflater.getContext());
// get display metrics
final DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
// get map controller
mController = mMapView.getController();
@ -172,6 +169,12 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
mController.setZoom(16);
}
// inform user that new/better location is on its way
if (mFirstStart && !mTrackerServiceRunning) {
Toast.makeText(mActivity, mActivity.getString(R.string.toast_message_acquiring_location), Toast.LENGTH_LONG).show();
mFirstStart = false;
}
// restore track
if (savedInstanceState != null) {
mTrack = savedInstanceState.getParcelable(INSTANCE_TRACK);
@ -200,8 +203,11 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
public void onResume() {
super.onResume();
// set visibility
mFragmentVisible = true;
// start preliminary tracking - if no TrackerService is running
if (!mTrackerServiceRunning) {
if (!mTrackerServiceRunning && mFragmentVisible) {
startPreliminaryTracking();
}
@ -222,6 +228,9 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
public void onPause() {
super.onPause();
// set visibility
mFragmentVisible = false;
// disable preliminary location listeners
stopPreliminaryTracking();
}
@ -266,9 +275,7 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
// get current position
GeoPoint position;
if (mCurrentBestLocation != null) {
// app has a current best estimate location
} else {
if (mCurrentBestLocation == null) {
// app does not have any location fix
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
}
@ -346,6 +353,15 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
}
/* Removes track crumbs from map */
public void clearMap() {
if (mTrackOverlay != null) {
Toast.makeText(mActivity, mActivity.getString(R.string.toast_message_clear_map), Toast.LENGTH_LONG).show();
mMapView.getOverlays().remove(mTrackOverlay);
}
}
/* Start preliminary tracking for map */
private void startPreliminaryTracking() {
mLocalTrackerRunning = true;
@ -438,8 +454,7 @@ public class MainActivityFragment extends Fragment implements TrackbookKeys {
mCurrentBestLocation = intent.getParcelableExtra(EXTRA_LAST_LOCATION);
mController.setCenter(convertToGeoPoint(mCurrentBestLocation));
// clear intent
intent.removeExtra(EXTRA_TRACK);
intent.removeExtra(EXTRA_LAST_LOCATION);
intent.setAction(ACTION_DEFAULT);
}
}
};

View file

@ -83,7 +83,7 @@ public class TrackerService extends Service implements TrackbookKeys {
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
}
// add last location as waypoint to track
// add last location as WayPoint to track
addWayPointToTrack();
// set timer to retrieve new locations and to prevent endless tracking
@ -106,6 +106,9 @@ public class TrackerService extends Service implements TrackbookKeys {
};
mTimer.start();
// put up notification
NotificationHelper.show(this,mTrack);
// create gps and network location listeners
startFindingLocation();
}
@ -117,6 +120,9 @@ public class TrackerService extends Service implements TrackbookKeys {
// stop timer
mTimer.cancel();
// change notification
NotificationHelper.update(mTrack, false);
// remove listeners
stopFindingLocation();
}
@ -160,7 +166,7 @@ public class TrackerService extends Service implements TrackbookKeys {
// add first location to track
newWayPoint = mTrack.addWayPoint(mCurrentBestLocation);
} else {
// get last waypoint and compare it to current location
// get last WayPoint and compare it to current location
Location lastWayPoint = mTrack.getWayPointLocation(trackSize - 1);
if (LocationHelper.isNewWayPoint(lastWayPoint, mCurrentBestLocation)) {
// if new, add current best location to track
@ -209,8 +215,6 @@ public class TrackerService extends Service implements TrackbookKeys {
/* Creates gps and network location listeners */
private void startFindingLocation() {
// put up notification
NotificationHelper.show(this,mTrack);
// register location listeners and request updates
List locationProviders = mLocationManager.getProviders(true);
@ -235,10 +239,6 @@ public class TrackerService extends Service implements TrackbookKeys {
i.putExtra(EXTRA_LAST_LOCATION, mCurrentBestLocation);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
// // cancel notification
// NotificationHelper.stop();
// change notification
NotificationHelper.update(mTrack, false);
}

View file

@ -1,7 +1,7 @@
/**
* Track.java
* Implements the Track class
* A Track stores a list of waypoints
* A Track stores a list of WayPoints
*
* This file is part of
* TRACKBOOK - Movement Recorder for Android
@ -26,6 +26,7 @@ import org.y20k.trackbook.helpers.TrackbookKeys;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
@ -71,29 +72,29 @@ public class Track implements TrackbookKeys, Parcelable {
};
/* Adds new waypoint */
/* Adds new WayPoint */
public WayPoint addWayPoint(Location location) {
// add up distance
mTrackLength = addDistanceToTrack(location);
int wayPointCount = mWayPoints.size();
// determine if last waypoint was a stopover
// determine if last WayPoint was a stopover
boolean stopOver = false;
if (wayPointCount > 1) {
Location lastLocation = mWayPoints.get(wayPointCount - 1).getLocation();
stopOver = LocationHelper.isStopOver(lastLocation, location);
}
if (stopOver) {
// mark last waypoint as stopover
// mark last WayPoint as stopover
LogHelper.v(LOG_TAG, "Last Location was a stop.");
mWayPoints.get(wayPointCount-1).setIsStopOver(true);
}
// create new waypoint
// create new WayPoint
WayPoint wayPoint = new WayPoint(location, false, mTrackLength);
// add new waypoint to track
// add new WayPoint to track
mWayPoints.add(wayPoint);
return wayPoint;
@ -128,7 +129,7 @@ public class Track implements TrackbookKeys, Parcelable {
public String getTrackDistance() {
float trackDistance = mWayPoints.get(mWayPoints.size()-1).getDistanceToStartingPoint();
return String.format ("%.0f", trackDistance) + "m";
return String.format (Locale.ENGLISH, "%.0f", trackDistance) + "m";
}
@ -139,7 +140,7 @@ public class Track implements TrackbookKeys, Parcelable {
/* Adds distance to given location to length of track */
private float addDistanceToTrack(Location location) {
// get number of previously recorded waypoints
// get number of previously recorded WayPoints
int wayPointCount = mWayPoints.size();
// at least two data points are needed

View file

@ -22,6 +22,7 @@ import android.location.LocationManager;
import android.os.SystemClock;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
@ -132,7 +133,7 @@ public final class LocationHelper implements TrackbookKeys {
}
/* Checks if given location is a new waypoint */
/* Checks if given location is a new WayPoint */
public static boolean isNewWayPoint(Location lastLocation, Location newLocation) {
float distance = newLocation.distanceTo(lastLocation);
long timeDifference = newLocation.getElapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos();
@ -217,12 +218,12 @@ public final class LocationHelper implements TrackbookKeys {
if (includeHours) {
// format hh:mm:ss
return String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(milliseconds),
return String.format(Locale.ENGLISH, "%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(milliseconds),
TimeUnit.MILLISECONDS.toMinutes(milliseconds) % TimeUnit.HOURS.toMinutes(1),
TimeUnit.MILLISECONDS.toSeconds(milliseconds) % TimeUnit.MINUTES.toSeconds(1));
} else if (TimeUnit.MILLISECONDS.toHours(milliseconds) < 1) {
// format mm:ss
return String.format("%02d:%02d", TimeUnit.MILLISECONDS.toMinutes(milliseconds) % TimeUnit.HOURS.toMinutes(1),
return String.format(Locale.ENGLISH, "%02d:%02d", TimeUnit.MILLISECONDS.toMinutes(milliseconds) % TimeUnit.HOURS.toMinutes(1),
TimeUnit.MILLISECONDS.toSeconds(milliseconds) % TimeUnit.MINUTES.toSeconds(1));
} else {
return null;

View file

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

View file

@ -90,14 +90,14 @@ public final class MapHelper {
final ArrayList<OverlayItem> overlayItems = new ArrayList<>();
for (int i = 0 ; i < track.getSize() ; i++) {
// get waypoint and check if it is current position
// get WayPoint and check if it is current position
wayPoint = wayPoints.get(i);
currentPosition = i == trackSize - 1;
// create marker
Drawable newMarker;
// CASE 1: Tracking active and waypoint is not current position
// CASE 1: Tracking active and WayPoint is not current position
if (trackingActive && !currentPosition) {
if (wayPoint.getIsStopOver()) {
// stop over marker
@ -108,7 +108,7 @@ public final class MapHelper {
}
}
// CASE 2: Tracking active and waypoint is current position
// CASE 2: Tracking active and WayPoint is current position
else if (trackingActive && currentPosition) {
if (wayPoint.getIsStopOver()) {
// stop over marker
@ -119,7 +119,7 @@ public final class MapHelper {
}
}
// CASE 3: Tracking not active and waypoint is not current position
// CASE 3: Tracking not active and WayPoint is not current position
else if (!trackingActive && !currentPosition) {
if (wayPoint.getIsStopOver()) {
// stop over marker
@ -130,7 +130,7 @@ public final class MapHelper {
}
}
// CASE 4: Tracking not active and waypoint is current position
// CASE 4: Tracking not active and WayPoint is current position
else {
// default marker
newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_location_crumb_blue_24dp);

View file

@ -31,7 +31,7 @@
android:layout_height="wrap_content"
android:id="@+id/trackbook_icon"
android:background="@mipmap/ic_launcher"
android:contentDescription="@string/layout_onboading_description_app_icon"
android:contentDescription="@string/layout_onboarding_description_app_icon"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:layout_gravity="center_vertical" />
@ -45,14 +45,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/layout_onboading_h2_app_name"
android:text="@string/layout_onboarding_h2_app_name"
android:id="@+id/h2_app_name" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/layout_onboading_p_app_claim"
android:text="@string/layout_onboarding_p_app_claim"
android:id="@+id/p_app_claim" />
</LinearLayout>
@ -63,7 +63,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/layout_onboading_h2_request_permissions"
android:text="@string/layout_onboarding_h2_request_permissions"
android:id="@+id/h2_request_permissions"
android:layout_marginTop="@dimen/activity_vertical_margin"/>
@ -72,14 +72,14 @@
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textStyle="bold"
android:text="@string/layout_onboading_h3_permission_location"
android:text="@string/layout_onboarding_h3_permission_location"
android:id="@+id/h3_permission_location"
android:layout_marginTop="@dimen/activity_vertical_margin"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/layout_onboading_p_permission_location"
android:text="@string/layout_onboarding_p_permission_location"
android:id="@+id/p_permission_location" />
<TextView
@ -87,14 +87,14 @@
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textStyle="bold"
android:text="@string/layout_onboading_h3_permission_storage"
android:text="@string/layout_onboarding_h3_permission_storage"
android:id="@+id/h3_permission_storage"
android:layout_marginTop="@dimen/activity_vertical_margin" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/layout_onboading_p_permission_storage"
android:text="@string/layout_onboarding_p_permission_storage"
android:id="@+id/p_permission_storage" />
<Button
@ -102,7 +102,7 @@
android:layout_height="wrap_content"
android:backgroundTint="@color/trackbook_blue"
android:textColor="@color/trackbook_white"
android:text="@string/layout_onboading_button_okay"
android:text="@string/layout_onboarding_button_okay"
android:id="@+id/button_okay"
android:layout_gravity="end"
android:layout_marginTop="@dimen/activity_vertical_margin"/>

View file

@ -28,29 +28,30 @@
<string name="toast_message_location_offline">Location is turned off.</string>
<string name="toast_message_acquiring_location">Acquiring current location.</string>
<string name="toast_message_last_location">Last location:</string>
<string name="toast_message_clear_map">Clearing map.</string>
<string name="toast_message_last_location_age_one_hour">over one hour</string>
<!-- map markers -->
<string name="marker_description_source">Source</string>
<string name="marker_description_accuracy">Accuracy</string>
<!-- onboading layout -->
<!-- onboarding layout -->
<string name="layout_onboarding_h1_welcome">Hello</string>
<string name="layout_onboading_description_app_icon">Trackbook App Icon</string>
<string name="layout_onboading_h2_app_name">Trackbook</string>
<string name="layout_onboading_p_app_claim">Movement Recorder for Android</string>
<string name="layout_onboading_h2_request_permissions">Trackbook cannot work without these permissions:</string>
<string name="layout_onboading_h3_permission_location">LOCATION</string>
<string name="layout_onboading_p_permission_location">Trackbook needs accurate GPS location data to be able to record your movements. If the GPS data is not available or not accurate enough Trackbook uses location data from cell tower and WiFi triangulation.</string>
<string name="layout_onboading_h3_permission_storage">STORAGE</string>
<string name="layout_onboading_p_permission_storage">Trackbook uses osmdroid, which caches map tiles on Android\'s external storage. You can find the map cache in the osmdroid folder on the top level of the user-facing file system.</string>
<string name="layout_onboading_button_okay">Got it!</string>
<string name="layout_onboarding_description_app_icon">Trackbook App Icon</string>
<string name="layout_onboarding_h2_app_name">Trackbook</string>
<string name="layout_onboarding_p_app_claim">Movement Recorder for Android</string>
<string name="layout_onboarding_h2_request_permissions">Trackbook cannot work without these permissions:</string>
<string name="layout_onboarding_h3_permission_location">LOCATION</string>
<string name="layout_onboarding_p_permission_location">Trackbook needs accurate GPS location data to be able to record your movements. If the GPS data is not available or not accurate enough Trackbook uses location data from cell tower and WiFi triangulation.</string>
<string name="layout_onboarding_h3_permission_storage">STORAGE</string>
<string name="layout_onboarding_p_permission_storage">Trackbook uses osmdroid, which caches map tiles on Android\'s external storage. You can find the map cache in the osmdroid folder on the top level of the user-facing file system.</string>
<string name="layout_onboarding_button_okay">Got it!</string>
<!-- infosheet about -->
<string name="infosheet_about_h1_about">About Trackbook</string>
<string name="infosheet_about_h2_recorder">Movement Recorder for Android</string>
<string name="infosheet_about_h3_version">Version 0.1 ("The Great Gig in the Sky")</string>
<string name="infosheet_about_p_bare">Trackbook is a bare bones app for recording your movements. Trackbook is great for hiking, vacation or workout. Once started it displays your movements on a map. You can save your recorded tracks and share them with friends.</string>
<string name="infosheet_about_p_bare">Trackbook is a bare bones app for recording your movements. Trackbook is great for hiking, vacation or workout. Once started it traces your movements on a map. The map data is provided by OpenStreetMap (OSM).</string>
<string name="infosheet_about_p_free">Trackbook is free software. You can find the code on GitHub. GitHub is also a good place to file bugs or even to contribute, if you are interested. Trackbook is published under the MIT open source license. Trackbook uses osmdroid to display the map, which is also free software published under the Apache License.</string>
<string name="infosheet_about_p_github">https://github.com/y20k/trackbook</string>
<string name="infosheet_about_p_osmdroid">https://github.com/osmdroid/osmdroid</string>