Google Maps API 2 MapView Not Updating

末鹿安然 提交于 2019-12-05 12:42:20

You have to let the map breathe so to speak.

Use animateCamera with a CancelableCallback then when the animation is completed you'll get a call back to onFinish() start the next animation.

public class KmlReader extends ActionBarActivity implements
    CancelableCallback {


@Override
public void onFinish() {
    startAnimation(); // start next map movement
}


@Override
public void onCancel() {
    //Called when user interacts with the map while it is moving.
}


public void startAnimation(){

cameraPosition = mMap.getCameraPosition();    
LatLng ll = new LatLng(expectedLocation.getLatitude(),
                    expectedLocation.getLongitude());
            cb.zoom(cameraPosition.zoom)
            // previous camera tilt
                    .tilt(cameraPosition.tilt)
                    // new expected destination
                    .target(ll)
                    // north up or heading view
                    .bearing((isHeading) ? bearing : 0f);
            cameraPosition = cb.build();
            CameraUpdate update = CameraUpdateFactory
                    .newCameraPosition(cameraPosition);
            mMap.animateCamera(update, working_interval, this);
}

* Edit this is the code I'm working on now.* it uses an asynctask for the calcuations. I've given it a walking test but haven't tested it in a vehicle.

private static CameraPosition currentCameraPosition;
private static com.google.android.gms.maps.model.CameraPosition.Builder cameraPositionBuilder;
private volatile CameraUpdate nextCameraUpdate;
// updates 
private static final long UPDATE_INTERVAL = 2500;
// fastest 
private static final int FASTEST_INTERVAL = 2500;
private static int working_interval = 5000; 
private volatile boolean isAnimating;


// Define the callback method that receives location updates
@SuppressLint("NewApi")
@Override
public void onLocationChanged(Location location) {
    Log.d("test", Boolean.toString(isAnimating)  +" onlocation");
    currentCameraPosition = mMap.getCameraPosition();

    NewCameraUpdateTask newCameraUpdateTask = new NewCameraUpdateTask();

// This task must run async
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    newCameraUpdateTask.executeOnExecutor(
            AsyncTask.THREAD_POOL_EXECUTOR, location);
} else {
    newCameraUpdateTask.execute(location);
}
    // speed display
    setMetersPerSecond(location.getSpeed());
}

// create a newCameraUpdate to move the map with
private class NewCameraUpdateTask extends
        AsyncTask<Location, Void, CameraUpdate> {

    @Override
    protected CameraUpdate doInBackground(Location... params) {
        Location workingLocation = null;
        CameraUpdate newCameraUpdate = null;

        float bearing = 0f;
        float speed = 0f;

        for (Location mlocation : params) {
            speed = mlocation.getSpeed();

            // camera position is saved before the start of each animation.
            LatLng ll;

        if (!mlocation.hasBearing() || speed == 0) {
            workingLocation = mlocation;
            // previous bearing
        } else {
            // current bearing
            bearing = mlocation.getBearing();
            // calculate the age of the location
            // atempt for animation to end a little bit past when
            // the
            // next
            // location arrives.
            // (location.getSpeed()m/s)(1/1000 interval seconds)(
            // 1/1000
            // km/m)
            // (1/6371 radians/km) = radians/6371000000.0
            double expectedDistance = working_interval / 6371000000.0
                    * speed;

            // latitude in Radians
            double currentLatitude = Math.toRadians(mlocation
                    .getLatitude());
            // longitude in Radians
            double currentlongitude = Math.toRadians(mlocation
                    .getLongitude());

            double calcBearing = Math.toRadians(bearing);

            // the camera position is needed so I can put in the
            // previous camera bearing when the location has no
            // bearing. This should prevent the map from
            // zooming to north when the device stops moving.

            // calculate the expected latitude and longitude based
            // on
            // staring
            // location
            // , bearing, and distance
            double sincurrentLatitude = Math.sin(currentLatitude);
            double coscurrentLatitude = Math.cos(currentLatitude);
            double cosexpectedDistance = Math.cos(expectedDistance);
            double sinexpectedDistance = Math.sin(expectedDistance);

            double expectedLatitude = Math.asin(sincurrentLatitude
                    * cosexpectedDistance + coscurrentLatitude
                    * sinexpectedDistance * Math.cos(calcBearing));
            double a = Math.atan2(
                    Math.sin(calcBearing) * sinexpectedDistance
                            * coscurrentLatitude,
                    cosexpectedDistance - sincurrentLatitude
                            * Math.sin(expectedLatitude));
            double expectedLongitude = currentlongitude + a;
            expectedLongitude = (expectedLongitude + PI3) % PI2 - PI;

            // convert to degrees for the expected destination
            double expectedLongitudeDestination = Math
                    .toDegrees(expectedLongitude);
            double expectedLatitudeDestination = Math
                    .toDegrees(expectedLatitude);

            mlocation.setLatitude(expectedLatitudeDestination);
            mlocation.setLongitude(expectedLongitudeDestination);
            workingLocation = mlocation;

        }
        break;
    }

    if (workingLocation != null) {
        if (workingLocation.hasBearing()) {
            bearing = workingLocation.getBearing();
        } else {
            bearing = currentCameraPosition.bearing;
        }
        LatLng ll = new LatLng(workingLocation.getLatitude(),
                workingLocation.getLongitude());
        cameraPositionBuilder.zoom(currentCameraPosition.zoom)
        // previous camera tilt
                .tilt(currentCameraPosition.tilt)
                // new expected destination
                .target(ll)
                // north up or heading view
                .bearing((isHeading) ? bearing : 0f);
        newCameraUpdate = CameraUpdateFactory
                .newCameraPosition(cameraPositionBuilder.build());
    }

    return newCameraUpdate;
}

@Override
protected void onPostExecute(CameraUpdate result) {
    Log.d("test", Boolean.toString(isAnimating) + " onPostExecute");
    if (result != null) {
        nextCameraUpdate = result;
        // stop the currently playing animation
        // there is a new one ready to start
        if (isAnimating) {
            if (mMap != null) {
                mMap.stopAnimation();
            }
        }
        // start the next animation
        startAnimation();
        Log.d("test", Boolean.toString(isAnimating)  +" onPostExecuteComplete");
    }


}
}


// called when map animation has been canceled
@Override
public void onCancel() {
    Log.d("test", Boolean.toString(isAnimating)  +" oncancel");
    isAnimating = false;
}

@Override
public void onFinish() {
    Log.d("test", Boolean.toString(isAnimating)  +" onfinish");
    isAnimating = false;
    startAnimation();

    // call to start saved animation.
}

private void startAnimation() {
    Log.d("test", Boolean.toString(isAnimating)  +" startAnimation");
    if (action_track) {
        if (isAnimating) {
            return;
        }
        if (nextCameraUpdate == null) {
            return;
        }
        // abort if animating
        isAnimating = true;
        CameraUpdate animateCameraUpdate = nextCameraUpdate;
        nextCameraUpdate = null;
        mMap.animateCamera(animateCameraUpdate, working_interval, this);
        Log.d("test", Boolean.toString(isAnimating)  +" startanimateCamera");
    }
}

In case someone is having this issue, the key is to keep the animateCamera call's animation duration less than the frequency with which you are calling the animateCamera method.

For example if you call animateCamera every 1000ms set tha animate camera duration to be less than that.

map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, ZOOM_LEVEL), 900, null)

If your animateCamera call is not being called at a constant time, then danny117's answer to use the callback to trigger the next camera update will work perfectly.

Inspired from danny117's solution, I found a simpler solution. I set the location request update for each 5 millisecond and I set the animate camera duration to be 2.5 ms. Problem solved

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!