How to detect moveCamera is finished on the Google map service? - android

I want to take a snapshot when moveCamera is finished.
I used both onCamerachange() and onMapLoaded() functions to Googlemap object,
But this callback handler's timing is not fit on my intention.
I want to move camera to what I want, and when loading map is finished, want to take a screnshot.
Who do you guys know about how can I do?
Thank you.
====================================================
+MYSOLUTION
Actually, I want to implement tilesloaded() call back function that is supported on the google map API of the javascript.
But, as a result, there is no function which is completely accomplished that function.
OnMapLoaded() callback function is just invoked once when the map is loaded first.
OnCameraChanged() or OnCancallableCallback is invoked before all the tiles are loaded.
So I implemented like below source code
...
mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10), this);
...
#Override
public void onFinish() {
mapFragment.getMapAsync(this);
}
..
#Override
public void onMapReady(GoogleMap googleMap) {
// TODO Auto-generated method stub
mMap = googleMap;// Add a marker in Sydney and move the camera
mMap.setOnMapLoadedCallback(this);
}
Now, when the camera is moved, onMapLoaded() is always invoked.
Thank you everybody.

You can implement this:
mMap.animateCamera(CameraUpdateFactory.zoomTo(16), 3000, new GoogleMap.CancelableCallback() {
#Override
public void onFinish() {
//Here you can take the snapshot or whatever you want
}
#Override
public void onCancel() {
}
});
The most detailed form of this method, GoogleMap.animateCamera(cameraUpdate, duration, callback), offers three arguments:
cameraUpdate
The CameraUpdate describing where to move the camera.
callback
An object that implements GoogleMap.CancellableCallback. This generalized interface for handling tasks defines two methods onCancel() and onFinished(). For animation, the methods are called in the following circumstances:
onFinish()
Invoked if the animation goes to completion without interruption.
onCancel()
Invoked if the animation is interrupted by calling stopAnimation() or starting a new camera movement.
Alternatively, this can also occur if you call GoogleMap.stopAnimation().
Source: Google Maps Android API Guides

So you are definitely in the right area by using the onCameraChange() and onMapLoaded() callback. The best way to handle this would be to handle your screenshot in the onMapLoaded() function.
Also, remember to use the newest libraries, and the support libraries when instantiating your map fragment. This is very important.
So:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...All of the other important things you have here
//Instantiate the map object using the support library
map = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
map.getMapAsync(this);
//Add the callback to your map object
map.setOnMapLoadedCallback(this);
}
#Override
public void onMapLoaded(){
//Perform screenshot here
}
EDIT
Here is code for a handler, complete with comments.
#Override
public void onCameraChange(){
//Constant for our time. I would put this below your class declaration
private static final int DELAY_TIME_IN_MILLI = 3000;
//Here is the handler for waiting
mMap.postDelayed(new Runnable() {
//This function runs after the time allotted below
#Override
public void run() {
//Call your screenshot function here
takeScreenShot();
}
},DELAY_TIME_IN_MILLI); //Our delay
}

Related

Android GoogleMaps slow onMapClick response

I set a click listener (GoogleMap.OnMapClickListener) for GoogleMap object in the onMapReady() method like this.
#Override
public void onMapReady(GoogleMap map) {
addClickListener(map);
}
Here is the addClickListener():
private void addClickListener(GoogleMap map) {
map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
Log.d("ON_MAP_CLICK", "1. OnMapClick called");
handleOnMapClick(point);
}
});
}
Since I set the map ready in the onMapReady method it is logical that I also add the click listener there.
The problem is that the delay for clicking on the map and the code to register that click is around 1 second while is should be instant.
Problem: The problem is not the time it takes to call addClickListener(GoogleMap) but the time that onMapClick() registers a click on the map (around 1 second).
Why is it so slow?
I am using GoogleMap V2
Thanks!
It is obvious that addClickListener method is called after 1 second because onMapReady call back will called only after intializing the map. So it take some delay initially for calling your addClickListener method.
So you will observe this delay only for the first time not all the time and it is working as like it is expected, No changes required in your code
onMapReady will call after the map is initialized, i had a project that took a while to load the map making all the functions "slow".
You can try to load the map earlier to prevent that by adding this to the Splashscreen or Activity.
new Thread(new Runnable() {
#Override
public void run() {
try {
MapView mv = new MapView(getApplicationContext());
mv.onCreate(null);
mv.onPause();
mv.onDestroy();
}catch (Exception ignored){
}
}
}).start();

How to call retrofit api call in sequence of 5sec after onCameraChange(CameraPosition arg0) event on map

I am working on google map with retrofit2 api call.
on every camera change i have to call api.
problem is when user swipe/pinch-zoom on map every time onCameraChange(CameraPosition arg0) method will fire and my api call also.
so multiple time api call are running and because of this my output on map is ruined completely.
#Override
public void onCameraChange(CameraPosition arg0) {
// TODO Auto-generated method stub
camerachange();
}
public void camerachange() {
Log.e("temp", "camera change");
// jarray = new JSONArray();
jarray = new ArrayList<String>();
LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;
jarray.add(String.valueOf(bounds.southwest.latitude));
jarray.add(String.valueOf(bounds.southwest.longitude));
jarray.add(String.valueOf(bounds.northeast.latitude));
jarray.add(String.valueOf(bounds.northeast.longitude));
getPropertyList(jarray, 1) // this function has my retrofit call.
}
guys please help me with this concern.
main concern is multiple time call should not be there it must take last swipe/pinch-zoom effect.
thanks
You can use the OnMapLoadedCallback. From the documentation:
public abstract void onMapLoaded ()
Called when the map has finished rendering. This will only be called once. You must request another callback if you want to be notified again.
So, you need to set an initial setOnMapLoadedCallback for your map for example on the onMapReady method:
public void onMapReady(GoogleMap map) {
map.setOnMapLoadedCallback(this);
}
And then reset a new setOnMapLoadedCallback every time the event is consumed:
public void onMapLoaded() {
//TODO: Do your stuff
map.setOnMapLoadedCallback(this);
}
Also, take into account hte disclaimer from the documentation:
This event will not fire if the map never loads due to connectivity issues, or if the map is continuously changing and never completes loading due to the user constantly interacting with the map.

How to pause at an Android lifecycle stage until callback is called?

I am trying to use Google Maps API in my Android app. I need to call getMapAsync() to retrieve the map object asynchronously and I need to get the GoogleMap object instance before my fragment calls onResume(), because otherwise the GoogleMap object will still be null and it will throw an exception.
Therefore, I want the Activity that holds the fragment to pause at onResume() until onMapReadyCallback is invoked, so that I am guaranteed that the GoogleMap object is created and I could proceed in the Activity lifecycle. However, if I use any locks or barrier synchronizers in the Activity's thread (main thread), the thread will block and will not receive any callbacks and thus will wait forever.
I tried to use an object to implement the onMapReadyCallback and put it in another thread, but according to the documentation, I must have the callback in the main thread.
So how can I make the main thread wait until the callback has arrived and prevent it from running down its lifecycle methods???
You have two methods to resolve your issue. One crappy, and one better.
The crappy way
If this can helps for tests purposes for instance, this can works.
Call the Handler#postDelayed method in your onResume() method when your map object is null. Here's an example.
#Override
public void onResume(){
super.onResume();
doMapStuff();
}
public void doMapStuff()
{
if (mMap == null) {
new Handler().postDelayed(new Runnable() {
public void run() {
doMapStuff();
}
}, 250);
return;
}
// do your stuff on the map here.
}
public void onMapReady(GoogleMap map) {
mMap = map;
doMapStuff();
}
As the handler is created on the UI thread, the delayed runnable will also be executed on the UI thread, so you will be able to make your map stuff.
BUT This is a crappy way to do this. It can works for tests, but avoid using this way!
The good way
If your map object is null when onResume() is called, that means the onMapReady callback will be called further.
If your map object is set when onResume() is called, that means the onMapReady callback was already called, so it will not be called again.
Basically, you need to "duplicate" your calls between onResume() and onMapReady() methods.
#Override
public void onResume(){
super.onResume();
doMapStuff();
}
public void doMapStuff()
{
if (mMap == null)
return;
// do your stuff on the map here.
}
public void onMapReady(GoogleMap map) {
mMap = map;
doMapStuff();
}
You can't pause or delay the activity lifecycle without causing problems, as you have seen.
If all the data you need is not available at the time of an activity lifecycle method, you can delay the visibility of the UI and postpone other work that needs to be done in the Activity. Show some sort of spinner or progress bar until all the data and connections are available, then update the views in response to everything becoming available.
Do a check to make sure that onMapReady has completed. Would this work for you:
MapFragment mMapFragment;
#Override
public View onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
public void onMapReady(GoogleMap map){
mMap = map;
}
then in onResume do a check:
#Override
public void onResume(){
super.onResume();
if(mMap == null){
mMapFragment.getMapAsync(this);
}
//rest of code
}

Accessing GoogleMap from outside the UI thread in Android

I'm using Google Map Android API v2 for my android application. There I have initialize GoogleMap as follows inside onCreate
SupportMapFragment fm = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
mGoogleMap = fm.getMap();
In my application, I need to do some background tasks and I'm using AsybcTask for that. While progress through the background tasks I want to update the map. Please refer the following sample.
#Override
protected Void doInBackground(Void...voids) {
while(Condition)
{
mGoogleMap.clear();
mGoogleMap.addMarker(marker);
Thread.sleep(5000);
}
}
I know that I can't directly access UI components inside the doInBackground method. Common UI components like buttons, edittexts, textviews can be accessed by parsing the context of the application to the AsyncTask class. But I can't figure out a way to access GoogleMap from the doInBackground method. Could you please give me a solution.
if your AsyncTask is a part of the Activity you can simply use runOnUiThread method, like this:
#Override
protected Void doInBackground(Void...voids) {
while(Condition)
{
runOnUiThread(new Runnable() {
#Override
public void run() {
mGoogleMap.clear();
mGoogleMap.addMarker(marker);
Thread.sleep(5000);
}
});
}
}

Android : Make application wait till the current location is found

I'm trying to make my app wait till the current location is found. I've tried few different ways using Threads and all have failed really. I was using wait() and notify() but application just hung and never found the current location.
I amen't using google map api as it is not part of the application. Does anyone have any ideas how to do this or examples.
EDIT : The Thread I was using did not start till the user pressed a button then within onLocationChanged other data is processed e.g. adding the new location to ArrayList, Calculate the distance between the current and last Location as well as the Time taken to get to the new location
You could try starting an AsyncTask in onCreateto get the location. Your default onCreate layout could be a "loading" page, then when your AsyncTask completes successfully with the location it draws your "real" UI.
So if I understand what you want to do correctly, then I would avoid making another thread in onClick(). Instead, onClick() should just request a location, display a progress dialog, and return. Since the work you want to do happens after you receive the new location, I would start an AsyncTask there. Then you finally remove the dialog box (removing it returns control to the user) when the AsyncTask finishes.
Code usually helps, so, I would put this in onCreate() or wherever:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.refresh();
}
});
And put this in your LocationListener:
public void refresh() {
myLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
myDialog = new ProgressDialog(myContext);
myDialog.setIndeterminate(true);
myDialog.show();
}
#Override
public void onLocationChanged(Location location) {
// now do work with your location,
// which your probably want to do in a different thread
new MyAsyncTask().execute(new Location[] { location });
}
And then you need an AsyncTask, which may look like this:
class MyAsyncTask extends AsyncTask<Location, Void, Void> {
#Override
protected Void doInBackground(Location... location) {
// start doing your distance/directions/etc work here
return null;
}
#Override
protected void onPostExecute(Void v) {
// this gets called automatically when you're done,
// so release the dialog box
myDialog.dismiss();
myDialog = null;
}
}

Categories

Resources