tabbed interface is now static (not swipeable anymore), removed a race condition between track save and load, fixed notification behavior, new osmdroid version (v5.6.1)

master
y20k 2016-12-19 17:53:20 +01:00
parent 382b094b92
commit d5b4d9b8c2
12 changed files with 183 additions and 73 deletions

View File

@ -26,6 +26,6 @@ dependencies {
compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.android.support:design:25.1.0'
compile 'com.android.support:cardview-v7:25.1.0'
compile 'org.osmdroid:osmdroid-android:5.5:release@aar'
compile 'org.osmdroid:osmdroid-android:5.6.1'
compile 'com.google.code.gson:gson:2.8.0'
}

View File

@ -30,6 +30,7 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- TODO App is not indexable by Google Search; consider adding at least one Activity with an ACTION-VIEW intent filter. See issue explanation for more details. -->
</activity>

View File

@ -18,7 +18,6 @@ package org.y20k.trackbook;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.DialogFragment;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -38,7 +37,6 @@ import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
@ -52,6 +50,7 @@ import android.widget.Toast;
import org.y20k.trackbook.helpers.LogHelper;
import org.y20k.trackbook.helpers.NotificationHelper;
import org.y20k.trackbook.helpers.TrackbookKeys;
import org.y20k.trackbook.layout.NonSwipeableViewPager;
import java.util.ArrayList;
import java.util.HashMap;
@ -69,13 +68,12 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
/* Main class variables */
private ViewPager mViewPager;
private NonSwipeableViewPager mViewPager;
private boolean mTrackerServiceRunning;
private boolean mCurrentTrackVisible;
private boolean mPermissionsGranted;
private boolean mFloatingActionButtonSubMenuVisible;
private List<String> mMissingPermissions;
private LinearLayout mFloatingActionButtonLayout;
private FloatingActionButton mFloatingActionButton;
private LinearLayout mFloatingActionButtonSubMenu1;
private LinearLayout mFloatingActionButtonSubMenu2;
@ -91,7 +89,7 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
super.onCreate(savedInstanceState);
// load saved state of app
loadAppState(this);
loadTrackState(this);
// check permissions on Android 6 and higher
mPermissionsGranted = false;
@ -187,10 +185,10 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
super.onResume();
LogHelper.v(LOG_TAG, "onResume called.");
// TODO loadAppState?
loadAppState(this);
// load state of track visibility
loadTrackState(this);
// handle new intents - onNewIntent does not seem to work
// handle incoming intent (from notification)
handleIncomingIntent();
// if not in onboarding mode: set state of FloatingActionButton
@ -201,6 +199,12 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
}
@Override
protected void onPause() {
super.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
@ -267,31 +271,12 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
}
/* Saves app state to SharedPreferences */
private void saveAppState(Context context) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = settings.edit();
// mCurrentTrackVisible is handled (= saved) by fragment
// editor.putBoolean(INSTANCE_FAB_SUB_MENU_VISIBLE, mFloatingActionButtonSubMenuVisible);
// editor.putBoolean(INSTANCE_TRACKING_STATE, mTrackerServiceRunning);
// editor.putInt(INSTANCE_SELECTED_TAB, mSelectedTab);
editor.apply();
LogHelper.v(LOG_TAG, "Saving state.");
}
/* Loads app state from preferences */
private void loadAppState(Context context) {
/* Loads state of track visibility from preferences */
private void loadTrackState(Context context) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
mCurrentTrackVisible = settings.getBoolean(INSTANCE_TRACK_VISIBLE, false);
// mFloatingActionButtonSubMenuVisible = settings.getBoolean(INSTANCE_FAB_SUB_MENU_VISIBLE, false);
// mTrackerServiceRunning = settings.getBoolean(INSTANCE_TRACKING_STATE, false);
// mSelectedTab = settings.getInt(INSTANCE_SELECTED_TAB, 0);
LogHelper.v(LOG_TAG, "Loading state.");
// mCurrentTrackVisible is handled / saved by fragment
LogHelper.v(LOG_TAG, "Loading state. Track visibility: " + mCurrentTrackVisible);
}
@ -309,7 +294,7 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager = (NonSwipeableViewPager) findViewById(R.id.container);
mViewPager.setAdapter(sectionsPagerAdapter);
mViewPager.setCurrentItem(mSelectedTab);
@ -347,7 +332,6 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
});
// get references to the record button and show/hide its sub menu
mFloatingActionButtonLayout = (LinearLayout) findViewById(R.id.fabFrameLayout);
mFloatingActionButton = (FloatingActionButton) findViewById(R.id.fabMainButton);
mFloatingActionButtonSubMenu1 = (LinearLayout) findViewById(R.id.fabSubMenu1);
mFloatingActionButtonSubMenu2 = (LinearLayout) findViewById(R.id.fabSubMenu2);
@ -380,15 +364,6 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
}
@Override
protected void onPause() {
super.onPause();
// save current state
saveAppState(this);
}
/* Handles tap on the record button */
private void handleFloatingActionButtonClick(View view) {
@ -453,19 +428,17 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
/* Handles tap on the save and clear button */
public void handleButtonSaveAndClearClick() {
private void handleButtonSaveAndClearClick() {
LogHelper.v(LOG_TAG, "User chose SAVE and CLEAR");
// clear map and save track
mMainActivityMapFragment.clearMap(true);
mCurrentTrackVisible = false;
// // reset current track // TODO is this still necessary?
// mMainActivityTrackFragment.refreshTrackView();
// display track tab
// display and update track tab
mSelectedTab = FRAGMENT_ID_TRACK;
mViewPager.setCurrentItem(mSelectedTab);
mMainActivityTrackFragment.refreshTrackView();
// dismiss notification
NotificationHelper.stop();
@ -482,7 +455,7 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
/* Handles tap on the clear button */
public void handleButtonClearClick() {
private void handleButtonClearClick() {
LogHelper.v(LOG_TAG, "User chose CLEAR");
// clear map, do not save track
@ -540,24 +513,23 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys {
/* Handles new incoming intents */
private void handleIncomingIntent() {
LogHelper.v(LOG_TAG, "Main Activity received intent.");
Intent intent = getIntent();
String intentAction = intent.getAction();
switch (intentAction) {
case ACTION_SHOW_MAP:
mSelectedTab = FRAGMENT_ID_MAP;
mViewPager.setCurrentItem(mSelectedTab);
if (intent.hasExtra(EXTRA_TRACKING_STATE)) {
mTrackerServiceRunning = intent.getBooleanExtra(EXTRA_TRACKING_STATE, false);
// mMainActivityMapFragment.setTrackingState(mTrackerServiceRunning);
if (mTrackerServiceRunning) {
mFloatingActionButtonState = FAB_STATE_RECORDING;
}
// prevent multiple reactions to intent
intent.setAction(ACTION_DEFAULT);
}
break;
default:
// log
LogHelper.v(LOG_TAG, "Intent received. Doing nothing. Type of ACTION: " + intentAction);
LogHelper.v(LOG_TAG, "Doing nothing. Type of ACTION: " + intentAction);
break;
}
}

View File

@ -96,6 +96,8 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LogHelper.v(LOG_TAG, "!!! MainActivityMapFragment onCreate called.");
// get activity
mActivity = getActivity();
@ -215,7 +217,7 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
// set visibility
mFragmentVisible = true;
// TODO
// handle incoming intent (from notification)
handleIncomingIntent();
// center map on current position - if TrackerService is running
@ -412,8 +414,30 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
/* Handles new incoming intents */
private void handleIncomingIntent() {
LogHelper.v(LOG_TAG, "Map Fragment received intent.");
Intent intent = mActivity.getIntent();
// TODO get track from intent if not present
String intentAction = intent.getAction();
switch (intentAction) {
case ACTION_SHOW_MAP:
if (intent.hasExtra(EXTRA_TRACK)) {
mTrack = intent.getParcelableExtra(EXTRA_TRACK);
drawTrackOverlay(mTrack);
}
if (intent.hasExtra(EXTRA_TRACKING_STATE)) {
mTrackerServiceRunning = intent.getBooleanExtra(EXTRA_TRACKING_STATE, false);
mMapView.getOverlays().remove(mMyLocationOverlay);
}
// prevent multiple reactions to intent
intent.setAction(ACTION_DEFAULT);
break;
default:
LogHelper.v(LOG_TAG, "Doing nothing. Type of ACTION: " + intentAction);
break;
}
}
@ -632,8 +656,14 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// clear track object
LogHelper.v(LOG_TAG, "Clearing track object after background save operation.");
LogHelper.v(LOG_TAG, "Saving finished.");
mTrack = null;
// notify track fragment that save is finished
Intent i = new Intent();
i.setAction(ACTION_TRACK_SAVE);
i.putExtra(EXTRA_SAVE_FINISHED, true);
LocalBroadcastManager.getInstance(mActivity).sendBroadcast(i);
}
}

View File

@ -17,14 +17,18 @@
package org.y20k.trackbook;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -61,17 +65,15 @@ public class MainActivityTrackFragment extends Fragment implements TrackbookKeys
private MapView mMapView;
private IMapController mController;
private ItemizedIconOverlay mTrackOverlay;
private View mStaticticsView;
private TextView mDistanceView;
private TextView mStepsView;
private TextView mWaypointsView;
private TextView mDurationView;
private TextView mRecordingStartView;
private TextView mRecordingStopView;
private View mStatisticsSheet;
private Snackbar mStatisticsSnackbar;
private BottomSheetBehavior mStatisticsSheetBehavior;
private Track mTrack;
private BroadcastReceiver mTrackSavedReceiver;
@ -84,6 +86,19 @@ public class MainActivityTrackFragment extends Fragment implements TrackbookKeys
// store activity
mActivity = getActivity();
// create receiver for finished save operation
mTrackSavedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.hasExtra(EXTRA_SAVE_FINISHED) && intent.getBooleanExtra(EXTRA_SAVE_FINISHED, false)) {
// load track and display map and statistics
LoadTrackAsyncHelper loadTrackAsyncHelper = new LoadTrackAsyncHelper();
loadTrackAsyncHelper.execute();
}
}
};
}
@ -124,14 +139,14 @@ public class MainActivityTrackFragment extends Fragment implements TrackbookKeys
// get views
mStaticticsView = mRootView.findViewById(R.id.statistics_view);
View mStaticticsView = mRootView.findViewById(R.id.statistics_view);
mDistanceView = (TextView) mRootView.findViewById(R.id.statistics_data_distance);
mStepsView = (TextView) mRootView.findViewById(R.id.statistics_data_steps);
mWaypointsView = (TextView) mRootView.findViewById(R.id.statistics_data_waypoints);
mDurationView = (TextView) mRootView.findViewById(R.id.statistics_data_duration);
mRecordingStartView = (TextView) mRootView.findViewById(R.id.statistics_data_recording_start);
mRecordingStopView = (TextView) mRootView.findViewById(R.id.statistics_data_recording_stop);
mStatisticsSheet = mRootView.findViewById(R.id.statistics_sheet);
View mStatisticsSheet = mRootView.findViewById(R.id.statistics_sheet);
if (mTrack == null) {
// load track and display map and statistics
@ -231,9 +246,9 @@ public class MainActivityTrackFragment extends Fragment implements TrackbookKeys
mMapView.getOverlays().remove(mTrackOverlay);
}
// load track and display map and statistics
LoadTrackAsyncHelper loadTrackAsyncHelper = new LoadTrackAsyncHelper();
loadTrackAsyncHelper.execute();
// listen for finished save
IntentFilter trackSavedReceiverIntentFilter = new IntentFilter(ACTION_TRACK_SAVE);
LocalBroadcastManager.getInstance(mActivity).registerReceiver(mTrackSavedReceiver, trackSavedReceiverIntentFilter);
}
@ -297,8 +312,11 @@ public class MainActivityTrackFragment extends Fragment implements TrackbookKeys
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
LogHelper.v(LOG_TAG, "Display map and statistics of track.");
LogHelper.v(LOG_TAG, "Loading finished. Displaying map and statistics of track.");
displayTrack();
// remove listener
LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(mTrackSavedReceiver);
}
}

View File

@ -46,7 +46,7 @@ public class Track implements TrackbookKeys, Parcelable {
private float mTrackLength;
private long mDuration;
private float mStepCount;
private Date mRecordingStart;
private final Date mRecordingStart;
private Date mRecordingStop;

View File

@ -30,7 +30,7 @@ public class WayPoint implements Parcelable {
private Location mLocation;
private boolean mIsStopOver;
private float mDistanceToStartingPoint;
private int mNumberSatellites;
private final int mNumberSatellites;
/* Constructor */
public WayPoint(Location location, boolean isStopOver, float distanceToStartingPoint) {

View File

@ -217,7 +217,7 @@ public class StorageHelper implements TrackbookKeys {
// file2 is not a track, file2 is greater
return -1;
} else {
// "compareTo" compares abstract pathnames lexicographically | 0 == equal | -1 == file2 less than file1 | 1 == file2 greater than file1
// "compareTo" compares abstract path names lexicographically | 0 == equal | -1 == file2 less than file1 | 1 == file2 greater than file1
return file2.compareTo(file1);
}

View File

@ -29,6 +29,7 @@ public interface TrackbookKeys {
String ACTION_SHOW_MAP = "SHOW_MAP";
String ACTION_TRACK_UPDATED = "TRACK_UPDATED";
String ACTION_TRACKING_STOPPED = "TRACKING_STOPPED";
String ACTION_TRACK_SAVE = "TRACK_SAVE";
/* EXTRAS */
String EXTRA_TRACK = "TRACK";
@ -37,6 +38,7 @@ public interface TrackbookKeys {
String EXTRA_CLEAR_MAP = "CLEAR_MAP";
String EXTRA_INFOSHEET_TITLE = "EXTRA_INFOSHEET_TITLE";
String EXTRA_INFOSHEET_CONTENT = "INFOSHEET_CONTENT";
String EXTRA_SAVE_FINISHED = "SAVE_FINISHED";
/* ARGS */
String ARG_PERMISSIONS_GRANTED = "ArgPermissionsGranted";

View File

@ -0,0 +1,87 @@
/**
* NonSwipeableViewPager.java
* Implements the NonSwipeableViewPager class
* A NonSwipeableViewPager is a ViewPager with swiping gestures disabled
*
* 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.layout;
/**
* NonSwipeableViewPager class
* adapted from: http://stackoverflow.com/a/9650884
*/
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller;
import java.lang.reflect.Field;
public class NonSwipeableViewPager extends ViewPager {
public NonSwipeableViewPager(Context context) {
super(context);
setMyScroller();
}
public NonSwipeableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
setMyScroller();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
//down one is added for smooth scrolling
private void setMyScroller() {
try {
Class<?> viewpager = ViewPager.class;
Field scroller = viewpager.getDeclaredField("mScroller");
scroller.setAccessible(true);
scroller.set(this, new MyScroller(getContext()));
} catch (Exception e) {
e.printStackTrace();
}
}
public class MyScroller extends Scroller {
public MyScroller(Context context) {
super(context, new DecelerateInterpolator());
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/);
}
}
}

View File

@ -37,7 +37,7 @@
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
<org.y20k.trackbook.layout.NonSwipeableViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- TODO add missing descriptions and color definitions -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
@ -98,6 +96,7 @@
android:layout_height="wrap_content"
android:contentDescription="@string/descr_fab_sub_menu_button_2"
app:srcCompat="@drawable/ic_clear_white_24dp"
app:backgroundTint="@color/trackbook_blue"
app:fabSize="mini" />
</LinearLayout>
@ -115,6 +114,7 @@
android:layout_height="wrap_content"
android:contentDescription="@string/descr_fab_main"
app:srcCompat="@drawable/ic_fiber_manual_record_white_24dp"
app:backgroundTint="@color/trackbook_blue"
app:fabSize="normal" />
</LinearLayout>