// MainActivityFragment.java
// Contains the Flag Quiz logic
package eu.geopaparazzi.core.ui.fragments;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import eu.geopaparazzi.library.GPApplication;
import eu.geopaparazzi.library.core.ResourcesManager;
import eu.geopaparazzi.library.database.DatabaseUtilities;
import eu.geopaparazzi.library.database.DefaultHelperClasses;
import eu.geopaparazzi.library.database.GPLog;
import eu.geopaparazzi.library.database.GPLogPreferencesHandler;
import eu.geopaparazzi.library.gps.GpsLoggingStatus;
import eu.geopaparazzi.library.gps.GpsServiceStatus;
import eu.geopaparazzi.library.gps.GpsServiceUtilities;
import eu.geopaparazzi.library.profiles.Profile;
import eu.geopaparazzi.library.profiles.ProfilesHandler;
import eu.geopaparazzi.library.sensors.OrientationSensor;
import eu.geopaparazzi.library.style.ColorUtilities;
import eu.geopaparazzi.library.util.AppsUtilities;
import eu.geopaparazzi.library.util.FileTypes;
import eu.geopaparazzi.library.util.FileUtilities;
import eu.geopaparazzi.library.util.GPDialogs;
import eu.geopaparazzi.library.util.IActivitySupporter;
import eu.geopaparazzi.library.util.LibraryConstants;
import eu.geopaparazzi.library.util.TextAndBooleanRunnable;
import eu.geopaparazzi.library.util.TimeUtilities;
import eu.geopaparazzi.library.util.Utilities;
import eu.geopaparazzi.mapsforge.BaseMapSourcesManager;
import eu.geopaparazzi.mapsforge.sourcesview.SourcesTreeListActivity;
import eu.geopaparazzi.core.GeopaparazziApplication;
import eu.geopaparazzi.core.R;
import eu.geopaparazzi.core.database.DaoMetadata;
import eu.geopaparazzi.core.database.TableDescriptions;
import eu.geopaparazzi.core.database.objects.Metadata;
import eu.geopaparazzi.core.mapview.MapviewActivity;
import eu.geopaparazzi.core.ui.activities.AboutActivity;
import eu.geopaparazzi.core.ui.activities.AddNotesActivity;
import eu.geopaparazzi.core.ui.activities.AdvancedSettingsActivity;
import eu.geopaparazzi.core.ui.activities.ExportActivity;
import eu.geopaparazzi.core.ui.activities.ImportActivity;
import eu.geopaparazzi.core.ui.activities.PanicActivity;
import eu.geopaparazzi.core.ui.activities.ProjectMetadataActivity;
import eu.geopaparazzi.core.ui.activities.SettingsActivity;
import eu.geopaparazzi.core.ui.dialogs.GpsInfoDialogFragment;
import eu.geopaparazzi.core.ui.dialogs.NewProjectDialogFragment;
import eu.geopaparazzi.core.utilities.Constants;
import eu.geopaparazzi.core.utilities.IApplicationChangeListener;
import static eu.geopaparazzi.library.util.LibraryConstants.MAPSFORGE_EXTRACTED_DB_NAME;
/**
* The fragment of the main geopap view.
*
* @author Andrea Antonello (www.hydrologis.com)
*/
public class GeopaparazziActivityFragment extends Fragment implements View.OnLongClickListener, View.OnClickListener, IActivitySupporter {
private final int RETURNCODE_BROWSE_FOR_NEW_PREOJECT = 665;
private ImageButton mNotesButton;
private ImageButton mMetadataButton;
private ImageButton mMapviewButton;
private ImageButton mGpslogButton;
private ImageButton mExportButton;
private ImageButton mImportButton;
private MenuItem mGpsMenuItem;
private OrientationSensor mOrientationSensor;
private IApplicationChangeListener appChangeListener;
private BroadcastReceiver mGpsServiceBroadcastReceiver;
private static boolean sCheckedGps = false;
private GpsServiceStatus mLastGpsServiceStatus;
private int[] mLastGpsStatusExtras;
private GpsLoggingStatus mLastGpsLoggingStatus = GpsLoggingStatus.GPS_DATABASELOGGING_OFF;
private double[] mLastGpsPosition;
private FloatingActionButton mPanicFAB;
private ResourcesManager mResourcesManager;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View v = inflater.inflate(R.layout.fragment_geopaparazzi, container, false);
// this fragment adds to the menu
setHasOptionsMenu(true);
Profile activeProfile = ProfilesHandler.INSTANCE.getActiveProfile();
if (activeProfile != null) {
if (activeProfile.projectPath != null && new File(activeProfile.projectPath).exists()) {
View dashboardView = v.findViewById(R.id.dashboardLayout);
String color = activeProfile.color;
if (color != null) {
dashboardView.setBackgroundColor(ColorUtilities.toColor(color));
}
}
}
try {
initializeResourcesManager();
} catch (Exception e) {
e.printStackTrace();
}
// start gps service
GpsServiceUtilities.startGpsService(getActivity());
// start map reading in background
new Thread(new Runnable() {
@Override
public void run() {
BaseMapSourcesManager.INSTANCE.getBaseMaps();
}
}).start();
return v; // return the fragment's view for display
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mNotesButton = (ImageButton) view.findViewById(R.id.dashboardButtonNotes);
mNotesButton.setOnClickListener(this);
mNotesButton.setOnLongClickListener(this);
mMetadataButton = (ImageButton) view.findViewById(R.id.dashboardButtonMetadata);
mMetadataButton.setOnClickListener(this);
mMetadataButton.setOnLongClickListener(this);
mMapviewButton = (ImageButton) view.findViewById(R.id.dashboardButtonMapview);
mMapviewButton.setOnClickListener(this);
mMapviewButton.setOnLongClickListener(this);
mGpslogButton = (ImageButton) view.findViewById(R.id.dashboardButtonGpslog);
mGpslogButton.setOnClickListener(this);
mGpslogButton.setOnLongClickListener(this);
mImportButton = (ImageButton) view.findViewById(R.id.dashboardButtonImport);
mImportButton.setOnClickListener(this);
mImportButton.setOnLongClickListener(this);
mExportButton = (ImageButton) view.findViewById(R.id.dashboardButtonExport);
mExportButton.setOnClickListener(this);
mExportButton.setOnLongClickListener(this);
mPanicFAB = (FloatingActionButton) view.findViewById(R.id.panicActionButton);
mPanicFAB.setOnClickListener(this);
enablePanic(false);
}
@Override
public void onResume() {
super.onResume();
GpsServiceUtilities.triggerBroadcast(getActivity());
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof IApplicationChangeListener) {
appChangeListener = (IApplicationChangeListener) context;
}
if (mOrientationSensor == null) {
SensorManager sensorManager = (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE);
mOrientationSensor = new OrientationSensor(sensorManager, null);
}
mOrientationSensor.register(getActivity(), SensorManager.SENSOR_DELAY_NORMAL);
if (mGpsServiceBroadcastReceiver == null) {
mGpsServiceBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
onGpsServiceUpdate(intent);
checkFirstTimeGps(context);
}
};
}
GpsServiceUtilities.registerForBroadcasts(getActivity(), mGpsServiceBroadcastReceiver);
}
// remove SourceUrlsFragmentListener when Fragment detached
@Override
public void onDetach() {
super.onDetach();
appChangeListener = null;
mOrientationSensor.unregister();
try {
GpsServiceUtilities.unregisterFromBroadcasts(getActivity(), mGpsServiceBroadcastReceiver);
} catch (Exception e) {
// TODO how do I check if it is already unregistered
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_main, menu);
mGpsMenuItem = menu.getItem(3);
Profile activeProfile = ProfilesHandler.INSTANCE.getActiveProfile();
if (activeProfile != null) {
if (activeProfile.projectPath != null && new File(activeProfile.projectPath).exists()) {
// hide new project and open project
menu.getItem(1).setVisible(false);
menu.getItem(2).setVisible(false);
}
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int i = item.getItemId();
if (i == R.id.action_tilesource) {
Intent preferencesIntent = new Intent(this.getActivity(), SourcesTreeListActivity.class);
startActivity(preferencesIntent);
return true;
} else if (i == R.id.action_new) {
NewProjectDialogFragment newProjectDialogFragment = new NewProjectDialogFragment();
newProjectDialogFragment.show(getFragmentManager(), "new project dialog");
return true;
} else if (i == R.id.action_load) {
try {
String title = getString(R.string.select_gpap_file);
AppsUtilities.pickFile(this, RETURNCODE_BROWSE_FOR_NEW_PREOJECT, title, new String[]{FileTypes.GPAP.getExtension()}, null);
} catch (Exception e) {
GPLog.error(this, null, e);
}
return true;
} else if (i == R.id.action_gps) {
GpsInfoDialogFragment gpsInfoDialogFragment = new GpsInfoDialogFragment();
gpsInfoDialogFragment.show(getFragmentManager(), "gpsinfo dialog");
return true;
} else if (i == R.id.action_gpsstatus) {
AppsUtilities.checkAndOpenGpsStatus(getActivity());
return true;
} else if (i == R.id.action_settings) {
Intent preferencesIntent = new Intent(this.getActivity(), SettingsActivity.class);
startActivity(preferencesIntent);
return true;
} else if (i == R.id.action_advanced_settings) {
Intent advancedSettingsIntent = new Intent(this.getActivity(), AdvancedSettingsActivity.class);
startActivity(advancedSettingsIntent);
return true;
} else if (i == R.id.action_about) {
Intent intent = new Intent(getActivity(), AboutActivity.class);
startActivity(intent);
return true;
} else if (i == R.id.action_exit) {
appChangeListener.onAppIsShuttingDown();
getActivity().finish();
return true;
}
return super.onOptionsItemSelected(item);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case (RETURNCODE_BROWSE_FOR_NEW_PREOJECT): {
if (resultCode == Activity.RESULT_OK) {
try {
String filePath = data.getStringExtra(LibraryConstants.PREFS_KEY_PATH);
if (filePath == null) return;
if (!filePath.endsWith(FileTypes.GPAP.getExtension())) {
GPDialogs.warningDialog(getActivity(), getActivity().getString(R.string.selected_file_is_no_geopap_project), null);
return;
}
File file = new File(filePath);
if (file.exists()) {
Utilities.setLastFilePath(getActivity(), filePath);
try {
DatabaseUtilities.setNewDatabase(getActivity(), GeopaparazziApplication.getInstance(), file.getAbsolutePath());
if (appChangeListener != null) {
appChangeListener.onApplicationNeedsRestart();
}
} catch (IOException e) {
GPLog.error(this, null, e);
GPDialogs.warningDialog(getActivity(), getActivity().getString(R.string.error_while_setting_project), null);
}
}
} catch (Exception e) {
GPDialogs.errorDialog(getActivity(), e, null);
}
}
break;
}
// case (RETURNCODE_NOTES): {
// if (resultCode == Activity.RESULT_OK) {
// String[] noteArray = data.getStringArrayExtra(LibraryConstants.PREFS_KEY_NOTE);
// if (noteArray != null) {
// try {
// double lon = Double.parseDouble(noteArray[0]);
// double lat = Double.parseDouble(noteArray[1]);
// double elev = Double.parseDouble(noteArray[2]);
// DaoNotes.addNote(lon, lat, elev, Long.parseLong(noteArray[3]), noteArray[4], "POI", null,
// null);
// } catch (Exception e) {
// GPLog.error(this, null, e); //$NON-NLS-1$
// Utilities.messageDialog(this, eu.geopaparazzi.library.R.string.notenonsaved, null);
// }
// }
// }
// break;
// }
}
}
@Override
public boolean onLongClick(View v) {
if (v instanceof ImageButton) {
ImageButton imageButton = (ImageButton) v;
String tooltip = imageButton.getContentDescription().toString();
Snackbar.make(v, tooltip, Snackbar.LENGTH_SHORT).show();
return true;
}
if (v == mNotesButton) {
String tooltip = "Available providers:";
for (PackageInfo pack : getActivity().getPackageManager().getInstalledPackages(PackageManager.GET_PROVIDERS)) {
ProviderInfo[] providers = pack.providers;
if (providers != null) {
for (ProviderInfo provider : providers) {
Log.d("Example", "provider: " + provider.authority);
tooltip = tooltip + "\n" + provider.authority;
}
}
}
Snackbar.make(v, tooltip, Snackbar.LENGTH_SHORT).show();
}
return true;
}
@Override
public void onClick(View v) {
if (v == mMetadataButton) {
try {
Intent projectMetadataIntent = new Intent(getActivity(), ProjectMetadataActivity.class);
startActivity(projectMetadataIntent);
} catch (Exception e) {
GPLog.error(this, null, e); //$NON-NLS-1$
}
} else if (v == mMapviewButton) {
Intent importIntent = new Intent(getActivity(), MapviewActivity.class);
startActivity(importIntent);
} else if (v == mGpslogButton) {
handleGpsLogAction();
} else if (v == mImportButton) {
Intent importIntent = new Intent(getActivity(), ImportActivity.class);
startActivity(importIntent);
} else if (v == mNotesButton) {
try {
Intent mapTagsIntent = new Intent(getActivity(), AddNotesActivity.class);
startActivity(mapTagsIntent);
} catch (Exception e) {
GPLog.error(this, null, e);
GPDialogs.errorDialog(getActivity(), e, null);
}
} else if (v == mExportButton) {
Intent exportIntent = new Intent(getActivity(), ExportActivity.class);
startActivity(exportIntent);
} else if (v == mPanicFAB) {
if (mLastGpsPosition == null) {
return;
}
Intent panicIntent = new Intent(getActivity(), PanicActivity.class);
double lon = mLastGpsPosition[0];
double lat = mLastGpsPosition[1];
panicIntent.putExtra(LibraryConstants.LATITUDE, lat);
panicIntent.putExtra(LibraryConstants.LONGITUDE, lon);
startActivity(panicIntent);
}
}
private void onGpsServiceUpdate(Intent intent) {
mLastGpsServiceStatus = GpsServiceUtilities.getGpsServiceStatus(intent);
mLastGpsLoggingStatus = GpsServiceUtilities.getGpsLoggingStatus(intent);
mLastGpsStatusExtras = GpsServiceUtilities.getGpsStatusExtras(intent);
mLastGpsPosition = GpsServiceUtilities.getPosition(intent);
// lastGpsPositionExtras = GpsServiceUtilities.getPositionExtras(intent);
// lastPositiontime = GpsServiceUtilities.getPositionTime(intent);
boolean doLog = GPLog.LOG_HEAVY;
if (doLog && mLastGpsStatusExtras != null) {
int satCount = mLastGpsStatusExtras[1];
int satForFixCount = mLastGpsStatusExtras[2];
GPLog.addLogEntry(this, "satellites: " + satCount + " of which for fix: " + satForFixCount);
}
if (mGpsMenuItem != null)
if (mLastGpsServiceStatus != GpsServiceStatus.GPS_OFF) {
if (doLog)
GPLog.addLogEntry(this, "GPS seems to be on");
if (mLastGpsLoggingStatus == GpsLoggingStatus.GPS_DATABASELOGGING_ON) {
if (doLog)
GPLog.addLogEntry(this, "GPS seems to be also logging");
mGpsMenuItem.setIcon(R.drawable.actionbar_gps_logging);
enablePanic(true);
} else {
if (mLastGpsServiceStatus == GpsServiceStatus.GPS_FIX) {
if (doLog) {
GPLog.addLogEntry(this, "GPS has fix");
}
mGpsMenuItem.setIcon(R.drawable.actionbar_gps_fix_nologging);
enablePanic(true);
} else {
if (doLog) {
GPLog.addLogEntry(this, "GPS doesn't have a fix");
}
mGpsMenuItem.setIcon(R.drawable.actionbar_gps_nofix);
enablePanic(false);
}
}
} else {
if (doLog)
GPLog.addLogEntry(this, "GPS seems to be off");
mGpsMenuItem.setIcon(R.drawable.actionbar_gps_off);
enablePanic(false);
}
}
private void checkFirstTimeGps(Context context) {
if (!sCheckedGps) {
sCheckedGps = true;
if (mLastGpsServiceStatus == GpsServiceStatus.GPS_OFF) {
String prompt = getResources().getString(R.string.prompt_gpsenable);
GPDialogs.yesNoMessageDialog(context, prompt, new Runnable() {
public void run() {
Intent gpsOptionsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(gpsOptionsIntent);
}
}, null);
}
}
}
private void enablePanic(boolean enable) {
if (enable) {
mPanicFAB.show();
} else {
mPanicFAB.hide();
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
/*
* avoid oncreate call when rotating device
* we don't want data to be reloaded
*/
super.onConfigurationChanged(newConfig);
}
private void initializeResourcesManager() throws Exception {
ResourcesManager.resetManager();
mResourcesManager = ResourcesManager.getInstance(getContext());
if (mResourcesManager == null) {
GPDialogs.yesNoMessageDialog(getActivity(), getString(eu.geopaparazzi.core.R.string.no_sdcard_use_internal_memory),
new Runnable() {
public void run() {
ResourcesManager.setUseInternalMemory(true);
try {
mResourcesManager = ResourcesManager.getInstance(getContext());
initIfOk();
} catch (Exception e) {
GPLog.error(this, null, e); //$NON-NLS-1$
}
}
}, new Runnable() {
public void run() {
getActivity().finish();
}
}
);
} else {
// create the default mapsforge data extraction db
File applicationSupporterDir = mResourcesManager.getApplicationSupporterDir();
File newDbFile = new File(applicationSupporterDir, MAPSFORGE_EXTRACTED_DB_NAME);
if (!newDbFile.exists()) {
AssetManager assetManager = getActivity().getAssets();
InputStream inputStream = assetManager.open(MAPSFORGE_EXTRACTED_DB_NAME);
FileUtilities.copyFile(inputStream, new FileOutputStream(newDbFile));
}
// initialize rest of resources
initIfOk();
}
}
private void initIfOk() {
if (mResourcesManager == null) {
GPDialogs.warningDialog(getActivity(), getString(R.string.sdcard_notexist), new Runnable() {
public void run() {
getActivity().finish();
}
});
return;
}
/*
* check the logging system
*/
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
GPLogPreferencesHandler.checkLog(preferences);
GPLogPreferencesHandler.checkLogHeavy(preferences);
GPLogPreferencesHandler.checkLogAbsurd(preferences);
checkLogButton();
// check for screen on
boolean keepScreenOn = preferences.getBoolean(Constants.PREFS_KEY_SCREEN_ON, false);
if (keepScreenOn) {
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
try {
GeopaparazziApplication.getInstance().getDatabase();
// Set the project name in the metadata, if not already available
List<Metadata> projectMetadata = DaoMetadata.getProjectMetadata();
for (Metadata metadata : projectMetadata) {
if (metadata.key.equals(TableDescriptions.MetadataTableDefaultValues.KEY_NAME.getFieldName())) {
String projectName = metadata.value;
if (projectName.length() == 0) {
File dbFile = mResourcesManager.getDatabaseFile();
String dbName = FileUtilities.getNameWithoutExtention(dbFile);
DaoMetadata.setValue(metadata.key, dbName);
break;
}
}
}
} catch (Exception e) {
Log.e(getClass().getSimpleName(), e.getLocalizedMessage(), e);
GPDialogs.toast(getActivity(), R.string.databaseError, Toast.LENGTH_LONG);
}
}
private void checkLogButton() {
if (mGpslogButton != null)
if (mLastGpsLoggingStatus == GpsLoggingStatus.GPS_DATABASELOGGING_ON) {
mGpslogButton.setBackgroundColor(ColorUtilities.getAccentColor(getContext()));
} else {
mGpslogButton.setBackgroundColor(ColorUtilities.getPrimaryColor(getContext()));
}
}
private void handleGpsLogAction() {
final GPApplication appContext = GeopaparazziApplication.getInstance();
if (mLastGpsLoggingStatus == GpsLoggingStatus.GPS_DATABASELOGGING_ON) {
GPDialogs.yesNoMessageDialog(getActivity(), getString(R.string.do_you_want_to_stop_logging),
new Runnable() {
public void run() {
getActivity().runOnUiThread(new Runnable() {
public void run() {
// stop logging
GpsServiceUtilities.stopDatabaseLogging(appContext);
mGpslogButton.setBackgroundColor(ColorUtilities.getPrimaryColor(getContext()));
GpsServiceUtilities.triggerBroadcast(getActivity());
}
});
}
}, null
);
} else {
// start logging
if (mLastGpsServiceStatus == GpsServiceStatus.GPS_FIX) {
final String defaultLogName = "log_" + TimeUtilities.INSTANCE.TIMESTAMPFORMATTER_LOCAL.format(new Date()); //$NON-NLS-1$
GPDialogs.inputMessageAndCheckboxDialog(getActivity(), getString(R.string.gps_log_name),
defaultLogName, getString(R.string.continue_last_log), false, new TextAndBooleanRunnable() {
public void run() {
getActivity().runOnUiThread(new Runnable() {
public void run() {
String newName = theTextToRunOn;
if (newName == null || newName.length() < 1) {
newName = defaultLogName;
}
mGpslogButton.setBackgroundColor(ColorUtilities.getAccentColor(getContext()));
GpsServiceUtilities.startDatabaseLogging(appContext, newName, theBooleanToRunOn,
DefaultHelperClasses.GPSLOG_HELPER_CLASS);
GpsServiceUtilities.triggerBroadcast(getActivity());
}
});
}
}
);
} else {
GPDialogs.warningDialog(getActivity(), getString(R.string.gpslogging_only), null);
}
}
}
public BroadcastReceiver getGpsServiceBroadcastReceiver() {
return mGpsServiceBroadcastReceiver;
}
@Override
public FragmentManager getSupportFragmentManager() {
return null;
}
}