Android maps v2 becomes low quality when map area is automatically moved
Asked Answered
P

2

6

I am simulating a car moving on a pre-recorded path on Android maps v2. When I zoom on the path by hand, it works great, but when I move the camera over the path with mMap.animateCamera(), it doesn't load the visible map area, I only get a very pixelated, low quality map. If I touch the screen and move the map or zoom a little, then it loads again this part.

How can I achieve, that it always loads clearly the visible part?

EDIT: I added an example image: this is what I see when I don't touch the map. After I touch it, it becomes clear (similar to the bottom left part).

Example image

EDIT2: I have an idea, that this is because Google want's to prevent the map to be cached by quickly moving the camera over an area. Is it possible, that this is the cause of this issue? (The map is showing Budapest, Hungary, which part of the map you can not download for offline use...) But here I only want to show the animation and place markers, I only need the visible area to be cached - are there any way to workaround this behaviour?

EDIT3: The animation code:

new Thread(new Runnable() {

    @Override
    public void run() {
        // ... Calculating and sending new location, in an infinite loop with sleeps for timing

        MainActivity.this.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                mMap.animateCamera(CameraUpdateFactory.newLatLng(new LatLng(location.getLatitude(), location.getLongitude())));
            }
        });
    }
}).start();
Proper answered 16/5, 2014 at 13:51 Comment(2)
Are you animating the camera from a separate thread? I couldn't recreate your problem; the map re-focuses after animation when I try it. Can you post your camera animation code?Myriapod
Yes, I am animating from a separate thread, using activity's runOnUiThread. (Source code above)Proper
M
2

Finally found a solution. I was able to recreate your problem using the code you provided. I replaced your code with the following and it worked for me.

    Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {

        @Override
        public void run() {
            // ... Calculating and sending new location, in an infinite loop with sleeps for timing

            MainActivity.this.runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    mMap.animateCamera(CameraUpdateFactory.newLatLng(new LatLng(location.getLatitude(), location.getLongitude())));
                }
            });         
        }

    }, 0, 2000);

Just remove your code for sleeping and replace the last argument in scheduleAtFixedRate (the 2000) with whatever value you were using for sleeping.

Myriapod answered 9/6, 2014 at 22:44 Comment(1)
Thank you for your solution, it's much better now with this code, but the error still occurs sometimes. Do you have any idea why it matters if I call it from a separate thread with sleeps or via Timer?Proper
L
1

I had the same issue. Since it did not happen when not animating the camera, it had to be something related to that.

Apperently the camera has to be able to finish its operation, before it will update the background/roads etc. Since my app updates the position every second and the map needs about 2 seconds to complete I end up with pixelated roads and no surroundings at all.

The solution is to use one of overloads of animateCamera:

public final void animateCamera (CameraUpdate update, int durationMs,
GoogleMap.CancelableCallback callback)

Moves the map according to the update with an animation over a specified duration, and calls an optional callback on completion. See CameraUpdateFactory for a set of updates.

I used for my case a duration of 900msec, so the animation is done before it receives a new location.

To get the callback to work you need to implement GoogleMap.CancelableCallback to your class. This requires you to add two overrides:

@Override
public void onFinish() {
}

@Override
public void onCancel() {
}

They are not required to get the problem solved, altough you are free to add extra logic there.

The call to update the camera can look like this:

cameraPosition = new CameraPosition.Builder()
                    .target(current)            
                    .zoom(zoomLevel)            
                    .bearing(bearing)   
                    .tilt(tilt)                   
                    .build();               

CameraUpdate update = CameraUpdateFactory.newCameraPosition(cameraPosition);

map.animateCamera(update, 900, this);
Lakin answered 24/11, 2016 at 14:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.