trkpt/app/src/main/java/org/y20k/trackbook/MainActivity.java

891 lines
33 KiB
Java
Raw Normal View History

2016-08-29 12:50:41 +00:00
/**
* MainActivity.java
* Implements the app's main activity
2017-11-28 21:02:45 +00:00
* The main activity sets up the main view
2016-08-29 12:50:41 +00:00
*
* This file is part of
* TRACKBOOK - Movement Recorder for Android
*
* Copyright (c) 2016-18 - Y20K.org
2016-08-29 12:50:41 +00:00
* Licensed under the MIT-License
* http://opensource.org/licenses/MIT
*
2016-08-29 12:50:41 +00:00
* Trackbook uses osmdroid - OpenStreetMap-Tools for Android
* https://github.com/osmdroid/osmdroid
*/
package org.y20k.trackbook;
import android.Manifest;
import android.annotation.TargetApi;
2017-05-17 13:43:53 +00:00
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
2016-08-29 12:50:41 +00:00
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
2016-08-29 12:50:41 +00:00
import android.content.pm.PackageManager;
import android.location.Location;
2016-08-29 12:50:41 +00:00
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
2018-02-21 10:47:09 +00:00
import android.os.Vibrator;
import android.preference.PreferenceManager;
2016-09-12 12:31:37 +00:00
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
2017-11-28 21:02:45 +00:00
import android.support.design.widget.BottomNavigationView;
2016-08-29 12:50:41 +00:00
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
2017-05-17 13:43:53 +00:00
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
2018-03-20 14:15:57 +00:00
import android.support.v4.app.FragmentStatePagerAdapter;
2016-08-29 12:50:41 +00:00
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
2016-08-29 12:50:41 +00:00
import android.support.v7.app.AppCompatActivity;
2017-11-28 21:02:45 +00:00
import android.support.v7.widget.CardView;
import android.util.SparseArray;
2016-08-29 12:50:41 +00:00
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
2016-08-29 12:50:41 +00:00
import android.widget.Button;
import android.widget.Toast;
import org.osmdroid.config.Configuration;
2017-05-17 13:43:53 +00:00
import org.y20k.trackbook.helpers.DialogHelper;
2016-09-12 12:31:37 +00:00
import org.y20k.trackbook.helpers.LogHelper;
2018-02-21 10:47:09 +00:00
import org.y20k.trackbook.helpers.NightModeHelper;
2016-08-29 12:50:41 +00:00
import org.y20k.trackbook.helpers.TrackbookKeys;
import org.y20k.trackbook.layout.NonSwipeableViewPager;
2016-08-29 12:50:41 +00:00
import java.lang.ref.WeakReference;
2016-08-29 12:50:41 +00:00
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 {
2016-08-29 12:50:41 +00:00
/* Define log tag */
private static final String LOG_TAG = MainActivity.class.getSimpleName();
2016-08-29 12:50:41 +00:00
/* Main class variables */
private TrackerService mTrackerService;
2017-11-28 21:02:45 +00:00
private BottomNavigationView mBottomNavigationView;
private NonSwipeableViewPager mViewPager;
private SectionsPagerAdapter mSectionsPagerAdapter;
2016-09-07 10:30:46 +00:00
private boolean mTrackerServiceRunning;
2016-08-29 12:50:41 +00:00
private boolean mPermissionsGranted;
private boolean mFloatingActionButtonSubMenuVisible;
2016-08-29 12:50:41 +00:00
private List<String> mMissingPermissions;
2017-11-28 21:02:45 +00:00
private FloatingActionButton mFloatingActionButtonMain;
private FloatingActionButton mFloatingActionButtonSubSave;
private FloatingActionButton mFloatingActionButtonSubClear;
2018-03-15 12:28:52 +00:00
private FloatingActionButton mFloatingActionButtonSubResume;
2017-11-28 21:02:45 +00:00
private FloatingActionButton mFloatingActionButtonLocation;
private CardView mFloatingActionButtonSubSaveLabel;
private CardView mFloatingActionButtonSubClearLabel;
2018-03-15 12:28:52 +00:00
private CardView mFloatingActionButtonSubResumeLabel;
private BroadcastReceiver mTrackingChangedReceiver;
private int mFloatingActionButtonState;
private int mSelectedTab;
2016-08-29 12:50:41 +00:00
boolean mBound = false;
2016-08-29 12:50:41 +00:00
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// check state of External Storage
checkExternalStorageState();
// load saved state of app
loadFloatingActionButtonState(this);
2016-08-29 12:50:41 +00:00
// check permissions on Android 6 and higher
mPermissionsGranted = false;
2016-08-29 12:50:41 +00:00
if (Build.VERSION.SDK_INT >= 23) {
// check permissions
mMissingPermissions = checkPermissions();
mPermissionsGranted = mMissingPermissions.size() == 0;
} else {
mPermissionsGranted = true;
}
2018-03-20 18:56:00 +00:00
// initialize state
if (savedInstanceState != null) {
2018-03-20 18:56:00 +00:00
// restore if saved instance is available
mTrackerServiceRunning = savedInstanceState.getBoolean(INSTANCE_TRACKING_STATE, false);
mSelectedTab = savedInstanceState.getInt(INSTANCE_SELECTED_TAB, FRAGMENT_ID_MAP);
mFloatingActionButtonSubMenuVisible = savedInstanceState.getBoolean(INSTANCE_FAB_SUB_MENU_VISIBLE, false);
2018-03-20 18:56:00 +00:00
} else {
// use default values
mTrackerServiceRunning = false;
mSelectedTab = FRAGMENT_ID_MAP;
mFloatingActionButtonSubMenuVisible = false;
}
2016-08-29 12:50:41 +00:00
// set user agent to prevent getting banned from the osm servers
Configuration.getInstance().setUserAgentValue(BuildConfig.APPLICATION_ID);
2016-08-29 12:50:41 +00:00
// set up main layout
setupLayout();
}
@Override
protected void onStart() {
super.onStart();
// bind to TrackerService
Intent intent = new Intent(this, TrackerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
// register broadcast receiver for changed tracking state
mTrackingChangedReceiver = createTrackingChangedReceiver();
IntentFilter trackingStoppedIntentFilter = new IntentFilter(ACTION_TRACKING_STATE_CHANGED);
LocalBroadcastManager.getInstance(this).registerReceiver(mTrackingChangedReceiver, trackingStoppedIntentFilter);
2016-08-29 12:50:41 +00:00
}
@Override
protected void onResume() {
super.onResume();
// load state of Floating Action Button
loadFloatingActionButtonState(this);
// handle incoming intent (from notification)
2016-09-12 12:31:37 +00:00
handleIncomingIntent();
2016-09-07 13:48:12 +00:00
// if not in onboarding mode: set state of FloatingActionButton
2017-11-28 21:02:45 +00:00
if (mFloatingActionButtonMain != null) {
setFloatingActionButtonState();
}
}
@Override
protected void onPause() {
super.onPause();
2018-04-09 15:07:19 +00:00
}
@Override
protected void onStop() {
super.onStop();
2018-04-09 15:07:19 +00:00
// unbind from TrackerService
unbindService(mConnection);
}
@Override
public void onDestroy() {
super.onDestroy();
LogHelper.v(LOG_TAG, "onDestroy called.");
// reset selected tab
mSelectedTab = FRAGMENT_ID_MAP;
// disable broadcast receiver
LocalBroadcastManager.getInstance(this).unregisterReceiver(mTrackingChangedReceiver);
}
2016-08-29 12:50:41 +00:00
@Override
2016-09-12 12:31:37 +00:00
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
2016-08-29 12:50:41 +00:00
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);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean(INSTANCE_TRACKING_STATE, mTrackerServiceRunning);
outState.putInt(INSTANCE_SELECTED_TAB, mSelectedTab);
outState.putBoolean(INSTANCE_FAB_SUB_MENU_VISIBLE, mFloatingActionButtonSubMenuVisible);
super.onSaveInstanceState(outState);
}
/* Handles FloatingActionButton dialog results - called by MainActivityMapFragment after Saving and/or clearing the map */
2017-05-17 13:43:53 +00:00
public void onFloatingActionButtonResult(int requestCode, int resultCode) {
switch(requestCode) {
case RESULT_SAVE_DIALOG:
if (resultCode == Activity.RESULT_OK) {
// user chose SAVE
handleStateAfterSave();
LogHelper.v(LOG_TAG, "Save dialog result: SAVE");
2017-05-17 13:43:53 +00:00
} else if (resultCode == Activity.RESULT_CANCELED){
LogHelper.v(LOG_TAG, "Save dialog result: CANCEL");
}
break;
case RESULT_CLEAR_DIALOG:
if (resultCode == Activity.RESULT_OK) {
// user chose CLEAR
handleStateAfterClear();
LogHelper.v(LOG_TAG, "Save dialog result: CLEAR");
2017-05-17 13:43:53 +00:00
} else if (resultCode == Activity.RESULT_CANCELED){
LogHelper.v(LOG_TAG, "Clear map: User chose CANCEL.");
}
break;
}
}
/* Handles the visual state after a save action */
private void handleStateAfterSave() {
// display and update tracks tab
mBottomNavigationView.setSelectedItemId(R.id.navigation_last_tracks);
2017-05-17 13:43:53 +00:00
// dismiss notification
dismissNotification();
2017-05-17 13:43:53 +00:00
// hide Floating Action Button sub menu
showFloatingActionButtonMenu(false);
// update Floating Action Button icon
mFloatingActionButtonState = FAB_STATE_DEFAULT;
setFloatingActionButtonState();
}
/* Start tracker service */
private void startTrackerService() {
// start service so that it keeps running after unbind
Intent intent = new Intent(this, TrackerService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// ... start service in foreground to prevent it being killed on Oreo
startForegroundService(intent);
} else {
startService(intent);
}
}
/* Start recording movements */
private void startRecording(Location lastLocation) {
startTrackerService();
if (mBound) {
mTrackerService.startTracking(lastLocation);
}
}
/* Resume recording movements */
private void resumeRecording(Location lastLocation) {
startTrackerService();
if (mBound) {
mTrackerService.resumeTracking(lastLocation);
}
}
/* Stop recording movements */
private void stopRecording() {
if (mBound) {
mTrackerService.stopTracking();
}
}
/* Dismiss notification */
private void dismissNotification() {
if (mBound) {
mTrackerService.dismissNotification();
}
}
2017-05-17 13:43:53 +00:00
/* Handles the visual state after a save action */
private void handleStateAfterClear() {
// notify user
Toast.makeText(this, getString(R.string.toast_message_track_clear), Toast.LENGTH_LONG).show();
// dismiss notification
dismissNotification();
2017-05-17 13:43:53 +00:00
// hide Floating Action Button sub menu
showFloatingActionButtonMenu(false);
// update Floating Action Button icon
mFloatingActionButtonState = FAB_STATE_DEFAULT;
setFloatingActionButtonState();
}
2018-03-15 12:28:52 +00:00
/* Handles tap on the button "save" */
private void handleSaveButtonClick() {
// save button click is handled by onActivityResult in MainActivityMapFragment
MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP);
mainActivityMapFragment.onActivityResult(RESULT_SAVE_DIALOG, Activity.RESULT_OK, getIntent());
}
/* Handles tap on the button "clear" */
private void handleClearButtonClick() {
// prepare delete dialog
int dialogTitle = -1;
String dialogMessage = getString(R.string.dialog_clear_content);
int dialogPositiveButton = R.string.dialog_clear_action_clear;
int dialogNegativeButton = R.string.dialog_default_action_cancel;
// show delete dialog
MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP);
DialogFragment dialogFragment = DialogHelper.newInstance(dialogTitle, dialogMessage, dialogPositiveButton, dialogNegativeButton);
dialogFragment.setTargetFragment(mainActivityMapFragment, RESULT_CLEAR_DIALOG);
dialogFragment.show(getSupportFragmentManager(), "ClearDialog");
// results of dialog are handled by onActivityResult in MainActivityMapFragment
}
2018-03-15 12:28:52 +00:00
/* Handles tap on the button "resume" */
private void handleResumeButtonClick(View view) {
// get last location from MainActivity Fragment // todo check -> may produce NullPointerException
MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP);
Location lastLocation = mainActivityMapFragment.getCurrentBestLocation();
if (lastLocation != null) {
// show snackbar
Snackbar.make(view, R.string.snackbar_message_tracking_resumed, Snackbar.LENGTH_SHORT).setAction("Action", null).show();
// resume tracking
resumeRecording(lastLocation);
// hide sub menu
showFloatingActionButtonMenu(false);
} else {
Toast.makeText(this, getString(R.string.toast_message_location_services_not_ready), Toast.LENGTH_LONG).show();
}
2018-03-15 12:28:52 +00:00
}
/* Loads state of Floating Action Button from preferences */
private void loadFloatingActionButtonState(Context context) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
mFloatingActionButtonState = settings.getInt(PREFS_FAB_STATE, FAB_STATE_DEFAULT);
}
2016-08-29 12:50:41 +00:00
/* Set up main layout */
private void setupLayout() {
if (mPermissionsGranted) {
// point to the main map layout
setContentView(R.layout.activity_main);
// create adapter that returns fragments for the maim map and the last track display
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// set up the ViewPager with the sections adapter.
2018-01-16 13:27:50 +00:00
mViewPager = (NonSwipeableViewPager) findViewById(R.id.fragmentContainer);
mViewPager.setAdapter(mSectionsPagerAdapter);
2017-11-28 21:02:45 +00:00
// setup bottom navigation
mBottomNavigationView = findViewById(R.id.navigation);
mBottomNavigationView.setOnNavigationItemSelectedListener(getOnNavigationItemSelectedListener());
// get references to the record button and show/hide its sub menu
2017-11-28 21:02:45 +00:00
mFloatingActionButtonMain = findViewById(R.id.fabMainButton);
2018-01-16 13:27:50 +00:00
mFloatingActionButtonLocation = findViewById(R.id.fabLocationButton);
2017-11-28 21:02:45 +00:00
mFloatingActionButtonSubSave = findViewById(R.id.fabSubMenuButtonSave);
mFloatingActionButtonSubSaveLabel = findViewById(R.id.fabSubMenuLabelSave);
mFloatingActionButtonSubClear = findViewById(R.id.fabSubMenuButtonClear);
mFloatingActionButtonSubClearLabel = findViewById(R.id.fabSubMenuLabelClear);
2018-03-15 12:28:52 +00:00
mFloatingActionButtonSubResume = findViewById(R.id.fabSubMenuButtonResume);
mFloatingActionButtonSubResumeLabel = findViewById(R.id.fabSubMenuLabelResume);
if (mFloatingActionButtonSubMenuVisible) {
showFloatingActionButtonMenu(true);
} else {
showFloatingActionButtonMenu(false);
}
// restore selected tab
if (mSelectedTab == FRAGMENT_ID_TRACKS) {
mBottomNavigationView.setSelectedItemId(R.id.navigation_last_tracks);
} else {
mBottomNavigationView.setSelectedItemId(R.id.navigation_map);
}
// add listeners to buttons
addListenersToViews();
2017-11-28 21:02:45 +00:00
} else {
// point to the on main onboarding layout
setContentView(R.layout.activity_main_onboarding);
// show the okay button and attach listener
Button okayButton = (Button) findViewById(R.id.button_okay);
okayButton.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);
}
}
});
}
}
/* Add listeners to ui buttons */
private void addListenersToViews() {
mFloatingActionButtonMain.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handleFloatingActionButtonClick(view);
}
});
mFloatingActionButtonSubSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handleSaveButtonClick();
}
});
mFloatingActionButtonSubSaveLabel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handleSaveButtonClick();
}
});
mFloatingActionButtonSubClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handleClearButtonClick();
}
});
mFloatingActionButtonSubClearLabel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handleClearButtonClick();
}
});
2018-03-15 12:28:52 +00:00
mFloatingActionButtonSubResume.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handleResumeButtonClick(view);
2018-03-15 12:28:52 +00:00
}
});
mFloatingActionButtonSubResumeLabel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handleResumeButtonClick(view);
2018-03-15 12:28:52 +00:00
}
});
mFloatingActionButtonLocation.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP);
mainActivityMapFragment.handleShowMyLocation();
}
});
2018-02-21 10:47:09 +00:00
mFloatingActionButtonLocation.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
longPressFeedback(R.string.toastmessage_long_press_night_mode_switch);
NightModeHelper.switchToOpposite(MainActivity.this);
recreate();
2018-02-21 10:47:09 +00:00
return true;
}
});
}
2016-08-29 12:50:41 +00:00
/* Handles tap on the record button */
private void handleFloatingActionButtonClick(View view) {
switch (mFloatingActionButtonState) {
case FAB_STATE_DEFAULT:
2016-08-29 12:50:41 +00:00
// get last location from MainActivity Fragment // todo check -> may produce NullPointerException
MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP);
Location lastLocation = mainActivityMapFragment.getCurrentBestLocation();
if (lastLocation != null) {
// show snackbar
Snackbar.make(view, R.string.snackbar_message_tracking_started, Snackbar.LENGTH_SHORT).setAction("Action", null).show();
// start recording
startRecording(lastLocation);
} else {
Toast.makeText(this, getString(R.string.toast_message_location_services_not_ready), Toast.LENGTH_LONG).show();
}
2016-08-29 12:50:41 +00:00
break;
case FAB_STATE_RECORDING:
// show snackbar
Snackbar.make(view, R.string.snackbar_message_tracking_stopped, Snackbar.LENGTH_SHORT).setAction("Action", null).show();
// stop tracker service
stopRecording();
break;
case FAB_STATE_SAVE:
// toggle visibility floating action button sub menu
showFloatingActionButtonMenu(!mFloatingActionButtonSubMenuVisible);
break;
2016-08-29 12:50:41 +00:00
}
// update tracking state in MainActivityMapFragment // todo check -> may produce NullPointerException
MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP);
mainActivityMapFragment.setTrackingState(mTrackerServiceRunning);
2016-08-29 12:50:41 +00:00
}
/* Set state of FloatingActionButton */
private void setFloatingActionButtonState() {
switch (mFloatingActionButtonState) {
case FAB_STATE_DEFAULT:
2017-11-28 21:02:45 +00:00
mFloatingActionButtonMain.setImageResource(R.drawable.ic_fiber_manual_record_white_24dp);
break;
case FAB_STATE_RECORDING:
2017-11-28 21:02:45 +00:00
mFloatingActionButtonMain.setImageResource(R.drawable.ic_fiber_manual_record_red_24dp);
break;
case FAB_STATE_SAVE:
2017-11-28 21:02:45 +00:00
mFloatingActionButtonMain.setImageResource(R.drawable.ic_save_white_24dp);
break;
default:
2017-11-28 21:02:45 +00:00
mFloatingActionButtonMain.setImageResource(R.drawable.ic_fiber_manual_record_white_24dp);
break;
}
}
/* Shows (and hides) the sub menu of the floating action button */
private void showFloatingActionButtonMenu(boolean visible) {
if (visible) {
2018-03-20 19:43:00 +00:00
mFloatingActionButtonSubResume.setVisibility(View.VISIBLE);
mFloatingActionButtonSubResumeLabel.setVisibility(View.VISIBLE);
2017-11-28 21:02:45 +00:00
mFloatingActionButtonSubClear.setVisibility(View.VISIBLE);
mFloatingActionButtonSubClearLabel.setVisibility(View.VISIBLE);
mFloatingActionButtonSubSave.setVisibility(View.VISIBLE);
mFloatingActionButtonSubSaveLabel.setVisibility(View.VISIBLE);
mFloatingActionButtonSubMenuVisible = true;
} else {
2018-03-20 19:43:00 +00:00
mFloatingActionButtonSubResume.setVisibility(View.INVISIBLE);
mFloatingActionButtonSubResumeLabel.setVisibility(View.INVISIBLE);
2017-11-28 21:02:45 +00:00
mFloatingActionButtonSubClear.setVisibility(View.INVISIBLE);
mFloatingActionButtonSubClearLabel.setVisibility(View.INVISIBLE);
mFloatingActionButtonSubSaveLabel.setVisibility(View.INVISIBLE);
mFloatingActionButtonSubSave.setVisibility(View.INVISIBLE);
mFloatingActionButtonSubMenuVisible = false;
}
2017-11-28 21:02:45 +00:00
}
/* Handles taps on the bottom navigation */
private BottomNavigationView.OnNavigationItemSelectedListener getOnNavigationItemSelectedListener() {
return new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_map:
// show the Floating Action Button
mFloatingActionButtonMain.show();
// show the my location button
mFloatingActionButtonLocation.show();
// show map fragment
mSelectedTab = FRAGMENT_ID_MAP;
mViewPager.setCurrentItem(mSelectedTab);
2017-11-28 21:02:45 +00:00
return true;
case R.id.navigation_last_tracks:
// hide the Floating Action Button - and its sub menu
mFloatingActionButtonMain.hide();
showFloatingActionButtonMenu(false);
// hide the my location button
mFloatingActionButtonLocation.hide();
// show tracks fragment
mSelectedTab = FRAGMENT_ID_TRACKS;
mViewPager.setCurrentItem(mSelectedTab);
2017-11-28 21:02:45 +00:00
return true;
default:
// show the Floating Action Button
mFloatingActionButtonMain.show();
return false;
}
}
};
}
2016-09-12 12:31:37 +00:00
/* Handles new incoming intents */
private void handleIncomingIntent() {
Intent intent = getIntent();
2017-01-25 13:19:50 +00:00
LogHelper.v(LOG_TAG, "Main Activity received intent. Content: " + intent.toString());
2016-09-12 12:31:37 +00:00
String intentAction = intent.getAction();
switch (intentAction) {
case ACTION_SHOW_MAP:
2017-01-25 13:19:50 +00:00
// show map fragment
mBottomNavigationView.setSelectedItemId(R.id.navigation_map);
// clear intent
intent.setAction(ACTION_DEFAULT);
2016-09-12 12:31:37 +00:00
break;
2018-03-20 14:15:57 +00:00
case ACTION_CLEAR:
// show map fragment
mBottomNavigationView.setSelectedItemId(R.id.navigation_map);
// show clear dialog
handleClearButtonClick();
// clear intent
intent.setAction(ACTION_DEFAULT);
break;
2016-09-12 12:31:37 +00:00
default:
break;
}
2016-09-07 13:48:12 +00:00
}
2018-02-21 10:47:09 +00:00
/* Inform user and give haptic feedback (vibration) */
private void longPressFeedback(int stringResource) {
// inform user
Toast.makeText(this, stringResource, Toast.LENGTH_LONG).show();
// vibrate 50 milliseconds
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(50);
// v.vibrate(VibrationEffect.createOneShot(50, DEFAULT_AMPLITUDE)); // todo check if there is a support library vibrator
}
2016-08-29 12:50:41 +00:00
/* 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;
}
/* Creates receiver for stopped tracking */
private BroadcastReceiver createTrackingChangedReceiver() {
return new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// change state
mTrackerServiceRunning = intent.getBooleanExtra(EXTRA_TRACKING_STATE, false);
if (mTrackerServiceRunning) {
mFloatingActionButtonState = FAB_STATE_RECORDING;
} else {
mFloatingActionButtonState = FAB_STATE_SAVE;
}
setFloatingActionButtonState();
// pass tracking state to MainActivityMapFragment // todo check -> may produce NullPointerException
MainActivityMapFragment mainActivityMapFragment = (MainActivityMapFragment) mSectionsPagerAdapter.getFragment(FRAGMENT_ID_MAP);
mainActivityMapFragment.setTrackingState(mTrackerServiceRunning);
}
};
}
/* Checks the state of External Storage */
private void checkExternalStorageState() {
String state = Environment.getExternalStorageState();
if (!state.equals(Environment.MEDIA_MOUNTED)) {
LogHelper.e(LOG_TAG, "Error: Unable to mount External Storage. Current state: " + state);
// move MainActivity to back
moveTaskToBack(true);
// shutting down app
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
2018-03-20 14:15:57 +00:00
// public class SectionsPagerAdapter extends FragmentPagerAdapter {
//
// public SectionsPagerAdapter(FragmentManager fm) {
// super(fm);
// }
//
// @Override
// public Fragment getItem(int position) {
// // getItem is called to instantiate the fragment for the given page.
// switch (position) {
// case FRAGMENT_ID_MAP:
// return new MainActivityMapFragment();
// case FRAGMENT_ID_TRACKS:
// return new MainActivityTrackFragment();
// }
// return null;
// }
//
// @Override
// public int getCount() {
// return 2;
// }
//
// public Fragment getFragment(int pos) {
// return getItem(pos);
// }
//
// }
/**
* Defines callbacks for service binding, passed to bindService()
*/
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
TrackerService.LocalBinder binder = (TrackerService.LocalBinder) service;
mTrackerService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
2018-03-20 14:15:57 +00:00
/**
* Inner class: SectionsPagerAdapter that returns a fragment corresponding to one of the tabs.
* see also: https://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html
* and: http://www.truiton.com/2015/12/android-activity-fragment-communication/
*/
2018-03-20 14:15:57 +00:00
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
private final SparseArray<WeakReference<Fragment>> instantiatedFragments = new SparseArray<>();
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
switch (position) {
case FRAGMENT_ID_MAP:
return new MainActivityMapFragment();
case FRAGMENT_ID_TRACKS:
return new MainActivityTrackFragment();
}
return null;
}
@Override
public int getCount() {
2018-03-20 14:15:57 +00:00
// show 2 total pages.
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case FRAGMENT_ID_MAP:
return getString(R.string.tab_map);
case FRAGMENT_ID_TRACKS:
return getString(R.string.tab_last_tracks);
}
return null;
}
2018-01-16 13:27:50 +00:00
@NonNull
@Override
public Object instantiateItem(final ViewGroup container, final int position) {
final Fragment fragment = (Fragment) super.instantiateItem(container, position);
instantiatedFragments.put(position, new WeakReference<>(fragment));
return fragment;
}
@Override
public void destroyItem(final ViewGroup container, final int position, final Object object) {
instantiatedFragments.remove(position);
super.destroyItem(container, position, object);
}
@Nullable
public Fragment getFragment(final int position) {
final WeakReference<Fragment> wr = instantiatedFragments.get(position);
if (wr != null) {
return wr.get();
} else {
return null;
}
}
}
/**
* End of inner class
*/
2016-08-29 12:50:41 +00:00
}