Google Maps возвращает ноль при обновлении местоположения - PullRequest
0 голосов
/ 16 мая 2018

В течение нескольких недель я получаю исключение нулевого указателя, когда программа пытается поместить маркер на карту.Я не знаю почему, я пробовал пару решений, но они не работали.Я получаю эту ошибку на нескольких устройствах.Например, нет ошибки на 100 устройствах, но на 5 или более устройствах эта ошибка возникает.
Также я не могу использовать функцию .getMap ().Доступен только getMapAsync.

Вот ошибка, которую я получаю от Firebase:

Fatal Exception: java.lang.NullPointerException
Attempt to invoke virtual method 'void com.google.android.gms.maps.GoogleMap.animateCamera(com.google.android.gms.maps.CameraUpdate)' on a null object reference

Вот фрагмент Google Maps:

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/map1"
        class="com.google.android.gms.maps.SupportMapFragment"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.ahmetbesli.eczanem.MapsActivityPicker"
        />

Воткод моей программы:

public class MapsActivityPicker extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, View.OnClickListener {
        SharedPreferences sharedPreferences;
        GoogleMap mGoogleMap;
        SupportMapFragment mapFrag;
        LocationRequest mLocationRequest;
        GoogleApiClient mGoogleApiClient;
        Location mLastLocation;
        Marker mCurrLocationMarker;
        FusedLocationProviderClient mFusedLocationClient;
        LocationManager mLocationManager;

        ArrayList<MarkerData> markers = new ArrayList<>();
        int counter = 1;
        int resumeCounter = 2;
        boolean add = true;
        LatLng midLatLng;
        LatLng latLngMaps;

        ImageView direction;
        ImageView bullet;
        ImageView share;
        ImageView nearMe;
        ImageView call;
        CountDownTimer timer;
        String pharmacyName;
        String pharmacyAddress;
        String markerPhone = null;
        Double markerLatitude;
        Double markerLongitude;

        private InterstitialAd mInterstitialAd;
        String shortURL;
        LocationCallback mLocationCallback;

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




            mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

            mapFrag = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map1);
            buildGoogleApiClient();
            mapFrag.getMapAsync(this);
            mLocationManager = (LocationManager) MapsActivityPicker.this
                    .getSystemService(Context.LOCATION_SERVICE);

            direction = findViewById(R.id.directionPicker);
            bullet = findViewById(R.id.bulletPicker);
            share = findViewById(R.id.sharePicker);
            nearMe = findViewById(R.id.accessPicker);
            call = findViewById(R.id.callPicker);

            direction.setOnClickListener(this);
            bullet.setOnClickListener(this);
            share.setOnClickListener(this);
            nearMe.setOnClickListener(this);
            call.setOnClickListener(this);

            sharedPreferences = this.getApplication().getSharedPreferences(Config.app_name,MODE_PRIVATE);

            mInterstitialAd = new InterstitialAd(this);
            mInterstitialAd.setAdUnitId("xxxxxxxxxx");
            mInterstitialAd.loadAd(new AdRequest.Builder().build());


            timer = new CountDownTimer(5000, 1000)
            {
                public void onTick(long millisUntilFinished) {
                }

                public void onFinish() {
                    if (add) {
                        if (mInterstitialAd != null) {
                            if (mInterstitialAd.isLoaded()) {
                                mInterstitialAd.show();
                            }
                        }
                    }
                }
            };
            timer.start();
        }

        @Override
        public void onPause() {
            super.onPause();

            if (mFusedLocationClient != null) {
                mFusedLocationClient.removeLocationUpdates(mLocationCallback);
            }
        }

        @Override
        public void onMapReady(final GoogleMap googleMap) {

            mGoogleMap = googleMap;
            mGoogleMap.getUiSettings().setMapToolbarEnabled(false);
            mGoogleMap.setInfoWindowAdapter(new CustomInfoWindowAdapter(MapsActivityPicker.this));
            mGoogleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
                public void onMapClick(LatLng latLng) {
                    bullet.setVisibility(View.VISIBLE);
                    share.setVisibility(View.GONE);
                    direction.setVisibility(View.GONE);
                    nearMe.setVisibility(View.VISIBLE);
                    call.setVisibility(View.GONE);
                }
            });
            mGoogleMap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
                @Override
                public void onInfoWindowClick(Marker marker) {
                    Intent intent = new Intent(MapsActivityPicker.this, HomePageShared.class);
                    intent.putExtra("name",marker.getTitle());
                    intent.putExtra("address",marker.getSnippet());
                    intent.putExtra("phone",markerPhone);
                    intent.putExtra("latitude",marker.getPosition().latitude);
                    intent.putExtra("longitude",marker.getPosition().longitude);
                    intent.putExtra("userLatitude", midLatLng.latitude);
                    intent.putExtra("userLongitude",midLatLng.longitude);
                    startActivity(intent);
                }
            });
            mGoogleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
                Marker currentShown;
                @Override
                public boolean onMarkerClick(Marker marker) {

                    if (marker.equals(currentShown)) {
                        marker.hideInfoWindow();
                        currentShown = null;
                    } else {
                        marker.showInfoWindow();
                        currentShown = marker;
                    }

                    pharmacyName = marker.getTitle();
                    pharmacyAddress = marker.getSnippet();
                    markerLatitude = marker.getPosition().latitude;
                    markerLongitude = marker.getPosition().longitude;

                    for(int i = 0; i < markers.size(); i++){
                        if(markers.get(i).getName().equals(pharmacyName)){
                            markerPhone = markers.get(i).getPhone();
                        }
                    }


                    shortURL = "http://maps.google.com/maps?daddr=" + markerLatitude + "," + markerLongitude;


                    latLngMaps = marker.getPosition();
                    share.setVisibility(View.VISIBLE);
                    direction.setVisibility(View.VISIBLE);
                    bullet.setVisibility(View.GONE);
                    nearMe.setVisibility(View.GONE);
                    call.setVisibility(View.VISIBLE);

                    return true;
                }

            });

            googleMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
                @Override
                public void onCameraIdle() {
                    //get latlng at the center by calling
                    midLatLng = googleMap.getCameraPosition().target;
                    //request();
                    requestRetrofit();
                    googleMap.clear();

                }
            });
            if(sharedPreferences.getBoolean(Config.theme,false)){
                mGoogleMap.setMapStyle(MapStyleOptions.loadRawResourceStyle(this, R.raw.night_mode));
            }
        }

        protected void getGPS() {
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                    this);
            alertDialogBuilder
                    .setMessage("Konum Servisiniz kapalı. Eczaneleri görebilmek için lütfen açınız.")
                    .setCancelable(false)
                    .setPositiveButton("Konum Servisini Aç",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog,
                                                    int id) {
                                    Intent callGPSSettingIntent = new Intent(
                                            android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                    MapsActivityPicker.this.startActivity(callGPSSettingIntent);
                                }
                            });
            alertDialogBuilder.setNegativeButton("Kapalı Kalsın",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    });
            AlertDialog alert = alertDialogBuilder.create();
            alert.show();
        }

        public void requestRetrofit(){
            ApiInterface apiInterface = ApiClient.getRetrofit().create(ApiInterface.class);
            Call<ArrayList<Eczane>> call = apiInterface.getPharmacies(new com.ahmetbesli.eczanem.Request(String.valueOf(midLatLng.latitude),String.valueOf(midLatLng.longitude)));
            call.enqueue(new Callback<ArrayList<Eczane>>() {
                @Override
                public void onResponse(Call<ArrayList<Eczane>> call, retrofit2.Response<ArrayList<Eczane>> response) {
                    markers.clear();
                    if (response.body().get(0) != null) {
                        for (int i = 0; i < 5; i++) {
                            if (!response.body().get(i).getLatitude().equals("undefined") && !response.body().get(i).getLongitude().equals("undefined") && !response.body().get(i).getLatitude().equals("") && !response.body().get(i).getLongitude().equals("")) {
                                createMarker(Double.valueOf(response.body().get(i).getLatitude()),
                                        Double.valueOf(response.body().get(i).getLongitude()), response.body().get(i).getName(),
                                        response.body().get(i).getAdress(), response.body().get(i).getPhone(), R.mipmap.marker);
                            }
                        }
                    }
                }

                @Override
                public void onFailure(Call<ArrayList<Eczane>> call, Throwable t) {

                }
            });
        }

        protected void starter() {
            //Initialize Google Play Services
            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED) {
                    //Location Permission already granted
                    buildGoogleApiClient();
                } else {
                    //Request Location Permission
                    checkLocationPermission();
                }
            } else {
                buildGoogleApiClient();
            }
        }

        protected synchronized void buildGoogleApiClient() {
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
            mGoogleApiClient.connect();
        }

        @Override
        public void onConnected(Bundle bundle) {
            mLocationRequest = LocationRequest.create();
            mLocationRequest.setInterval(120000); // two minute interval
            mLocationRequest.setFastestInterval(120000);
            mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
            if (ContextCompat.checkSelfPermission(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)
                    == PackageManager.PERMISSION_GRANTED) {
                mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
            }
        }

        @Override
        public void onConnectionSuspended(int i) {
        }

        @Override
        public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        }

        public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;

        private void checkLocationPermission() {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED) {

                // Should we show an explanation?
                if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                        Manifest.permission.ACCESS_FINE_LOCATION)) {

                    // Show an explanation to the user *asynchronously* -- don't block
                    // this thread waiting for the user's response! After the user
                    // sees the explanation, try again to request the permission.
                    new AlertDialog.Builder(this)
                            .setTitle("Konum Servisi için izin gerekli.")
                            .setMessage("Bu uygulama konum servisi iznine ihtiyaç duymaktadır. Lütfen kabul ediniz.")
                            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    //Prompt the user once explanation has been shown
                                    ActivityCompat.requestPermissions(MapsActivityPicker.this,
                                            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                            MY_PERMISSIONS_REQUEST_LOCATION);
                                }
                            })
                            .create()
                            .show();


                } else {
                    // No explanation needed, we can request the permission.
                    ActivityCompat.requestPermissions(this,
                            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                            MY_PERMISSIONS_REQUEST_LOCATION);
                }
            }
        }

        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
            switch (requestCode) {
                case MY_PERMISSIONS_REQUEST_LOCATION: {
                    // If request is cancelled, the result arrays are empty.
                    if (grantResults.length > 0
                            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                        // permission was granted, yay! Do the
                        // location-related task you need to do.
                        if (ContextCompat.checkSelfPermission(this,
                                Manifest.permission.ACCESS_FINE_LOCATION)
                                == PackageManager.PERMISSION_GRANTED) {

                            if (mGoogleApiClient == null) {
                                buildGoogleApiClient();
                            }
                        }

                    } else {
                        // permission denied, boo! Disable the
                        // functionality that depends on this permission.
                        Toast.makeText(this, "İzin Reddedildi", Toast.LENGTH_LONG).show();
                    }
                }

                // other 'case' lines to check for other
                // permissions this app might request
            }
        }

        @Override
        public void onResume() {
            super.onResume();
            if (resumeCounter <= 2) {
                starter();
                resumeCounter++;
            }
            if (counter == 0) {
                if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                    starter();
                    counter++;
                } else {
                    getGPS();
                    counter++;
                }
            }
        }

        protected void createMarker(double latitude, double longitude, String title, String snippet, String phone, int iconResID) {
            MarkerData marker = new MarkerData(title, snippet, phone, latitude, longitude);
            markers.add(marker);

            mGoogleMap.addMarker(new MarkerOptions()
                    .position(new LatLng(latitude, longitude))
                    .anchor(0.5f, 0.5f)
                    .title(title)
                    .snippet(snippet)
                    .icon(BitmapDescriptorFactory.fromResource(iconResID)));
        }

        @Override
        protected void onStart(){
            super.onStart();
            mLocationCallback = new LocationCallback() {
                @Override
                public void onLocationResult(LocationResult locationResult) {
                    for (Location location : locationResult.getLocations()) {
                        mLastLocation = location;
                        if (mCurrLocationMarker != null) {
                            mCurrLocationMarker.remove();
                        }

                        mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 10.7f));
                    }
                }
            };
        }

    }

1 Ответ

0 голосов
/ 16 мая 2018

В вашем методе onStart вы вызываете mGoogleMap.animateCamera(), вероятно, в тот момент, когда он не назначен. Он присваивается в onMapReady вам нужно проверить, не является ли оно нулевым.

if(mGoogleMap != null){
    mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 10.7f));
}

Я подозреваю, что у вас есть состояние гонки: на некоторых устройствах метод onMapReady() вызывается раньше, чем onLocationResult() ... так что все работает нормально. Но на других устройствах onLocationResult() вызывается до onMapReady() метода и, следовательно, mGoogleMap имеет значение null! Поэтому вы должны проверить, назначен ли «mGoogleMap».

Сделайте это вместо:

//create a class variable mLatLng
private LatLng mLatLng;

Теперь измените код в вашем методе onLocationResult(), чтобы он выглядел следующим образом:

public void onLocationResult(LocationResult locationResult) {
    for (Location location : locationResult.getLocations()) {
        mLastLocation = location;
        if (mCurrLocationMarker != null) {
            mCurrLocationMarker.remove();
        }
        mLatLng = new LatLng(location.getLatitude(), location.getLongitude());
        moveMapTo();
}

Добавить метод:

private void moveMapTo(){
    if(mLatLng == null) return;

    if(mGoogleMap != null){
        mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 10.7f));
    }
}

И в onMapReady() методе все, что вам нужно, это добавить:

moveMapTo();

Таким образом, когда onLocationResult() вызывается до onMapReady(), переменная «mLatLng» определена и допустима, но «mGoogleMap» имеет значение null - что может привести к ошибке. Как только mGoogleMap будет правильно определен в * 1030, moveMapTo() будет вызван снова, и ваша анимация будет отправлена ​​в нужное место. Если, однако, onMapReady() вызывается до onLocationResult(), то mGoogleMap уже назначен, а в onLocationResult() все работает как положено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...