无法在 google 地图中导航 activity 它总是会回到我当前的位置
Can't navigate in google maps activity it always spawns back to my current location
我是 android 开发的新手,正在开发一个需要 google 地图 activity 的应用程序。
我面临的问题是,当我尝试平移(或滚动)地图时,我会立即重生到我最初设置的当前位置。
一点帮助会很棒,因为我被困在这一点上并且无法找到解决方案。
这是代码:-
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMapsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.getUiSettings().setScrollGesturesEnabled(true);
locationManager=(LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
locationListener=new LocationListener() {
@Override
public void onLocationChanged(@NonNull Location location) {
centerOnMap(location,"Your Location");
}
};
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
}
else{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
Location lastKnownLocation=locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
centerOnMap(lastKnownLocation,"Your Location");
}
}
public void centerOnMap(Location location,String address)
{
LatLng userLocation = new LatLng(location.getLatitude(),location.getLongitude());
mMap.addMarker(new MarkerOptions().position(userLocation).title(address));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull @org.jetbrains.annotations.NotNull String[] permissions, @NonNull @org.jetbrains.annotations.NotNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED)
{
if(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
}
}
}
}
您可能有但未说明的一项要求是:
When the lastLocation
becomes available and the user has
not moved the map then center the map on the location. If the
user has already moved the map then do not center the map. In
either case, add a marker at the user's location.
在走得太远之前必须注意 Google 地图提供了一个
功能类似于您要实现的功能,尽管您仍然需要“移动相机”。标记是一个蓝球,而不是典型的标记。参见 myMap.setMyLocationEnabled(true)
。而已!在获得地图权限后执行此操作。
但如果您不想使用它,那么这里是您需要的简单更改。
请记住 LocationManager
getLastKnownLocation
可以 return
如果设备(还)没有,则为 null。所以我推荐一个小的
改变一点无关 - 让位置侦听器完成所有工作并摆脱这个特殊情况:
// this is where you initially check permissions and have them.
else{
locationManager.requestLocationUpdates (LocationManager.GPS_PROVIDER,0,0,locationListener);
// Here I removed the last location centering and let the
// location listener always handle it.
}
所以这打开了可能性
用户可以与地图进行交互,最后到达最后一个位置。我了解到这是您要解决的问题。
(顺便说一句,在我看来,您将 android.location.LocationManager
与
FusedLocationProviderApi
(com.google.android.gms.location) 所以我无法得到你的
由于 LocationListener
s 不兼容而需要编译的代码。
不幸的是,Google 地图有两个 LocationListener
class,所以
可以肯定的是,您必须包括您的导入才能进一步理解。)
总之...
当地图第一次准备好(onMapReady
)时,地图的相机是
以 (0,0)
为中心。您可以获得相机目标位置(中心)
随时使用 LatLng tgtCtr = mMap.getCameraPosition().target;
.
奇怪的是,要知道用户是否有
以任何方式与地图互动:滚动事件生成相机
变化而触摸事件产生一个单独的事件。相机变化
不能专门使用,因为您的代码或用户可能只是
缩放不移动地图。你可以走这条路但是
为了这个答案的目的,为了简单起见,相机
使用目标。
声明一个class实例变量(与定义mMap
的区域相同):
LatLng tgtCtr;
所以在你的 onMapReady
分配 mMap
之后做:
tgtCtr = mMap.getCameraPosition().target;
因此,假设您的代码在您发布时存在(非常接近),那么这些
更改可能会有所帮助:
// This change simply restricts centering of the map on location
// update to only when user has not moved the map (scrolled).
@Override
public void onLocationChanged(@NonNull Location location) {
LatLng currentCtr = mMap.getCamaraPosition().target;
// This is not the ideal check since `double` comparisons
// should account for epsilon but in this case of (0,0) it should work.
// Alternatively you could compute the distance of current
// center to (0,0) and then use an epsilon:
// see `com.google.maps.android.SphericalUtil.computeDistanceBetween`.
if (currentCtr.latitude == 0 && currentCtr.longitude == 0) {
centerOnMap(location,"Your Location");
}
}
保存为用户添加的标记似乎也是个好主意
location - 这是可选的,但可能会派上用场以防止多个标记
从被添加到那个位置:
// Define a class instance variable
Marker myLocMarker = nulll;
// and then in centerOnMap
public void centerOnMap(Location location, String address)
{
// ... other code
if (myLocMarker == null) {
myLocMarker = mMap.addMarker(new MarkerOptions().position(userLocation).title(address));
}
// ... more code
}
所以真正唯一的困难是弄清楚“有
用户移动了地图。”在这种情况下,基于初始需求
你不想移动地图。
正如您在评论部分提到的,使用 FusedLocationProviderClient 而不是 LocationManager。
在应用级别 gradle 中添加 implementation 'com.google.android.gms:play-services-location:17.0.0'
。并且不要忘记为精细位置添加清单权限。
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
FusedLocationProviderClient mFusedLocationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.getUiSettings().setScrollGesturesEnabled(true);
getLastLocation();
mMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
@Override
public void onMapLongClick(@NonNull LatLng latLng) {
Location location = new Location(LocationManager.GPS_PROVIDER);
location.setLatitude(latLng.latitude);
location.setLongitude(latLng.longitude);
centerOnMap(location,"Your location");
}
});
}
@SuppressLint("MissingPermission")
private void getLastLocation() {
if (checkPermissions()) {
if (isLocationEnabled()) {
mFusedLocationClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
@Override
public void onComplete(@NonNull Task<Location> task) {
Location location = task.getResult();
if (location == null) {
requestNewLocationData();
} else {
centerOnMap(location,"Your Location");
}
}
});
} else {
Toast.makeText(this, "Please turn on" + " your location...", Toast.LENGTH_LONG).show();
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
} else {
requestPermissions();
}
}
@SuppressLint("MissingPermission")
private void requestNewLocationData() {
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(5);
mLocationRequest.setFastestInterval(0);
mLocationRequest.setNumUpdates(1);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
private LocationCallback mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
Location mLastLocation = locationResult.getLastLocation();
centerOnMap(mLastLocation,"Your Location");
}
};
private boolean checkPermissions() {
return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
private void requestPermissions() {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}
private boolean isLocationEnabled() {
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
public void centerOnMap(Location location,String address)
{
LatLng userLocation = new LatLng(location.getLatitude(),location.getLongitude());
mMap.clear();
mMap.addMarker(new MarkerOptions().position(userLocation).title(address));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED)
{
getLastLocation();
}
}
}
我是 android 开发的新手,正在开发一个需要 google 地图 activity 的应用程序。 我面临的问题是,当我尝试平移(或滚动)地图时,我会立即重生到我最初设置的当前位置。 一点帮助会很棒,因为我被困在这一点上并且无法找到解决方案。 这是代码:-
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMapsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.getUiSettings().setScrollGesturesEnabled(true);
locationManager=(LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
locationListener=new LocationListener() {
@Override
public void onLocationChanged(@NonNull Location location) {
centerOnMap(location,"Your Location");
}
};
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
}
else{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
Location lastKnownLocation=locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
centerOnMap(lastKnownLocation,"Your Location");
}
}
public void centerOnMap(Location location,String address)
{
LatLng userLocation = new LatLng(location.getLatitude(),location.getLongitude());
mMap.addMarker(new MarkerOptions().position(userLocation).title(address));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull @org.jetbrains.annotations.NotNull String[] permissions, @NonNull @org.jetbrains.annotations.NotNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED)
{
if(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
}
}
}
}
您可能有但未说明的一项要求是:
When the
lastLocation
becomes available and the user has not moved the map then center the map on the location. If the user has already moved the map then do not center the map. In either case, add a marker at the user's location.
在走得太远之前必须注意 Google 地图提供了一个
功能类似于您要实现的功能,尽管您仍然需要“移动相机”。标记是一个蓝球,而不是典型的标记。参见 myMap.setMyLocationEnabled(true)
。而已!在获得地图权限后执行此操作。
但如果您不想使用它,那么这里是您需要的简单更改。
请记住 LocationManager
getLastKnownLocation
可以 return
如果设备(还)没有,则为 null。所以我推荐一个小的
改变一点无关 - 让位置侦听器完成所有工作并摆脱这个特殊情况:
// this is where you initially check permissions and have them.
else{
locationManager.requestLocationUpdates (LocationManager.GPS_PROVIDER,0,0,locationListener);
// Here I removed the last location centering and let the
// location listener always handle it.
}
所以这打开了可能性 用户可以与地图进行交互,最后到达最后一个位置。我了解到这是您要解决的问题。
(顺便说一句,在我看来,您将 android.location.LocationManager
与
FusedLocationProviderApi
(com.google.android.gms.location) 所以我无法得到你的
由于 LocationListener
s 不兼容而需要编译的代码。
不幸的是,Google 地图有两个 LocationListener
class,所以
可以肯定的是,您必须包括您的导入才能进一步理解。)
总之...
当地图第一次准备好(onMapReady
)时,地图的相机是
以 (0,0)
为中心。您可以获得相机目标位置(中心)
随时使用 LatLng tgtCtr = mMap.getCameraPosition().target;
.
奇怪的是,要知道用户是否有 以任何方式与地图互动:滚动事件生成相机 变化而触摸事件产生一个单独的事件。相机变化 不能专门使用,因为您的代码或用户可能只是 缩放不移动地图。你可以走这条路但是 为了这个答案的目的,为了简单起见,相机 使用目标。
声明一个class实例变量(与定义mMap
的区域相同):
LatLng tgtCtr;
所以在你的 onMapReady
分配 mMap
之后做:
tgtCtr = mMap.getCameraPosition().target;
因此,假设您的代码在您发布时存在(非常接近),那么这些 更改可能会有所帮助:
// This change simply restricts centering of the map on location
// update to only when user has not moved the map (scrolled).
@Override
public void onLocationChanged(@NonNull Location location) {
LatLng currentCtr = mMap.getCamaraPosition().target;
// This is not the ideal check since `double` comparisons
// should account for epsilon but in this case of (0,0) it should work.
// Alternatively you could compute the distance of current
// center to (0,0) and then use an epsilon:
// see `com.google.maps.android.SphericalUtil.computeDistanceBetween`.
if (currentCtr.latitude == 0 && currentCtr.longitude == 0) {
centerOnMap(location,"Your Location");
}
}
保存为用户添加的标记似乎也是个好主意 location - 这是可选的,但可能会派上用场以防止多个标记 从被添加到那个位置:
// Define a class instance variable
Marker myLocMarker = nulll;
// and then in centerOnMap
public void centerOnMap(Location location, String address)
{
// ... other code
if (myLocMarker == null) {
myLocMarker = mMap.addMarker(new MarkerOptions().position(userLocation).title(address));
}
// ... more code
}
所以真正唯一的困难是弄清楚“有 用户移动了地图。”在这种情况下,基于初始需求 你不想移动地图。
正如您在评论部分提到的,使用 FusedLocationProviderClient 而不是 LocationManager。
在应用级别 gradle 中添加 implementation 'com.google.android.gms:play-services-location:17.0.0'
。并且不要忘记为精细位置添加清单权限。
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
FusedLocationProviderClient mFusedLocationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.getUiSettings().setScrollGesturesEnabled(true);
getLastLocation();
mMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
@Override
public void onMapLongClick(@NonNull LatLng latLng) {
Location location = new Location(LocationManager.GPS_PROVIDER);
location.setLatitude(latLng.latitude);
location.setLongitude(latLng.longitude);
centerOnMap(location,"Your location");
}
});
}
@SuppressLint("MissingPermission")
private void getLastLocation() {
if (checkPermissions()) {
if (isLocationEnabled()) {
mFusedLocationClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
@Override
public void onComplete(@NonNull Task<Location> task) {
Location location = task.getResult();
if (location == null) {
requestNewLocationData();
} else {
centerOnMap(location,"Your Location");
}
}
});
} else {
Toast.makeText(this, "Please turn on" + " your location...", Toast.LENGTH_LONG).show();
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
} else {
requestPermissions();
}
}
@SuppressLint("MissingPermission")
private void requestNewLocationData() {
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(5);
mLocationRequest.setFastestInterval(0);
mLocationRequest.setNumUpdates(1);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
private LocationCallback mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
Location mLastLocation = locationResult.getLastLocation();
centerOnMap(mLastLocation,"Your Location");
}
};
private boolean checkPermissions() {
return ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
private void requestPermissions() {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}
private boolean isLocationEnabled() {
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
public void centerOnMap(Location location,String address)
{
LatLng userLocation = new LatLng(location.getLatitude(),location.getLongitude());
mMap.clear();
mMap.addMarker(new MarkerOptions().position(userLocation).title(address));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED)
{
getLastLocation();
}
}
}