Android GoogleMap getProjection() not working - java

This is my first post here, so I hope I'll explain my problem clear enough:
I'm extending the FragmentActivity class to create a HeatMapActivity. In this activity I use a GoogleMap object, which I obtain as follows:
// Try to obtain the map from the SupportMapFragment.
map = ((SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.heatmap)).getMap();
Now, after doing a null-Check etc., I'm adding a TileOverlay in the setUpMap() method, as shown below:
// Configure and add overlay
tileProvider = new HeatMapTileProvider(map);
map.addTileOverlay(new TileOverlayOptions()
.tileProvider(tileProvider));
Ok, so far no problem at all. I implemented the TileProvider interface to provide the tiles for the HeatMap overlay.
I want to use the Projection object for converting latitude/longuitude to and from pixels on the screen. The Projection object should be returned by the getProjection() method of the GoogleMap class.
So now here's the problem: If I use the following code in the HeatMapActivity class, everything is fine:
System.err.println("Test1: " + map.getProjection().fromScreenLocation(new Point(50, 50)));
But if I forward the GoogleMap object to the TileProvider, respectively to the renderer I use, the code is not working anymore:
public byte[] render(int x, int y, int zoom, GoogleMap map) {
...
System.err.println("Test2: " + map);
System.err.println("Test3: " + map.getProjection().fromScreenLocation(new Point(50, 50)));
...
}
I definitely know, that the map parameter is not null (see Test 2), but the code just seems to block when I call getProjection(). There is no error coming up and if I don't use the Projection object, everything else is working fine. I don't have any clue, why I should not be allowed to call getProjection() from another class than the activity...
I am using the ADT bundle for Windows (version x86_64-20130729), Android SDK version from 8 to 17, testing on Android 2.3.5 at the moment. The map is displayed, the needed libraries are included and the permissions are set in the android manifest.
Any ideas? Any help or hints are appreciated.
Seb

The issue here is that getTile (and your render method) are called outside UI thread.
This will cause exception, which you won't see, because it is probably silently handled by the code calling getTile. This is really bad it doesn't crash, so someone could post an issue on gmaps api issues.
Try to wrap call to getProjection in try-catch to see it.
Because you should not interact with GoogleMap outside of main thread, you will have to find another way to achieve, what you want to achieve...
Anyway, I can imagine no good reason for a need to call getProjection in getTile. Maybe another question describing your real problem?

Related

Citymaps questions on Android studio

I have some new questions in today's citymaps development.
In the Android studio,if I develop the code for citymap, there are always no logs showing but for others that does not happen. Why?
According to the citymaps official website, to create a map instance with CitymapsMapFragment, but in the sample project which citymaps provides, it uses SupportCitymapsMpaFragment ,What is the difference between them?
When the map is loading complete, is it automatically positioning to the current position or some other default position? Where is it?
If I open the GPS location,I can locate to the current position and show a blue arrow quickly, but too much power consumption,are there any other location way like network or base station location?
Code follows:
CitymapsMapFragment fragment = (CitymapsMapFragment)fragmentManager.findFragmentById(R.id.map);
if (fragment != null) {
fragment.setMapViewListener(this);
}
I did not find the fragment have the method setMapViewListener but setMapViewReadyListener,does it right?
Other code:
CitymapsMapView mapView = new CitymapsMapView(this, options, this);
When I add animate in additional methods like this:
mapView.setMapPosition(position, 300, new MapViewAnimationListener() {
#Override
public void onAnimationEnd(boolean completed) {
Log.d("SomeApp", "Move Complete!");
}
});
the project fails and exits,I tried to surround the code with try-catch block to catch exception for purpose, but nothing shows in logcat view. Why?
I am developer on the Citymaps project. I will do my best to answer all your questions
1) If you are not receiving log statements, this is likely an issue with your own application, IDE, or device configuration. In our own application, which uses the Citymaps SDK, we have no issues with logging.
2) Prior to using the Citymaps SDK, it is highly advisable that you familiarize yourself with fragments, but the short version is that SupportCitymapsMapFragment extends from the Fragment class in the v4 support library.
3) It is up to you to set the default position the map.
4) If you create a class which implements from the LocationSource interface, and then call mapView.setLocationSource, you can modify the behaviors of the map's location services. For an example, have a look at CitymapsLocationSource.java, which is the default implementation for this interface used by the SDK.
As for the exception you are having, you have not provided nearly enough information. Please show a stack trace, and I may be able to help.
Thank you for using our SDK, feel free to post again with any more questions.

How to load a Google maps static map using Picasso?

In my Android app I use Picasso to load images. This normally works perfectly well.
Today I tried loading a static image from the google maps api, but this doesn't seem to work. When I open the example link as provided on their info page, I get to see the static map image perfectly well. When I load it in my Android app using the line below, I get nothing at all.
Picasso.with(getContext()).load("http://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=13&size=370x250&maptype=roadmap%20&markers=color:blue|label:S|40.702147,-74.015794&markers=color:green|label:G|40.711614,-74.012318%20&markers=color:red|color:red|label:C|40.718217,-73.998284&sensor=false").into(mapView);
I also tried to download the image and uploading it to my personal webspace, from which it loads perfectly well, but somehow, it doesn't seem to load directly from the direct google API url.
Does anybody know why this is so, and how I can solve it?
The only programmatic point-of-failure that comes to mind is in parsing the URI. Looking at the current Picasso code (https://github.com/square/picasso/blob/master/picasso/src/main/java/com/squareup/picasso/Picasso.java) I see the following:
public RequestCreator load(String path) {
if (path == null) {
return new RequestCreator(this, null, 0);
}
if (path.trim().length() == 0) {
throw new IllegalArgumentException("Path must not be empty.");
}
return load(Uri.parse(path));
}
So I'd first debug
Uri.parse("http://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=13&size=370x250&maptype=roadmap%20&markers=color:blue|label:S|40.702147,-74.015794&markers=color:green|label:G|40.711614,-74.012318%20&markers=color:red|color:red|label:C|40.718217,-73.998284&sensor=false")
and see what that Object looks like. Does it drop or confuse any of your parameters?
If that doesn't lead you anwhere, try downloading the file manually using a HttpClient [or similar]. Then at least you can fully debug the request/response.
Also, I know Google maps has some limits -- are you sure you haven't reached them?
replace http with https
replace | with %7C
add api key
The .loadMap() function has many declared variables. This is the heart of the whole process.
So what is required for the static maps API to give us an image is that we make an http request with a given url, for which an image response (URL) is received. Let us run through the meaning and utility of these variables. Yes, all of them have a completely different meaning!
The mapUrlInitial variable is always the same while making an API call. It has a query of center ( ?center ) which specifies that we want the location to be centered in the map.
The mapUrlProperties variable contains a string where you control the actual zooming of the image response you will get, the size ofthe image and the color of the marker which will point out our place.
The mapUrlMapType variable is a string where you can actually determine the marker size you want and the type of the map. We are using a roadtype map in the app.
Finally latLong is a string which concatenates the latitude and the longitude of the place we want to pinpoint!
We then concatenate all of these strings to form a feasible Url. The Url is then loaded as we have seen above, in the Picasso code. One thing we can notice is that an event object is always required for all of this to happen, because we are able to fetch the position details using the event object! Final Code:-
fun loadMap(event: Event): String{
//location handling
val mapUrlInitial = “https://maps.googleapis.com/maps/api/staticmap?center=”
val mapUrlProperties = “&zoom=12&size=1200×390&markers=color:red%7C”
val mapUrlMapType = “&markers=size:mid&maptype=roadmap”
val latLong: String = “” +event.latitude + “,” + event.longitude
return mapUrlInitial + latLong + mapUrlProperties + latLong + mapUrlMapType
}
//load image
Picasso.get()
.load(loadMap(event))
.placeholder(R.drawable.ic_map_black_24dp)
.into(rootView.image_map)

Add custom View as marker in Google Maps API v2

I've developed a class that inherits from a View class and I want it to serve as a marker on a MapFragment/MapView from a Google Maps API v2. As I recall, such thing was possible in API v1 and even now it is possible on iOS. I'm looking for something like this:
MapView map = (MapView)findViewById(R.id.mapview);
CircleTimerView myTimer = new CircleTimerView(this);
LayoutParams lp = new LayoutParams(iv.getWidth(), iv.getHeight(), geoPoint, LayoutParams.BOTTOM);
map.addView(myTimer,lp);
My custom View is animated and it is a key feature of my app.
My question is: Is it possible for a current state of Google Maps API? Or should I try to obtain API v1 key and work with something that was deprecated?
Thanks in advance for your replies.
should I try to obtain API v1 key and work with something that was deprecated?
You cannot obtain new keys for API v1.
My custom View is animated and it is a key feature of my app.
You cannot have animated Marker icon unless you repeatedly change the icon using Marker.setIcon.
Is it possible for a current state of Google Maps API?
You can use a View as icon if you draw it into a Bitmap first.
This library from Chris Broadfoot can greatly help you with that task:
https://github.com/googlemaps/android-maps-utils
See this video for what the lib can do: http://www.youtube.com/watch?v=nb2X9IjjZpM
Or the new website: http://googlemaps.github.io/android-maps-utils/
in order to customize / use your own custom maker on google maps api v2 you could write the code as follows:
in onCreate declare the marker:
userIcon = R.drawable.red;
and then i used it where you need it, in my case i used it in a method:
if(userMarker!=null) userMarker.remove();
userMarker = theMap.addMarker(new MarkerOptions()
.position(lastLatLng)
.title("You are here")
.icon(BitmapDescriptorFactory.fromResource(userIcon))
.snippet("Your last recorded location"));
theMap.animateCamera(CameraUpdateFactory.newLatLng(lastLatLng), 100, null);
CameraUpdate center=
CameraUpdateFactory.newLatLng(lastLatLng);
CameraUpdate zoom=CameraUpdateFactory.zoomTo(15);
theMap.moveCamera(center);
theMap.animateCamera(zoom);
hope this helped. good luck
i had the same issue these days and you should do the switch for v2 as you can do all the same stuff from v1 easier + many new features.
MapView has been replaced with the new GoogleMap-Objecttype.
A very detailed and decent Tutorial site can be found HERE!

progressbar circle in SherlockActionBar using Fragments

I have a SherlockFragmentActivity using tabhost and viewpager. Calling
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
in the fragmentactivity creates the spinner, and calling
setSupportProgressBarIndeterminateVisibility(false);
won't disable it. I also don't seem to be able to call getActivity().setSupportProgressBarIndeterminateVisibility(false);
from the fragments;
I get the error "The Method setSupportProgressBarIndeterminateVisibility(boolean) is undefined for the type FragmentActivity."
What am I doing wrong, can someone show me the way how to use it properly in fragments? I want to be able to create the progressbar in my asynctask pre execute and stop it in postexecute.
I'm using2.2 emulator and importing import com.actionbarsherlock.view.Window; instead of the android.view one.
[Edit] I just confirmed using setProgressBarIndeterminateVisibility works in the 4.1 emulator. Anyway, I need to get this work in 2.2
"I also don't seem to be able to call getActivity().setSupportProgressBarIndeterminateVisibility(false); from the fragments;"
You need to be calling getSherlockActivity() instead of getActivity().
"I'm using2.2 emulator and importing import com.actionbarsherlock.view.Window; instead of the android.view one."
Plus one for that, hadn't spotted that import and came across this post which fixed my bug - wasn't showing the progress indicator in Gingerbread before, many thanks :)
This works perfect for me:
getActivity().setProgressBarIndeterminate(true);
ProgressDialog progressDialog = new ProgressDialog(getActivity());
progressDialog.show(getActivity(), "This is", " a message...");
May you help ;)

How to clear the (CSS) visited history of an Android WebView?

I try to reuse an existing WebView by clearing any private data the previous user left behind:
CookieManager.getInstance().removeAllCookie();
webview.clearHistory();
webview.clearFormData();
webview.clearCache(true);
clearHistory seems only to clear the back/forward list, accessible via API, but not the internal list used for coloring links inside the web content.
I even tried the following, suggested by another stackoverflow answer:
deleteDatabase("webview.db");
deleteDatabase("webviewCache.db");
I still have no luck: CSS :visited selectors still work after reloading the page.
An alternative would be to use the API level 11 private browsing feature (new constructor argument), but then I cannot benefit from visited links at all; and can no longer target older versions.
Maybe someone has a solution for this issue? Thanks for your help.
Summary of the answers I got so far:
I tried these two answers, but the first seems to clear HTML5 data storage and the latter seems to be specific to the built-in browser:
WebStorage.getInstance().deleteAllData();
Browser.clearHistory(getContentResolver());
WebChromeClient.getVisitedHistory(ValueCallback<String[]> callback) is only called after the first time I create a new WebView in a recently installed application.
I tried to remove the WebView from view hierachy and create a new one, but unfortunately the visited history seems to be stored for the whole application.
Override WebChromeClient and WebViewClient... Damn that was hidden.
I actually had to dig up a bit to find this out.
WebView webView = (WebView)findViewById(R.id.myWebView);
WebChromeClient myWebChromeClient = new WebChromeClient(){
#Override
public void getVisitedHistory(ValueCallback<String[]> callback) {
// called during webview initialization, original implementation does strictly nothing
// and defaults to the native method WebViewCore.nativeProvideVisitedHistory()
String[] myUserHistory = getVisitedUrlsFromMyOwnDatabase(userId);
callback.onReceiveValue(myUserHistory);
}
};
WebViewClient myWebViewClient = new WebViewClient(){
#Override
public void doUpdateVisitedHistory(WebView view, String url,
boolean isReload) {
// called whenever there is a new link being visited
insertIfNotExistVisitedUrlIntoMyOwnDatabaseForUser(userId);
super(view, url, isReload);
}
}
webView.setWebViewClient(myWebViewClient);
webView.setChromeClient(myWebChromeClient);
webView.getSettings().etc(whatever)...
I think I'm "almost there". Here's the part I managed: what it does so far is remove css history altogether, so we're halfway there. I can't get the browser to recognize the url format I'm providing in "myUserHistory", so in effect the only feature this code does is reset css history altogether, but it's only called once when the WebView is instanciated (or created, didn't check), so for a true multiuser experience you'd need to recreate the webview at each login.
My problem now is that I can't manage to load the urlHistory properly. My Honeycomb Xoom webview seems to ignore my data.
Ah well, I hope it works for you. For me just calling callback.onReceiveValue(new String[]{}); in getVisitedHistory() will be good enough.
EDIT:
I just put twenty more minutes into it because I'm curious. This method is what delegates to the WebChromeClient (mCallbackProxy = WebChromeClient).
protected void populateVisitedLinks() {
ValueCallback callback = new ValueCallback<String[]>() {
public void onReceiveValue(String[] value) {
sendMessage(EventHub.POPULATE_VISITED_LINKS, (Object)value);
}
};
mCallbackProxy.getVisitedHistory(callback);
}
It's protected in WebViewCore, which is a private attribute of WebView with no accessor. The sendMessage delegates to EventHub which is private, and WebViewCore is filled with private native methods, and one of these seems to be the one actually calling the populateVisitedLinks() method during the initialization.
Unless someone at Google adds a public method to WebView to trigger the repopulation, I'm afraid it's practically impossible to achieve your goal. Sorry :(
As a side note, all these native visited history handling really makes me wonder: why do hardware manufacturers care so much about which urls we visited? ;) <<< sarcasm
As an alternate solution, you could try adding your own CSS with the same base colors the default CSS has and switch the CSS by another one (with same color for both "types" of links) when you want to reset the visited links.
A:link{color: "#990000"; text-decoration: none;}
A:visited{color: "#990000"; text-decoration: none;}
A:hover{color: "#ff0000"; text-decoration: none;}
If you can obtain a Browser instance (maybe you can set a WebChromeClient to WebView) you can use its clearHistory() method.
Does WebStorage.clearAllData() have the desired effect? Unfortunately, the documentation on this class is very sparse compared to WebView and doesn't say whether it applies to WebViews.
The exact time you're calling clearHistory() may also have an effect. Clearing it and then navigating to a new page may still keep the first page in history, and you have to call the method after the new page has loaded.
Personally, if privacy is a real issue, I would create a new set of objects from scratch for this new session if possible.

Categories