initial commit
commit
33606faac1
|
@ -0,0 +1,11 @@
|
|||
How to contribute to Trackbook
|
||||
==============================
|
||||
|
||||
### Report a bug or suggest a new feature
|
||||
tbd
|
||||
|
||||
### Help with translations
|
||||
tbd
|
||||
|
||||
### Submit your own solutions
|
||||
tbd
|
|
@ -0,0 +1,23 @@
|
|||
The MIT License (MIT)
|
||||
=====================
|
||||
|
||||
Copyright (c) 2016 - Y20K.org
|
||||
-----------------------------
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -0,0 +1,39 @@
|
|||
README
|
||||
======
|
||||
|
||||
Trackbook - Movement recorder for Android
|
||||
-----------------------------------------
|
||||
|
||||
**Version 0.1.x ("The Great Gig in the Sky")**
|
||||
|
||||
Trackbook is a bare bones app for recording you own movements. Trackbook 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.
|
||||
|
||||
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. osmdroid is also free software. It is 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.
|
||||
|
||||
Install Trackbook
|
||||
------------------
|
||||
tbd
|
||||
|
||||
How to use Trackbook
|
||||
---------------------
|
||||
tbd
|
||||
|
||||
Which Permissions does Trackbook need?
|
||||
---------------------------------------
|
||||
### Permission "INTERNET"
|
||||
tbd
|
||||
|
||||
### Permission "ACCESS_NETWORK_STATE"
|
||||
tbd
|
||||
|
||||
### Permission "ACCESS_WIFI_STATE"
|
||||
tbd
|
||||
|
||||
### Permission "ACCESS_COARSE_LOCATION"
|
||||
tbd
|
||||
|
||||
### Permission "ACCESS_FINE_LOCATION"
|
||||
tbd
|
||||
|
||||
### Permission "WRITE_EXTERNAL_STORAGE"
|
||||
tbd
|
|
@ -0,0 +1,29 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 24
|
||||
buildToolsVersion "24.0.0"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "org.y20k.trackbook"
|
||||
minSdkVersion 22
|
||||
targetSdkVersion 24
|
||||
versionCode 1
|
||||
versionName "0.1 (The Great Gig in the Sky)"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile 'com.android.support:appcompat-v7:24.2.0'
|
||||
compile 'com.android.support:design:24.2.0'
|
||||
compile 'org.osmdroid:osmdroid-android:5.2@aar'
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /Users/solaris/Library/Android/sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.y20k.trackbook">
|
||||
|
||||
<!-- NORMAL PERMISSIONS, automatically granted -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<!-- DANGEROUS PERMISSIONS, must request -->
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:fullBackupContent="@xml/backupscheme"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/TrackbookAppTheme">
|
||||
|
||||
<!-- MAIN ACTIVITY -->
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/TrackbookAppTheme.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- PLAYER SERVICE -->
|
||||
<service
|
||||
android:name=".TrackerService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="org.y20k.transistor.action.START" />
|
||||
<action android:name="org.y20k.transistor.action.STOP" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
|
@ -0,0 +1,243 @@
|
|||
/**
|
||||
* MainActivity.java
|
||||
* Implements the app's main activity
|
||||
* The main activity sets up the main view end inflates a menu bar menu
|
||||
*
|
||||
* This file is part of
|
||||
* TRACKBOOK - Movement Recorder for Android
|
||||
*
|
||||
* Copyright (c) 2016 - 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;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.y20k.trackbook.helpers.LogHelper;
|
||||
import org.y20k.trackbook.helpers.TrackbookKeys;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* MainActivity class
|
||||
*/
|
||||
public class MainActivity extends AppCompatActivity implements TrackbookKeys {
|
||||
|
||||
/* Define log tag */
|
||||
private static final String LOG_TAG = MainActivityFragment.class.getSimpleName();
|
||||
|
||||
|
||||
/* Main class variables */
|
||||
private boolean mTracking;
|
||||
private boolean mPermissionsGranted;
|
||||
private List<String> mMissingPermissions;
|
||||
private FloatingActionButton mFloatingActionButton;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mTracking = false;
|
||||
mPermissionsGranted = false;
|
||||
|
||||
// check permissions on Android 6 and higher
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
// check permissions
|
||||
mMissingPermissions = checkPermissions();
|
||||
mPermissionsGranted = mMissingPermissions.size() == 0;
|
||||
} else {
|
||||
mPermissionsGranted = true;
|
||||
}
|
||||
|
||||
// set user agent to prevent getting banned from the osm servers
|
||||
org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants.setUserAgentValue(BuildConfig.APPLICATION_ID);
|
||||
|
||||
// set up main layout
|
||||
setupLayout();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// inflate action bar options menu
|
||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
|
||||
// handle action bar options menu selection
|
||||
switch (item.getItemId()) {
|
||||
|
||||
// CASE SETTINGS
|
||||
case R.id.action_settings:
|
||||
LogHelper.v(LOG_TAG, "Settings was selected");
|
||||
return true;
|
||||
|
||||
// CASE DEFAULT
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: {
|
||||
Map<String, Integer> perms = new HashMap<>();
|
||||
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
|
||||
perms.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
|
||||
for (int i = 0; i < permissions.length; i++)
|
||||
perms.put(permissions[i], grantResults[i]);
|
||||
|
||||
// check for ACCESS_FINE_LOCATION and WRITE_EXTERNAL_STORAGE
|
||||
Boolean location = perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
|
||||
Boolean storage = perms.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
if (location && storage) {
|
||||
// permissions granted - notify user
|
||||
Toast.makeText(this, R.string.toast_message_permissions_granted, Toast.LENGTH_SHORT).show();
|
||||
mPermissionsGranted = true;
|
||||
// switch to main map layout
|
||||
setupLayout();
|
||||
} else {
|
||||
// permissions denied - notify user
|
||||
Toast.makeText(this, R.string.toast_message_unable_to_start_app, Toast.LENGTH_SHORT).show();
|
||||
mPermissionsGranted = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Set up main layout */
|
||||
private void setupLayout() {
|
||||
if (mPermissionsGranted) {
|
||||
// point to the main map layout
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
// show action bar
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
// show the record button and attach listener
|
||||
mFloatingActionButton = (FloatingActionButton) findViewById(R.id.fab);
|
||||
mFloatingActionButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
handleFloatingActionButtonClick(view);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
// point to the on main onboarding layout
|
||||
setContentView(R.layout.onboarding_main);
|
||||
|
||||
// show the okay button and attach listener
|
||||
Button okButton = (Button) findViewById(R.id.button_okay);
|
||||
okButton.setOnClickListener(new View.OnClickListener() {
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (mMissingPermissions != null && !mMissingPermissions.isEmpty()) {
|
||||
// request permissions
|
||||
String[] params = mMissingPermissions.toArray(new String[mMissingPermissions.size()]);
|
||||
requestPermissions(params, REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Handles tap on the record button */
|
||||
private void handleFloatingActionButtonClick(View view) {
|
||||
if (mTracking) {
|
||||
Snackbar.make(view, R.string.snackbar_message_tracking_stopped, Snackbar.LENGTH_SHORT).setAction("Action", null).show();
|
||||
|
||||
// change state
|
||||
mFloatingActionButton.setImageResource(R.drawable.ic_fiber_manual_record_white_24dp);
|
||||
mTracking = false;
|
||||
|
||||
// re-start preliminary tracking
|
||||
// startFindingLocation();
|
||||
|
||||
// stop tracker service
|
||||
Intent intent = new Intent(this, TrackerService.class);
|
||||
intent.setAction(ACTION_STOP);
|
||||
startService(intent);
|
||||
LogHelper.v(LOG_TAG, "Stopping tracker service.");
|
||||
|
||||
|
||||
} else {
|
||||
Snackbar.make(view, R.string.snackbar_message_tracking_started, Snackbar.LENGTH_SHORT).setAction("Action", null).show();
|
||||
|
||||
// change state
|
||||
mFloatingActionButton.setImageResource(R.drawable.ic_fiber_manual_record_red_24dp);
|
||||
mTracking = true;
|
||||
|
||||
// TODO putParcelable lastLocation
|
||||
|
||||
// start tracker service
|
||||
Intent intent = new Intent(this, TrackerService.class);
|
||||
intent.setAction(ACTION_START);
|
||||
startService(intent);
|
||||
LogHelper.v(LOG_TAG, "Starting tracker service.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Check which permissions have been granted */
|
||||
private List<String> checkPermissions() {
|
||||
List<String> permissions = new ArrayList<>();
|
||||
|
||||
// check for location permission
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||
// add missing permission
|
||||
permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
|
||||
}
|
||||
|
||||
// check for storage permission
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
// add missing permission
|
||||
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,335 @@
|
|||
/**
|
||||
* MainActivityFragment.java
|
||||
* Implements the main fragment of the main activity
|
||||
* This fragment displays a map using osmdroid
|
||||
*
|
||||
* This file is part of
|
||||
* TRACKBOOK - Movement Recorder for Android
|
||||
*
|
||||
* Copyright (c) 2016 - 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;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.osmdroid.api.IMapController;
|
||||
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
|
||||
import org.osmdroid.util.GeoPoint;
|
||||
import org.osmdroid.views.MapView;
|
||||
import org.osmdroid.views.overlay.ItemizedIconOverlay;
|
||||
import org.osmdroid.views.overlay.compass.CompassOverlay;
|
||||
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider;
|
||||
import org.y20k.trackbook.helpers.LocationHelper;
|
||||
import org.y20k.trackbook.helpers.LogHelper;
|
||||
import org.y20k.trackbook.helpers.MapHelper;
|
||||
import org.y20k.trackbook.helpers.TrackbookKeys;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* MainActivityFragment class
|
||||
*/
|
||||
public class MainActivityFragment extends Fragment implements TrackbookKeys {
|
||||
|
||||
/* Define log tag */
|
||||
private static final String LOG_TAG = MainActivityFragment.class.getSimpleName();
|
||||
|
||||
|
||||
/* Main class variables */
|
||||
private Activity mActivity;
|
||||
private MapView mMapView;
|
||||
private IMapController mController;
|
||||
private CompassOverlay mCompassOverlay = null;
|
||||
private LocationManager mLocationManager;
|
||||
private LocationListener mGPSListener;
|
||||
private LocationListener mNetworkListener;
|
||||
private Location mCurrentBestLocation;
|
||||
private ItemizedIconOverlay mMyLocationOverlay;
|
||||
|
||||
|
||||
/* Constructor (default) */
|
||||
public MainActivityFragment() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// get activity
|
||||
mActivity = getActivity();
|
||||
|
||||
// action bar has options menu
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
// acquire reference to Location Manager
|
||||
mLocationManager = (LocationManager) mActivity.getSystemService(Context.LOCATION_SERVICE);
|
||||
|
||||
// get last know location
|
||||
List locationProviders = mLocationManager.getProviders(true);
|
||||
if (locationProviders.size() > 0) {
|
||||
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
|
||||
} else {
|
||||
promptUserForLocation();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
// create basic map
|
||||
mMapView = new MapView(inflater.getContext());
|
||||
|
||||
// get display metrics
|
||||
final DisplayMetrics dm = mActivity.getResources().getDisplayMetrics();
|
||||
|
||||
// get map controller
|
||||
mController = mMapView.getController();
|
||||
|
||||
// basic map setup
|
||||
mMapView.setTileSource(TileSourceFactory.MAPNIK);
|
||||
mMapView.setTilesScaledToDpi(true);
|
||||
|
||||
// add multi-touch capability
|
||||
mMapView.setMultiTouchControls(true);
|
||||
|
||||
// initiate map state
|
||||
if (savedInstanceState != null) {
|
||||
// restore saved instance of map
|
||||
GeoPoint position = new GeoPoint(savedInstanceState.getDouble(INSTANCE_LATITUDE), savedInstanceState.getDouble(INSTANCE_LONGITUDE));
|
||||
mController.setCenter(position);
|
||||
mController.setZoom(savedInstanceState.getInt(INSTANCE_ZOOM_LEVEL, 16));
|
||||
// restore current location
|
||||
mCurrentBestLocation = savedInstanceState.getParcelable(INSTANCE_CURRENT_LOCATION);
|
||||
} else if (mCurrentBestLocation != null) {
|
||||
// fallback or first run: set map to current position
|
||||
GeoPoint position = new GeoPoint(mCurrentBestLocation.getLatitude(), mCurrentBestLocation.getLongitude());
|
||||
mController.setCenter(position);
|
||||
mController.setZoom(16);
|
||||
}
|
||||
|
||||
// add compass to map
|
||||
mCompassOverlay = new CompassOverlay(mActivity, new InternalCompassOrientationProvider(mActivity), mMapView);
|
||||
mCompassOverlay.enableCompass();
|
||||
mMapView.getOverlays().add(mCompassOverlay);
|
||||
|
||||
// mark user's location on map
|
||||
if (mCurrentBestLocation != null) {
|
||||
mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation);
|
||||
mMapView.getOverlays().add(mMyLocationOverlay);
|
||||
}
|
||||
|
||||
return mMapView;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// start tracking position
|
||||
startFindingLocation();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
// disable location listener
|
||||
stopFindingLocation();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroyView(){
|
||||
super.onDestroyView();
|
||||
|
||||
// deactivate map
|
||||
mMapView.onDetach();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
|
||||
// handle action bar options menu selection
|
||||
switch (item.getItemId()) {
|
||||
|
||||
// CASE MY LOCATION
|
||||
case R.id.action_my_location:
|
||||
|
||||
Toast.makeText(mActivity, mActivity.getString(R.string.toast_message_my_location), Toast.LENGTH_LONG).show();
|
||||
|
||||
if (mLocationManager.getProviders(true).size() == 0) {
|
||||
// location services are off - ask user to turn them on
|
||||
promptUserForLocation();
|
||||
return true;
|
||||
}
|
||||
|
||||
// get current position
|
||||
GeoPoint position;
|
||||
if (mCurrentBestLocation != null) {
|
||||
// app has a current best estimate location
|
||||
position = new GeoPoint(mCurrentBestLocation.getLatitude(), mCurrentBestLocation.getLongitude());
|
||||
} else {
|
||||
// app does not have any location fix
|
||||
mCurrentBestLocation = LocationHelper.determineLastKnownLocation(mLocationManager);
|
||||
position = new GeoPoint(mCurrentBestLocation.getLatitude(), mCurrentBestLocation.getLongitude());
|
||||
}
|
||||
|
||||
// center map on current position
|
||||
mController.setCenter(position);
|
||||
|
||||
// mark user's new location on map and remove last marker
|
||||
mMapView.getOverlays().remove(mMyLocationOverlay);
|
||||
mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation);
|
||||
mMapView.getOverlays().add(mMyLocationOverlay);
|
||||
|
||||
return true;
|
||||
|
||||
// CASE DEFAULT
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
// save map position
|
||||
outState.putDouble(INSTANCE_LATITUDE, mMapView.getMapCenter().getLatitude());
|
||||
outState.putDouble(INSTANCE_LONGITUDE, mMapView.getMapCenter().getLongitude());
|
||||
outState.putInt(INSTANCE_ZOOM_LEVEL, mMapView.getZoomLevel());
|
||||
outState.putParcelable(INSTANCE_CURRENT_LOCATION, mCurrentBestLocation);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
|
||||
/* Start finding location for map */
|
||||
private void startFindingLocation() {
|
||||
|
||||
// listener that responds to location updates
|
||||
mGPSListener = createLocationsListener();
|
||||
mNetworkListener = createLocationsListener();
|
||||
|
||||
// start listener
|
||||
List locationProviders = mLocationManager.getProviders(true);
|
||||
if (locationProviders.contains(LocationManager.GPS_PROVIDER)) {
|
||||
try {
|
||||
// enable location listener (gps)
|
||||
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mGPSListener);
|
||||
} catch (SecurityException e) {
|
||||
// catches permission problems
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (locationProviders.contains(LocationManager.NETWORK_PROVIDER)) {
|
||||
try {
|
||||
// enable location listener (network)
|
||||
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mNetworkListener);
|
||||
} catch (SecurityException e) {
|
||||
// catches permission problems
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Stops finding location for map */
|
||||
private void stopFindingLocation() {
|
||||
// disable location listeners
|
||||
List locationProviders = mLocationManager.getProviders(true);
|
||||
if (locationProviders.contains(LocationManager.GPS_PROVIDER)) {
|
||||
try {
|
||||
mLocationManager.removeUpdates(mGPSListener);
|
||||
} catch (SecurityException e) {
|
||||
// catches permission problems
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (locationProviders.contains(LocationManager.NETWORK_PROVIDER)) {
|
||||
try {
|
||||
mLocationManager.removeUpdates(mNetworkListener);
|
||||
} catch (SecurityException e) {
|
||||
// catches permission problems
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Creates listener for changes in location status */
|
||||
private LocationListener createLocationsListener() {
|
||||
return new LocationListener() {
|
||||
public void onLocationChanged(Location location) {
|
||||
// check if the new location is better
|
||||
if (LocationHelper.isBetterLocation(location, mCurrentBestLocation)) {
|
||||
// save location
|
||||
mCurrentBestLocation = location;
|
||||
|
||||
// mark user's new location on map and remove last marker
|
||||
mMapView.getOverlays().remove(mMyLocationOverlay);
|
||||
mMyLocationOverlay = MapHelper.createMyLocationOverlay(mActivity, mCurrentBestLocation);
|
||||
mMapView.getOverlays().add(mMyLocationOverlay);
|
||||
}
|
||||
}
|
||||
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
// TODO do something
|
||||
}
|
||||
|
||||
public void onProviderEnabled(String provider) {
|
||||
LogHelper.v(LOG_TAG, "Location provider enabled: " + provider);
|
||||
}
|
||||
|
||||
public void onProviderDisabled(String provider) {
|
||||
LogHelper.v(LOG_TAG, "Location provider disabled: " + provider);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* Prompts user to turn on location */
|
||||
private void promptUserForLocation() {
|
||||
// TODO prompt user to turn on location
|
||||
Toast.makeText(mActivity, mActivity.getString(R.string.toast_message_location_offline), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
|
||||
/* Saves state of map */
|
||||
private void saveMaoState(Context context) {
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
SharedPreferences.Editor editor = settings.edit();
|
||||
editor.putInt(PREFS_ZOOM_LEVEL, mMapView.getZoomLevel());
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
|
||||
/* Loads app state from preferences */
|
||||
private void loadMapState(Context context) {
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
int zoom = settings.getInt(PREFS_ZOOM_LEVEL, 16);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* TrackerService.java
|
||||
* Implements the app's movement tracker service
|
||||
* The TrackerService creates a Track object and displays a notification
|
||||
*
|
||||
* This file is part of
|
||||
* TRACKBOOK - Movement Recorder for Android
|
||||
*
|
||||
* Copyright (c) 2016 - 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;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.location.Location;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import org.y20k.trackbook.core.Track;
|
||||
import org.y20k.trackbook.helpers.TrackbookKeys;
|
||||
|
||||
|
||||
/**
|
||||
* TrackerService class
|
||||
*/
|
||||
public class TrackerService extends Service implements TrackbookKeys {
|
||||
|
||||
// TODO study this https://developer.android.com/guide/topics/location/strategies.html
|
||||
|
||||
/* Define log tag */
|
||||
private static final String LOG_TAG = TrackerService.class.getSimpleName();
|
||||
|
||||
|
||||
/* Main class variables */
|
||||
private Track mTrack;
|
||||
private CountDownTimer mTimer;
|
||||
private LocationManager mLocationManager;
|
||||
private LocationListener mLocationListener;
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
// return super.onStartCommand(intent, flags, startId);
|
||||
|
||||
// checking for empty intent
|
||||
if (intent == null) {
|
||||
Log.v(LOG_TAG, "Null-Intent received. Stopping self.");
|
||||
// remove notification
|
||||
stopForeground(true);
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
// ACTION START
|
||||
else if (intent.getAction().equals(ACTION_START)) {
|
||||
Log.v(LOG_TAG, "Service received command: START");
|
||||
|
||||
// create a new track
|
||||
mTrack = new Track();
|
||||
|
||||
// acquire reference to Location Manager
|
||||
mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
|
||||
|
||||
// listener that responds to location updates
|
||||
mLocationListener = new LocationListener() {
|
||||
public void onLocationChanged(Location location) {
|
||||
// add new location to track
|
||||
mTrack.addWayPoint(location, false);
|
||||
}
|
||||
|
||||
public void onStatusChanged(String provider, int status, Bundle extras) {
|
||||
// TODO do something
|
||||
}
|
||||
|
||||
public void onProviderEnabled(String provider) {
|
||||
// TODO do something
|
||||
}
|
||||
|
||||
public void onProviderDisabled(String provider) {
|
||||
// TODO do something
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
|
||||
|
||||
|
||||
|
||||
mTimer = new CountDownTimer(CONSTANT_MAXIMAL_DURATION, CONSTANT_TRACKING_INTERVAL) {
|
||||
@Override
|
||||
public void onTick(long l) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
// TODO
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ACTION STOP
|
||||
else if (intent.getAction().equals(ACTION_STOP)) {
|
||||
// Remove the listener you previously added
|
||||
mLocationManager.removeUpdates(mLocationListener);
|
||||
Log.v(LOG_TAG, "Service received command: STOP");
|
||||
}
|
||||
|
||||
// START_STICKY is used for services that are explicitly started and stopped as needed
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
Log.v(LOG_TAG, "onDestroy called.");
|
||||
|
||||
// Remove the listener you previously added
|
||||
mLocationManager.removeUpdates(mLocationListener);
|
||||
|
||||
// cancel notification
|
||||
stopForeground(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* Track.java
|
||||
* Implements the Track class
|
||||
* A Track stores a list of waypoints
|
||||
*
|
||||
* This file is part of
|
||||
* TRACKBOOK - Movement Recorder for Android
|
||||
*
|
||||
* Copyright (c) 2016 - 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.core;
|
||||
|
||||
import android.location.Location;
|
||||
import android.util.Log;
|
||||
|
||||
import org.y20k.trackbook.helpers.TrackbookKeys;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Track class
|
||||
*/
|
||||
public class Track implements TrackbookKeys {
|
||||
|
||||
/* Define log tag */
|
||||
private static final String LOG_TAG = Track.class.getSimpleName();
|
||||
|
||||
|
||||
/* Main class variables */
|
||||
private List mWayPoints;
|
||||
|
||||
|
||||
/* Constructor */
|
||||
public Track() {
|
||||
mWayPoints = new ArrayList<WayPoint>();
|
||||
}
|
||||
|
||||
|
||||
/* Adds new waypoint */
|
||||
public void addWayPoint(Location location, boolean isStopOver) {
|
||||
// create new waypoint
|
||||
WayPoint wayPoint = new WayPoint(location, isStopOver);
|
||||
|
||||
// TODO check if last waypoint is a stopover
|
||||
if (CONSTANT_MINIMAL_STOP_TIME != CONSTANT_MINIMAL_STOP_TIME) {
|
||||
wayPoint.isStopOver = true;
|
||||
} else {
|
||||
wayPoint.isStopOver = false;
|
||||
}
|
||||
|
||||
// add new waypoint to track
|
||||
mWayPoints.add(wayPoint);
|
||||
|
||||
// TODO remove debugging log
|
||||
Log.v(LOG_TAG, "!!! new location: " + wayPoint.location.toString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class: Defines data type WayPoint ***
|
||||
*/
|
||||
private class WayPoint {
|
||||
|
||||
private Location location;
|
||||
private boolean isStopOver;
|
||||
|
||||
/* Constructor */
|
||||
public WayPoint(Location location, boolean isStopOver) {
|
||||
this.location = location;
|
||||
this.isStopOver = isStopOver;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* End of inner class
|
||||
*/
|
||||
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/**
|
||||
* LocationHelper.java
|
||||
* Implements the LocationHelper class
|
||||
* A LocationHelper offers helper methods for dealing with location issues
|
||||
*
|
||||
* This file is part of
|
||||
* TRACKBOOK - Movement Recorder for Android
|
||||
*
|
||||
* Copyright (c) 2016 - 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 android.location.LocationManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* LocationHelper class
|
||||
*/
|
||||
public final class LocationHelper {
|
||||
|
||||
/* Main class variables */
|
||||
private static final int TWO_MINUTES = 1000 * 60 * 2;
|
||||
|
||||
|
||||
/* Determines last known location */
|
||||
public static Location determineLastKnownLocation(LocationManager locationManager) {
|
||||
// define variables
|
||||
List locationProviders = locationManager.getProviders(true);
|
||||
Location gpsLocation = null;
|
||||
Location networkLocation = null;
|
||||
|
||||
// set location providers
|
||||
String gpsProvider = LocationManager.GPS_PROVIDER;
|
||||
String networkProvider = LocationManager.NETWORK_PROVIDER;
|
||||
|
||||
|
||||
if (locationProviders.contains(gpsProvider)) {
|
||||
// get last know location from gps
|
||||
try {
|
||||
gpsLocation = locationManager.getLastKnownLocation(gpsProvider);
|
||||
} catch (SecurityException e) {
|
||||
// catches permission problems
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (locationProviders.contains(networkProvider)) {
|
||||
// get last known location from wifi and cell
|
||||
try {
|
||||
networkLocation = locationManager.getLastKnownLocation(networkProvider);
|
||||
} catch (SecurityException e) {
|
||||
// catches permission problems
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// return best estimate location
|
||||
if (isBetterLocation(gpsLocation, networkLocation)) {
|
||||
return gpsLocation;
|
||||
} else {
|
||||
return networkLocation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Determines whether one location reading is better than the current location fix */
|
||||
public static boolean isBetterLocation(Location location, Location currentBestLocation) {
|
||||
// credit: the isBetterLocation method was sample code from: https://developer.android.com/guide/topics/location/strategies.html
|
||||
|
||||
if (currentBestLocation == null) {
|
||||
// a new location is always better than no location
|
||||
return true;
|
||||
}
|
||||
|
||||
// check whether the new location fix is newer or older
|
||||
long timeDelta = location.getTime() - currentBestLocation.getTime();
|
||||
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
|
||||
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
|
||||
boolean isNewer = timeDelta > 0;
|
||||
|
||||
// if it's been more than two minutes since the current location, use the new location because the user has likely moved
|
||||
if (isSignificantlyNewer) {
|
||||
return true;
|
||||
} else if (isSignificantlyOlder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check whether the new location fix is more or less accurate
|
||||
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
|
||||
boolean isLessAccurate = accuracyDelta > 0;
|
||||
boolean isMoreAccurate = accuracyDelta < 0;
|
||||
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
|
||||
|
||||
// check if the old and new location are from the same provider
|
||||
boolean isFromSameProvider = isSameProvider(location.getProvider(),
|
||||
currentBestLocation.getProvider());
|
||||
|
||||
// determine location quality using a combination of timeliness and accuracy
|
||||
if (isMoreAccurate) {
|
||||
return true;
|
||||
} else if (isNewer && !isLessAccurate) {
|
||||
return true;
|
||||
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Checks whether two location providers are the same */
|
||||
private static boolean isSameProvider(String provider1, String provider2) {
|
||||
// credit: the isSameProvider method was sample code from: https://developer.android.com/guide/topics/location/strategies.html
|
||||
if (provider1 == null) {
|
||||
return provider2 == null;
|
||||
}
|
||||
return provider1.equals(provider2);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* LogHelper.java
|
||||
* Implements the LogHelper class
|
||||
* A LogHelper wraps the logging calls to be able to strip them out of release versions
|
||||
*
|
||||
* This file is part of
|
||||
* TRACKBOOK - Movement Recorder for Android
|
||||
*
|
||||
* Copyright (c) 2016 - 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.support.v4.BuildConfig;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
/**
|
||||
* LogHelper class
|
||||
*/
|
||||
public final class LogHelper {
|
||||
|
||||
private final static boolean mTesting = true;
|
||||
|
||||
public static void d(final String tag, String message) {
|
||||
// include logging only in debug versions
|
||||
if (BuildConfig.DEBUG || mTesting) {
|
||||
Log.d(tag, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void v(final String tag, String message) {
|
||||
// include logging only in debug versions
|
||||
if (BuildConfig.DEBUG || mTesting) {
|
||||
Log.v(tag, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void e(final String tag, String message) {
|
||||
Log.e(tag, message);
|
||||
}
|
||||
|
||||
|
||||
public static void i(final String tag, String message) {
|
||||
Log.i(tag, message);
|
||||
}
|
||||
|
||||
|
||||
public static void w(final String tag, String message) {
|
||||
Log.w(tag, message);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* MapHelper.java
|
||||
* Implements the MapHelper class
|
||||
* A MapHelper offers helper methods for dealing with Trackbook's map
|
||||
*
|
||||
* This file is part of
|
||||
* TRACKBOOK - Movement Recorder for Android
|
||||
*
|
||||
* Copyright (c) 2016 - 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.graphics.drawable.Drawable;
|
||||
import android.location.Location;
|
||||
import android.support.v7.widget.AppCompatDrawableManager;
|
||||
|
||||
import org.osmdroid.util.GeoPoint;
|
||||
import org.osmdroid.views.overlay.ItemizedIconOverlay;
|
||||
import org.osmdroid.views.overlay.OverlayItem;
|
||||
import org.y20k.trackbook.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
* MapHelper class
|
||||
*/
|
||||
public final class MapHelper {
|
||||
|
||||
/* Define log tag */
|
||||
private static final String LOG_TAG = MapHelper.class.getSimpleName();
|
||||
|
||||
|
||||
/* Creates icon overlay for current position */
|
||||
public static ItemizedIconOverlay createMyLocationOverlay(Context context, Location currentBestLocation) {
|
||||
|
||||
final GeoPoint position = new GeoPoint(currentBestLocation.getLatitude(), currentBestLocation.getLongitude());
|
||||
final ArrayList<OverlayItem> overlayItems = new ArrayList<>();
|
||||
|
||||
// create marker
|
||||
Drawable newMarker = AppCompatDrawableManager.get().getDrawable(context, R.drawable.ic_my_loacation_dot_blue_24dp);
|
||||
OverlayItem overlayItem = new OverlayItem(context.getString(R.string.marker_my_location_title), context.getString(R.string.marker_my_location_description), position);
|
||||
overlayItem.setMarker(newMarker);
|
||||
overlayItems.add(overlayItem);
|
||||
|
||||
// create overlay
|
||||
ItemizedIconOverlay myLocationOverlay = new ItemizedIconOverlay<>(overlayItems,
|
||||
new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
|
||||
@Override
|
||||
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
|
||||
LogHelper.v(LOG_TAG, "Tap on the My Location dot icon detected.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongPress(final int index, final OverlayItem item) {
|
||||
LogHelper.v(LOG_TAG, "Long press on the My Location dot icon detected.");
|
||||
return true;
|
||||
}
|
||||
}, context);
|
||||
|
||||
// return overlay for current position
|
||||
return myLocationOverlay;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package org.y20k.trackbook.helpers;
|
||||
|
||||
/**
|
||||
* Created by solaris on 29/07/16.
|
||||
*/
|
||||
public class NotificationHelper {
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* TrackbookKeys.java
|
||||
* Implements the keys used throughout the app
|
||||
* This class hosts all keys used to control Trackbook's state
|
||||
*
|
||||
* This file is part of
|
||||
* TRACKBOOK - Movement Recorder for Android
|
||||
*
|
||||
* Copyright (c) 2016 - 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;
|
||||
|
||||
|
||||
/**
|
||||
* TrackbookKeys.class
|
||||
*/
|
||||
public interface TrackbookKeys {
|
||||
|
||||
/* ACTIONS */
|
||||
public static final String ACTION_START = "org.y20k.transistor.action.START";
|
||||
public static final String ACTION_STOP = "org.y20k.transistor.action.STOP";
|
||||
|
||||
/* EXTRAS */
|
||||
|
||||
/* ARGS */
|
||||
public static final String ARG_PERMISSIONS_GRANTED = "ArgPermissionsGranted";
|
||||
|
||||
/* PREFS */
|
||||
public static final String PREFS_NAME = "org.y20k.trackbook.prefs";
|
||||
public static final String PREFS_TILE_SOURCE = "tilesource";
|
||||
public static final String PREFS_LATITUDE = "latitude";
|
||||
public static final String PREFS_LONGITUDE = "longitude";
|
||||
public static final String PREFS_ZOOM_LEVEL = "zoomLevel";
|
||||
public static final String PREFS_SHOW_LOCATION = "showLocation";
|
||||
public static final String PREFS_SHOW_COMPASS = "showCompass";
|
||||
|
||||
/* INSTANCE STATE */
|
||||
public static final String INSTANCE_LATITUDE = "latitude";
|
||||
public static final String INSTANCE_LONGITUDE = "longitude";
|
||||
public static final String INSTANCE_ZOOM_LEVEL = "zoomLevel";
|
||||
public static final String INSTANCE_CURRENT_LOCATION = "currentLocation";
|
||||
|
||||
/* RESULTS */
|
||||
|
||||
/* CONSTANTS */
|
||||
public static final int CONSTANT_MINIMAL_STOP_TIME = 300000; // equals 5 minutes
|
||||
public static final long CONSTANT_MAXIMAL_DURATION = 43200000; // equals 8 hours
|
||||
public static final long CONSTANT_TRACKING_INTERVAL = 5000; // equals 5 seconds
|
||||
|
||||
/* MISC */
|
||||
public static final int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
|
||||
public static final int LOCATION_STATUS_OFFLINE = 0;
|
||||
public static final int LOCATION_STATUS_OK = 1;
|
||||
public static final int LOCATION_STATUS_GPS_ONLY = 2;
|
||||
public static final int LOCATION_STATUS_NETWORK_ONLY = 3;
|
||||
|
||||
}
|
|
@ -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="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
|
||||
android:fillColor="#DC2B00"/>
|
||||
</vector>
|
|
@ -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="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
</vector>
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:viewportHeight="96.0"
|
||||
android:viewportWidth="96.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillAlpha="0.33" android:fillColor="#2095F2" android:pathData="M48,48m-48,0a48,48 0,1 1,96 0a48,48 0,1 1,-96 0"/>
|
||||
<path android:fillColor="#2095F2" android:pathData="M48,48m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0"/>
|
||||
</vector>
|
|
@ -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:fillColor="#FFFFFFFF"
|
||||
android:pathData="M12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06C6.83,3.52 3.52,6.83 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c4.17,-0.46 7.48,-3.77 7.94,-7.94L23,13v-2h-2.06zM12,19c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
|
||||
</vector>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context="org.y20k.trackbook.MainActivity">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/TrackbookAppTheme.AppBarOverlay">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:popupTheme="@style/TrackbookAppTheme.PopupOverlay" />
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main" />
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
app:srcCompat="@drawable/ic_fiber_manual_record_white_24dp"
|
||||
app:fabSize="auto"/>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<fragment
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/fragment"
|
||||
android:name="org.y20k.trackbook.MainActivityFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:layout="@layout/fragment_main" />
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
tools:context="org.y20k.trackbook.MainActivityFragment"
|
||||
tools:showIn="@layout/activity_main">
|
||||
|
||||
<org.osmdroid.views.MapView android:id="@+id/map"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<!-- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
tools:context="org.y20k.trackbook.MainActivityFragment"
|
||||
tools:showIn="@layout/activity_main">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World!" />
|
||||
|
||||
</RelativeLayout> -->
|
|
@ -0,0 +1,114 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/onboarding" >
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/activity_horizontal_margin"
|
||||
android:scrollbars="vertical">
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:text="@string/layout_onboading_h1_welcome"
|
||||
android:id="@+id/h1_welcome" />
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="@dimen/activity_vertical_margin" >
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/trackbook_icon"
|
||||
android:background="@mipmap/ic_launcher"
|
||||
android:contentDescription="@string/layout_onboading_description_app_icon"
|
||||
android:layout_marginEnd="@dimen/activity_horizontal_margin"
|
||||
android:layout_gravity="center_vertical" />
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical" >
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="@string/layout_onboading_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:id="@+id/p_app_claim" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="@string/layout_onboading_h2_request_permissions"
|
||||
android:id="@+id/h2_request_permissions"
|
||||
android:layout_marginTop="@dimen/activity_vertical_margin"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/layout_onboading_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:id="@+id/p_permission_location" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/layout_onboading_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"
|