在请求权限后,应用程序的地图在首次运行时仍为空白,但是在关闭并重新打开后,该地图仍可正常运行

时间:2018-11-20 04:53:09

标签: java android xml google-maps android-studio

我正在制作一个向您显示地图的应用程序,您可以添加一些信息的自定义标记。我仍在努力将其连接到数据库中以保存所有内容。

因此,每次我运行我的应用程序且没有允许的权限时,它都会要求它们。然后,它应该然后在当前位置居中并缩放地图。但是,它没有任何作用,如果您单击屏幕,它将变成蓝色。如果我关闭该应用程序并重新打开它,它将正常运行。

我不确定是否是因为权限询问是异步的并且地图只是失败并停止询问位置,因为当我查看logcat时,它有时会显示“成功插入1个位置”,只是永远不会在拐角处添加标准的蓝色圆点标记或myLocation按钮,地图只会变成蓝色,什么也没给我显示。

这是我的主要代码:

package com.example.lipel.mapeador003;

import android.Manifest;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Handler;
import android.os.Looper;
import android.os.ResultReceiver;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatCallback;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.view.ActionMode;
import android.util.Log;
import android.view.Menu;
import android.support.v7.widget.Toolbar;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;


import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
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.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.maps.CameraUpdate;
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.UiSettings;
import com.google.android.gms.maps.model.CameraPosition;
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.android.gms.tasks.Task;

import static com.google.android.gms.location.LocationServices.getFusedLocationProviderClient;

public class Mapa extends FragmentActivity implements OnMapReadyCallback, AppCompatCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, GoogleMap.OnMyLocationButtonClickListener {

    public static final String TAG = Mapa.class.getSimpleName(); //Tag de log para verificar no Run

    private static final int MY_PERMISSIONS_ACCESS_FINE_LOCATION = 1; //Variável que permite identificar se aplicativo é autorizado a utilizar localização pelo usuário
    private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 1000; //Variável que faz request de o que fazer com Google Play API caso haja falha
    private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;


    private AppCompatDelegate delegate; //Para resolver problemas de implementação

    private GoogleMap mMap; //Mapa do aplicativo
    private FusedLocationProviderClient mFusedLocationClient; //Cliente que puxa a localização atual do celular
    private Location mLocalizacaoAtual; //Objeto que salva localização atual para marcador
    private Marker mark; //Marcador da localização atual

    private LocationRequest locReq; //Objeto que permite puxar localização contínua
    private GoogleApiClient googleAPI; //API google para puxar localizações contínuas
    private GoogleApiAvailability gAAPI; //Verifica se a API do google está instalada ou funcionando

    private LocationCallback loccall;


    static final int ADICIONAR_MARCADOR = 1;
    private static final long INTERVAL = 10000; //Número que permite definir com facilidade o intervalo de chamada de localização
    private static final long FASTEST_INTERVAL = 5000; //Número que permite definir com facilidade o mínimo intervalo de chamada de localização


    // Configura os pedidos de localização: seus intervalos e precisão
    protected void createLocationRequest() {
        locReq = new LocationRequest();
        locReq.setInterval(INTERVAL);
        locReq.setFastestInterval(FASTEST_INTERVAL);
        locReq.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    //Checa o status do Google Play Services
    private boolean checkPlayServices() {
        gAAPI = GoogleApiAvailability.getInstance();
        int resultAAPI = gAAPI.isGooglePlayServicesAvailable(this);
        if (resultAAPI != ConnectionResult.SUCCESS) {
            //Verifica se é um erro que pode ser resolvido na aplicação ou pelo usuário
            if (gAAPI.isUserResolvableError(resultAAPI)) {
                gAAPI.getErrorDialog(this, resultAAPI, PLAY_SERVICES_RESOLUTION_REQUEST).show();
            }
            //retorna falso se não puder ser resolvido
            return false;
        }
        //retorna verdadeiro se não encontra erro, ou seja, se tiver sucesso
        return true;

    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Verifica se o Google Play Services está funcionando. Se não, dá finish na OnCreate e não continua
        if (!checkPlayServices()) {
            finish();
        }

        // Coloca o mapa na activity
        setContentView(R.layout.activity_mapa);
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
       mapFragment.getMapAsync(this);

        // Habilita a API de localização do Google que permite encontrar última localização
        mFusedLocationClient = getFusedLocationProviderClient(this);

        //Adiciona suporte para barra de ferramentas, permitindo multiplos implement
        delegate = AppCompatDelegate.create(this, this);
        delegate.onCreate(savedInstanceState);
        Toolbar myToolbar = findViewById(R.id.toolbar);
        delegate.setSupportActionBar(myToolbar);

        //Utilizado para iniciar o aplicativo na tela de ativar localização
        /*Intent gpsOptionsIntent = new Intent(
                android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        startActivity(gpsOptionsIntent);*/
    }

    private boolean checkPermissions() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED)
            return true;
        else {
            requestPermissions();
        }
        return false;
    }

    //Pede as permissões
    private void requestPermissions() {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                MY_PERMISSIONS_ACCESS_FINE_LOCATION);
    }


    //Verifica as permissões do aplicativo
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_ACCESS_FINE_LOCATION: {
                // Coloca as permissões em ordem e checa se elas estão habilitadas.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    //Se aplicativo não foi permitido depois de perguntar, o fecha
                } else {
                    moveTaskToBack(true);
                    android.os.Process.killProcess(android.os.Process.myPid());
                    System.exit(1);
                }
                return;
            }
        }
    }


    //Inicia o app com a localização atual
    @Override
    public void onMapReady(GoogleMap googleMap) {

        mMap = googleMap;

        //Pede permissões
        if (checkPermissions()) {
            mMap.setMyLocationEnabled(true);
        }

        //Cria um listener para pegar última localização do celular
        mFusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
            @Override
            public void onSuccess(Location location) {
                //Se encontra a localização (App autorizado e localização ligada), aplica tal localização no mapa
                if (location != null) {
                    LatLng rj1 = new LatLng(location.getLatitude(), location.getLongitude());
                    //mark = mMap.addMarker(new MarkerOptions().position(rj1).title("Posição Atual"));
                    mMap.moveCamera(CameraUpdateFactory.newLatLng(rj1));
                    mMap.setMinZoomPreference(15);

                    //Salva localização atual em um objeto Location
                    mLocalizacaoAtual = new Location("");
                    mLocalizacaoAtual.setLatitude(location.getLatitude());
                    mLocalizacaoAtual.setLongitude(location.getLongitude());

                    mMap.animateCamera(CameraUpdateFactory.zoomTo(18));
                    mMap.getUiSettings().setCompassEnabled(true);
                    mMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() {
                        @Override
                        public boolean onMyLocationButtonClick() {
                            mMap.moveCamera(CameraUpdateFactory.newLatLng(getLatLng()));
                            mMap.animateCamera(CameraUpdateFactory.zoomTo(20));
                            return true;
                        }
                    });

                }
            }
        });
    }


    //Inicia o serviço de atualização constante de localização
    protected void startLocationUpdates() {

        Log.v("LocationUpdates","ok");

        //Inicia o serviço de localização contínuo e adiciona o que ele utilizará para localizar, depois o construindo
        createLocationRequest();


        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder(); //Builder que permite configurar intervalos, etc de pedidos de localização
        builder.addLocationRequest(locReq);
        LocationSettingsRequest locSetReq = builder.build();

        SettingsClient settingsClient = LocationServices.getSettingsClient(this);
        settingsClient.checkLocationSettings(locSetReq);

        getFusedLocationProviderClient(this).requestLocationUpdates(locReq, loccall = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {

                if (locationResult != null){
                onLocationChanged(locationResult.getLastLocation());
                }

            }
        }, Looper.myLooper());
    }
    @Override
    public void onLocationChanged(Location location){

        if (location != null){
            if (checkPermissions()){
                mLocalizacaoAtual = new Location("");
            }
            mLocalizacaoAtual.setLatitude(location.getLatitude());
            mLocalizacaoAtual.setLongitude(location.getLongitude());
            mMap.setMinZoomPreference(15);
        }

        else
        {
            mLocalizacaoAtual.setLatitude(0.00);
            mLocalizacaoAtual.setLongitude(0.00);
        }

        //if (mark != null)
        //    mark.remove();

        LatLng Ll = new LatLng(location.getLatitude(), location.getLongitude());
        //MarkerOptions mpo = new MarkerOptions();
        //mpo.position(Ll);
        //mpo.title("Posição Atual");

        //mark = mMap.addMarker(mpo);


    }


    @Override
    public void onStart() {
        super.onStart();
        googleAPI = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

        googleAPI.connect();

        Log.v("onStart","ok");

    }

    @Override
    public void onStop() {
        super.onStop();
        googleAPI.disconnect();
    }

    @Override
    public void onConnected(Bundle bundle) {
        Task<Location> loc = LocationServices.getFusedLocationProviderClient(this).getLastLocation();
        startLocationUpdates();
        Log.v("onConnected","ok");
    }

    private void handleNewLocation(Task<Location> location){
        Log.d(TAG, location.toString());
    }

    private void handleNewLocation (Location location){
        Log.d(TAG, location.toString());
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onResume(){
        super.onResume();
        googleAPI.connect();
    }

    @Override
    public void onPause(){
        super.onPause();
        googleAPI.disconnect();
    }


    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        if (connectionResult.hasResolution()) {
            try {
                // Tenta corrigir o erro
                connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }
        } else {
            Log.i(TAG, "Conexão falhou com código: " + connectionResult.getErrorCode());
        }
    }

    @Override
    public void onSupportActionModeStarted(ActionMode actionMode) {

    }

    @Override
    public void onSupportActionModeFinished(ActionMode actionMode) {

    }

    @Nullable
    @Override
    public ActionMode onWindowStartingSupportActionMode(ActionMode.Callback callback) {
        return null;
    }

    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {

    }


    //Permite pegar os itens da barra de ferramenta de seu XML
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_items, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {


        switch (item.getItemId()) {
            case R.id.adicionar:

                Bundle args = new Bundle();
                args.putDouble("long_dataProvider", getLongitude());
                args.putDouble("lat_dataProvider", getLatitude());

                Intent adInt = new Intent(this, Adicionar.class);
                adInt.putExtras(args);
                startActivityForResult(adInt, ADICIONAR_MARCADOR);
                return true;

            case R.id.lista:
                Intent listInt = new Intent(this, Lista.class);
                startActivity(listInt);
                return true;

            default:
                return super.onOptionsItemSelected(item);

        }
    }

    protected LatLng getLatLng(){
        return new LatLng(mLocalizacaoAtual.getLatitude(),mLocalizacaoAtual.getLongitude());

    }

    protected double getLatitude(){
        return mLocalizacaoAtual.getLatitude();
    }

    protected double getLongitude(){
        return mLocalizacaoAtual.getLongitude();
    }

    protected GoogleMap getMap(){return mMap;}

    protected Location getCurrLoc(){return mLocalizacaoAtual;}

    @Override
    protected void onActivityResult(int reqCode, int resCode, Intent resultIntent){
        if (reqCode == ADICIONAR_MARCADOR) {
            if (resCode == RESULT_OK){
                String markNom = resultIntent.getStringExtra("nome");
                String markDescr = resultIntent.getStringExtra("descr");
                Double markLat = resultIntent.getDoubleExtra("lat", getLatitude());
                Double markLong = resultIntent.getDoubleExtra("long", getLongitude());

                //Call function to add marker into DB and then from the DB to the map
                //For now, testing directly here

                mMap.addMarker(new MarkerOptions()
                     .position(new LatLng(markLat,markLong))
                     .title(markNom)
                     .snippet(markDescr)
                );


                //Do stuff with intent. Get the title, lat, long, nome, descrição
            }
        }
    }



    @Override
    public boolean onMyLocationButtonClick(){

        mMap.animateCamera(CameraUpdateFactory.zoomTo(20));
        return true;

    }

    //protected void zoomCamera (View view){
    //    mMap.moveCamera(CameraUpdateFactory.newLatLng(getLatLng()));
    //    mMap.animateCamera(CameraUpdateFactory.zoomTo(20));

    //    mMap.getCameraPosition();

    //    CameraPosition.Builder camPos = new CameraPosition.Builder().target(getLatLng()).bearing(0);
    //}
}

这是我主要的xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/linearLayout3"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Mapa">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        android:theme="?attr/actionBarTheme"
        android:visibility="visible"
        app:layout_constraintBottom_toTopOf="@+id/map"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:title="@string/app_name" />

    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar"
        tools:context=".Mapa" />

</android.support.constraint.ConstraintLayout>

这是地图在请求权限后的第一次运行中显示的方式:

Blue Map

最奇怪的是,它以前曾经工作过。然后我添加了一些东西,它坏了。我从Android Studio中删除了使用历史记录工具添加的东西,但它仍然坏了。

1 个答案:

答案 0 :(得分:1)

您可以尝试通过更改下面的代码或方法来尝试,蓝屏并不是问题所在,而是地图显示在默认位置(表示海洋中的任何位置):

//Verifica as permissões do aplicativo
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_ACCESS_FINE_LOCATION: {
                // Coloca as permissões em ordem e checa se elas estão habilitadas.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                     if (mMap!=null && checkPermissions()) {
                          mMap.setMyLocationEnabled(true);
                      }

                    //Se aplicativo não foi permitido depois de perguntar, o fecha
                } else {
                    moveTaskToBack(true);
                    android.os.Process.killProcess(android.os.Process.myPid());
                    System.exit(1);
                }
                return;
            }
        }
    }