I have created a small Android app which should track POIs. I navigate through a route and placed 10 trackable POIs at the beginning of the route and many other trackable POIs along the whole route. As I put annotations on the trackable POIs one can see that they are created. I want to track them with SKPOITrackerManager. But none of these POIs are tracked.
I implemented the SKPOITrackerListener and onUpdatePOIsinRadius() is called the first two times without any POIs added. The third time it is called (~ 2 minutes after the app I starting) it adds many POIs. But onReceivedPOIs() does not find the POIs. It is only called once. And the List<SKDetectedPOI> only has size one with a detected POI having an ID equal to -1.
Here is my complete code, containing two Activites.
MainActivity:
package com.example.michi.mapapplication;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.os.StatFs;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import com.skobbler.ngx.SKDeveloperKeyException;
import com.skobbler.ngx.SKMaps;
import com.skobbler.ngx.SKMapsInitSettings;
import com.skobbler.ngx.SKPrepareMapTextureListener;
import com.skobbler.ngx.SKPrepareMapTextureThread;
import com.skobbler.ngx.map.SKMapViewStyle;
import com.skobbler.ngx.navigation.SKAdvisorSettings;
import com.skobbler.ngx.util.SKLogging;
import com.skobbler.ngx.versioning.SKMapUpdateListener;
import com.skobbler.ngx.versioning.SKVersioningManager;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MainActivity extends AppCompatActivity implements SKPrepareMapTextureListener{
private final static String TAG = "MainActivity";
private String mapResourcesDirPath = "";
public static final long KILO = 1024;
public static final long MEGA = KILO * KILO;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String applicationPath = chooseStoragePath(this);
mapResourcesDirPath = applicationPath + "/" + "SKMaps/";
new SKPrepareMapTextureThread(this, mapResourcesDirPath, "SKMaps.zip", this).start();
if (initializeLibrary(this)) {
finish();
startActivity(new Intent(this, MapActivity.class));
}
}
private boolean initializeLibrary(final Activity context) {
SKLogging.enableLogs(true);
SKMapsInitSettings initMapSettings = new SKMapsInitSettings();
initMapSettings.setMapResourcesPaths(mapResourcesDirPath,
new SKMapViewStyle(mapResourcesDirPath + "daystyle/", "daystyle.json"));
final SKAdvisorSettings advisorSettings = initMapSettings.getAdvisorSettings();
advisorSettings.setAdvisorConfigPath(mapResourcesDirPath +"/Advisor");
advisorSettings.setResourcePath(mapResourcesDirPath +"/Advisor/Languages");
advisorSettings.setLanguage(SKAdvisorSettings.SKAdvisorLanguage.LANGUAGE_DE);
advisorSettings.setAdvisorVoice("en");
initMapSettings.setAdvisorSettings(advisorSettings);
try {
SKMaps.getInstance().initializeSKMaps(context, initMapSettings);
return true;
}catch (SKDeveloperKeyException exception){
exception.printStackTrace();
return false;
}
}
public static String chooseStoragePath(Context context) {
if (getAvailableMemorySize(Environment.getDataDirectory().getPath()) >= 50 * MEGA) {
if (context != null && context.getFilesDir() != null) {
return context.getFilesDir().getPath();
}
} else {
if ((context != null) && (context.getExternalFilesDir(null) != null)) {
if (getAvailableMemorySize(context.getExternalFilesDir(null).toString()) >= 50 * MEGA) {
return context.getExternalFilesDir(null).toString();
}
}
}
SKLogging.writeLog(TAG, "There is not enough memory on any storage, but return internal memory",
SKLogging.LOG_DEBUG);
if (context != null && context.getFilesDir() != null) {
return context.getFilesDir().getPath();
} else {
if ((context != null) && (context.getExternalFilesDir(null) != null)) {
return context.getExternalFilesDir(null).toString();
} else {
return null;
}
}
}
public static long getAvailableMemorySize(String path) {
StatFs statFs = null;
try {
statFs = new StatFs(path);
} catch (IllegalArgumentException ex) {
SKLogging.writeLog("SplashActivity", "Exception when creating StatF ; message = " + ex,
SKLogging.LOG_DEBUG);
}
if (statFs != null) {
Method getAvailableBytesMethod = null;
try {
getAvailableBytesMethod = statFs.getClass().getMethod("getAvailableBytes");
} catch (NoSuchMethodException e) {
SKLogging.writeLog(TAG, "Exception at getAvailableMemorySize method = " + e.getMessage(),
SKLogging.LOG_DEBUG);
}
if (getAvailableBytesMethod != null) {
try {
SKLogging.writeLog(TAG, "Using new API for getAvailableMemorySize method !!!", SKLogging.LOG_DEBUG);
return (Long) getAvailableBytesMethod.invoke(statFs);
} catch (IllegalAccessException e) {
return (long) statFs.getAvailableBlocks() * (long) statFs.getBlockSize();
} catch (InvocationTargetException e) {
return (long) statFs.getAvailableBlocks() * (long) statFs.getBlockSize();
}
} else {
return (long) statFs.getAvailableBlocks() * (long) statFs.getBlockSize();
}
} else {
return 0;
}
}
#Override
public void onMapTexturesPrepared(boolean b) {
initializeLibrary(this);
}
}
MapActivity:
package com.example.michi.mapapplication;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.skobbler.ngx.SKCoordinate;
import com.skobbler.ngx.map.SKAnimationSettings;
import com.skobbler.ngx.map.SKAnnotation;
import com.skobbler.ngx.map.SKCalloutView;
import com.skobbler.ngx.map.SKCoordinateRegion;
import com.skobbler.ngx.map.SKMapCustomPOI;
import com.skobbler.ngx.map.SKMapPOI;
import com.skobbler.ngx.map.SKMapSettings;
import com.skobbler.ngx.map.SKMapSurfaceListener;
import com.skobbler.ngx.map.SKMapSurfaceView;
import com.skobbler.ngx.map.SKMapViewHolder;
import com.skobbler.ngx.map.SKPOICluster;
import com.skobbler.ngx.map.SKScreenPoint;
import com.skobbler.ngx.navigation.SKNavigationListener;
import com.skobbler.ngx.navigation.SKNavigationManager;
import com.skobbler.ngx.navigation.SKNavigationSettings;
import com.skobbler.ngx.navigation.SKNavigationState;
import com.skobbler.ngx.poitracker.SKDetectedPOI;
import com.skobbler.ngx.poitracker.SKPOITrackerListener;
import com.skobbler.ngx.poitracker.SKPOITrackerManager;
import com.skobbler.ngx.poitracker.SKTrackablePOI;
import com.skobbler.ngx.poitracker.SKTrackablePOIRule;
import com.skobbler.ngx.poitracker.SKTrackablePOIType;
import com.skobbler.ngx.routing.SKRouteInfo;
import com.skobbler.ngx.routing.SKRouteJsonAnswer;
import com.skobbler.ngx.routing.SKRouteListener;
import com.skobbler.ngx.routing.SKRouteManager;
import com.skobbler.ngx.routing.SKRouteSettings;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import static com.skobbler.ngx.map.SKMapSettings.SKMapDisplayMode.MODE_2D;
import static com.skobbler.ngx.map.SKMapSettings.SKMapDisplayMode.MODE_3D;
public class MapActivity extends AppCompatActivity implements SKMapSurfaceListener, SKRouteListener, SKNavigationListener, SKPOITrackerListener {
public static final double SOURCE_LONGITUDE = 11.5;
public static final double SOURCE_LATITUDE = 48.12;
public static final double DEST_LONGITUDE = 11.5;
public static final double DEST_LATITUDE = 51.12;
private SKNavigationManager navigationManager;
private HashMap<Integer, SKTrackablePOI> trackablePOIs;
private SKPOITrackerManager poiTrackerManager;
protected SKMapSurfaceView mapView;
#Bind(R.id.view_group_map)
protected SKMapViewHolder mapHolder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
ButterKnife.bind(this);
mapHolder.setMapSurfaceListener(this);
}
#Override
protected void onPause() {
super.onPause();
mapHolder.onPause();
}
#Override
protected void onResume() {
super.onResume();
mapHolder.onResume();
}
#Override
public void onActionPan() {}
#Override
public void onActionZoom() { }
#Override
public void onSurfaceCreated(SKMapViewHolder skMapViewHolder) {
mapView = mapHolder.getMapSurfaceView();
mapView.centerMapOnPosition(new SKCoordinate(11.5, 48.12));
launchRouteCalculation();
}
#Override
public void onMapRegionChanged(SKCoordinateRegion skCoordinateRegion) {
mapView.getMapSettings().setFollowerMode(SKMapSettings.SKMapFollowerMode.NONE);
final SKCalloutView mapPopup = mapHolder.getCalloutView();
mapPopup.setTitle("Fortsetzen").setVisibility(View.VISIBLE);
mapPopup.setViewColor(Color.argb(255, 200, 200, 255));
mapPopup.setOnLeftImageClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MapActivity.this, "Left image clicked", Toast.LENGTH_SHORT).show();
mapView.getMapSettings().setFollowerMode(SKMapSettings.SKMapFollowerMode.NAVIGATION);
mapPopup.setVisibility(View.GONE);
}
});
mapPopup.showAtLocation(new SKCoordinate(23.56, 46.77), true);
}
#Override
public void onMapRegionChangeStarted(SKCoordinateRegion skCoordinateRegion) {}
#Override
public void onMapRegionChangeEnded(SKCoordinateRegion skCoordinateRegion) {}
#Override
public void onDoubleTap(SKScreenPoint skScreenPoint) {}
#Override
public void onSingleTap(SKScreenPoint skScreenPoint) {}
#Override
public void onRotateMap() {}
#Override
public void onLongPress(SKScreenPoint skScreenPoint) {}
#Override
public void onInternetConnectionNeeded() {}
#Override
public void onMapActionDown(SKScreenPoint skScreenPoint) {}
#Override
public void onMapActionUp(SKScreenPoint skScreenPoint) {}
#Override
public void onPOIClusterSelected(SKPOICluster skpoiCluster) {}
#Override
public void onMapPOISelected(SKMapPOI skMapPOI) {}
#Override
public void onAnnotationSelected(SKAnnotation skAnnotation) {
}
#Override
public void onCustomPOISelected(SKMapCustomPOI skMapCustomPOI) {}
#Override
public void onCompassSelected() {
}
#Override
public void onCurrentPositionSelected() {}
#Override
public void onObjectSelected(int i) {}
#Override
public void onInternationalisationCalled(int i) {}
#Override
public void onDebugInfo(double v, float v1, double v2) { }
#Override
public void onBoundingBoxImageRendered(int i) {}
#Override
public void onGLInitializationError(String s) {}
private void launchRouteCalculation() {
SKRouteSettings route = new SKRouteSettings();
route.setStartCoordinate(new SKCoordinate(SOURCE_LONGITUDE, SOURCE_LATITUDE));
route.setDestinationCoordinate(new SKCoordinate(DEST_LONGITUDE, DEST_LATITUDE));
route.setNoOfRoutes(1);
route.setRouteMode(SKRouteSettings.SKRouteMode.CAR_FASTEST);
route.setRouteExposed(true);
SKRouteManager.getInstance().setRouteListener(this);
SKRouteManager.getInstance().calculateRoute(route);
}
#Override
public void onRouteCalculationCompleted(SKRouteInfo skRouteInfo) {}
#Override
public void onRouteCalculationFailed(SKRoutingErrorCode skRoutingErrorCode) {}
#Override
public void onAllRoutesCompleted() {
SKNavigationSettings navigationSettings = new SKNavigationSettings();
navigationSettings.setNavigationType(SKNavigationSettings.SKNavigationType.SIMULATION);
navigationManager = SKNavigationManager.getInstance();
navigationManager.setMapView(mapView);
navigationManager.setNavigationListener(this);
navigationManager.startNavigation(navigationSettings);
initTrackablePOIs();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
startPOITracking();
}
private void initTrackablePOIs() {
Log.w(getClass().getName(), "initTrackablePOIs(): ");
trackablePOIs = new HashMap<Integer, SKTrackablePOI>();
initOnlySomePOIs();
int i = 0;
double longitude, latitude;
for (double d = 0; d < 1; d+= 0.01) {
longitude = SOURCE_LONGITUDE + d * (DEST_LONGITUDE - SOURCE_LONGITUDE);
latitude = SOURCE_LATITUDE + d * (DEST_LATITUDE - SOURCE_LATITUDE);
trackablePOIs.put(i, new SKTrackablePOI(i, 1, longitude, latitude, -1, "STREET_NAME " + i));
SKAnnotation skAnnotation = new SKAnnotation(64000 + i);
skAnnotation.setAnnotationType(SKAnnotation.SK_ANNOTATION_TYPE_MARKER);
skAnnotation.setLocation(new SKCoordinate(longitude, latitude));
mapView.addAnnotation(skAnnotation, SKAnimationSettings.ANIMATION_PIN_DROP);
i++;
}
}
private void initOnlySomePOIs() {
double longitude, latitude;
longitude = SOURCE_LONGITUDE + 0.001;
latitude = SOURCE_LATITUDE + 0.001;
trackablePOIs.put(101, new SKTrackablePOI(101, 1, longitude, latitude, -1, "STREET_NAME 101"));
SKAnnotation skAnnotation1 = new SKAnnotation(101);
skAnnotation1.setAnnotationType(SKAnnotation.SK_ANNOTATION_TYPE_MARKER);
skAnnotation1.setLocation(new SKCoordinate(longitude, latitude));
mapView.addAnnotation(skAnnotation1, SKAnimationSettings.ANIMATION_PIN_DROP);
longitude = SOURCE_LONGITUDE + 0.001;
latitude = SOURCE_LATITUDE - 0.001;
trackablePOIs.put(102, new SKTrackablePOI(102, 1, longitude, latitude, -1, "STREET_NAME 102"));
SKAnnotation skAnnotation2 = new SKAnnotation(102);
skAnnotation2.setAnnotationType(SKAnnotation.SK_ANNOTATION_TYPE_MARKER);
skAnnotation2.setLocation(new SKCoordinate(longitude, latitude));
mapView.addAnnotation(skAnnotation2, SKAnimationSettings.ANIMATION_PIN_DROP);
longitude = SOURCE_LONGITUDE - 0.001;
latitude = SOURCE_LATITUDE + 0.001;
trackablePOIs.put(103, new SKTrackablePOI(103, 1, longitude, latitude, -1, "STREET_NAME 103"));
SKAnnotation skAnnotation3 = new SKAnnotation(103);
skAnnotation3.setAnnotationType(SKAnnotation.SK_ANNOTATION_TYPE_MARKER);
skAnnotation3.setLocation(new SKCoordinate(longitude, latitude));
mapView.addAnnotation(skAnnotation3, SKAnimationSettings.ANIMATION_PIN_DROP);
longitude = SOURCE_LONGITUDE - 0.001;
latitude = SOURCE_LATITUDE - 0.001;
trackablePOIs.put(104, new SKTrackablePOI(104, 1, longitude, latitude, -1, "STREET_NAME 104"));
SKAnnotation skAnnotation4 = new SKAnnotation(104);
skAnnotation4.setAnnotationType(SKAnnotation.SK_ANNOTATION_TYPE_MARKER);
skAnnotation4.setLocation(new SKCoordinate(longitude, latitude));
mapView.addAnnotation(skAnnotation4, SKAnimationSettings.ANIMATION_PIN_DROP);
longitude = SOURCE_LONGITUDE + 0.002;
latitude = SOURCE_LATITUDE + 0.002;
trackablePOIs.put(105, new SKTrackablePOI(105, 105, longitude, latitude, -1, "STREET_NAME 105"));
SKAnnotation skAnnotation5 = new SKAnnotation(105);
skAnnotation5.setAnnotationType(SKAnnotation.SK_ANNOTATION_TYPE_MARKER);
skAnnotation5.setLocation(new SKCoordinate(longitude, latitude));
mapView.addAnnotation(skAnnotation5, SKAnimationSettings.ANIMATION_PIN_DROP);
longitude = SOURCE_LONGITUDE + 0.002;
latitude = SOURCE_LATITUDE - 0.002;
trackablePOIs.put(106, new SKTrackablePOI(106, 1, longitude, latitude, -1, "STREET_NAME 106"));
SKAnnotation skAnnotation6 = new SKAnnotation(106);
skAnnotation6.setAnnotationType(SKAnnotation.SK_ANNOTATION_TYPE_MARKER);
skAnnotation6.setLocation(new SKCoordinate(longitude, latitude));
mapView.addAnnotation(skAnnotation6, SKAnimationSettings.ANIMATION_PIN_DROP);
longitude = SOURCE_LONGITUDE - 0.002;
latitude = SOURCE_LATITUDE + 0.002;
trackablePOIs.put(107, new SKTrackablePOI(107, 1, longitude, latitude, -1, "STREET_NAME 107"));
SKAnnotation skAnnotation7 = new SKAnnotation(107);
skAnnotation7.setAnnotationType(SKAnnotation.SK_ANNOTATION_TYPE_MARKER);
skAnnotation7.setLocation(new SKCoordinate(longitude, latitude));
mapView.addAnnotation(skAnnotation7, SKAnimationSettings.ANIMATION_PIN_DROP);
longitude = SOURCE_LONGITUDE - 0.001;
latitude = SOURCE_LATITUDE - 0.001;
trackablePOIs.put(108, new SKTrackablePOI(108, 1, longitude, latitude, -1, "STREET_NAME 108"));
SKAnnotation skAnnotation8 = new SKAnnotation(108);
skAnnotation8.setAnnotationType(SKAnnotation.SK_ANNOTATION_TYPE_MARKER);
skAnnotation8.setLocation(new SKCoordinate(longitude, latitude));
mapView.addAnnotation(skAnnotation8, SKAnimationSettings.ANIMATION_PIN_DROP);
longitude = 9.767972;
latitude = 52.378958;
trackablePOIs.put(109, new SKTrackablePOI(109, 1, longitude, latitude, -1, "STREET_NAME 109"));
SKAnnotation skAnnotation9 = new SKAnnotation(109);
skAnnotation9.setAnnotationType(SKAnnotation.SK_ANNOTATION_TYPE_MARKER);
skAnnotation9.setLocation(new SKCoordinate(longitude, latitude));
mapView.addAnnotation(skAnnotation9, SKAnimationSettings.ANIMATION_PIN_DROP);
}
private void startPOITracking() {
SKTrackablePOIRule rule = new SKTrackablePOIRule();
rule.setAerialDistance(5000); // this would be our main constraint, stating that all the POIs with 5000m, aerial distance should be detected
rule.setNumberOfTurns(100); // this has to be increased – otherwise some points will be disconsidered
rule.setRouteDistance(10000);//this has to be increased as the real road route will be longer than the aerial distance
rule.setMinSpeedIgnoreDistanceAfterTurn(20); //decrease this to evaluate all candidates
rule.setMaxDistanceAfterTurn(10000); //increase this to make sure we don't exclude any candidates
rule.setEliminateIfUTurn(false); // setting this to true (default) excludes points that require us to make an U-turn to get to them
rule.setPlayAudioWarning(false);
poiTrackerManager = new SKPOITrackerManager(this);
poiTrackerManager.startPOITrackerWithRadius(1500, 0.5);
poiTrackerManager.setRuleForPOIType(SKTrackablePOIType.SPEEDCAM, rule);
}
#Override
public void onServerLikeRouteCalculationCompleted(SKRouteJsonAnswer skRouteJsonAnswer) {}
#Override
public void onOnlineRouteComputationHanging(int i) {}
#Override
public void onDestinationReached() {}
#Override
public void onSignalNewAdviceWithInstruction(String s) {}
#Override
public void onSignalNewAdviceWithAudioFiles(String[] strings, boolean b) {}
#Override
public void onSpeedExceededWithAudioFiles(String[] strings, boolean b) {}
#Override
public void onSpeedExceededWithInstruction(String s, boolean b) {}
#Override
public void onUpdateNavigationState(SKNavigationState skNavigationState) { Log.v(getClass().getName(), "onUpdateNavigationState: " + skNavigationState.toString());}
#Override
public void onReRoutingStarted() {}
#Override
public void onFreeDriveUpdated(String s, String s1, SKNavigationState.SKStreetType skStreetType, double v, double v1) {}
#Override
public void onViaPointReached(int i) {}
#Override
public void onVisualAdviceChanged(boolean b, boolean b1, SKNavigationState skNavigationState) {}
#Override
public void onTunnelEvent(boolean b) {}
#Override
public void onFcdTripStarted(String s) {}
#Override
public void onUpdatePOIsInRadius(double latitude, double longitude, int radius) {
Log.i(getClass().getName(), "onUpdatePOIsInRadius(): ");
// set the POIs to be tracked by the POI tracker
for (SKTrackablePOI skTrackablePOI : trackablePOIs.values()) {
Log.i(getClass().getName(), "onUpdatePOIsInRadius() skTrackablePOI: " + skTrackablePOI);
}
poiTrackerManager.setTrackedPOIs(SKTrackablePOIType.SPEEDCAM, new ArrayList<SKTrackablePOI>(trackablePOIs.values()));
}
#Override
public void onReceivedPOIs(SKTrackablePOIType type, List<SKDetectedPOI> detectedPois) {
Log.i(getClass().getName(), "onReceivedPOIs() detectedPois.size(): " + detectedPois.size());
if (detectedPois.size() == 1 && detectedPois.get(0).getPoiID() == -1) {
return;
}
for (SKDetectedPOI skDetectedPOI : detectedPois) {
Log.i(getClass().getName(), "onReceivedPOIs() skDetectedPOI: " + skDetectedPOI);
SKAnnotation skAnnotation = new SKAnnotation(skDetectedPOI.getPoiID());
skAnnotation.setAnnotationType(SKAnnotation.SK_ANNOTATION_TYPE_GREEN);
skAnnotation.setLocation(trackablePOIs.get(skDetectedPOI.getPoiID()).getCoordinate());
mapView.addAnnotation(skAnnotation, SKAnimationSettings.ANIMATION_PIN_DROP);
}
}
}
I don't know why the tracker isn't working. :(
The rules are OK.
You'll need to modify your logic to something similar to the demo project:
(the following code is to be added in the demo project, MapActivity.java, the onAllRoutesCompleted callback, the currentMapOption == MapOption.POI_TRACKING branch)
poiTrackingManager.startPOITrackerWithRadius(10000, 0.5);
// set warning rules for trackable POIs
// SKTrackablePOIType myType =SKTrackablePOIType.forInt(1000);
SKTrackablePOIRule rule = new SKTrackablePOIRule();
rule.setAerialDistance(5000); // this would be our main constraint, stating that all the POIs with 5000m, aerial distance should be detected
rule.setNumberOfTurns(100); // this has to be increased – otherwise some points will be disconsidered
rule.setRouteDistance(10000);//this has to be increased as the real road route will be longer than the aerial distance
rule.setMinSpeedIgnoreDistanceAfterTurn(20); //decrease this to evaluate all candidates
rule.setMaxDistanceAfterTurn(10000); //increase this to make sure we don't exclude any candidates
rule.setEliminateIfUTurn(false); // setting this to true (default) excludes points that require us to make an U-turn to get to them
rule.setPlayAudioWarning(false);
poiTrackingManager.setRuleForPOIType(SKTrackablePOIType.SPEEDCAM, rule);
launchNavigation();
In onUpdatePOIsInRadius you have to make the "refreshed" POI list available to the tracker. This callback will be triggered by the tracker once the refreshMargin condition is reached.
#Override
public void onUpdatePOIsInRadius(double latitude, double longitude, int radius) {
// set the POIs to be tracked by the POI tracker
// SKTrackablePOIType myType =SKTrackablePOIType.forInt(1000);
poiTrackingManager.setTrackedPOIs(SKTrackablePOIType.SPEEDCAM,
new ArrayList<SKTrackablePOI>(trackablePOIs.values()));
}
In onReceivedPOIs you'll get information about the POIs that were detected:
public void onReceivedPOIs(SKTrackablePOIType type, List<SKDetectedPOI> detectedPois) {
//add code here to handle the detected POIs
}
I've edited the vanilla demo project with the above code (with the default definition of points to track) and I get lots of notifications.
Depending on the "density" of your tracked POIs, you might want to reduce the refreshMargin (and trigger POI set updates more often) - i.e. poiTrackerManager.startPOITrackerWithRadius(5000, 0.1);
Also see http://sdkblog.skobbler.com/detecting-tracking-pois-in-your-way/ for more insights into the POI tracking functionality
Related
I am trying to add markers clustering feature in my android based app and I'm using this example:
https://github.com/mapbox/mapbox-android-demo/blob/master/MapboxAndroidDemo/src/main/java/com/mapbox/mapboxandroiddemo/examples/dds/CircleLayerClusteringActivity.java
but I am unable to implement it properly.
Here is my code and the main logic of clustering is in "setUpMarkerLayersClustered" function:
package com.tripmate.travelguidePakistan;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PointF;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import com.google.gson.Gson;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.annotations.BubbleLayout;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonOptions;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import org.json.JSONObject;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import static android.graphics.Color.rgb;
import static com.mapbox.mapboxsdk.style.expressions.Expression.all;
import static com.mapbox.mapboxsdk.style.expressions.Expression.division;
import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
import static com.mapbox.mapboxsdk.style.expressions.Expression.gt;
import static com.mapbox.mapboxsdk.style.expressions.Expression.gte;
import static com.mapbox.mapboxsdk.style.expressions.Expression.has;
import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
import static com.mapbox.mapboxsdk.style.expressions.Expression.lt;
import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
import static com.mapbox.mapboxsdk.style.expressions.Expression.toNumber;
import static com.mapbox.mapboxsdk.style.layers.Property.ICON_ANCHOR_BOTTOM;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAnchor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOffset;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textIgnorePlacement;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textSize;
/**
* Use a SymbolLayer to show a BubbleLayout above a SymbolLayer icon. This is a more performant
* way to show the BubbleLayout that appears when using the MapboxMap.addMarker() method.
*/
public class InfoWindowSymbolLayerActivity extends AppCompatActivity implements
OnMapReadyCallback, MapboxMap.OnMapClickListener {
private static final String GEOJSON_SOURCE_ID = "GEOJSON_SOURCE_ID";
private static final String MARKER_IMAGE_ID = "MARKER_IMAGE_ID";
private static final String MARKER_LAYER_ID_UNCLUSTERED = "MARKER_LAYER_ID_UNCLUSTERED";
private static final String MARKER_LAYER_ID_CLUSTERED = "MARKER_LAYER_ID_CLUSTERED";
private static final String CALLOUT_LAYER_ID = "CALLOUT_LAYER_ID";
private static final String PROPERTY_SELECTED = "selected";
private static final String PROPERTY_NAME = "name";
private static final String PROPERTY_CAPITAL = "capital";
private MapView mapView;
private MapboxMap mapboxMap;
private GeoJsonSource source;
private FeatureCollection featureCollection;
private LatLng baseLocation;
private ArrayList attractionsDataList;
private static List<Feature> markerCoordinates = new ArrayList<>();
private String attractionType;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Mapbox access token is configured here. This needs to be called either in your application
// object or in the same activity which contains the mapview.
Mapbox.getInstance(this, getString(R.string.MAPBOX_ACCESS_KEY));
// This contains the MapView in XML and needs to be called after the access token is configured.
setContentView(R.layout.activity_info_window_symbol_layer);
attractionsDataList = MainActivity.getArrayList();
attractionType = MainActivity.getAttractionType();
// Initialize the map view
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
}
#Override
public void onMapReady(#NonNull final MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull Style style) {
createListOfFeatures();
loadGeoJsonData();
//new LoadGeoJsonDataTask(InfoWindowSymbolLayerActivity.this).execute();
//addClusteredGeoJsonSource(style);
mapboxMap.addOnMapClickListener(InfoWindowSymbolLayerActivity.this);
//Set Camera to base location
int cameraZoom = 7;
int cameraBearing = 0;
int cameraTilt = 10;
CameraPosition position = new CameraPosition.Builder()
.target(baseLocation) // Sets the new camera position
.zoom(cameraZoom) // Sets the zoom
.bearing(cameraBearing) // Rotate the camera
.tilt(cameraTilt) // Set the camera tilt
.build(); // Creates a CameraPosition from the builder
//Animate the camera towards base Location
mapboxMap.animateCamera(CameraUpdateFactory
.newCameraPosition(position), 2000);
}
});
}
#Override
public boolean onMapClick(#NonNull LatLng point) {
return handleClickIcon(mapboxMap.getProjection().toScreenLocation(point));
}
/**
* Sets up all of the sources and layers needed for this example
*
* #param collection the FeatureCollection to set equal to the globally-declared FeatureCollection
*/
public void setUpData(final FeatureCollection collection) {
featureCollection = collection;
if (mapboxMap != null) {
Style style = mapboxMap.getStyle();
if (style != null) {
setupSource(style);
setUpImage(style);
setUpMarkerLayerUnclustered(style);
setUpMarkerLayersClustered(style);
setUpInfoWindowLayer(style);
}
}
}
/**
* Adds the GeoJSON source to the map
*/
private void setupSource(#NonNull Style loadedStyle) {
source = new GeoJsonSource(GEOJSON_SOURCE_ID, featureCollection,
new GeoJsonOptions()
.withCluster(true)
.withClusterMaxZoom(14)
.withClusterRadius(50));
loadedStyle.addSource(source);
//Log.d("debug", "#setupSource: Source: " + source.toString());
}
/**
* Adds the marker image to the map for use as a SymbolLayer icon
*/
private void setUpImage(#NonNull Style loadedStyle) {
Log.d("debug", "#setUpImage: Called");
switch (attractionType) {
case "Banks":
Log.d("debug", "#setUpImage: Bank Tile");
loadedStyle.addImage(MARKER_IMAGE_ID, BitmapFactory.decodeResource(
this.getResources(), R.drawable.banks));
break;
case "Gas Stations":
loadedStyle.addImage(MARKER_IMAGE_ID, BitmapFactory.decodeResource(
this.getResources(), R.drawable.gas_stations));
break;
case "Hotels":
loadedStyle.addImage(MARKER_IMAGE_ID, BitmapFactory.decodeResource(
this.getResources(), R.drawable.hotels));
break;
case "Mobile Wallets":
loadedStyle.addImage(MARKER_IMAGE_ID, BitmapFactory.decodeResource(
this.getResources(), R.drawable.mobile_wallets));
break;
case "Rental Services":
loadedStyle.addImage(MARKER_IMAGE_ID, BitmapFactory.decodeResource(
this.getResources(), R.drawable.rental_services));
break;
case "Restaurants":
loadedStyle.addImage(MARKER_IMAGE_ID, BitmapFactory.decodeResource(
this.getResources(), R.drawable.resturants));
break;
case "Shopping Marts":
loadedStyle.addImage(MARKER_IMAGE_ID, BitmapFactory.decodeResource(
this.getResources(), R.drawable.shopping_marts));
break;
case "Workshops":
loadedStyle.addImage(MARKER_IMAGE_ID, BitmapFactory.decodeResource(
this.getResources(), R.drawable.workshops));
break;
case "Attraction Points":
loadedStyle.addImage(MARKER_IMAGE_ID, BitmapFactory.decodeResource(
this.getResources(), R.drawable.attraction_point));
break;
default:
Log.d("debug", "Match couldn't found");
break;
}
}
/**
* Updates the display of data on the map after the FeatureCollection has been modified
*/
private void refreshSource() {
if (source != null && featureCollection != null) {
source.setGeoJson(featureCollection);
}
}
/**
* Setup a layer with maki icons, eg. west coast city.
*/
private void setUpMarkerLayerUnclustered(#NonNull Style loadedStyle) {
Log.d("debug", "#setUpMarkerLayerUnclustered: Called");
loadedStyle.addLayer(new SymbolLayer(MARKER_LAYER_ID_UNCLUSTERED, GEOJSON_SOURCE_ID)
.withProperties(
iconImage(MARKER_IMAGE_ID),
iconAllowOverlap(true)
));
}
private void setUpMarkerLayersClustered(#NonNull Style loadedStyle) {
Log.d("debug", "#setUpMarkerLayersClustered: Called");
// Use the earthquakes GeoJSON source to create three layers: One layer for each cluster category.
// Each point range gets a different fill color.
int[][] layers = new int[][] {
new int[] {150, ContextCompat.getColor(this, R.color.mapboxRed)},
new int[] {20, ContextCompat.getColor(this, R.color.mapboxGreen)},
new int[] {0, ContextCompat.getColor(this, R.color.mapbox_blue)}
};
for (int i = 0; i < layers.length; i++) {
//Add clusters' circles
CircleLayer circles = new CircleLayer("cluster-" + i, "earthquakes");
circles.setProperties(
circleColor(layers[i][1]),
circleRadius(18f)
);
Expression pointCount = toNumber(get("point_count"));
// Add a filter to the cluster layer that hides the circles based on "point_count"
circles.setFilter(
i == 0
? all(has("point_count"),
gte(pointCount, literal(layers[i][0]))
) : all(has("point_count"),
gt(pointCount, literal(layers[i][0])),
lt(pointCount, literal(layers[i - 1][0]))
)
);
loadedStyle.addLayer(circles);
}
//Add the count labels
Log.d("debug", "#setUpMarkerLayersClustered: Adding counts label");
SymbolLayer count = new SymbolLayer("count", "earthquakes");
count.setProperties(
textField(Expression.toString(get("point_count"))),
textSize(12f),
textColor(Color.WHITE),
textIgnorePlacement(true),
textAllowOverlap(true)
);
loadedStyle.addLayer(count);
}
/**
* Setup a layer with Android SDK call-outs
* <p>
* name of the feature is used as key for the iconImage
* </p>
*/
private void setUpInfoWindowLayer(#NonNull Style loadedStyle) {
loadedStyle.addLayer(new SymbolLayer(CALLOUT_LAYER_ID, GEOJSON_SOURCE_ID)
.withProperties(
/* show image with id title based on the value of the name feature property */
iconImage("{name}"),
/* set anchor of icon to bottom-left */
iconAnchor(ICON_ANCHOR_BOTTOM),
/* all info window and marker image to appear at the same time*/
iconAllowOverlap(true),
/* offset the info window to be above the marker */
iconOffset(new Float[]{-2f, -25f})
)
/* add a filter to show only when selected feature property is true */
.withFilter(eq((get(PROPERTY_SELECTED)), literal(true))));
}
/**
* This method handles click events for SymbolLayer symbols.
* <p>
* When a SymbolLayer icon is clicked, we moved that feature to the selected state.
* </p>
*
* #param screenPoint the point on screen clicked
*/
private boolean handleClickIcon(PointF screenPoint) {
List<Feature> features = mapboxMap.queryRenderedFeatures(screenPoint, MARKER_LAYER_ID_UNCLUSTERED);
if (!features.isEmpty()) {
String name = features.get(0).getStringProperty(PROPERTY_NAME);
List<Feature> featureList = featureCollection.features();
for (int i = 0; i < featureList.size(); i++) {
if (featureList.get(i).getStringProperty(PROPERTY_NAME).equals(name)) {
if (featureSelectStatus(i)) {
setFeatureSelectState(featureList.get(i), false);
} else {
setSelected(i);
}
}
}
return true;
} else {
return false;
}
}
/**
* Set a feature selected state.
*
* #param index the index of selected feature
*/
private void setSelected(int index) {
Feature feature = featureCollection.features().get(index);
setFeatureSelectState(feature, true);
refreshSource();
}
/**
* Selects the state of a feature
*
* #param feature the feature to be selected.
*/
private void setFeatureSelectState(Feature feature, boolean selectedState) {
feature.properties().addProperty(PROPERTY_SELECTED, selectedState);
refreshSource();
}
/**
* Checks whether a Feature's boolean "selected" property is true or false
*
* #param index the specific Feature's index position in the FeatureCollection's list of Features.
* #return true if "selected" is true. False if the boolean property is false.
*/
private boolean featureSelectStatus(int index) {
if (featureCollection == null) {
return false;
}
return featureCollection.features().get(index).getBooleanProperty(PROPERTY_SELECTED);
}
/**
* Invoked when the bitmaps have been generated from a view.
*/
public void setImageGenResults(HashMap<String, Bitmap> imageMap) {
if (mapboxMap != null) {
Style style = mapboxMap.getStyle();
if (style != null) {
// calling addImages is faster as separate addImage calls for each bitmap.
style.addImages(imageMap);
}
}
}
private void loadGeoJsonData(){
featureCollection = FeatureCollection.fromFeatures(markerCoordinates);
if(featureCollection != null){
for (Feature singleFeature : featureCollection.features()) {
singleFeature.addBooleanProperty(PROPERTY_SELECTED, false);
}
setUpData(featureCollection);
new GenerateViewIconTask(InfoWindowSymbolLayerActivity.this).execute(featureCollection);
}else {
Log.d("debug", "FeatureCollection is null");
return;
}
}
/**
* AsyncTask to generate Bitmap from Views to be used as iconImage in a SymbolLayer.
* <p>
* Call be optionally be called to update the underlying data source after execution.
* </p>
* <p>
* Generating Views on background thread since we are not going to be adding them to the view hierarchy.
* </p>
*/
private static class GenerateViewIconTask extends AsyncTask<FeatureCollection, Void, HashMap<String, Bitmap>> {
private final HashMap<String, View> viewMap = new HashMap<>();
private final WeakReference<InfoWindowSymbolLayerActivity> activityRef;
private final boolean refreshSource;
GenerateViewIconTask(InfoWindowSymbolLayerActivity activity, boolean refreshSource) {
this.activityRef = new WeakReference<>(activity);
this.refreshSource = refreshSource;
}
GenerateViewIconTask(InfoWindowSymbolLayerActivity activity) {
this(activity, false);
}
#SuppressWarnings("WrongThread")
#Override
protected HashMap<String, Bitmap> doInBackground(FeatureCollection... params) {
InfoWindowSymbolLayerActivity activity = activityRef.get();
if (activity != null) {
HashMap<String, Bitmap> imagesMap = new HashMap<>();
LayoutInflater inflater = LayoutInflater.from(activity);
FeatureCollection featureCollection = params[0];
Log.d("debug", "#doInBackground: Called for setting data on symbolLayerInfo");
for (Feature feature : featureCollection.features()) {
try {
BubbleLayout bubbleLayout = (BubbleLayout)
inflater.inflate(R.layout.symbol_layer_info_window_layout_callout, null);
if (feature != null) {
Log.d("debug", "#doInBackground: Feature: " + feature.toString());
} else {
Log.d("debug", "#doInBackground: Feature is null");
}
String name = feature.getStringProperty(PROPERTY_NAME);
TextView titleTextView = bubbleLayout.findViewById(R.id.info_window_title);
titleTextView.setText(name);
//String style = feature.getStringProperty(PROPERTY_CAPITAL);
TextView descriptionTextView = bubbleLayout.findViewById(R.id.info_window_description);
descriptionTextView.setText("Capital");
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
bubbleLayout.measure(measureSpec, measureSpec);
int measuredWidth = bubbleLayout.getMeasuredWidth();
bubbleLayout.setArrowPosition(measuredWidth / 2 - 5);
Bitmap bitmap = SymbolGenerator.generate(bubbleLayout);
imagesMap.put(name, bitmap);
viewMap.put(name, bubbleLayout);
} catch (Exception e) {
Log.d("debug", "#doInBackground: Exception: " + e.getMessage());
}
}
return imagesMap;
} else {
return null;
}
}
#Override
protected void onPostExecute(HashMap<String, Bitmap> bitmapHashMap) {
super.onPostExecute(bitmapHashMap);
InfoWindowSymbolLayerActivity activity = activityRef.get();
if (activity != null && bitmapHashMap != null) {
activity.setImageGenResults(bitmapHashMap);
if (refreshSource) {
activity.refreshSource();
}
}
//Toast.makeText(activity,"text", Toast.LENGTH_SHORT).show();
}
}
/**
* Utility class to generate Bitmaps for Symbol.
*/
private static class SymbolGenerator {
/**
* Generate a Bitmap from an Android SDK View.
*
* #param view the View to be drawn to a Bitmap
* #return the generated bitmap
*/
static Bitmap generate(#NonNull View view) {
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(measureSpec, measureSpec);
int measuredWidth = view.getMeasuredWidth();
int measuredHeight = view.getMeasuredHeight();
view.layout(0, 0, measuredWidth, measuredHeight);
Bitmap bitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);
bitmap.eraseColor(Color.TRANSPARENT);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
}
#Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
#Override
public void onResume() {
super.onResume();
mapView.onResume();
}
#Override
public void onPause() {
super.onPause();
mapView.onPause();
}
#Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
#Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mapboxMap != null) {
mapboxMap.removeOnMapClickListener(this);
}
markerCoordinates.clear();
mapView.onDestroy();
}
private void createListOfFeatures() {
Log.d("debug", "#createListOfFeatures: Called");
Gson gson = new Gson();
String jsonString;
String name;
double lat = 30.375320;
double lng = 69.345116;
Iterator iterator = attractionsDataList.iterator();
//Building list of Markers co-ordinates to be placed on map
while (iterator.hasNext()) {
jsonString = gson.toJson(iterator.next());
try {
JSONObject jsonObject = new JSONObject(jsonString);
//Getting data from jsonObject
name = jsonObject.getString("name");
lat = jsonObject.getJSONObject("Location").getDouble("latitude");
lng = jsonObject.getJSONObject("Location").getDouble("longitude");
//attractionType = jsonObject.getString("class");
//Creating feature from data extracted form jsonObject
Feature feature = Feature.fromGeometry(Point.fromLngLat(lng, lat));
feature.addStringProperty(PROPERTY_NAME, name);
feature.addBooleanProperty(PROPERTY_SELECTED, false);
//Adding feature to the list of Features
markerCoordinates.add(feature);
Log.d("debug", "#createListOfFeatures:" + feature.toString());
} catch (Exception e) {
Log.d("debug", "#createListOfFeatures: Exception: " + e.getMessage());
}
}
//Setting base location
baseLocation = new LatLng(lat, lng);
Log.d("debug", "#createListOfFeatures: attractionType: " + attractionType);
}
}
The expected result is :
The actual result is :
with the following logs:
can't find source for layer 'cluster-0'
can't find source for layer 'cluster-1'
can't find source for layer 'cluster-3'
The logs are telling you that the source of those CircleLayers you are creating does not exist. Check whether earthquakes is a GeoJsonSource and it has been initialized.
Eventually you can add circles.setSourceLayer("NAME_OF_THE_SOURCE") after CircleLayer circles = new CircleLayer("cluster-" + i, "earthquakes");, where "NAME_OF_THE_SOURCE" is the name of your source layer.
Address Dailoge This is an Fragment when I click on image another activity (Location Activity)start in which Google map open.
Here is code of Address Dailoge fragment
when map open i want show the Current Location of user and user select the location from map using map picker
when user select the Location i want to take the Addresses of the street zipcode,state,country set it to the form.
public class AddressDialog extends DialogFragment {
public interface AddressListener {
void address(Address address);
void editedAddress(Address locationModel, int index);
}
private static final String TAG = "AddressDialog";
#BindView(R.id.addresslineone)
FormAnimationView addresslineone;
private GoogleApiClient mClient;
#BindView(R.id.addresslinetwo)
FormAnimationView addresslinetwo;
#BindView(R.id.city)
FormAnimationView cityView;
#BindView(R.id.state)
FormAnimationView stateView;
#BindView(R.id.country)
FormAnimationView countryView;
private boolean isfromEdit;
#BindView(R.id.pincode)
FormAnimationView pincode;
#BindView(R.id.edit_spinner_1)
EditSpinner mEditSpinner1;
private Address address = new Address();
private AddressListener addressListener;
private int index;
#OnClick(R.id.closedialog)
public void closeClick() {
this.dismiss();
}
#BindView(R.id.searchmap)
ImageView openmap;
#OnClick(R.id.searchmap)
public void searchmapclick() {
startActivityForResult(new Intent(getActivity(), LocationActivity.class), 100);
}
#OnClick(R.id.addaddressimg)
public void addClick() {
if (addressListener != null && address != null) {
if (!TextUtils.isEmpty(mEditSpinner1.getText()) &&
!TextUtils.isEmpty(addresslineone.getText())
&& !TextUtils.isEmpty(addresslinetwo.getText())
&& !TextUtils.isEmpty(cityView.getText())
&& !TextUtils.isEmpty(stateView.getText())
&& !TextUtils.isEmpty(pincode.getText())
&& !TextUtils.isEmpty(countryView.getText())) {
//locationModel.setAddressType(mEditSpinner1.getText().toString());
//address.setCountry(addresslinetwo.getText().toString());
// address.setLocality();
//address.setLocality("");
address.setRegion(stateView.getText().toString());
address.setFormatted(addresslineone.getText().toString());
address.setFormatted(addresslinetwo.getText().toString());
address.setCountry(countryView.getText().toString());
address.setLocality(cityView.getText().toString());
// address.setState(stateView.getText().toString());
address.setPostalCode(pincode.getText().toString());
address.setStreetAddress(addresslineone.getText().toString());
address.setStreetAddress(addresslinetwo.getText().toString());
address.setType(mEditSpinner1.getText().toString());
// address.setRegion();
if (!isfromEdit) {
addressListener.address(address);
} else {
addressListener.editedAddress(address, address.getIndex());
}
this.dismiss();
} else {
Toast.makeText(getActivity(), "All fields are mandetory", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onStart() {
super.onStart();
mClient.connect();
}
#Override
public void onStop() {
mClient.disconnect();
super.onStop();
}
// #Override
// public void onAttach(Context context) {
// super.onAttach(context);
// //addressListener = (AddressListener) context;
// }
public void setListener(AddressListener addressListener) {
this.addressListener = addressListener;
}
/* #NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final View view = View.inflate(getActivity(), R.layout.address_selection_view, null);
Dialog dialog = new Dialog(getActivity(), R.style.DialogFragment);
dialog.setContentView(view);
return dialog;
}*/
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
// getDialog().getWindow().getWindowStyle().gets;
View rootView = inflater.inflate(R.layout.address_selection_view, container, false);
// getDialog().setTitle("Simple Dialog");
ButterKnife.bind(this, rootView);
mClient = new GoogleApiClient
.Builder(getContext())
.addApi(Places.GEO_DATA_API)
.addApi(Places.PLACE_DETECTION_API)
.build();
try {
Address locationModel = (Address) getArguments().get("data");
if (locationModel != null) {
// getAddressDetails(locationModel.getAddress());
address.setAddressId(locationModel.getAddressId());
address.setFormatted("");
address.setCountry(addresslinetwo.getText().toString());
address.setLocality("");
address.setRegion("");
address.setPostalCode(pincode.getText().toString());
address.setStreetAddress(addresslineone.getText().toString());
address.setStreetAddress(addresslinetwo.getText().toString());
addresslineone.setText(locationModel.getStreetAddress());
addresslinetwo.setText(locationModel.getStreetAddress());
/*addresslinetwo.setText(locationModel.getCountry());*/
pincode.setText(locationModel.getPostalCode());
mEditSpinner1.setText(locationModel.getType());
countryView.setText(locationModel.getCountry());
stateView.setText(locationModel.getRegion());
cityView.setText(locationModel.getLocality());
isfromEdit = true;
}
} catch (Exception e) {
}
return rootView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
init();
}
private void init() {
addresslineone.setHintMessage("Address Line 1 (Street / landmark)");
addresslineone.setInputType(InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS);
addresslineone.setTintColor(Color.parseColor("#de3f5abd"));
addresslineone.setFontStyle("fonts/Helvetica.otf");
addresslinetwo.setHintMessage("Address Line 2 (City / Country)");
addresslinetwo.setInputType(InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS);
addresslinetwo.setTintColor(Color.parseColor("#de3f5abd"));
addresslinetwo.setFontStyle("fonts/Helvetica.otf");
pincode.setHintMessage("Post / Zip / Pin Code");
pincode.setInputType(InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS);
pincode.setFontStyle("fonts/Helvetica.otf");
pincode.setTintColor(Color.parseColor("#de3f5abd"));
stateView.setInputType(InputType.TYPE_CLASS_TEXT);
stateView.setHintMessage("State");
stateView.setTintColor(Color.parseColor("#de3f5abd"));
stateView.setFontStyle("fonts/Helvetica.otf");
countryView.setInputType(InputType.TYPE_CLASS_TEXT);
countryView.setHintMessage("Country");
countryView.setTintColor(Color.parseColor("#de3f5abd"));
countryView.setFontStyle("fonts/Helvetica.otf");
cityView.setInputType(InputType.TYPE_CLASS_TEXT);
cityView.setHintMessage("City");
cityView.setTintColor(Color.parseColor("#de3f5abd"));
cityView.setFontStyle("fonts/Helvetica.otf");
ListAdapter adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_dropdown_item,
getResources().getStringArray(R.array.edits_array_1));
mEditSpinner1.setAdapter(adapter);
}
public void getAddressDetails(String address) {
StringBuilder stringBuilder = new StringBuilder();
if (address != null) {
String[] addressSlice = address.toString().split(", ");
String country = addressSlice[addressSlice.length - 1];
if (country != null) {
addresslinetwo.setText(country);
countryView.setText(country);
}
stringBuilder.append("Country:" + country);
if (addressSlice.length > 1) {
String[] stateAndPostalCode = addressSlice[addressSlice.length - 2].split(" ");
if (stateAndPostalCode.length > 1) {
String postalCode = stateAndPostalCode[stateAndPostalCode.length - 1];
String state = "";
for (int i = 0; i < stateAndPostalCode.length - 1; i++) {
state += (i == 0 ? "" : " ") + stateAndPostalCode[i];
}
stringBuilder.append("PostalCode:" + postalCode);
stringBuilder.append("State:" + state);
if (postalCode != null) {
pincode.setText(postalCode);
}
if (state != null) {
stateView.setText("" + state);
// pincode.setText(pincode.getText() + "," + state);
}
} else {
String state = stateAndPostalCode[stateAndPostalCode.length - 1];
stringBuilder.append("State:" + state);
stateView.setText("" + state);
}
}
String city = null;
if (addressSlice.length > 2)
city = addressSlice[addressSlice.length - 3].toString();
if (city != null) {
cityView.setText("" + city);
// addresslinetwo.setText(addresslinetwo.getText() + "," + city);
stringBuilder.append("City:" + city);
}
String stAddress1 = "";
if (addressSlice.length == 4)
stAddress1 = addressSlice[0];
else if (addressSlice.length > 3) {
String stAddress2 = addressSlice[addressSlice.length - 4];
for (int i = 0; i < addressSlice.length - 4; i++) {
stAddress1 += (i == 0 ? "" : ", ") + addressSlice[i];
}
}
stringBuilder.append("Address1:" + stAddress1);
if (stAddress1 != null) {
addresslineone.setText(stAddress1);
// addresslineone.getText().replaceAll("null", "");
}
}
// if(place.getLatLng()!=null)
// {
// String latitude = "" + place.getLatLng().latitude;
// String longitude = "" + place.getLatLng().longitude;
// }
Log.e(TAG, "getAddressDetails: " + stringBuilder.toString());
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//Log.e(TAG, "onActivityResult: " + requestCode);
if (requestCode == 100) {
try {
if (data.getExtras() != null && data.getExtras().getSerializable("data") != null) {
LocationModel locationModel = (LocationModel) data.getExtras().getSerializable("data");
if (locationModel != null) {
// addresslineone.setText(locationModel.getLocationname());
getAddressDetails(locationModel.getAddress());
//latitude = String.valueOf(locationModel.getLatitude());
//longitude = String.valueOf(locationModel.getLongitude());
}
}
} catch (Exception e) {
}
}
}
}
Here is the code of Location Activity
Map
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.PlaceBuffer;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.location.places.ui.PlaceSelectionListener;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.planfisheye.fisheye.BaseActivity;
import com.planfisheye.fisheye.R;
import com.planfisheye.fisheye.adapters.NearByGetLocationParser;
import com.planfisheye.fisheye.adapters.PlacesAutoCompleteAdapter;
import com.planfisheye.fisheye.adapters.PlacesModel;
import com.planfisheye.fisheye.helper.CustomDialog;
import com.planfisheye.fisheye.models.LocationModel;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
/**
* Created by venkateshmurthy on 24/12/16.
*/
public class LocationActivity extends BaseActivity implements OnMapReadyCallback, GoogleApiClient.OnConnectionFailedListener, PlaceSelectionListener {
private static final String TAG = "LocationActivity";
MapView mapView;
GoogleMap map;
private GoogleApiClient mClient;
#BindView(R.id.autocompletesearch)
AutoCompleteTextView autoSearch;
private static final int REQUEST_SELECT_PLACE = 1000;
private LatLng latlangObj;
private String address;
private String locationname;
private CustomDialog mCustomDialog;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
#OnClick(R.id.doneclick)
public void doneClick() {
if(latlangObj!=null) {
LocationModel locationModel=new LocationModel();
locationModel.setLatitude(latlangObj.latitude);
locationModel.setLongitude(latlangObj.longitude);
locationModel.setLocationname(locationname);
locationModel.setAddress(address);
Intent intent=new Intent();
intent.putExtra("data",locationModel);
setResult(13, intent);
finish();
}else {
finish();
}
overridePendingTransition(R.anim.enter, R.anim.exit);
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location_select);
ButterKnife.bind(this);
mapView = (MapView) findViewById(R.id.mapview);
mapView.onCreate(savedInstanceState);
mCustomDialog=new CustomDialog(this);
// try {
// Intent intent = new PlaceAutocomplete.IntentBuilder
// (PlaceAutocomplete.MODE_OVERLAY)
// // .setBoundsBias(BOUNDS_MOUNTAIN_VIEW)
// .build(this);
// startActivityForResult(intent, REQUEST_SELECT_PLACE);
// } catch (GooglePlayServicesRepairableException |
// GooglePlayServicesNotAvailableException e) {
// e.printStackTrace();
// }
// PlaceAutocompleteFragment autocompleteFragment = (PlaceAutocompleteFragment)
// getFragmentManager().findFragmentById(R.id.place_autocomplete_fragment);
// autocompleteFragment.setOnPlaceSelectedListener(this);
// autocompleteFragment.setHint("Search a Location");
mClient = new GoogleApiClient
.Builder(this)
.addApi(Places.GEO_DATA_API)
.enableAutoManage(this, this)
.addApi(Places.PLACE_DETECTION_API)
.build();
mClient.connect();
autoSearch.setAdapter(new PlacesAutoCompleteAdapter(this, R.layout.autocomplete_list_item));
autoSearch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
autoSearch.setText("");
}
});
autoSearch.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//CommonUtils.hideKeyBoard(getActivity());
mCustomDialog.show();
final PlacesModel hm = (PlacesModel) autoSearch.getAdapter().getItem(position);
Log.e("place_id", "" + hm.getPlaceid());
// placetext.setText("" + hm.getDescription());
//AIzaSyA9_CVo9IETbjjqqBHC1eEYesVsaMPflIk
String[] codeInfo =
TextUtils.split(hm.getDescription(), ",");
// getLatLng(hm.getPlaceid());
Places.GeoDataApi.getPlaceById(mClient, hm.getPlaceid())
.setResultCallback(new ResultCallback<PlaceBuffer>() {
#Override
public void onResult(PlaceBuffer places) {
mCustomDialog.dismiss();
if (places.getStatus().isSuccess() && places.getCount() > 0) {
final Place myPlace = places.get(0);
//getAddressDetails(myPlace);
Log.e("name", "Place found: " + myPlace.getName() + "\t" + myPlace.getAddress()+"\t"+myPlace.getLatLng());
if(myPlace.getAddress()!=null) {
address = myPlace.getAddress().toString();
}
latlangObj= myPlace.getLatLng();
locationname=hm.getDescription();
Log.e("latitude:", "" + latlangObj.latitude);
Log.e("longitude:", "" + latlangObj.longitude);
Marker marker = map.addMarker(new MarkerOptions()
.position(new LatLng(latlangObj.latitude, latlangObj.longitude))
.title("" + hm.getDescription()));
marker.showInfoWindow();
marker.setDraggable(true);
map.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener() {
#Override
public void onMarkerDragStart(Marker marker) {
}
#Override
public void onMarkerDrag(Marker marker) {
}
#Override
public void onMarkerDragEnd(Marker marker) {
map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 12.0f));
} else {
Log.e("place", "Place not found");
}
places.release();
}
});
autoSearch.setText(""+hm.getDescription());
autoSearch.setSelection(autoSearch.getText().length());
}
});
// Needs to call MapsInitializer before doing any CameraUpdateFactory calls
MapsInitializer.initialize(this);
}
#Override
public void onResume() {
mapView.onResume();
super.onResume();
}
#Override
public void onPause() {
super.onPause();
mapView.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
mClient.disconnect();
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
public void onMapReady(GoogleMap googleMap) {
this.map = googleMap;
}
#Override
public void onPlaceSelected(Place place) {
}
#Override
public void onError(Status status) {
}
private class NearbyLatlngTask extends AsyncTask<String, Integer, String> {
String data = null;
#Override
protected String doInBackground(String... url) {
try {
data = downloadUrl(url[0]);
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
// Executed after the complete execution of doInBackground() method
#Override
protected void onPostExecute(String result) {
GetLatLngTask parserTask = new GetLatLngTask();
// Start parsing the Google places in JSON format
// Invokes the "doInBackground()" method of the class ParseTask
parserTask.execute(result);
}
}
/**
* A class to parse the Google Places in JSON format
*/
private class GetLatLngTask extends AsyncTask<String, Integer, List<HashMap<String, Double>>> {
JSONObject jObject;
// Invoked by execute() method of this object
#Override
protected List<HashMap<String, Double>> doInBackground(String... jsonData) {
List<HashMap<String, Double>> places = null;
NearByGetLocationParser nearPlaceJsonParser = new NearByGetLocationParser();
try {
jObject = new JSONObject(jsonData[0]);
/** Getting the parsed data as a List construct */
places = nearPlaceJsonParser.parse(jObject);
} catch (Exception e) {
Log.d("Exception", e.toString());
}
return places;
}
// Executed after the complete execution of doInBackground() method
#Override
protected void onPostExecute(List<HashMap<String, Double>> list) {
// Clears all the existing markers
// mGoogleMap.clear();
if (list != null) {
for (int i = 0; i < list.size(); i++) {
// Creating a marker
MarkerOptions markerOptions = new MarkerOptions();
// Getting a place from the places list
HashMap<String, Double> hmPlace = list.get(i);
// Getting latitude of the place
double lat = hmPlace.get("lat");
// Getting longitude of the place
double lng = hmPlace.get("lng");
Log.e("lat", "lat" + lat);
Log.e("long", "long" + lng);
Toast.LENGTH_SHORT).show();
}
}
}
}
/**
* A method to download json data from url
*/
private String downloadUrl(String strUrl) throws IOException {
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
data = sb.toString();
br.close();
} catch (Exception e) {
//Log.d("Exception while downloading url", e.toString());
} finally {
iStream.close();
urlConnection.disconnect();
}
return data;
}
private void getLatLng(String placeID) {
StringBuilder sb = new StringBuilder("https://maps.googleapis.com/maps/api/place/details/json?placeid=" + placeID);
sb.append("&key=AIzaSyBiV3T00af_2jM0Vinlcws2Gc6K7ktVp38");
NearbyLatlngTask placesTask = new NearbyLatlngTask();
// Invokes the "doInBackground()" method of the class PlaceTask
placesTask.execute(sb.toString());
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
}
Check this,
map.setOnMapLongClickListener(new OnMapLongClickListener() {
#Override
public void onMapLongClick(LatLng latLng) {
addMarker();
}
});
add this is addMarker method,
private void addMarker() {
// create marker
MarkerOptions marker = new MarkerOptions().position(new LatLng(latitude, longitude)).title("Hello Maps");
googleMap.addMarker(marker);
}
I made a lot of research on this topic but couldn't find an appropriate solution.
I simply have an api which include school name and its latitude,longitude.
[
{
"id":1,
"name":"Little Angels Higher Secondary School",
"latitude":27.6514,
"longitude":85.3359
},
{
"id":6,
"name":"Baltimore Secondary School",
"latitude":27.6514,
"longitude":85.3359
}
]
I parsed this api data.Using GPStracker class I successfully included a marker on google map at my current location.Now I want to add a marker to all the school location in that google map so that I can know the nearest school to me once I open the google map.This is all what I did how ever it shows null pointer exception.
package com.example.user.educationhunt.fragment;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.JsonArrayRequest;
import com.example.user.educationhunt.R;
import com.example.user.educationhunt.SchoolDetails;
import com.example.user.educationhunt.adapter.CustomListAdapter;
import com.example.user.educationhunt.pojos.AppController;
import com.example.user.educationhunt.pojos.FeeClass;
import com.example.user.educationhunt.pojos.GpsLocation;
import com.example.user.educationhunt.pojos.MySchool;
import com.example.user.educationhunt.pojos.OurSchool;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
/**
* A simple {#link Fragment} subclass.
*/
public class NearMe extends Fragment {
MapView mMapView;
private GoogleMap googleMap;
GpsLocation gpsLocation;
double longitude, latitude;
private ProgressDialog pDialog;
private RadioButton radioSexButton;
ArrayList al = new ArrayList();
MySchool mySchool;
Marker place;
LatLng current_location ;
private static final String TAG = NearMe.class.getSimpleName();
private static final String url = "http://www.myeducationhunt.com/api/v1/schools";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_near_me, container, false);
radioSexButton = (RadioButton) v.findViewById(R.id.radioSchool);
if (isConnected()) {
mMapView = (MapView) v.findViewById(R.id.mapView);
mMapView.onCreate(savedInstanceState);
mMapView.onResume();
try {
MapsInitializer.initialize(getActivity().getApplicationContext());
} catch (Exception e) {
e.printStackTrace();
}
gpsLocation = new GpsLocation(getContext());
if (gpsLocation.canGetLocation()) {
longitude = gpsLocation.getLongitude();
latitude = gpsLocation.getLatitude();
Toast.makeText(getContext(), "latitude:" + latitude + "Longitude:" + longitude, Toast.LENGTH_LONG).show();
}
pDialog = new ProgressDialog(getContext());
pDialog.setMessage("Loading…");
pDialog.show();
JsonArrayRequest schoolRequest = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
hidePDialog();
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
mySchool = new MySchool();
mySchool.setId(""+obj.getInt("id"));
mySchool.setName(""+obj.getString("name"));
mySchool.setLatitude(Double.parseDouble(""+obj.getDouble("latitude")));
mySchool.setLongitude(Double.parseDouble(""+obj.getDouble("longitude")));
al.add(mySchool);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(schoolRequest);
mMapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap mMap) {
googleMap = mMap;
LatLng schoollatlng = new LatLng(latitude, longitude);
googleMap.addMarker(new MarkerOptions().position(schoollatlng).title("MyLocation"));
CameraPosition cameraPosition = new CameraPosition.Builder().target(schoollatlng).zoom(10).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
LatLng latlng = new LatLng(mySchool.getLatitude(), mySchool.getLongitude());
googleMap.addMarker(new MarkerOptions().position(latlng).title(mySchool.getName()));
CameraPosition cameraPosition1 = new CameraPosition.Builder().target(latlng).zoom(10).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition1));
}
});
} else {
Toast.makeText(getContext(), "Please check your internet connection", Toast.LENGTH_LONG).show();
}
return v;
}
public boolean isConnected() {
ConnectivityManager connMgr = (ConnectivityManager) getActivity().getSystemService(Activity.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected())
return true;
else
return false;
}
private void hidePDialog() {
if (pDialog != null) {
pDialog.dismiss();
pDialog = null;
}
}
}
Is there any one to help me?Please Help.Thanks in advance
This is MySchool class
package com.example.user.educationhunt.pojos;
/**
* Created by user on 12/28/2016.
*/
public class MySchool {
String id;
String name;
double latitude;
double longitude;
public String getId() {
return id;
}
public String getName() {
return name;
}
public double getLatitude() {
return latitude;
}
public double getLongitude() {
return longitude;
}
public void setId(String id) {
this.id = id;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public void setName(String name) {
this.name = name;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
}
This is my error log
FATAL EXCEPTION: main
Process: com.example.user.educationhunt, PID: 20472
java.lang.NullPointerException: Attempt to invoke virtual method 'double com.example.user.educationhunt.pojos.MySchool.getLatitude()' on a null object reference
at com.example.user.educationhunt.fragment.NearMe$3.onMapReady(NearMe.java:159)
at com.google.android.gms.maps.MapView$zza$1.zza(Unknown Source)
at com.google.android.gms.maps.internal.zzt$zza.onTransact(Unknown Source)
at android.os.Binder.transact(Binder.java:387)
at zu.a(:com.google.android.gms.DynamiteModulesB:82)
at maps.ad.t$5.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
12-28 10:06:05.046 20472-21276/com.example.user.educationhunt I/qtaguid: Untagging socket 81
Your school marker should run after google complete initialized. Below are the code sample.
mMapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap mMap) {
googleMap = mMap;
LatLng schoollatlng = new LatLng(latitude, longitude);
googleMap.addMarker(new MarkerOptions().position(schoollatlng).title("MyLocation"));
CameraPosition cameraPosition = new CameraPosition.Builder().target(schoollatlng).zoom(10).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
drawSchoolMarker();
}
});
Create new method in the class
private void drawSchoolMarker(){
JsonArrayRequest schoolRequest = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
hidePDialog();
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
MySchool school = new MySchool();
school.setId(""+obj.getInt("id"));
school.setName(""+obj.getString("name"));
school.setLatitude(Double.parseDouble(""+obj.getDouble("latitude")));
school.setLongitude(Double.parseDouble(""+obj.getDouble("longitude")));
al.add(school);
} catch (JSONException e) {
e.printStackTrace();
}
}
//iterate from arraylist
for(MySchool school : al){
LatLng latlng = new LatLng(school.getLatitude(), school.getLongitude());
googleMap.addMarker(new MarkerOptions().position(latlng).title(school.getName()));
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(schoolRequest);
}
I didn't test the code but it should work.
After reading all school locations do some thing like by using your Array List
Marker place;
LatLng current_location ;
for(int i = 0; i < al.size(); i++){
current_location = new LatLng(Double.parseDouble(al.get(i).getLatitude()),Double.parseDouble(al.get(i).getLongitude()));
place= map.addMarker(new MarkerOptions().position(current_location).title("school name here"));
}
You should get NullPointerException in the line:
LatLng latlng = new LatLng(ourSchool.latitude, ourSchool.longitude);
because ourSchool is pointing to Null. You have added all the ourSchool objects in the ArrayList "al" like : al.add(ourSchool)
now try to iterate from the ArrayList "al" after adding the data in the ArrayList.
Also your below code is running before the getting response from the url and your "ourSchool" not initialise till that time.
mMapView.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap mMap) {
googleMap = mMap;
LatLng schoollatlng = new LatLng(latitude, longitude);
googleMap.addMarker(new MarkerOptions().position(schoollatlng).title("MyLocation"));
CameraPosition cameraPosition = new CameraPosition.Builder().target(schoollatlng).zoom(10).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
LatLng latlng = new LatLng(ourSchool.latitude, ourSchool.longitude);
googleMap.addMarker(new MarkerOptions().position(latlng).title(ourSchool.schoolName));
CameraPosition cameraPosition1 = new CameraPosition.Builder().target(latlng).zoom(10).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition1));
}
});
OurSchool class:
class OurSchool{
String id;
String name;
double latitude;
double longitude;
public void setId(String id){
this.id=id;
}
public String getId(){
return id;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setLatitude(double latitude){
this.latitute=latitude;
}
public double getLatitude(){
return latitude;
}
public void setLongitude(String longitude){
this.longitude=longitude;
}
public double getLongitude(){
return longitude;
}
}
then set value in OurSchool class object like:
ourSchool.setId(""+obj.getInt("id"));
in place of
ourSchool.schoolId = obj.getInt("id");
same way set values for other also
I have the following code and basically I am wondering how I can use this location method distanceBetween() to find the objects in my .JSON file that are under 500km away. I tried to craft together an if statement and a distanceBetween usage but it doesn't recognize it and I know my syntax has some real problems. Is this the right way to be trying to do this? Any help or tips or code is greatly greatly appreciated!
package com.dredaydesigns.radiostationfinder;
import android.R;
import android.app.Activity;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
import com.google.gson.JsonParser;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Text;
import java.io.IOException;
import butterknife.Bind;
import butterknife.ButterKnife;
public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks {
// String HTTPRadioURL = "https://transition.fcc.gov/fcc-bin/fmq?state=&call=&city=&arn=&serv=FC&vac=3&freq=0.0&fre2=107.9&facid=&asrn=&class=&dkt=&list=0&dist=100&dlat2="
// + latitude + "&mlat2=&slat2=&NS=N&dlon2="
// + longitude +"&mlon2=&slon2=&EW=W&size=9";
public static final String TAG = MainActivity.class.getSimpleName();
private RadioData mRadioData;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
#Bind(R.id.longitudeLabel) TextView mLongitudeLabel;
#Bind(R.id.latitudeLabel) TextView mLatitudeLabel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_content);
ButterKnife.bind(this);
double latitude = 32;
double longitude = -96;
double latitudeStations;
double longitudeStations;
final RadioData[] mRadioData = new RadioData[1];
//String radioFinderURL = "http://data.fcc.gov/lpfmapi/rest/v1/lat/" + latitude + "/long/" + longitude + "?format=json&secondchannel=true";
//String HTTPRadioURL = "https://transition.fcc.gov/fcc-bin/fmq?state=&call=&city=&arn=&serv=FC&vac=3&freq=0.0&fre2=107.9&facid=&asrn=&class=&dkt=&list=0&dist=100&dlat2="
// + latitude + "&mlat2=&slat2=&NS=N&dlon2="
// + longitude +"&mlon2=&slon2=&EW=W&size=9";
String radioFinderURL = "http://dredaycreative.com/json/radioData.json";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(radioFinderURL)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
}
#Override
public void onResponse(Response response) throws IOException {
try {
String jsonData = response.body().string();
Log.v(TAG,jsonData);
if (response.isSuccessful()) {
mRadioData[0] = getCurrentDetails(jsonData);
}
} catch (IOException e) {
Log.e(TAG, "Exception Caught: ", e);
}
catch(JSONException e){
Log.e(TAG, "Exception Caught:", e);
}
}
});
}
private RadioData getCurrentDetails(String jsonData) throws JSONException {
JSONObject radioData = new JSONObject(jsonData);
String callSign;
double latitudeStations;
double longitudeStations;
int frequency;
JSONArray jsonArray = radioData.getJSONArray("array");
for(int i =0; i<jsonArray.length(); i++){
callSign = radioData.getJSONObject(i+"")
.getJSONArray("array").getJSONObject(i).getString("FIELD1");
frequency = Integer.parseInt(radioData.getJSONObject(i + "")
.getJSONArray("array").getJSONObject(i).getString("FIELD2"));
longitudeStations = Double.parseDouble(radioData.getJSONObject(i+"")
.getJSONArray("array").getJSONObject(i).getString("FIELD20"));
latitudeStations = Double.parseDouble(radioData.getJSONObject(i+"")
.getJSONArray("array").getJSONObject(i).getString("FIELD24"));
Log.i(TAG, "From JSON: " + callSign + frequency + latitudeStations + longitudeStations);
if {
distanceBetween(double latitude, double longitude, double latitudeStations, double longitudeStations, float[] results) <100km
RadioData currently = new RadioData();
}
}
return new RadioData();
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener((GoogleApiClient.OnConnectionFailedListener) this)
.addApi(LocationServices.API)
.build();
}
#Override
public void onConnected(Bundle bundle) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
mLatitudeLabel.setText(String.valueOf(mLastLocation.getLatitude()));
mLongitudeLabel.setText(String.valueOf(mLastLocation.getLongitude()));
}
}
#Override
public void onConnectionSuspended(int i) {
}
}
UPDATED CODER AFTER COMMENT AT 7:55PMCMT 8/17/15
Okay thank you for your help! I switched it up in this way am I getting warmer, ha?
private RadioData getCurrentDetails(String jsonData) throws JSONException {
JSONObject radioData = new JSONObject(jsonData);
static void distanceBetween;
String callSign;
double latitudeStations;
double longitudeStations;
int frequency;
private int mRadius = distanceBetween(double latitude, double longitude, double latitudeStations, double longitudeStations, float[] results)
callSign = radioData.getJSONObject(i + "")
.getJSONObject(i).getString("FIELD1");
frequency = Integer.parseInt(radioData.getJSONObject(i + "")
.getJSONObject(i).getString("FIELD2"));
longitudeStations = Double.parseDouble(radioData.getJSONObject(i + "")
.getJSONObject(i).getString("FIELD20"));
latitudeStations = Double.parseDouble(radioData.getJSONObject(i + "")
.getJSONObject(i).getString("FIELD24"));
Log.i(TAG, "From JSON: " + callSign + frequency + latitudeStations + longitudeStations);
if{
500 >= mRadius;
RadioData radioData = new RadioData();
}
}
return new RadioData();
}
I have an app which takes android map marker locations (lat/long) from mysql database. And user from my app can add markers too. The problem is that when user adds location of the new marker it does not appear on map. However the lat and long values appear in mysql database and if i reinstall the app it will show added location. Issue here seems to be that i have to refresh the map and i don't know how to do it in google maps v2. I found some answers that i should clear all markers and then load them again like this:
googleMap.clear();
But sadly it did not work. I found that in version one there was this method
map.invalidate();
Sadly in Google Maps v2 there is no such method. Has anyone have any idea how to refresh Google Maps v2 when i reactivate activity or if i press refresh button, any suggestion will be appreciated.
Update
Code:
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.JsonArrayRequest;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.wunderlist.slidinglayer.SlidingLayer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import app.AppController;
import util.Content;
public class MainActivity extends Activity {
private GoogleMap googleMap;
// json object response url
private String urlJsonObj = "alsodontneedthis.json";
// json array response url
private String urlJsonArry = "dontneedthis";
private static String TAG = MainActivity.class.getSimpleName();
// Progress dialog
private ProgressDialog pDialog;
Content content = new Content();
public static String valueEntered;
// temporary string to show the parsed response
private String jsonResponse;
private SlidingLayer mSlidingLayer;
private TextView swipeText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
googleMap.getUiSettings();
googleMap.getUiSettings().setZoomControlsEnabled(true);
bindViews();
initState();
mSlidingLayer.bringToFront();
redirect();
googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
mSlidingLayer.openLayer(true);
return true;
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#SuppressLint("NewApi")
#Override
protected void onResume() {
super.onResume();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getActionBar().setDisplayHomeAsUpEnabled(true);
}
}
/**
* View binding
*/
private void bindViews() {
mSlidingLayer = (SlidingLayer) findViewById(R.id.slidingLayer1);
// swipeText = (TextView) findViewById(R.id.swipeText);
}
/**
* Initializes the origin state of the layer
*/
private void initState() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
setupSlidingLayerPosition(prefs.getString("layer_location", "right"));
setupShadow(prefs.getBoolean("layer_has_shadow", false));
setupLayerOffset(prefs.getBoolean("layer_has_offset", false));
setupPreviewMode(prefs.getBoolean("preview_mode_enabled", false));
}
private void setupSlidingLayerPosition(String layerPosition) {
LayoutParams rlp = (LayoutParams) mSlidingLayer.getLayoutParams();
int textResource;
Drawable d;
// if (layerPosition.equals("right")) {
textResource = R.string.swipe_right_label;
d = getResources().getDrawable(R.drawable.container_rocket_right);
mSlidingLayer.setStickTo(SlidingLayer.STICK_TO_RIGHT);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
// swipeText.setCompoundDrawables(null, d, null, null);
// swipeText.setText(getResources().getString(textResource));
mSlidingLayer.setLayoutParams(rlp);
}
private void setupShadow(boolean enabled) {
if (enabled) {
mSlidingLayer.setShadowSizeRes(R.dimen.shadow_size);
mSlidingLayer.setShadowDrawable(R.drawable.sidebar_shadow);
} else {
mSlidingLayer.setShadowSize(0);
mSlidingLayer.setShadowDrawable(null);
}
}
private void setupLayerOffset(boolean enabled) {
int offsetDistance = enabled ? getResources().getDimensionPixelOffset(R.dimen.offset_distance) : 0;
mSlidingLayer.setOffsetDistance(offsetDistance);
}
private void setupPreviewMode(boolean enabled) {
int previewOffset = enabled ? getResources().getDimensionPixelOffset(R.dimen.preview_offset_distance) : -1;
mSlidingLayer.setPreviewOffsetDistance(previewOffset);
}
public void buttonClicked(View v) {
switch (v.getId()) {
// case R.id.buttonOpen:
// mSlidingLayer.openLayer(true);
// break;
case R.id.buttonClose:
mSlidingLayer.closeLayer(true);
break;
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (mSlidingLayer.isOpened()) {
mSlidingLayer.closeLayer(true);
return true;
}
default:
return super.onKeyDown(keyCode, event);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.addNewEvent:
Intent intent = new Intent(this, AddEvent.class);
startActivity(intent);
;
}
return true;
}
private void redirect() {
//showpDialog();
JsonArrayRequest req = new JsonArrayRequest(urlJsonArry,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
try {
Content content = new Content();
// Parsing json array response
// loop through each json object
jsonResponse = "";
for (int i = 0; i < response.length(); i++) {
JSONObject person = (JSONObject) response
.get(i);
String name = person.getString("nosaukums");
String email = person.getString("nosaukums");
String relation = person.getString("nosaukums");
Double lat=person.getDouble("latCo");
Double lng=person.getDouble("longCo");
content.setName(name);
content.setPopulation(email);
content.setlat(lat);
content.setlng(lng);
content.setRelation(relation);
System.out.println("name="+content.getName()+content.getlat());
LatLng lt = new LatLng(content.getlat(), content.getlng());
content.setLatlng(lt);
//valueEntered=lt.toString();
System.out.println("address="+content.getLatlng());
/*String home = latlng.getLong("home");
String mobile = phone.getString("mobile");*/
System.out.println("relation="+content.getRelation());
jsonResponse += "Name: " + name + "\n\n";
jsonResponse += "Population: " + email + "\n\n";
jsonResponse += "Latitude: " + lat + "\n\n";
jsonResponse += "Longitude: " + lng + "\n\n\n";
jsonResponse += "Relation" + relation +"\n\n\n";
if(content.getRelation().equals("son"))
{
googleMap.addMarker(new MarkerOptions()
.position(lt)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_son))
.snippet(email)
.title(content.getName())).showInfoWindow();
}
else
{
googleMap.addMarker(new MarkerOptions()
.position(lt)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_daughter))
.title(content.getName())).showInfoWindow();
}
CameraPosition cameraPosition = new CameraPosition.Builder().target(lt).zoom(15.0f).build();
CameraUpdate cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition);
googleMap.moveCamera(cameraUpdate);
}
//txtResponse.setText(jsonResponse);
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),
"Error: " + e.getMessage(),
Toast.LENGTH_LONG).show();
}
//hidepDialog();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_SHORT).show();
//hidepDialog();
}
});
// Adding request to request queue
//AppController.getInstance() == null;
AppController.getInstance().addToRequestQueue(req);
}
}
Since googleMap.appMarker() seems not to get called, you propaply catch an Exception when calling content.getRelation().equals("son").