Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

Solucionado
(ver solução)
13
respostas

Não consigo abrir mapa dentro do onRequestPermissionsResult()

Por mais que eu implemente o método onRequestPermissionsResult() com as condições para as permissões, eu não consigo abrir o mapa logo após clicar em permitir, ou seja, tenho que clicar no mapa, clicar em permitir e depois em mapa de novo, para aí sim abrir o mapa.

O que estou fazendo de errado?

@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case REQUEST_PERMISSOES:
                if(grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED){
                    chamaMapa();
                }
                break;
        }
    }

Segue também classe MapaActivity completa:

public class MapaActivity extends AppCompatActivity {

    private static final int REQUEST_PERMISSOES = 1;
    private FragmentManager manager;
    private FragmentTransaction tx;

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

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSOES);
                finish();
            }
            chamaMapa();
        }
    }

private void chamaMapa() {
        manager = getSupportFragmentManager();
        tx = manager.beginTransaction();
        tx.replace(R.id.frame_mapa, new MapaFragment());
        tx.commit();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case REQUEST_PERMISSOES:
                if(grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED){
                    chamaMapa();
                }
                break;
        }
    }
}
13 respostas

Gilmar, tudo bem ?

Cara não entendi seu problema, vi seu código e mentalmente acho que a lógica está corretamente, consegue me dar um pouco mais de contexto

Com o código desta maneira está acontecendo o seguinte:

Clico no ícone do mapa, aí me pede a permissão, quando clico em permitir, nada acontece, aí tenho que clicar no ícone mapa novamente, para aí sim abrir o mapa.

Como eu queria que acontecesse:

Clico no ícone do mapa, aí me pede a permissão, quando clico em permitir, aí já abre o mapa. Sem que eu tenha que clicar no ícone mapa novamente.

De acordo com a atividade, assim que chamasse o método ActivityCompat.checkSelfPermission() e identificasse que não possuí as permissões iria chamar o método ActivityCompat.requestPermissions(), como fiz no código acima, aí assim que eu clicasse em "permitir", teria que chamar método onRequestPermissionsResult() e executar o que está la dentro, mas isso não está acontecendo, porque se estivesse chamando o método onRequestPermissionsResult() iria abrir o mapa assim que eu clicasse em "permitir".

Fiz mais alguns testes, e acho que possível causa de não chamar o mapa assim que eu clico em permitir seria a chamada do método finish(). No minha análise estaria acontecendo o seguinte:

Executa o método ActivityCompat.requestPermissions(), quando clico em "permitir" ele chama o método onRequestPermissionsResult() e quando termina, volta para dentro do if e chama o método finish() que mata a chamada ao mapa. Quando clico no ícone mapa novamente, uma vez que já tem a permissão, ele executa o método chamaMapa() fora do if (sem o finish()), aí sim consegue abrir o mapa.

O teste que fiz foi colocar o método finish() depois da chamada do método chamaMapa() fora do if, da seguinte forma:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSOES);
            }
            chamaMapa();
            finish();
        }

Aí rodei a aplicação novamente, dei a permissão manualmente e cliquei no ícone mapa, nesse caso não entrou dentro do if (uma vez que já tinha a permissão), executando a chamada de método chamaMapa() e depois o método finish(). Se o problema não fosse o finish() teria que abrir o mapa, mas isso não aconteceu, quando cliquei no ícone mapa, mesmo com as permissões, não aconteceu nada.

Se o problema for mesmo o finish() eu não sei qual seria a solução, porque se eu tirar ele a aplicação vai abrir o pop-up requisitando a permissão e antes que eu clique em "permitir" a aplicação também vai tentar abrir o mapa, causando uma exception. Isto era o que estava acontecendo antes de eu usar o finish() (solução sugerida pelo instrutor Jeferson Silva na resposta de outra dúvida do forum).

Teria algum modo de contornar esse problema?

Gilmar,

O finish estava matando a activity logo após você fazer a chamada das permissões.

É interessante você não o chamar, apenas quando você quer matar de fato aquela activity.

Então Matheus, como complementei com a resposta acima, o problema é exatamente esse, se eu não chamar o finish() vou tomar uma exception.

A aplicação vai abrir o pop-up requisitando a permissão e antes que eu clique em "permitir" a aplicação também vai tentar abrir o mapa, causando a exception.

Me sugere algum modo de contornar essa exception, que não seja com o método finish()?

Gilmar, você tem que fazer o tratamento na volta :

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case REQUEST_PERMISSOES:
                if(grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED){
                    chamaMapa();
                } else {
                      finish();
            }
                break;
        }
    }

Matheus, coloquei o código assim como você indicou, mas resulta na mesma exception que eu recebia quando não usava o finish().

Quando clico no ícone do mapa, a aplicação chama o pop-up de permissão e antes que eu dê a permissão ele já tenta chamar o mapa e resulta na exception abaixo:

java.lang.SecurityException: Client must have ACCESS_FINE_LOCATION permission to request PRIORITY_HIGH_ACCURACY locations.

Faz esse else :


 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSOES);
            } else {
               chamaMapa();
            }
        }

Fiz como você indicou acima e retornou a seguinte uma exception diferente, segue abaixo:

java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=1, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {br.com.alura.agenda/br.com.alura.agenda.MapaActivity}: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

Me mostra o código de como está hoje, por favor.

public class MapaActivity extends AppCompatActivity {

    private static final int REQUEST_PERMISSOES = 1;
    private FragmentManager manager;
    private FragmentTransaction tx;

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

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSOES);
            } else {
                chamaMapa();
            }
        }

    }

    private void chamaMapa() {
        manager = getSupportFragmentManager();
        tx = manager.beginTransaction();
        tx.replace(R.id.frame_mapa, new MapaFragment());
        tx.commit();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case REQUEST_PERMISSOES:
                if(grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED){
                    chamaMapa();
                } else {
                    finish();
                }
                break;
        }
    }
}
solução!

Faz um teste para mim, por gentileza.


 private void chamaMapa() {
        manager = getSupportFragmentManager();
        tx = manager.beginTransaction();
        tx.replace(R.id.frame_mapa, new MapaFragment());
        tx.commitAllowingStateLoss();
    }

Funcionou Matheus, tudo ocorreu como esperado.

Ainda não entendi muito bem o por que estava acontecendo aquela ultima exception, mas vou pesquisar um pouco mais para poder esclarecer, e vou pesquisar também sobre o método commitAllowingStateLoss();

Muito obrigado por toda a ajuda e atenção.

Segue código completo da classe MapaActivity, caso seja dúvida de mais alguém.

public class MapaActivity extends AppCompatActivity {

    private static final int REQUEST_PERMISSOES = 1;
    private FragmentManager manager;
    private FragmentTransaction tx;

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

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSOES);
            } else {
                chamaMapa();
            }
        }

    }

    private void chamaMapa() {
        manager = getSupportFragmentManager();
        tx = manager.beginTransaction();
        tx.replace(R.id.frame_mapa, new MapaFragment());
        tx.commitAllowingStateLoss();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case REQUEST_PERMISSOES:
                if(grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED){
                    chamaMapa();
                } else {
                    finish();
                }
                break;
        }
    }
}