package org.redcross.openmapkit;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.text.InputType;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.TouchDelegate;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import com.mapbox.mapboxsdk.geometry.BoundingBox;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.overlay.Marker;
import com.mapbox.mapboxsdk.views.MapView;
import com.spatialdev.osm.OSMMap;
import com.spatialdev.osm.events.OSMSelectionListener;
import com.spatialdev.osm.model.OSMElement;
import com.spatialdev.osm.model.OSMNode;
import org.fieldpapers.listeners.FPListener;
import org.fieldpapers.model.FPAtlas;
import org.json.JSONException;
import org.redcross.openmapkit.deployments.DeploymentsActivity;
import org.redcross.openmapkit.odkcollect.ODKCollectHandler;
import org.redcross.openmapkit.odkcollect.tag.ODKTag;
import org.redcross.openmapkit.server.MBTilesServer;
import org.redcross.openmapkit.tagswipe.TagSwipeActivity;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
public class MapActivity extends AppCompatActivity implements OSMSelectionListener, FPListener {
protected static final String PREVIOUS_LAT = "org.redcross.openmapkit.PREVIOUS_LAT";
protected static final String PREVIOUS_LNG = "org.redcross.openmapkit.PREVIOUS_LNG";
protected static final String PREVIOUS_ZOOM = "org.redcross.openmapkit.PREVIOUS_ZOOM";
private static String version = "";
protected MapView mapView;
protected OSMMap osmMap;
protected TextView fieldPapersMsg;
protected ListView mTagListView;
protected ImageButton mCloseListViewButton;
protected ImageButton tagButton;
protected ImageButton moveButton;
protected Button nodeModeButton;
protected Button addTagsButton;
protected LinearLayout mTopLinearLayout;
protected LinearLayout mBottomLinearLayout;
protected TextView mTagTextView;
protected Basemap basemap;
protected TagListAdapter tagListAdapter;
private boolean nodeMode = false;
private boolean moveNodeMode = false;
/**
* intent request codes
*/
private static final int ODK_COLLECT_TAG_ACTIVITY_CODE = 2015;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Turn on MBTiles HTTP server.
/**
* We are waiting to enable this until we need it for a new map renderer.
*/
// initializeMBTilesServer();
determineVersion();
if(android.os.Build.VERSION.SDK_INT >= 21) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.setStatusBarColor(getResources().getColor(R.color.osm_light_green));
}
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setIcon(R.mipmap.ic_omk_nobg);
}
// create directory structure for app if needed
ExternalStorage.checkOrCreateAppDirs();
// Move constraints assets to ExternalStorage if necessary
ExternalStorage.copyConstraintsToExternalStorageIfNeeded(this);
// Register the intent to the ODKCollect handler
// This will determine if we are in ODK Collect Mode or not.
ODKCollectHandler.registerIntent(getIntent());
// Initialize the constraints singleton.
// Loads up all the constraints JSON configs.
Constraints.initialize();
//set layout
setContentView(R.layout.activity_map);
//get the layout the ListView is nested in
mBottomLinearLayout = (LinearLayout)findViewById(R.id.bottomLinearLayout);
//the ListView from layout
mTagListView = (ListView)findViewById(R.id.tagListView);
//the ListView close image button
mCloseListViewButton = (ImageButton)findViewById(R.id.imageViewCloseList);
//get the layout the Map is nested in
mTopLinearLayout = (LinearLayout)findViewById(R.id.topLinearLayout);
//get map from layout
mapView = (MapView)findViewById(R.id.mapView);
// get Field Papers Message
fieldPapersMsg = (TextView)findViewById(R.id.fieldPapersMsg);
// initialize basemap object
basemap = new Basemap(this);
initializeFP();
initializeOsmXml();
// add user location toggle button
initializeLocationButton();
// setup move button
initializeMoveButton();
initializeNodeModeButton();
initializeAddNodeButtons();
initializeMoveNodeButtons();
positionMap();
initializeListView();
}
@Override
protected void onPause() {
super.onPause();
saveMapPosition();
}
protected void saveMapPosition() {
LatLng c = mapView.getCenter();
float lat = (float) c.getLatitude();
float lng = (float) c.getLongitude();
float z = mapView.getZoomLevel();
SharedPreferences.Editor editor = getPreferences(Context.MODE_PRIVATE).edit();
editor.putFloat(PREVIOUS_LAT, lat);
editor.putFloat(PREVIOUS_LNG, lng);
editor.putFloat(PREVIOUS_ZOOM, z);
editor.apply();
}
protected void positionMap() {
SharedPreferences pref = getPreferences(Context.MODE_PRIVATE);
double lat = (double) pref.getFloat(PREVIOUS_LAT, -999);
double lng = (double) pref.getFloat(PREVIOUS_LNG, -999);
float z = pref.getFloat(PREVIOUS_ZOOM, -999);
// no shared pref
if (lat == -999 || lng == -999 || z == -999) {
mapView.setUserLocationEnabled(true);
mapView.goToUserLocation(true);
}
// there is a shared pref
else {
LatLng c = new LatLng(lat, lng);
mapView.setCenter(c);
mapView.setZoom(z);
}
}
/**
* For initializing the ListView of tags
*/
protected void initializeListView() {
//the ListView title
mTagTextView = (TextView)findViewById(R.id.tagTextView);
mTagTextView.setText(R.string.tagListViewTitle);
//hide the ListView by default
proportionMapAndList(100, 0);
//handle when user taps on the close button in the list view
mCloseListViewButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
proportionMapAndList(100, 0);
}
});
//increase the 'hit area' of the down arrow
View parent = findViewById(R.id.bottomLinearLayout);
parent.post(new Runnable() {
public void run() {
Rect delegateArea = new Rect();
ImageButton delegate = mCloseListViewButton;
delegate.getHitRect(delegateArea);
delegateArea.top -= 100;
delegateArea.bottom += 100;
delegateArea.left -= 100;
delegateArea.right += 100;
TouchDelegate expandedArea = new TouchDelegate(delegateArea, delegate);
if (View.class.isInstance(delegate.getParent())) {
((View) delegate.getParent()).setTouchDelegate(expandedArea);
}
}
});
View.OnClickListener tagSwipeLaunchListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ODKCollectHandler.isODKCollectMode()) {
//launch the TagSwipeActivity
Intent tagSwipe = new Intent(getApplicationContext(), TagSwipeActivity.class);
startActivityForResult(tagSwipe, ODK_COLLECT_TAG_ACTIVITY_CODE);
} else {
launchODKCollectSnackbar();
}
}
};
// tag button
tagButton = (ImageButton)findViewById(R.id.tagButton);
tagButton.setOnClickListener(tagSwipeLaunchListener);
// add tags button
addTagsButton = (Button)findViewById(R.id.addTagsBtn);
addTagsButton.setOnClickListener(tagSwipeLaunchListener);
//handle list view item taps
mTagListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (ODKCollectHandler.isODKCollectMode()) {
String tappedKey = tagListAdapter.getTagKeyForIndex(position);
Intent tagSwipe = new Intent(getApplicationContext(), TagSwipeActivity.class);
tagSwipe.putExtra("TAG_KEY", tappedKey);
startActivityForResult(tagSwipe, ODK_COLLECT_TAG_ACTIVITY_CODE);
} else {
launchODKCollectSnackbar();
}
}
});
}
/**
* For identifying an OSM element and presenting it's tags in the ListView
* @param osmElement The target OSMElement.
*/
protected void identifyOSMFeature(OSMElement osmElement) {
// only open it if we render the OSM vectors,
// otherwise it is confusing for the user
if (mapView.getZoomLevel() < OSMMapBuilder.MIN_VECTOR_RENDER_ZOOM) {
return;
}
int numRequiredTags = 0;
if (ODKCollectHandler.isODKCollectMode()) {
Collection<ODKTag> requiredTags = ODKCollectHandler.getODKCollectData().getRequiredTags();
numRequiredTags = requiredTags.size();
}
int tagCount = osmElement.getTags().size();
if (tagCount > 0 || numRequiredTags > 0) {
mTagListView.setVisibility(View.VISIBLE);
addTagsButton.setVisibility(View.GONE);
} else {
mTagListView.setVisibility(View.GONE);
addTagsButton.setVisibility(View.VISIBLE);
}
/**
* If we have a node that is selected, we want to activate the
* move button. Ways should not be editable.
*/
if (osmElement instanceof OSMNode) {
moveButton.setVisibility(View.VISIBLE);
} else {
moveButton.setVisibility(View.GONE);
}
//pass the tags to the list adapter
tagListAdapter = new TagListAdapter(this, osmElement);
//set the ListView's adapter
mTagListView.setAdapter(tagListAdapter);
//show the ListView under the map
proportionMapAndList(50, 50);
}
/**
* For setting the proportions of the Map weight and the ListView weight for dual display
* @param topWeight Refers to the layout weight. Note, topWeight + bottomWeight must equal the weight sum of 100
* @param bottomWeight Referes to the layotu height. Note, bottomWeight + topWeight must equal the weight sum of 100
*/
protected void proportionMapAndList(int topWeight, int bottomWeight) {
LinearLayout.LayoutParams topLayoutParams = (LinearLayout.LayoutParams)mTopLinearLayout.getLayoutParams();
LinearLayout.LayoutParams bottomLayoutParams = (LinearLayout.LayoutParams)mBottomLinearLayout.getLayoutParams();
//update weight of top and bottom linear layouts
mTopLinearLayout.setLayoutParams(new LinearLayout.LayoutParams(topLayoutParams.width, topLayoutParams.height, topWeight));
mBottomLinearLayout.setLayoutParams(new LinearLayout.LayoutParams(bottomLayoutParams.width, bottomLayoutParams.height, bottomWeight));
}
/**
* Adds FieldPapers Overlay to the map (if we have one).
*/
protected void initializeFP() {
try {
FPAtlas.addToMap(this, mapView);
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* Loads OSM XML stored on the device.
*/
protected void initializeOsmXml() {
try {
OSMMapBuilder.buildMapFromExternalStorage(this);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* For instantiating the location button and setting up its tap event handler
*/
protected void initializeLocationButton() {
final ImageButton locationButton = (ImageButton)findViewById(R.id.locationButton);
//set tap event
locationButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean userLocationIsEnabled = mapView.getUserLocationEnabled();
if (userLocationIsEnabled) {
mapView.setUserLocationEnabled(false);
locationButton.setBackground(getResources().getDrawable(R.drawable.roundedbutton));
} else {
mapView.setUserLocationEnabled(true);
mapView.goToUserLocation(true);
locationButton.setBackground(getResources().getDrawable(R.drawable.roundedbutton_blue));
}
}
});
}
protected void initializeMoveButton() {
moveButton = (ImageButton)findViewById(R.id.moveNodeModeBtn);
moveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toggleMoveNodeMode();
}
});
}
protected void initializeNodeModeButton() {
nodeModeButton = (Button)findViewById(R.id.nodeModeButton);
nodeModeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toggleNodeMode();
}
});
}
protected void initializeAddNodeButtons() {
final Button addNodeBtn = (Button)findViewById(R.id.addNodeBtn);
final ImageButton addNodeMarkerBtn = (ImageButton)findViewById(R.id.addNodeMarkerBtn);
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
OSMNode node = osmMap.addNode();
toggleNodeMode();
node.select();
identifyOSMFeature(node);
}
};
addNodeMarkerBtn.setOnClickListener(listener);
addNodeBtn.setOnClickListener(listener);
}
protected void initializeMoveNodeButtons() {
final Button moveNodeBtn = (Button)findViewById(R.id.moveNodeBtn);
final ImageButton moveNodeMarkerBtn = (ImageButton)findViewById(R.id.moveNodeMarkerBtn);
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
osmMap.moveNode();
toggleMoveNodeMode();
}
};
moveNodeBtn.setOnClickListener(listener);
moveNodeMarkerBtn.setOnClickListener(listener);
}
private void toggleNodeMode() {
final Button addNodeBtn = (Button)findViewById(R.id.addNodeBtn);
final ImageButton addNodeMarkerBtn = (ImageButton)findViewById(R.id.addNodeMarkerBtn);
if (nodeMode) {
addNodeBtn.setVisibility(View.GONE);
addNodeMarkerBtn.setVisibility(View.GONE);
nodeModeButton.setBackground(getResources().getDrawable(R.drawable.roundedbutton));
} else {
addNodeBtn.setVisibility(View.VISIBLE);
addNodeMarkerBtn.setVisibility(View.VISIBLE);
nodeModeButton.setBackground(getResources().getDrawable(R.drawable.roundedbutton_green));
OSMElement.deselectAll();
mapView.invalidate();
}
nodeMode = !nodeMode;
}
private void deleteNode() {
final OSMNode deletedNode = osmMap.deleteNode();
Snackbar.make(findViewById(R.id.mapActivity),
"Deleted Node",
Snackbar.LENGTH_LONG)
.setAction("UNDO", new View.OnClickListener() {
// undo action
@Override
public void onClick(View v) {
osmMap.addNode(deletedNode);
}
})
.setActionTextColor(Color.rgb(126,188,111))
.show();
}
private void toggleMoveNodeMode() {
final ImageButton moveNodeModeBtn = (ImageButton)findViewById(R.id.moveNodeModeBtn);
final ImageButton moveNodeMarkerBtn = (ImageButton)findViewById(R.id.moveNodeMarkerBtn);
final Button moveNodeBtn = (Button)findViewById(R.id.moveNodeBtn);
if (moveNodeMode) {
moveNodeMarkerBtn.setVisibility(View.GONE);
moveNodeBtn.setVisibility(View.GONE);
moveNodeModeBtn.setBackground(getResources().getDrawable(R.drawable.roundedbutton));
showSelectedMarker();
} else {
moveNodeMarkerBtn.setVisibility(View.VISIBLE);
moveNodeBtn.setVisibility(View.VISIBLE);
moveNodeModeBtn.setBackground(getResources().getDrawable(R.drawable.roundedbutton_orange));
hideSelectedMarker();
proportionMapAndList(100, 0);
}
moveNodeMode = !moveNodeMode;
}
private void hideSelectedMarker() {
LinkedList<OSMElement> selectedElements = OSMElement.getSelectedElements();
if (selectedElements.size() < 1) return;
OSMNode node = (OSMNode)selectedElements.getFirst();
Marker marker = node.getMarker();
if (marker != null) {
node.getMarker().setVisibility(false);
}
mapView.invalidate();
}
private void showSelectedMarker() {
LinkedList<OSMElement> selectedElements = OSMElement.getSelectedElements();
if (selectedElements.size() < 1) return;
OSMNode node = (OSMNode)selectedElements.getFirst();
Marker marker = node.getMarker();
if (marker != null) {
node.getMarker().setVisibility(true);
}
mapView.invalidate();
}
/**
* For presenting a dialog to allow the user to choose which OSM XML files to use.
*/
private void presentOSMOptions() {
final File[] osmFiles = ExternalStorage.fetchOSMXmlFiles();
String[] osmFileNames = ExternalStorage.fetchOSMXmlFileNames();
final boolean[] checkedOsmFiles = OSMMapBuilder.isFileArraySelected(osmFiles);
final Set<File> filesToAdd = new HashSet<>();
final Set<File> filesToRemove = new HashSet<>();
if (osmFileNames.length > 0) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.osmChooserDialogTitle));
builder.setMultiChoiceItems(osmFileNames, checkedOsmFiles, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i, boolean isChecked) {
// load the file
if (isChecked) {
File fileToAdd = osmFiles[i];
filesToAdd.add(fileToAdd);
}
// remove the file
else {
File fileToRemove = osmFiles[i];
filesToRemove.add(fileToRemove);
}
}
});
//handle OK tap event of dialog
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
OSMMapBuilder.removeOSMFilesFromModel(filesToRemove);
OSMMapBuilder.addOSMFilesToModel(filesToAdd);
}
});
//handle cancel button tap event of dialog
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
//user clicked cancel
}
});
builder.show();
} else {
Snackbar.make(findViewById(R.id.mapActivity),
"You have not yet downloaded any OSM data. Please check out a deployment or add .osm files to external storage.",
Snackbar.LENGTH_INDEFINITE)
.setAction("OK", new View.OnClickListener() {
// undo action
@Override
public void onClick(View v) {
}
})
.setActionTextColor(Color.rgb(126,188,111))
.show();
}
}
private void inputOSMCredentials() {
final SharedPreferences userNamePref = getSharedPreferences("org.redcross.openmapkit.USER_NAME", Context.MODE_PRIVATE);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("OpenStreetMap User Name");
builder.setMessage("Please enter your OpenStreetMap user name.");
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
String userName = userNamePref.getString("userName", null);
if (userName != null) {
input.setText(userName);
}
builder.setView(input);
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
// just dismiss
}
});
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String userName = input.getText().toString();
SharedPreferences.Editor editor = userNamePref.edit();
editor.putString("userName", userName);
editor.apply();
}
});
builder.show();
}
private void askIfDownloadOSM() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.downloadOSMTitle);
builder.setMessage(R.string.downloadOSMMessage);
builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
// just dismiss
}
});
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
downloadOSM();
}
});
builder.show();
}
private void downloadOSM() {
BoundingBox bbox = mapView.getBoundingBox();
OSMDownloader downloader = new OSMDownloader(this, bbox);
downloader.execute();
}
private void showInfo() {
Snackbar.make(findViewById(R.id.mapActivity),
"Version: " + MapActivity.getVersion(),
Snackbar.LENGTH_INDEFINITE)
.setAction("OK", new View.OnClickListener() {
@Override
public void onClick(View v) {
}
})
.setActionTextColor(Color.rgb(126, 188, 111))
.show();
}
/**
* OSMMapBuilder sets a reference to OSMMap in this class.
*
* @param osmMap
*/
public void setOSMMap(OSMMap osmMap) {
this.osmMap = osmMap;
}
/**
* For adding action items to the action bar
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_map, menu);
return true;
}
/**
* For handling when a user taps on a menu item (top right)
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
super.onOptionsItemSelected(item);
int id = item.getItemId();
if (id == R.id.deployments) {
launchDeploymentsActivity();
return true;
} else if (id == R.id.osmdownloader) {
askIfDownloadOSM();
return true;
} else if (id == R.id.basemaps) {
basemap.presentBasemapsOptions();
return true;
} else if (id == R.id.osmcredentials) {
inputOSMCredentials();
return true;
} else if (id == R.id.osmXmlLayers) {
presentOSMOptions();
return true;
} else if (id == R.id.info) {
showInfo();
return true;
} else if (id == R.id.action_save_to_odk_collect) {
saveToODKCollectAndExit();
return true;
}
return false;
}
private void launchDeploymentsActivity() {
Intent deploymentsActivity = new Intent(getApplicationContext(), DeploymentsActivity.class);
startActivity(deploymentsActivity);
}
@Override
public void selectedElementsChanged(LinkedList<OSMElement> selectedElements) {
if (selectedElements != null && selectedElements.size() > 0) {
// tagsButton.setVisibility(View.VISIBLE);
//fetch the tapped feature
OSMElement tappedOSMElement = selectedElements.get(0);
//present OSM Feature tags in bottom ListView
identifyOSMFeature(tappedOSMElement);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if ( requestCode == ODK_COLLECT_TAG_ACTIVITY_CODE ) {
if(resultCode == RESULT_OK) {
saveToODKCollectAndExit();
}
}
}
protected void saveToODKCollectAndExit() {
String osmXmlFileFullPath = ODKCollectHandler.getODKCollectData().getOSMFileFullPath();
String osmXmlFileName = ODKCollectHandler.getODKCollectData().getOSMFileName();
Intent resultIntent = new Intent();
resultIntent.putExtra("OSM_PATH", osmXmlFileFullPath);
resultIntent.putExtra("OSM_FILE_NAME", osmXmlFileName);
setResult(Activity.RESULT_OK, resultIntent);
finish();
}
public MapView getMapView() {
return mapView;
}
private void determineVersion() {
try {
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
version = pInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
public static String getVersion() {
return version;
}
private void initializeMBTilesServer() {
try {
MBTilesServer.singleton().start();
} catch(IOException ioe) {
Log.w("Httpd", "MBTiles HTTP server could not start.");
}
Log.w("MBTilesServer", "MBTiles HTTP server initialized.");
}
private void launchODKCollectSnackbar() {
if (isAppInstalled("org.odk.collect.android")) {
Snackbar.make(findViewById(R.id.mapActivity),
"To edit tags, OpenMapKit must be launched from within an ODK Collect survey.",
Snackbar.LENGTH_LONG)
.setAction("Launch ODK Collect", new View.OnClickListener() {
// undo action
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setClassName("org.odk.collect.android", "org.odk.collect.android.activities.SplashScreenActivity");
startActivity(intent);
}
})
.setActionTextColor(Color.rgb(126, 188, 111))
.show();
} else {
Snackbar.make(findViewById(R.id.mapActivity),
"Please install ODK Collect.",
Snackbar.LENGTH_LONG)
.setAction("Launch Play Store", new View.OnClickListener() {
// undo action
@Override
public void onClick(View v) {
final String appPackageName = "org.odk.collect.android";
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName)));
} catch (android.content.ActivityNotFoundException anfe) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
}
}
})
.setActionTextColor(Color.rgb(126, 188, 111))
.show();
}
}
private boolean isAppInstalled(String uri) {
PackageManager pm = getPackageManager();
boolean app_installed;
try {
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
app_installed = true;
}
catch (PackageManager.NameNotFoundException e) {
app_installed = false;
}
return app_installed;
}
@Override
public void onMapCenterPageChangeMessage(String msg) {
if (msg != null) {
fieldPapersMsg.setText(msg);
fieldPapersMsg.setVisibility(View.VISIBLE);
} else {
fieldPapersMsg.setVisibility(View.GONE);
}
}
}