无法使用唯一键从 Firebase 检索用户位置数据
Posted
技术标签:
【中文标题】无法使用唯一键从 Firebase 检索用户位置数据【英文标题】:Unable to retrieve user location data from Firebase with unique key 【发布时间】:2021-12-02 16:21:20 【问题描述】:我已成功地在 Firebase 中为我的数据库架构添加了一个唯一键,而不是使用 push()
,以防止它在位置刷新时生成新的推送键。
"Users" :
"RCX2HZXIwlSmMHFgDytf1DgZBgi2" :
"Alert Level" : "High",
"Emergency Type" : "Natural Disaster",
"User Location" :
"latitude" : 15.5352917,
"longitude" : 120.7742867
,
"address" : "Lapaz Tarlac",
"emergencyNum" : "0981232387346",
"name" : "Rafael Campos",
"phoneNum" : "0981233445675"
我检查了从 Realtime Databse 检索位置的另一个应用程序,但用户的位置根本没有反映在地图上。我一直在代码中配置数据库引用以获取用户位置的正确路径,但应用程序不断从 NullPointerExceptions 崩溃。我应该如何引用正确的子键,尤其是用户的唯一键?
private GoogleMap mMap;
private ActivityRetrieveMapsBinding binding;
private Location mLocation;
private LocationManager mLocationManager;
private LocationRequest mLocationRequest;
private com.google.android.gms.location.LocationListener listener;
private LocationManager locationManager;
GoogleApiClient mGoogleApiClient;
public static final int REQUEST_CHECK_SETTINGS = 1001;
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
binding = ActivityRetrieveMapsBinding.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);
mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
checkLocation();
if (mGoogleApiClient == null)
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks((GoogleApiClient.ConnectionCallbacks) this)
.addOnConnectionFailedListener((GoogleApiClient.OnConnectionFailedListener) this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>()
@Override
public void onResult(@NonNull LocationSettingsResult locationSettingsResult)
final Status status = locationSettingsResult.getStatus();
final LocationSettingsStates LS_state = locationSettingsResult.getLocationSettingsStates();
switch (status.getStatusCode())
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(RetrieveMapsActivity.this, REQUEST_CHECK_SETTINGS);
catch (IntentSender.SendIntentException e)
// Ignore the error.
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
);
private boolean checkLocation()
if(!isLocationEnabled())
showAlert();
return isLocationEnabled();
private void showAlert()
final AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle("Enable Location")
.setMessage("Your Locations Settings is set to 'Off'.\nPlease Enable Location to " +
"use this app")
.setPositiveButton("Location Settings", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt)
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(myIntent);
)
.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface paramDialogInterface, int paramInt)
);
dialog.show();
private boolean isLocationEnabled()
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
@Override
public void onMapReady(GoogleMap googleMap)
mMap = googleMap;
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference locationRef = rootRef.child("Users").child(uid).child("User Location");
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference locationRef = rootRef.child("Users").child(uid).child("User Location");
locationRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>()
@Override
public void onComplete(@NonNull Task<DataSnapshot> task)
if (task.isSuccessful())
DataSnapshot dataSnapshot = task.getResult();
double latitude = dataSnapshot.child("latitude").getValue(Double.class);
double longitude = dataSnapshot.child("longitude").getValue(Double.class);
LatLng location = new LatLng(latitude, longitude);
Log.d("Tag", "latitude, longitude");
mMap.addMarker(new MarkerOptions().position(location).title(getCompleteAddress(latitude, longitude)));
mMap.moveCamera(CameraUpdateFactory.newLatLng(location));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(location,14F));
else
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
);
private String getCompleteAddress(double Latitude,double Longitude)
String address = "";
Geocoder geocoder = new Geocoder(RetrieveMapsActivity.this, Locale.getDefault());
try
List<Address> addresses = geocoder.getFromLocation(Latitude,Longitude,1);
if(address!=null)
Address returnAddress = addresses.get(0);
StringBuilder stringBuilderReturnAddress = new StringBuilder("");
for(int i=0; i<=returnAddress.getMaxAddressLineIndex();i++)
stringBuilderReturnAddress.append(returnAddress.getAddressLine(i)).append("\n");
address = stringBuilderReturnAddress.toString();
else
Toast.makeText(this, "Address not found", Toast.LENGTH_SHORT).show();
catch (Exception e)
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
return address;
@Override
public void onLocationChanged(@NonNull Location location)
@Override
public void onConnected(@Nullable Bundle bundle)
@Override
public void onConnectionSuspended(int i)
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
if (requestCode == REQUEST_CHECK_SETTINGS)
switch (resultCode)
case Activity.RESULT_OK:
// All required changes were successfully made
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings but chose not to
break;
default:
break;
编辑:我已经按照 Alex 的规定添加了更改后的代码:
@Override
public void onMapReady(GoogleMap googleMap)
mMap = googleMap;
DatabaseReference rootRef =
FirebaseDatabase.getInstance().getReference();
DatabaseReference locationRef =
rootRef.child("Users").child(uid).child("User Location");
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference locationRef = rootRef.child("Users").child(uid).child("User Location");
locationRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>()
@Override
public void onComplete(@NonNull Task<DataSnapshot> task)
if (task.isSuccessful())
DataSnapshot dataSnapshot = task.getResult();
double latitude = dataSnapshot.child("latitude").getValue(Double.class);
double longitude = dataSnapshot.child("longitude").getValue(Double.class);
LatLng location = new LatLng(latitude, longitude);
Log.d("Tag", "latitude, longitude");
mMap.addMarker(new MarkerOptions().position(location).title(getCompleteAddress(latitude, longitude)));
mMap.moveCamera(CameraUpdateFactory.newLatLng(location));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(location,14F));
else
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
);
我仍然没有看到用户的当前位置被反映并且出现以下错误:
java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“double java.lang.Double.doubleValue()” 在 com.example.rescuealertadmin.RetrieveMapsActivity$4.onComplete(RetrieveMapsActivity.java:194) 在 com.google.android.gms.tasks.zzj.run(com.google.android.gms:play-services-tasks@@17.2.0:4) 在 android.os.Handler.handleCallback(Handler.java:938) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:223) 在 android.app.ActivityThread.main(ActivityThread.java:7656) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
【问题讨论】:
【参考方案1】:使用以下参考时:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("Users").child(uid).child("User Location");
请注意,无需循环遍历结果。您应该只在DataSnapshot
对象上再次调用.child()
,如以下代码行所示:
uidRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>()
@Override
public void onComplete(@NonNull Task<DataSnapshot> task)
if (task.isSuccessful())
DataSnapshot snapshot = task.getResult();
double latitude = snapshot.child("latitude").getValue(Double.class);
double longitude = snapshot.child("longitude").getValue(Double.class);
Log.d("TAG", "latitude, longitude");
else
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
);
logcat 中的结果将是:
15.44318, 120.7148767
【讨论】:
只要确定一下,这一切都在 OnMapReady() 中,对吧? 是的,在同一个地方你已经拥有它。试一试,告诉我它是否有效。 我仍然在使用 NullPointerException 的代码时遇到错误 “我仍然有错误”没有提供足够的信息,所以我可以提供进一步的帮助。请编辑您的问题并添加更改后的代码,以便我查看。我亲自测试了这段代码,它确实有效。 我已经添加了修改后的代码。它仍然没有反映用户在地图上的当前位置。以上是关于无法使用唯一键从 Firebase 检索用户位置数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Firebase 向用户检索附近的面包店 [关闭]
给springmvc接口快速增加字段检索,外键从表检索,外键从表查询的searchdb注解
给springmvc接口快速增加字段检索,外键从表检索,外键从表查询的searchdb注解