Custom marker icon from image URL GoogleMap API V2 - android

I have one problem.
My goal is to load custom image of company and show it instead default marker icon.
But I have faced with the problem.
Icons are shown only if I close and open activity again.
Here is my code for adding markers to the map.
private void addMarkerToTheMap(GoogleMapInfoBundle infoBundle) {
if (infoBundle.placeMarker) {
LatLng latLng = new LatLng(infoBundle.company.getLatitude(), infoBundle.firm.getLongitude());
MarkerOptions markerOptions = new MarkerOptions()
.title(infoBundle.company.getName())
.snippet(infoBundle.company.getAddress())
.position(latLng);
Marker marker = mGoogleMap.addMarker(markerOptions);
try {
Picasso.with(this).load(NetworkUtils.getUrlOfScaledImage(infoBundle.company.getLogo(), DEFAULT_ICON_SCALE_PERCENTAGE)).into(new PicassoMarker(marker));
} catch (IllegalArgumentException ignore) {
// Do nothing
}
}
And PicassoMarker
public class PicassoMarker implements Target {
Marker mMarker;
public PicassoMarker(Marker marker) {
mMarker = marker;
}
#Override
public int hashCode() {
return mMarker.hashCode();
}
#Override
public boolean equals(Object o) {
if (o instanceof PicassoMarker) {
Marker marker = ((PicassoMarker) o).mMarker;
return mMarker.equals(marker);
} else {
return false;
}
}
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
mMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
}
In this case it displays default icon .
I have tried to make it in another way like this
MarkerOptions markerOptions = new MarkerOptions()
.title(infoBundle.company.getName())
.snippet(infoBundle.company.getAddress())
.position(latLng);
try {
Picasso.with(this).load(NetworkUtils.getUrlOfScaledImage(infoBundle.company.getLogo(), DEFAULT_ICON_SCALE_PERCENTAGE)).into(new PicassoMarker(mGoogleMap, markerOptions));
} catch (IllegalArgumentException ignore) {
// Do nothing
}
And add marker to the map in callback after image has been downloaded.
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
mMarkerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap));
mGoogleMap.addMarker(mMarkerOptions);
}
It doesn't show any marker in this case.
But in both cases if I close Activity and open it again everything will be displayed correctly with icons as it should.
I have no idea what can cause such problem. It seems GoogleMap caches icon image or something else.
I have a little experience working with GoogleMaps API, maybe I am missing something.
Hope someone can help.
Thanks.

The problem was not in GoogleMap or SupportMapFragment it was in Picasso, not exactly in Picasso but in my flow.
The thing you should always remember using custom Target classes is that internally Picasso uses WeakReference for storing Target objects, so if you will just create new Target directly inside Picasso call it will be destroyed by garbage collector.
Picasso provides Callback class, so you can create anonymous class instead and that you class will hold the reference.
But one thing that is I am missing Callback class that provides Bitmap in response like Target(but targets are mostly used by custom views).
So I have found such solution, it ugly, but here it is.
I have created special list for storing target objects, not to be garbaged.
Marker marker = mGoogleMap.addMarker(markerOptions);
mMarkerCompanyMap.put(marker, infoBundle.firm);
try {
PicassoMarkerTarget markerTarget = new PicassoMarkerTarget(marker, mImageLoadingCallback);
mPicassoMarkerTargetList.add(markerTarget);
Picasso.with(this)
.load(NetworkUtils.getUrlOfScaledImage(infoBundle.firm.getLogo(), DEFAULT_ICON_SCALE_PERCENTAGE))
.into(markerTarget);
} catch (IllegalArgumentException ignore) {
// Do nothing
}
I am passing mImageLoadingCallback for having callback back to the activity from Target
And it looks like.
private Callback mImageLoadingCallback = new Callback() {
#Override
public void onSuccess() {
Logger.logError("IMAGE LOADED IN CALLBACK " + mPendingImagesCount);
if (mPendingImagesCount <= 0) {
mPicassoMarkerTargetList.clear();
} else {
mPendingImagesCount--;
}
}
#Override
public void onError() {
// You may start laughing, but just for the sake of not duplicating code
onSuccess();
}
};
This callback can be used for other purposes, but now only for clear array.
And of course PicassoMarkerTarget
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
mMarker.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
mDownloadListenerCallback.onSuccess();
Logger.logError("IMAGE LOADED IN PICASSO MARKER TARGET");
}
This is ugly solution but maybe this callback can be helpful in the future.
Please, if you have idea how to make solution better - please share it.
Thanks.

Related

Android get properties for polygon from GeoJson

Im adding GeoJsonLayer to Google map on my application. This json contains coordinates for polygon and properties for each polygon. What I need is to get those properties when polygon is clicked. This is the code Im using to achieve that.
GeoJsonLayer jsonLayer = new GeoJsonLayer(mMap, geoJSON);
jsonLayer.addLayerToMap();
jsonLayer.setOnFeatureClickListener(new GeoJsonLayer.GeoJsonOnFeatureClickListener() {
#Override
public void onFeatureClick(final com.google.maps.android.data.Feature feature) {
mMap.setOnPolygonClickListener(new GoogleMap.OnPolygonClickListener() {
#Override
public void onPolygonClick(Polygon polygon) {
for (Object s : feature.getProperties()) {
Log.d("getProperties", "getProperties = " + s.toString());
}
}
});
}
});
The problem is that it returns all properties. I want it to return properties only for the polygon I clicked.
Also its possible to draw polygons with user input. When I click on those polygons it triggers onPolygonClick() inside jsonLayer.setOnFeatureClickListener(). How to check if clicked polygon is from jsonLayer?

How do I calculate path between two map points in Android?

I am working on iOS/Android map application.
To find a path between two locations in iOS, I am using MKDirectionsRequest.
How do I do it in Android?
I found Directions API, which is a Web service. So that I will have to send HTTP requests.
Isn't there any Java interface to calculate directions in Android?
To set this as an answer.
You can use Android-GoogleDirectionLibrary
As such:
GoogleDirection.withServerKey("YOUR_SERVER_API_KEY")
.from(new LatLng(37.7681994, -122.444538))
.to(new LatLng(37.7749003,-122.4034934))
.avoid(AvoidType.FERRIES)
.avoid(AvoidType.HIGHWAYS)
.execute(new DirectionCallback() {
#Override
public void onDirectionSuccess(Direction direction, String rawBody) {
if(direction.isOK()) {
// Do something
} else {
// Do something
}
}
#Override
public void onDirectionFailure(Throwable t) {
// Do something
}
});

Android ARCGIS Shape file labeling polylines

I have my ARCGIS android app displaying a polyline shapefile file - a roading network in this case.
The shape file has a field that contains the name of the road "ROAD_NAME' - the question i have is how do i create a layer to have the road name automatically displayed?
cheers
B
I also tried to display labels on the map.
By my experiment, there are 2 ways. I realized it.One way is that draw those labels programmatically on the map. but it needs a lot of effort. I did it, it is not pretty. I think so.
public class LabelLayer extends GraphicsLayer {
...
private void showLabel(final FeatureLayer fly, final QueryParameters query,final String labelField) {
new Thread(new Runnable() {
#Override
public void run() {
fly.getFeatureTable().queryFeatures(query, new CallbackListener<FeatureResult>() {
#Override
public void onCallback(FeatureResult objects) {
Iterator<Object> fet=objects.iterator();
while (fet.hasNext()){
Feature f=(Feature) fet.next();
Geometry geom= f.getGeometry();
Point p=null;
switch (geom.getType()){
case POINT:p=(Point)geom;break;
case POLYLINE: Polyline polyline=(Polyline)geom;break;
case POLYGON: p= GeometryEngine.getLabelPointForPolygon((Polygon)geom,mapView.getSpatialReference());break;
default:break;
}
txtSymbol.setFontWeight(FontWeight.BOLD);
txtSymbol.setColor(Color.DKGRAY);
txtSymbol.setText(f.getAttributeValue(labelField).toString());
Graphic gr = new Graphic(p, txtSymbol);
LabelLayer.this.addGraphic(gr);
}
}
#Override
public void onError(Throwable throwable) {
}
});
}
}).start();
}
...
}
this class should be implemented in onDraw() method.
the second is that use the tpk of ArcGIS.
I think it would be better much.

UI Hang while replacing fragment from setOnInfoWindowClickListener interface method of Google Map

I am using google map in my application and display markers.
Now on click of marker window I want to replace the current fragment with other fragment.
for (StoreData store : comp.getArrStoreList()) {
LatLng l = new LatLng(Double.parseDouble(store.getLat()),
Double.parseDouble(store.getLng()));
MarkerOptions marker = new MarkerOptions()
.position(l)
.title(store.getName())
.snippet(store.getCity())
.icon(BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));
Marker mrkr = mapCompanyList.addMarker(marker);
CompanyStoreData companyStoreData = new CompanyStoreData();
companyStoreData.setStoreData(store);
companyStoreData.setCompanyId(comp.getId());
listStoreData.put(mrkr, companyStoreData);
mapCompanyList
.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
try {
StoreDetailsFragment storeDetails = new StoreDetailsFragment();
Bundle b = new Bundle();
b.putSerializable(UserDefaults.STORE_OBJECT,
listStoreData.get(marker).getStoreData());
b.putString("StoreAppID", listStoreData.get(marker).getCompanyId());
storeDetails.setArguments(b);
((BaseTabbarContainer) companyListFragment.getParentFragment()).replaceFragment(
storeDetails, true); // here my UI is hang
} catch (Exception e) {
Log.e("Exception", "Exception :: " + e.getMessage());
}
}
});
}
I am creating one hashmap which has <marker,storedata> marker as a key and storedata (my custom class object) as a value.
on onInfoWindowClick I am getting instance of store data on basis of key of hashmap(). It is working well but
((BaseTabbarContainer) companyListFragment.getParentFragment()).replaceFragment(
storeDetails, true);
Here my UI is getting hang. What is the issue
I resolved the issue . if any one facing this issue please refer this.
What I done is create one handler to run the code snippet after some delay and return from the onInfoWindowClick method after calling handler.
mapCompanyList
.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
final Marker mark = marker;
try {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
callStore(mark);
}
}, 100);
return;
} catch (Exception e) {
Log.e("Exception", "Exception :: " + e.getMessage());
}
}
});
callStore
private void callStore(Marker marker) {
StoreDetailsFragment storeDetails = new StoreDetailsFragment();
Bundle b = new Bundle();
b.putSerializable(UserDefaults.STORE_OBJECT,
listStoreData.get(marker).getStoreData());
b.putString("StoreAppID", listStoreData.get(marker).getCompanyId());
storeDetails.setArguments(b);
((BaseTabbarContainer) CompanyListFragment.this.getParentFragment()).replaceFragment(
storeDetails, true);
}
and It worked;
But I still don't get why it is getting hang though and why it is resolved after returning from onInfoWindowClick method while running code in post delay?if any one have any idea please share.
I was also facing this problem, for me I solved by stop using fragmentManager.executePendingTransactions(), if I use this line to replace fragment then its just HANG, but without this line its working without any problem. hope it will help for someone who will face similar problem. thanks.

How to access Drawable when using Picasso?

I'm using the Picasso framework to handle image loading in my Android app.
After the image is loaded, I need to access the Drawable to apply some masking operations. The issue is that Picasso converts the Drawable to a PicassoDrawable, and a simple cast back to Drawable does not work.
This is the code I have:
Picasso.with(mContext).load(image.getPath()).into(mImageView, new Callback() {
#Override
public void onSuccess() {
Util.applyMask(imageView);
}
#Override
public void onError() {
}
});
and the Util.applyMask(ImageView) method:
public static void applyMask(ImageView imageView) {
// this is where a class cast exception happens since it's actually a PicassoDrawable and not a Drawable
Bitmap mainImage = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
// ...
}
A possible solution is given by Jake Wharton in this github issue: https://github.com/square/picasso/issues/38
To sum up, the solution is: "If you want access to the Bitmap directly then you'll need to use the Target callbacks. The PicassoDrawable is used to allow fading and the debug indicator."
I'm not exactly sure how to access the Target callback. Anyone knows how to solve this?
Thanks.
This was answered at github (https://github.com/square/picasso/issues/38):
private Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
}
#Override
public void onBitmapFailed() {
}
}
private void loadBitmap() {
Picasso.with(this).load("url").into(target);
}

Categories

Resources