使用Google Maps Android API v2在Google Maps上绘制路线

6

我有一个应用程序,使用谷歌地图的新服务API,持续跟踪用户位置。我每秒更新一次位置,并检查用户的活动,如静止、倾斜、在车内等,以获得更好的位置跟踪。我能够使用我的代码绘制路径,但它不准确并且与用户实际行驶/步行的道路非常不同。它总是在用户实际路径的某个远离位置绘制线条。

我的服务:

public class MyService extends Service implements LocationListener {

    private final Context mContext;
    private static MyService mInstance = null;
    private final static String TAG = "RidingTimerService";

    boolean isGPSEnabled = false;

    private long mStartTime = 0L;
    private long timeInMilliseconds = 0L;
    private long timeSwapBuff = 0L;
    private long updatedTime = 0L;
    private Handler mHandler = null;
    private int mHours = 0;

    // Declaring a Location Manager
    private LocationManager mLocationManager = null;
    private Location mCurrentLocation = null; // location
    private double[][] positions;
    private long[] times;
    private final Integer data_points = 2; // how many data points to calculate
    private double mTravelledDistance = 0.0f;

    private SharedPreferences mPreferences = null;
    private ArrayList<LatLng> mDirectionsPoints = new ArrayList<LatLng>();

    public boolean mIsPhoneMoving = false;
    public int mActivityType = -1;
    int counter = 0;

    private IntentFilter mBroadcastFilter;
    private DetectionRequester mDetectionRequester;
    private DetectionRemover mDetectionRemover;

    public MyService() {
        mContext = this;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
        // two arrays for position and time.
        positions = new double[data_points][2];
        times = new long[data_points];

        mStartTime = SystemClock.uptimeMillis();
        mHandler = new Handler();
        mHandler.postDelayed(countDownTimerThread, 0);
        mPreferences = getSharedPreferences(MyPreferences.PREFERENCES,
                Context.MODE_PRIVATE);
        // Create a new Intent filter for the broadcast receiver
        mBroadcastFilter = new IntentFilter(
                MyConstants.ACTION_REFRESH_STATUS_LIST);
        mBroadcastFilter.addCategory(MyConstants.CATEGORY_LOCATION_SERVICES);

        // Get detection requester and remover objects
        mDetectionRequester = new DetectionRequester(this);
        mDetectionRemover = new DetectionRemover(this);
        mDirectionsPoints.clear();
    }

    /**
     * Pause the timer
     */
    public void pauseRide() {
        timeSwapBuff += timeInMilliseconds;
        mHandler.removeCallbacks(countDownTimerThread);
        mLocationManager.removeUpdates(this);
    }

    /**
     * Restart the timer
     */
    public void reStartRide() {
        mStartTime = SystemClock.uptimeMillis();
        mHandler.postDelayed(countDownTimerThread, 0);
        mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                0, 0, this);
    }

    @Override
    public void onDestroy() {
        mHandler.removeCallbacks(countDownTimerThread);
        mLocationManager.removeUpdates(this);
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        getLocation();
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * Timer thread
     */
    private final Runnable countDownTimerThread = new Runnable() {

        public void run() {
            mHours = 0;
            timeInMilliseconds = SystemClock.uptimeMillis() - mStartTime;
            updatedTime = timeSwapBuff + timeInMilliseconds;
            int secs = (int) (updatedTime / 1000);
            final int mins = secs / 60;
            mHours = mins / 60;
            secs = secs % 60;

            final Message msg = new Message();
            final Bundle bundle = new Bundle();
            bundle.putInt(MyPreferences.BROADCAST_CODES, 300);
            bundle.putString(
                    "time",
                    String.format("%02d", mHours) + ":"
                            + String.format("%02d", mins) + ":"
                            + String.format("%02d", secs));
            msg.setData(bundle);
            final Intent intent = new Intent(MyConstants.BROADCAST_INTENT);
            intent.putExtras(bundle);
            sendBroadcast(intent);
            mHandler.postDelayed(this, 1000);
        }
    };

    @Override
    public IBinder onBind(final Intent intent) {
        return null;
    }

    @Override
    public void onLocationChanged(final Location location) {
        if (location != null) {
            LocationUtils.sLatitude = location.getLatitude();
            LocationUtils.sLongitude = location.getLongitude();

            mDirectionsPoints.add(new LatLng(LocationUtils.sLatitude,
                    LocationUtils.sLongitude));
            riderLocation(location);
        } else {
            Log.i(TAG, "Location is not available.");
        }
    }

    /**
     * Calculate speed, distance and average speed. Send Broadcast which
     * received by activities
     * 
     * @param location
     */
    private void riderLocation(final Location location) {
        DecimalFormat formatter = new DecimalFormat("#0.00");
        double distance = 0.0;
        Double speed = 0.0;
        long t1 = 0l;
        final float[] results = new float[3];

        positions[counter][0] = location.getLatitude();
        positions[counter][1] = location.getLongitude();
        times[counter] = location.getTime();

        final Bundle bundle = new Bundle();
        bundle.putInt(MyPreferences.BROADCAST_CODES, 200);

        distance = calculateDistance(positions[counter][0],
                positions[counter][1], positions[(counter + (data_points - 1))
                        % data_points][0],
                positions[(counter + (data_points - 1)) % data_points][1]);

        Location.distanceBetween(positions[counter][0], positions[counter][1],
                positions[(counter + (data_points - 1)) % data_points][0],
                positions[(counter + (data_points - 1)) % data_points][1],
                results);

        mTravelledDistance += results[0] / 1000;
        LocationUtils.sDistance = formatter
                .format((mTravelledDistance * 100.0) / 100.0);

        final double averageSpeed = mTravelledDistance / mHours;
        LocationUtils.sAverageSpeed = formatter
                .format((averageSpeed * 100.0) / 100.0);

        if (location.hasSpeed()) {
            speed = location.getSpeed() * 3.6;
            LocationUtils.sSpeed = speed.intValue();
        } else {
            try {
                t1 = times[counter]
                        - times[(counter + (data_points - 1)) % data_points];
            } catch (final NullPointerException e) {
                // all good, just not enough data yet.
            }

            speed = (distance / t1) * 3.6;
            LocationUtils.sSpeed = speed.intValue();
            counter = (counter + 1) % data_points;
        }

        LocationUtils.sLatitude = location.getLatitude();
        LocationUtils.sLongitude = location.getLongitude();

        final Intent intent = new Intent(MyConstants.BROADCAST_INTENT);
        intent.putExtras(bundle);
        sendBroadcast(intent);
    }

    public void onProviderDisabled(final String arg0) {
        Toast.makeText(getApplicationContext(), "Gps Disabled",
                Toast.LENGTH_LONG).show();
    }

    public void onProviderEnabled(final String arg0) {
        Toast.makeText(getApplicationContext(), "Gps Enabled",
                Toast.LENGTH_SHORT).show();
    }

    /**
     * @return location
     */
    public Location getLocation() {
        try {
            mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

            // getting GPS status
            isGPSEnabled = mLocationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER);

            if (!isGPSEnabled) {
                // no network provider is enabled
                showSettingsAlert();
            } else {
                // if GPS Enabled get lat/long using GPS Services
                if (isGPSEnabled) {
                    mLocationManager.requestLocationUpdates(
                            LocationManager.GPS_PROVIDER, 0, 0, this);
                    Log.d(TAG, "GPS Enabled");
                    if (mCurrentLocation == null) {
                        if (mLocationManager != null) {
                            mCurrentLocation = mLocationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);

                            if (mCurrentLocation != null) {
                                LocationUtils.sLatitude = mCurrentLocation
                                        .getLatitude();
                                LocationUtils.sLongitude = mCurrentLocation
                                        .getLongitude();
                            }
                        }
                    } else {
                        LocationUtils.sLatitude = mCurrentLocation
                                .getLatitude();
                        LocationUtils.sLongitude = mCurrentLocation
                                .getLongitude();
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return mCurrentLocation;
    }

    /**
     * @fn public static RidingTimerService getInstance()
     * @brief returns instance of the service.
     * @return RidingTimerService instance
     */
    public static MyService getInstance() {
        return mInstance;
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

    /**
     * Reset all the values stored in Preferences
     */
    public void resetAllText() {
        mPreferences.edit().putString(MyPreferences.LATITUDE, "0.0").commit();
        mPreferences.edit().putString(MyPreferences.LONGITUDE, "0.0")
                .commit();
        mPreferences.edit().putString(MyPreferences.SPEED, "0.0").commit();
        mPreferences.edit().putString(MyPreferences.AVERAGE_SPEED, "0.0")
                .commit();
        mPreferences.edit().putString(MyPreferences.DISTANCE, "0.0").commit();
    }

    /**
     * Respond to "Start" button by requesting activity recognition updates.
     * 
     * @param view
     *            The view that triggered this method.
     */
    public void onStartUpdates() {
        // Pass the update request to the requester object
        mDetectionRequester.requestUpdates();
    }

    /**
     * Respond to "Stop" button by canceling updates.
     * 
     * @param view
     *            The view that triggered this method.
     */
    public void onStopUpdates() {
        // Pass the remove request to the remover object
        mDetectionRemover.removeUpdates(mDetectionRequester
                .getRequestPendingIntent());

        /*
         * Cancel the PendingIntent. Even if the removal request fails,
         * canceling the PendingIntent will stop the updates.
         */
        mDetectionRequester.getRequestPendingIntent().cancel();
    }

    /**
     * Function to show settings alert dialog On pressing Settings button will
     * lauch Settings Options
     * */
    public void showSettingsAlert() {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
        alertDialog.setTitle("GPS");
        alertDialog.setMessage("GPS is not enabled. Do you want to enable it?");

        // On pressing Settings button
        alertDialog.setPositiveButton("Settings",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        Intent intent = new Intent(
                                Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        mContext.startActivity(intent);
                    }
                });

        // on pressing cancel button
        alertDialog.setNegativeButton("Cancel",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                });

        // Showing Alert Message
        alertDialog.show();
    }

    /**
     * @return List of Direction points
     */
    public ArrayList<LatLng> getDirectionsPoints() {
        if (mDirectionsPoints != null) {
            return mDirectionsPoints;
        } else {
            mDirectionsPoints = new ArrayList<LatLng>();
            return mDirectionsPoints;
        }
    }

    /**
     * Calculate distance
     * 
     * @param lat1
     * @param lon1
     * @param lat2
     * @param lon2
     * @return
     */
    private double calculateDistance(final double lat1, final double lon1,
            final double lat2, final double lon2) {
        // haversine great circle distance approximation, returns meters
        final double theta = lon1 - lon2;
        double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2))
                + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2))
                * Math.cos(deg2rad(theta));
        dist = Math.acos(dist);
        dist = rad2deg(dist);
        dist = dist * 60; // 60 nautical miles per degree of seperation
        dist = dist * 1852; // 1852 meters per nautical mile
        return dist;
    }

    private double deg2rad(final double deg) {
        return (deg * Math.PI / 180.0);
    }

    private double rad2deg(final double rad) {
        return (rad * 180.0 / Math.PI);
    }
}

我每1秒钟保持一次位置更新和每3秒钟进行一次活动识别更新。我能够获取位置信息,但在谷歌地图上路径未被正确绘制。

绘制路径的代码如下:

public class MapsActivity extends FragmentActivity {

    private static GoogleMap mGoogleMap = null;
    private static final String TAG = "MapsActivity";
    private Button mBtnStartRide, mBtnPauseRide, mBtnStopRide = null;
    private static TextView mTxtLatLong, mTxtTimer, mTxtTotalSize,
            mTxtSpeed = null;
    private static PolylineOptions mPolyLineOptions = null;
    // Storing the directions returned by the direcction api
    private SharedPreferences mPreferences = null;
    private MapsBroadcastReceiver receiver = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);

        receiver = new MapsBroadcastReceiver();
        mPreferences = getSharedPreferences(TestPreferences.PREFERENCES,
                Context.MODE_PRIVATE);

        mTxtLatLong = (TextView) findViewById(R.id.txtLatLong);
        mTxtTimer = (TextView) findViewById(R.id.txtTimer);
        mTxtTotalSize = (TextView) findViewById(R.id.txtDirectionsSize);
        mTxtSpeed = (TextView) findViewById(R.id.txtSpeed);

        mBtnStartRide = (Button) findViewById(R.id.btn_start_ride);
        mBtnPauseRide = (Button) findViewById(R.id.btn_pause_ride);
        mBtnStopRide = (Button) findViewById(R.id.btn_stop_ride);

        final Button mBtnCenter = (Button) findViewById(R.id.btn_center);
        mBtnCenter.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                animateCameraTo();
            }
        });

        mBtnStartRide.setOnClickListener(btnStartRideClickListener);
        mBtnPauseRide.setOnClickListener(btnPauseRideClickListener);
        mBtnStopRide.setOnClickListener(btnStopRideClickListener);

        initilizeMap();
    }

    /**
     * Start Ride Button Click Listener
     */
    private OnClickListener btnStartRideClickListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            if (mPreferences.getBoolean(TestPreferences.IS_RIDE_PAUSE, false)) {
                if (MyService.getInstance() != null) {
                    MyService.getInstance().reStartRide();
                }
            } else {
                startService(new Intent(MapsActivity.this,
                        MyService.class));
            }

            mPreferences.edit().putBoolean(TestPreferences.IS_RIDE_START, true)
                    .commit();
            mPreferences.edit().remove(TestPreferences.IS_RIDE_PAUSE).commit();
            mPreferences.edit().remove(TestPreferences.IS_RIDE_STOPPED)
                    .commit();

            mBtnStartRide.setVisibility(View.GONE);
            mBtnPauseRide.setVisibility(View.VISIBLE);
            mBtnStopRide.setVisibility(View.VISIBLE);
        }
    };

    /**
     * Start Ride Button Click Listener
     */
    private OnClickListener btnPauseRideClickListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            MyService.getInstance().pauseRide();

            mPreferences.edit().putBoolean(TestPreferences.IS_RIDE_PAUSE, true)
                    .commit();
            mPreferences.edit()
                    .putBoolean(TestPreferences.IS_RIDE_START, false).commit();
            mBtnStartRide.setVisibility(View.VISIBLE);
            mBtnPauseRide.setVisibility(View.GONE);
            mBtnStopRide.setVisibility(View.VISIBLE);
        }
    };

    /**
     * Stop Ride Button Click Listener
     */
    private OnClickListener btnStopRideClickListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            stopService(new Intent(MapsActivity.this, MyService.class));
            mPreferences.edit().remove(TestPreferences.IS_RIDE_PAUSE).commit();
            mPreferences.edit()
                    .putBoolean(TestPreferences.IS_RIDE_START, false).commit();
            mPreferences.edit()
                    .putBoolean(TestPreferences.IS_RIDE_STOPPED, true).commit();
            mBtnStartRide.setVisibility(View.VISIBLE);
            mBtnPauseRide.setVisibility(View.GONE);
            mBtnStopRide.setVisibility(View.GONE);
        }
    };

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(receiver, new IntentFilter(
                MyConstants.BROADCAST_INTENT));
        initilizeMap();

        if (mPreferences.getBoolean(TestPreferences.IS_RIDE_START, false)) {
            mBtnStartRide.setVisibility(View.GONE);
            mBtnPauseRide.setVisibility(View.VISIBLE);
            mBtnStopRide.setVisibility(View.VISIBLE);
        } else if (mPreferences
                .getBoolean(TestPreferences.IS_RIDE_PAUSE, false)) {
            mBtnStartRide.setVisibility(View.VISIBLE);
            mBtnPauseRide.setVisibility(View.GONE);
            mBtnStopRide.setVisibility(View.VISIBLE);
        } else if (mPreferences.getBoolean(TestPreferences.IS_RIDE_STOPPED,
                false)) {
            // Show start button and gone Pause & Stop both
            mBtnStartRide.setVisibility(View.VISIBLE);
            mBtnPauseRide.setVisibility(View.GONE);
            mBtnStopRide.setVisibility(View.GONE);
        } else {
            // Show start button and gone Pause & Stop both
            mBtnStartRide.setVisibility(View.VISIBLE);
            mBtnPauseRide.setVisibility(View.GONE);
            mBtnStopRide.setVisibility(View.GONE);
        }

        setAllText();
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(receiver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mGoogleMap = null;
    }

    /**
     * Function to load map. If map is not created it will create it for you
     * */
    private void initilizeMap() {
        if (mGoogleMap == null) {
            mGoogleMap = ((MapFragment) getFragmentManager().findFragmentById(
                    R.id.map)).getMap();
            // check if map is created successfully or not
            if (mGoogleMap == null) {
                Toast.makeText(getApplicationContext(),
                        "Sorry! unable to create maps", Toast.LENGTH_SHORT)
                        .show();
            } else {
                mPolyLineOptions = new PolylineOptions().width(6).color(
                        Color.BLUE);
                mGoogleMap.setTrafficEnabled(true);
                mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
                mGoogleMap.getUiSettings().setRotateGesturesEnabled(true);
                mGoogleMap.getUiSettings().setCompassEnabled(true);
                mGoogleMap.getUiSettings().setZoomGesturesEnabled(true);
                mGoogleMap.getUiSettings().setZoomControlsEnabled(true);

                if (MyService.getInstance() != null
                        && MyService.getInstance().getDirectionsPoints() != null
                        && !MyService.getInstance().getDirectionsPoints()
                                .isEmpty()
                        && MyService.getInstance().getDirectionsPoints()
                                .size() >= 1) {
                    mGoogleMap.addMarker(new MarkerOptions()
                            .position(
                                    MyService.getInstance()
                                            .getDirectionsPoints().get(0))
                            .anchor(0.8f, 1.0f).title("Your Location"));

                    animateCameraTo(MyService.getInstance()
                            .getDirectionsPoints().get(0).latitude,
                            MyService.getInstance().getDirectionsPoints()
                                    .get(0).longitude);
                }
            }
        } else {
            mPolyLineOptions = new PolylineOptions().width(6).color(Color.BLUE);
            mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
            mGoogleMap.getUiSettings().setRotateGesturesEnabled(true);
            mGoogleMap.getUiSettings().setCompassEnabled(true);
            mGoogleMap.getUiSettings().setZoomGesturesEnabled(true);
            mGoogleMap.getUiSettings().setZoomControlsEnabled(true);

            if (MyService.getInstance() != null
                    && MyService.getInstance().getDirectionsPoints() != null
                    && !MyService.getInstance().getDirectionsPoints()
                            .isEmpty()
                    && MyService.getInstance().getDirectionsPoints().size() >= 1) {

                Log.i(TAG, "Lat long in resume2222222222 = "
                        + MyService.getInstance().getDirectionsPoints()
                                .get(0).latitude
                        + ", "
                        + MyService.getInstance().getDirectionsPoints()
                                .get(0).longitude);

                mGoogleMap.addMarker(new MarkerOptions()
                        .position(
                                MyService.getInstance().getDirectionsPoints()
                                        .get(0)).anchor(0.8f, 1.0f)
                        .title("Your Location"));

                animateCameraTo(MyService.getInstance().getDirectionsPoints()
                        .get(0).latitude, MyService.getInstance()
                        .getDirectionsPoints().get(0).longitude);
            }
        }
    }

    /**
     * @author Scorpion
     * 
     */
    private class MapsBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            switch (intent.getExtras().getInt(TestPreferences.BROADCAST_CODES)) {
            case 100:
                showErrorDialog(intent.getExtras().getInt(
                        TestPreferences.BROADCAST_CODES));
                break;

            case 200:
                setAllText();
                break;

            case 300:
                if (intent.getExtras().getString("time") != null) {
                    mTxtTimer.setText("Timer - "
                            + intent.getExtras().getString("time"));
                } else {
                    mTxtTimer.setText("Timer - 00:00:00");
                }
                break;

            default:
                break;
            }

            if (MyService.getInstance() != null
                    && !MyService.getInstance().getDirectionsPoints()
                            .isEmpty()
                    && MyService.getInstance().getDirectionsPoints().size() == 1) {
                mGoogleMap.addMarker(new MarkerOptions()
                        .position(
                                MyService.getInstance().getDirectionsPoints()
                                        .get(0)).anchor(0.8f, 1.0f)
                        .title("Your Location"));
            }

        }
    }

    /**
     * 
     */
    public void setAllText() {
        mTxtLatLong.setText("Lat - " + LocationUtils.sLatitude + ", Lng - "
                + LocationUtils.sLongitude);

        mTxtSpeed.setText("Speed - " + LocationUtils.sSpeed);
        mTxtTotalSize.setText("Distance - " + LocationUtils.sDistance);
    }

    /**
     * Animate to position on Google Maps
     * 
     * @param lat
     * @param lng
     */
    private void animateCameraTo() {
        // Saving the points in a polyline

        if (MyService.getInstance() != null
                && MyService.getInstance().getDirectionsPoints() != null
                && !MyService.getInstance().getDirectionsPoints().isEmpty()) {
            mPolyLineOptions.geodesic(true);
            mPolyLineOptions.addAll(MyService.getInstance()
                    .getDirectionsPoints());

            // Drawing the path on the map Polyline route =
            mGoogleMap.addPolyline(mPolyLineOptions);

            int index = MyService.getInstance().getDirectionsPoints().size() - 1;
            CameraPosition cameraPosition = new CameraPosition.Builder()
                    .target(MyService.getInstance().getDirectionsPoints()
                            .get(index)).zoom(20).build();

            mGoogleMap.animateCamera(CameraUpdateFactory
                    .newCameraPosition(cameraPosition));
        }

    }

    /**
     * Animate to position on Google Maps
     * 
     * @param lat
     * @param lng
     */
    private void animateCameraTo(final double lat, final double lng) {
        // Saving the points in a polyline
        if (MyService.getInstance() != null
                && MyService.getInstance().getDirectionsPoints() != null
                && !MyService.getInstance().getDirectionsPoints().isEmpty()) {
            mPolyLineOptions.geodesic(true);
            mPolyLineOptions.addAll(MyService.getInstance()
                    .getDirectionsPoints());

            // Drawing the path on the map
            mGoogleMap.addPolyline(mPolyLineOptions);
            CameraPosition cameraPosition = new CameraPosition.Builder()
                    .target(new LatLng(lat, lng)).zoom(20).build();

            mGoogleMap.animateCamera(CameraUpdateFactory
                    .newCameraPosition(cameraPosition));
        }

    }

    /**
     * Show a dialog returned by Google Play services for the connection error
     * code
     * 
     * @param errorCode
     *            An error code returned from onConnectionFailed
     */
    private void showErrorDialog(int errorCode) {

        // Get the error dialog from Google Play services
        Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(errorCode,
                MapsActivity.this,
                LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);

        // If Google Play services can provide an error dialog
        if (errorDialog != null) {

            // Create a new DialogFragment in which to show the error dialog
            ErrorDialogFragment errorFragment = new ErrorDialogFragment();

            // Set the dialog in the DialogFragment
            errorFragment.setDialog(errorDialog);

            // Show the error dialog in the DialogFragment
            errorFragment.show(getSupportFragmentManager(),
                    LocationUtils.APPTAG);
        }
    }
}

从位置提供程序得到的坐标结果: 23.030392522689674、72.5570888165469、23.030408166940184、72.55708600340783、23.030451207802273、72.55708215400317、23.030448342522195、72.5570607428365、23.03045605637773、72.55702903413072、23.03046687434995、72.55702007867455、23.030481227996425、72.55702017125606、23.03049188235562、72.55701618151457、23.030501580461667、72.55701051075931、23.030506644074638、72.55700568837983、23.030510243171772、72.55699463185964、23.03051656621021、72.55698811382064、23.030523584332027、72.55698589863236、23.030527893257556、72.5569835596、23.03052731568596、72.55698681171178、23.030533706759005、72.55699683791043、23.03053795413862、72.5570022232021、23.03054422659466、72.55700788646914、23.030550353227323、72.5570133047868、23.03056167617575、72.5570171806126、23.030572274532982、72.55702744953462、23.03057623596164、72.55703687229187、23.03058756510295、72.55703589208271、23.030591797598742、72.5570396833694、23.030597556470788、72.55703954449652、23.030602030769657、72.55704359454182、23.030606735158617、72.55704993131606、23.030611670633565、72.55705060538087、23.030618875802222、72.55705181604097、23.030629137631596、72.55705043471286、23.030651405170016、72.55705440295588、23.03066642161307、72.55705285209174、23.030690454277963、72.55703884780276、23.030708214416187、72.55703489882957、23.03072341369183、72.5570340196122、23.030737371000015、72.55703289416898、23.03075088423441、72.55703750535102、23.030767572625837、72.55704489874579、23.030794398930176、72.55703870239826、23.03081655932613、72.55702474270966、23.030827505666753、72.5570121351611、23.03083720431765、72.55700390084714、23.03084624667527、72.55700122660554、23.030859495795887、72.55699948514881、23.030870357210333、72.55699625144317、23.030881843633054

这有点困难,因为有很多编码,很可能与问题无关。但是,使用LocationUtils的静态字段非常可疑。如果此类被不同线程同时使用,则结果坐标是不可预测的。 - user2808624
我使用了LocationUtils类来存储速度、距离和位置(纬度/经度),其他活动也会使用这些值。因此,我同意这些值被同时使用,但只有我的服务在其中写入值,其他活动和类只是读取这些值以显示它们。没有别的…… - Scorpion
你有检查过一次GPS更新中onLocationChanged被调用的频率吗?我不确定如果同一个LocationListener被多次注册会发生什么(就像在你的服务中那样)。我记得我曾经设法被多次调用。但我不记得是不是相同的情况,或者是我意外地创建了多个LocationListeners实例。 - user2808624
我每秒都在获取位置更新,我只注册了一个位置监听器而不是多个。我还检查速度,所以如果速度为0,我就不会将点添加到我的列表中并避免这些点。主要问题是绘制的路线实际上并不是应该绘制的位置。由于某种原因,它总是在道路外绘制。 - Scorpion
1
现在,我看到 requestLocationUpdates 两次。其中一个在 reStart 方法内部,似乎被多次调用。结合静态的 LocationUtils,这仍然看起来很可疑。 - user2808624
3个回答

9
这段代码将会运行。
GoogleMap map;
   // ... get a map.
   // Add a thin red line from London to New York.
   Polyline line = map.addPolyline(new PolylineOptions()
       .add(new LatLng(51.5, -0.1), new LatLng(40.7, -74.0))
       .width(5)
       .color(Color.RED));

2
我正在使用相同的代码,但它并没有按照要求工作。它绘制了偏离道路的路径,而不是用户实际行驶/步行的准确位置。 - Scorpion
@Scorpion,为了让它更好地按照要求工作,您可以将位置更新请求中的准确度设置为优先准确度,并稍微缩短更新间隔。 - Daniel Kvist

2
你应该将问题分解为数据收集和数据展示两个方面。
因此,选择两个你精确知道的坐标,并在Google地图上绘制一条直线折线。 如果它显示在错误的位置,那么GoogleMap确实存在一个bug,不过我并不相信。
然后在绘制之前将你的坐标打印出来,例如使用LogCat,并检查这些坐标。如果它们是错误的,那么问题不是GoogleMaps的问题,而是LocationProvider或者你如何使用它的问题。
如果正确收集了坐标,你可以从LogCat中获取这些坐标并直接在你的代码中使用它们来绘制折线。如果折线再次错位,那么你可能又发现了一个GoogleMap的bug。那么你应该在此处粘贴坐标,以便有人可以复制它。它可能与设备有关。我从未遇到过折线与地图不匹配的情况。

我已经加入了从位置提供者获取的位置。你知道如何在Google地图上从这个位置获取路线吗?我不是在询问如何使用Android绘制路线。我想要在线交叉检查这个位置。有没有任何方法可以交叉检查它? - Scorpion
或者你可以从位置结果判断它们是否正确? - Scorpion
得到了这个网站..http://www.darrinward.com/lat-long/ 我把所有的位置都添加进去了,它显示的结果和我的设备上一样。所以我们可以说问题出在位置(纬度/经度)上,这是我从位置提供者那里获取的。但我不认为这是一个问题,还有其他我可能忽略的东西。 - Scorpion
也许你的GPS有点不准确。我认为有很多应用程序可以跟踪并在地图上显示路线。只需在同一设备上尝试使用它们,看看它们是否显示更好的结果。 - user2808624

1
你绘制路径的代码看起来很奇怪。在for循环内部,你应该只将点添加到PolylineOptions的实例中(在进入for循环之前创建)。
然后,在for循环之后,你可以向polylineOptions对象添加widthcolor等属性,最后使用mGoogleMap.addPolyline()
在你的编码中,你以某种方式为每个点添加了一个新的polyline(我想知道这是否真的会画出线,因为每条“线”仅由一个点组成)。

感谢您的评论。最初我在循环内部使用了PolyLineOptions,但我已经在代码中进行了更新。但即使如此,路径仍然绘制在道路之外,我正在驾驶车辆行驶在道路上,但我的路径始终显示在道路附近...这是代码的主要问题... - Scorpion
我非常确定问题与绘制折线无关,而是与来自RidingTimerService的LatLng点有关。(这是您自己的类还是某个库?找不到它。)我有一个类似的应用程序,其中折线完美地匹配了我的实际路径。 - user2808624
这是我自己的类,没有使用任何库。如果您不介意,能否分享一些您的代码片段。我从Android开发者网站使用了代码,并使用了Google Maps Android API v2最新的代码示例,并为此使用了Google Play服务sdk... - Scorpion
同样为了准确获取位置,我设置了位置更新间隔为1秒。在onLocationChanged方法中,我将经度和纬度存储在一个列表中,并从该列表中在谷歌地图上绘制路径。 - Scorpion
我已经添加了我的服务类的完整源代码以供参考。如果您能帮助我解决这个问题,那对我来说将是非常大的帮助。 - Scorpion
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接