android - 在实时纬度和经度之间绘制路线
问题描述
现在我正在获取纬度和经度 n 时间,如果我用手机移动标记也会根据纬度和经度移动,但是如果手机改变位置,我需要画一条路线。例如,我有 T1、T2、T4、T5 时间纬度经度点我需要绘制从 T1 到 T2 和 T2 到 T3 和 T3 到 T4 的路线所以实时,我无法画线。
主要活动
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private static final int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 5445;
private GoogleMap googleMap;
private FusedLocationProviderClient fusedLocationProviderClient;
private Marker currentLocationMarker;
private Location currentLocation;
private boolean firstTimeFlag = true;
private final View.OnClickListener clickListener = view -> {
if (view.getId() == R.id.currentLocationImageButton && googleMap != null && currentLocation != null)
animateCamera(currentLocation);
};
private final LocationCallback mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
if (locationResult.getLastLocation() == null)
return;
currentLocation = locationResult.getLastLocation();
if (firstTimeFlag && googleMap != null) {
animateCamera(currentLocation);
firstTimeFlag = false;
}
showMarker(currentLocation);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SupportMapFragment supportMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment);
supportMapFragment.getMapAsync(this);
findViewById(R.id.currentLocationImageButton).setOnClickListener(clickListener);
mydb = new DatabaseHelper(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
this.googleMap = googleMap;
}
private void startCurrentLocationUpdates() {
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(3000);
//locationRequest.setFastestInterval(1000);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
return;
}
}
fusedLocationProviderClient.requestLocationUpdates(locationRequest, mLocationCallback,
Looper.myLooper());
}
private boolean isGooglePlayServicesAvailable() {
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
int status = googleApiAvailability.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status)
return true;
else {
if (googleApiAvailability.isUserResolvableError(status))
Toast.makeText(this, "Please Install google play services to use this application", Toast.LENGTH_LONG).show();
}
return false;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION) {
if (grantResults[0] == PackageManager.PERMISSION_DENIED)
Toast.makeText(this, "Permission denied by uses", Toast.LENGTH_SHORT).show();
else if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
startCurrentLocationUpdates();
}
}
private void animateCamera(@NonNull Location location) {
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(getCameraPositionWithBearing(latLng)));
addLines(latLng);
AddData(location);
}
@NonNull
private CameraPosition getCameraPositionWithBearing(LatLng latLng) {
addLines(latLng);
return new CameraPosition.Builder().target(latLng).zoom(16).build();
}
private void showMarker(@NonNull Location currentLocation) {
LatLng latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
BitmapDescriptor icon =
BitmapDescriptorFactory.fromResource(R.drawable.ic_person_pin_circle_black_24dp);
addLines(latLng);
viewAll();
if (currentLocationMarker == null)
currentLocationMarker = googleMap.addMarker(new
MarkerOptions().icon(BitmapDescriptorFactory.defaultMarker()).flat(true).position(latLng));
else
MarkerAnimation.animateMarkerToGB(currentLocationMarker, latLng, new LatLngInterpolator.Spherical());
}
@Override
protected void onStop() {
super.onStop();
if (fusedLocationProviderClient != null)
fusedLocationProviderClient.removeLocationUpdates(mLocationCallback);
}
@Override
protected void onResume() {
super.onResume();
if (isGooglePlayServicesAvailable()) {
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
startCurrentLocationUpdates();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
fusedLocationProviderClient = null;
googleMap = null;
}
private void addLines(LatLng latLng) {
LatLng TIMES_SQUARE = new LatLng(latLng.latitude, latLng.longitude);
LatLng BROOKLYN_BRIDGE = new LatLng(latLng.latitude, latLng.longitude);
LatLng LOWER_MANHATTAN = new LatLng(latLng.latitude, latLng.longitude);
Log.i("===Lat", String.valueOf(latLng.latitude));
Log.i("===Longt", String.valueOf(latLng.longitude));
String polyLine = "q`epCakwfP_@EMvBEv@iSmBq@GeGg@}C]mBS{@KTiDRyCiBS";
List<LatLng> polyLineList = Collections.singletonList(TIMES_SQUARE);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (LatLng latLng1 : polyLineList) {
builder.include(latLng1);
googleMap.addPolyline((new PolylineOptions())
//.add(TIMES_SQUARE, LOWER_MANHATTAN,TIMES_SQUARE).width(5).color(Color.RED)
//.add( new LatLng(14.2354843, 76.2484165), new LatLng(14.2251, 76.3980)).width(5).color(Color.RED)
.add(new LatLng(latLng.latitude, latLng.longitude), new LatLng(latLng.latitude, latLng.longitude)).addAll(polyLineList).width(5).color(Color.BLUE)
.geodesic(true));
PolylineOptions polylineOptions = new PolylineOptions();
polylineOptions.color(Color.BLACK);
polylineOptions.width(5);
polylineOptions.startCap(new SquareCap());
polylineOptions.endCap(new SquareCap());
polylineOptions.jointType(ROUND);
polylineOptions.addAll(polyLineList);
Polyline greyPolyLine = googleMap.addPolyline(polylineOptions);
}
;
// move camera to zoom on map
// googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LOWER_MANHATTAN,13));
}
}
标记动画
public class MarkerAnimation {
public static void animateMarkerToGB(final Marker marker, final LatLng finalPosition, final LatLngInterpolator latLngInterpolator) {
final LatLng startPosition = marker.getPosition();
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final Interpolator interpolator = new AccelerateDecelerateInterpolator();
final float durationInMs = 3000;
handler.post(new Runnable() {
long elapsed;
float t;
float v;
@Override
public void run() {
// Calculate progress using interpolator
elapsed = SystemClock.uptimeMillis() - start;
t = elapsed / durationInMs;
v = interpolator.getInterpolation(t);
marker.setPosition(latLngInterpolator.interpolate(v, startPosition, finalPosition));
// Repeat till progress is complete.
if (t < 1) {
// Post again 16ms later.
//handler.postDelayed(this, 16);
handler.postDelayed(this, 16);
}
}
});
}
}
LatLngInterpolator 接口
public interface LatLngInterpolator {
LatLng interpolate(float fraction, LatLng a, LatLng b);
class Spherical implements LatLngInterpolator {
/* From github.com/googlemaps/android-maps-utils */
@Override
public LatLng interpolate(float fraction, LatLng from, LatLng to) {
// http://en.wikipedia.org/wiki/Slerp
double fromLat = toRadians(from.latitude);
double fromLng = toRadians(from.longitude);
double toLat = toRadians(to.latitude);
double toLng = toRadians(to.longitude);
double cosFromLat = cos(fromLat);
double cosToLat = cos(toLat);
// Computes Spherical interpolation coefficients.
double angle = computeAngleBetween(fromLat, fromLng, toLat, toLng);
double sinAngle = sin(angle);
if (sinAngle < 1E-6) {
return from;
}
double a = sin((1 - fraction) * angle) / sinAngle;
double b = sin(fraction * angle) / sinAngle;
// Converts from polar to vector and interpolate.
double x = a * cosFromLat * cos(fromLng) + b * cosToLat * cos(toLng);
double y = a * cosFromLat * sin(fromLng) + b * cosToLat * sin(toLng);
double z = a * sin(fromLat) + b * sin(toLat);
// Converts interpolated vector back to polar.
double lat = atan2(z, sqrt(x * x + y * y));
double lng = atan2(y, x);
return new LatLng(toDegrees(lat), toDegrees(lng));
}
private double computeAngleBetween(double fromLat, double fromLng, double toLat, double toLng) {
// Haversine's formula
double dLat = fromLat - toLat;
double dLng = fromLng - toLng;
return 2 * asin(sqrt(pow(sin(dLat / 2), 2) +
cos(fromLat) * cos(toLat) * pow(sin(dLng / 2), 2)));
}
}
}
解决方案
考虑用此方法替换您的addLines
方法,该方法在每次更新时维护和重绘折线:
private List<LatLng> polyLineList = new ArrayList<>();
private Polyline greyPolyLine;
private void addToLine(LatLng pt)
{
polyLineList.add(pt);
if (greyPolyLine != null)
{
greyPolyLine.remove();
}
PolylineOptions polylineOptions = new PolylineOptions();
polylineOptions.color(Color.BLACK);
polylineOptions.width(5);
polylineOptions.startCap(new SquareCap());
polylineOptions.endCap(new SquareCap());
polylineOptions.jointType(ROUND);
polylineOptions.addAll(polyLineList);
greyPolyLine = googleMap.addPolyline(polylineOptions);
}
您addLine
只是在每次调用时绘制一个点 - 单个点不太可能是可见的。
可能只需要在showMarker
方法中调用它 - 不知道你为什么addLines
在相机方法中调用它。
推荐阅读
- jquery - 使用 ajax 传递链接的值
- css - 设置显示:无不适用于 fa 图标
- javascript - vue中如何在父子组件之间传递值?
- java - Spring MVC 多模块
- ruby-on-rails - 修改.erb文件时如何自动重新加载RoR应用程序页面
- redis - 如何在脚本中对 lua 表结果进行 zscan
- c++ - 即使 C++ 中包含类头文件,类也不命名类型错误?
- java - .whereArrayContains() 查询时的意外行为
- php - 使用 set_exception_handler 在 PHP error_log 中重复条目
- java - 如何使用java将excel文件导入数据库而不给出“create table ...”脚本