Я делаю приложение для обмена поездками, которое использует карты Google и точно определяет местоположение пользователей при загрузке. Он отлично работает на моем студийном устройстве BlU с Android версии 4.4.2 и сервисами воспроизведения 19.4.2, но у меня происходит сбой приложения, когда я запускаю его на своем Cricket Android версии 7 с сервисами Google Play 19.2.75. Я убедился, что службы определения местоположения включены на обоих телефонах. На синем студийном телефоне приложение загрузит страницу входа в систему, затем я войду в систему, и появится карта Google, и карта приблизится к фактическому местоположению пользователей. На телефоне Cricket загружается страница входа в систему, я вхожу в систему, и когда карта Google пытается найти приложение, происходит сбой. Ниже мой код.
Примечание: Когда я запускаю это на телефоне Cricket, я получаю сообщение об ошибке в этой строке кода в моей CustomerMapsActivity LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
CustomerMapsActivity
package com.example.mjrlo.uberbestshot;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.firebase.geofire.GeoFire;
import com.firebase.geofire.GeoLocation;
import com.firebase.geofire.GeoQuery;
import com.firebase.geofire.GeoQueryEventListener;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.HashMap;
import java.util.List;
public class CustomerMapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleMap.OnMyLocationButtonClickListener,
GoogleMap.OnMyLocationClickListener, GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks, OnSuccessListener, LocationListener, com.google.android.gms.location.LocationListener {
private GoogleMap mMap;
private FirebaseAuth mAuth;
private LocationCallback mLocationCallback;
private FusedLocationProviderClient mFusedLocationClient;
Location mLastLocation;
private GoogleApiClient googleApiClient;
LocationRequest mlocationRequest;
LatLng position;
private SupportMapFragment mapFragment;
private Button CallUberButton;
private String RemoveUserId;
private Button LogOutButton;
Double theDirverLat;
Double theDiriverLong;
// final int LOCATION_REQUEST_CODE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_customer_maps2);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
final SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
CallUberButton = (Button) findViewById(R.id.call_uber_button);
LogOutButton = (Button) findViewById(R.id.Log_Out_Button);
RemoveUserId = FirebaseAuth.getInstance().getCurrentUser().getUid();
CallUberButton.setOnClickListener(onClick);
LogOutButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
FirebaseAuth.getInstance().signOut();
} catch (Exception e) {
e.printStackTrace();
}
Intent intent = new Intent(CustomerMapsActivity.this,MainActivity.class);
startActivity(intent);
finish();
return;
}
});
}
public View.OnClickListener onClick= new View.OnClickListener() {
@Override
public void onClick(View v) {
String userid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("customerRequest");
GeoFire geoFire= new GeoFire(ref);
geoFire.setLocation(userid, new GeoLocation(mLastLocation.getLatitude(), mLastLocation.getLongitude()), new GeoFire.CompletionListener() {
@Override
public void onComplete(String key, DatabaseError error) {
}
});
position = new LatLng(mLastLocation.getLatitude(),mLastLocation.getLongitude());
mMap.addMarker(new MarkerOptions().position(position).title("Pick up Here"));
// Do something in response to button click
findClosestDriver();
}
};
private int radius=1;
private Boolean driverFound= false;
private String driverFoundID;
private DatabaseReference databaseReference;
private DatabaseReference driverReference;
private void findClosestDriver(){
databaseReference = FirebaseDatabase.getInstance().getReference("DriversAvailable");
GeoFire geoFire = new GeoFire(databaseReference);
GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(position.latitude,position.longitude),radius);
geoQuery.removeAllListeners();
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
@Override
public void onKeyEntered(String key, GeoLocation location) {
if (!driverFound){
driverFound = true;
driverFoundID= key;
driverReference = FirebaseDatabase.getInstance().getReference("Users").child("Drivers").child(driverFoundID);
String customerID = FirebaseAuth.getInstance().getCurrentUser().getUid();
HashMap map = new HashMap();
map.put("customerRideId",customerID);
driverReference.updateChildren(map);
CallUberButton.setText("Looking For Drivers Location");
getDriverLocation();
}
radius++;
}
@Override
public void onKeyExited(String key) {
}
@Override
public void onKeyMoved(String key, GeoLocation location) {
}
@Override
public void onGeoQueryReady() {
if(!driverFound){
radius++;
findClosestDriver();
}
}
@Override
public void onGeoQueryError(DatabaseError error) {
}
});
}
private void takeDriverOutOfDiversAvailableIntoDriversWorking(DatabaseReference fromPath, final DatabaseReference toPath){
}
private Marker DriverMarker;
private DatabaseReference driverLocationReferenceGetLocation;
private GeoFire driverLocationFire;
private Location driverAvailableLocationLatitude;
private Location driverAvailableLocationLongitude;
private ValueEventListener driverLocationListener;
private DatabaseReference dWork;
private void getDriverLocation(){
driverLocationReferenceGetLocation = FirebaseDatabase.getInstance().getReference("DriversWorking").child(driverFoundID).child("l");
driverLocationReferenceGetLocation.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
List<Object> map = (List<Object>) dataSnapshot.getValue();
double locationLat = 0;
double locationLong =0;
if (map.get(0)!=null) {
locationLat= Double.parseDouble(map.get(0).toString());
}
if (map.get(1)!=null){
locationLong = Double.parseDouble(map.get(1).toString());
}
LatLng driverLatLong = new LatLng(locationLat,locationLong);
if(DriverMarker!=null){
DriverMarker.remove();
}
mMap.addMarker(new MarkerOptions().position(driverLatLong).title("Your Driver Is Here!"));
CallUberButton.setText("Driver Found");
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
/* LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
*/
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
buildGoogleApiclient();
mMap.setMyLocationEnabled(true);
}
protected synchronized void buildGoogleApiclient() {
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
googleApiClient.connect();
}
final int LOCATION_REQUEST_CODE = 1;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case LOCATION_REQUEST_CODE:
if (grantResults.length>0 && grantResults[0]== PackageManager.PERMISSION_GRANTED) {
mapFragment.getMapAsync(this);
}else{
Toast.makeText(getApplicationContext(),"plese provide permission",Toast.LENGTH_LONG).show();
}
break;
}
}
@Override
public boolean onMyLocationButtonClick() {
return false;
}
@Override
public void onMyLocationClick(@NonNull Location location) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
public void onSuccess(Object o) {
}
@Override
public void onLocationChanged(Location location) {
mLastLocation = location;
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onConnected(@Nullable Bundle bundle) {
mlocationRequest = new LocationRequest();
mlocationRequest.setInterval(1000);
mlocationRequest.setFastestInterval(1000);
mlocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
ActivityCompat.requestPermissions(CustomerMapsActivity.this,new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},LOCATION_REQUEST_CODE);
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, mlocationRequest, this);
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
protected void onStop() {
super.onStop();
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
//String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("customerRequest");
GeoFire geoFire = new GeoFire(ref);
geoFire.removeLocation(RemoveUserId, new GeoFire.CompletionListener() {
@Override
public void onComplete(String key, DatabaseError error) {
}
});
}
}
манифест Android
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mjrlo.uberbestshot">
<!--
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
Google Maps Android API v2, but you must specify either coarse or fine
location permissions for the 'MyLocation' functionality.
-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<uses-library android:name="com.google.android.maps" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--
The API key for Google Maps-based APIs is defined as a string resource.
(See the file "res/values/google_maps_api.xml").
Note that the API key is linked to the encryption key used to sign the APK.
You need a different API key for each encryption key, including the release key that is used to
sign the APK for publishing.
You can define the keys for the debug and release targets in src/debug/ and src/release/.
-->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<activity
android:name=".DriverMapActivity"
android:label="@string/title_activity_driver_map" />
<activity
android:name=".RiderLoginPage"
android:label="@string/title_activity_rider_login_page"
android:theme="@style/AppTheme.NoActionBar" />
<uses-library
android:name="org.apache.http.legacy"
android:required="false" />
<activity
android:name=".CustomerMapsActivity"
android:label="@string/title_activity_customer_maps" />
<activity
android:name="com.example.mjrlo.uberbestshot.DriverLoginPage"
android:parentActivityName=".MainActivity">
<!-- The meta-data tag is required if you support API level 15 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</activity>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
</application>
</manifest>
Build.Gradle (приложение)
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.mjrlo.uberbestshot"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
//noinspection GradleCompatible
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.google.firebase:firebase-database:16.1.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.google.android.gms:play-services-maps:16.0.0'
// implementation 'com.google.android.gms:play-services-maps:5.+'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.google.firebase:firebase-auth:16.2.0'
implementation "com.android.support:support-core-utils:28.0.0"
implementation 'com.android.support:support-annotations:28.0.0'
implementation 'com.android.support:support-v4:28.0.0'
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.google.android.gms:play-services-location:16.0.0'
implementation 'com.google.firebase:firebase-core:16.0.8'
implementation 'com.firebase:geofire-android:2.3.1'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
}
allprojects {
repositories {
google()
jcenter()
}
}
apply plugin: 'com.google.gms.google-services'