java - 应用程序的 map 在请求权限后首次运行时保持空白,但在关闭并重新打开后可以正常工作

标签 java android xml google-maps android-studio

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

因此,每次我运行我的应用程序并且它没有允许的权限时,它都会请求它们。然后,它应该以当前位置为中心并缩放 map 。但是,它不会执行任何操作,如果您单击屏幕,它只会变成蓝色。如果我关闭应用程序并重新打开它,它就会正常工作。

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

这是我的主类代码:

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>

这是请求权限后第一次运行时 map 的显示方式:

Blue Map

最奇怪的是它以前可以用。然后我加了一些东西,它就坏了。我删除了使用 Android Studio 中的历史记录工具添加的这个东西,但它仍然损坏。

最佳答案

您好,尝试更改以下代码或方法,还有一件事是蓝屏不是 map 的问题,而是它显示在默认位置(意味着海洋中的任何位置):

//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;
            }
        }
    }

关于java - 应用程序的 map 在请求权限后首次运行时保持空白,但在关闭并重新打开后可以正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53386439/

相关文章:

xml - XPath是否具有最大值?

java - 输出流问题

java - 如何让 LevelLoader 方法 'ignore' 未定义实体?

java - Admob 通过 Adwhirl : Not enough space to show ad! 想要 : 480, 75,有 : 480, 0

java - 扩展 JPanel 在添加到另一个 JPanel 时显示很小

Android Studio 永远无法下载 fastutil-7.2.0.jar

java - 不确定如何使用 Android 在新 Activity 中显示结果

android - 是否会为新用户运行房间迁移?

c# - 使用 XmlNode.selectSingleNode 选择一个节点

javascript - 通过 xml 将数据从一个数据库传递到另一个数据库