Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

Problema com a permissão

Estou tentando fazer acontecer essa solicitação de permissão, e mesmo vendo no código já resolvido por vocês, estou tendo o problema na conversão dos dados de uma classe para outra. O problema está no método onRequestPermissionsResult no parâmetro que preciso passar para a classe Localizador.

Segue código de ambas classes:

MapaAlunosActivity:

package br.com.alura.agenda;

import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.google.android.gms.maps.GoogleMap;

import java.util.jar.*;
import java.util.jar.Manifest;

public class MapaAlunosActivity extends AppCompatActivity {

    private static final int REQUEST_PERMISSOES = 1;
    private MapaFragment mapaFragment;

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

        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction tx = manager.beginTransaction();

        mapaFragment = new MapaFragment();

        tx.replace(R.id.frame_mapa, new MapaFragment());
        tx.commit();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){

            if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    || ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){

                String [] permissoes = {android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION};
                requestPermissions(permissoes, REQUEST_PERMISSOES);
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if(requestCode == REQUEST_PERMISSOES){

            if(grantResults[0] == PackageManager.PERMISSION_GRANTED &&
                    grantResults[1] == PackageManager.PERMISSION_GRANTED){

                new Localizador(this, mapaFragment);
            }
        }
    }
}

Localizador:

package br.com.alura.agenda;

import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.Nullable;

import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
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.model.LatLng;

/**
 * Created by Birbara on 31/08/2016.
 */
public class Localizador implements GoogleApiClient.ConnectionCallbacks, LocationListener {

    private final GoogleApiClient client;
    private final GoogleMap mapa;

    public Localizador(Context context, GoogleMap mapa){
        client = new GoogleApiClient.Builder(context)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .build();

        client.connect();

        this.mapa = mapa;
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {

        LocationRequest request = new LocationRequest();
        request.setSmallestDisplacement(50);
        request.setInterval(1000);
        request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        LocationServices.FusedLocationApi.requestLocationUpdates(client, request, this);
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onLocationChanged(Location location) {

        LatLng coordenada = new LatLng(location.getLatitude(), location.getLongitude());
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(coordenada);
        mapa.moveCamera(cameraUpdate);
    }
}
5 respostas

Olá Lucas,

Realmente os tipos não estão batendo no que está sendo passado para o Localizador. Nessa caso é melhor alterar o Localizador para que ele receba o MapaFragment e peça para ele centralizar o mapa quando necessário.

Começaríamos mudando o MapaFragment:

public class MapaFragment extends SupportMapFragment implements OnMapReadyCallback {
    private GoogleMap mapa;

    // ... todos os outros métodos continuam

    @Override
    public void onMapReady(GoogleMap googleMap) {
    this.mapa = mapa;  // guardamos o mapa
        LatLng posicaoDaEscola = pegaCoordenadaDoEndereco("Rua Vergueiro 3185, Vila Mariana, Sao Paulo");
        if (posicaoDaEscola != null) {
            centralizaEm(posicaoDaEscola);  // usamos um método aqui agora
        }

    // ... resto do método aqui
    }

    // esse método é novo
    public centralizaEm(LatLng coordenada) {
        if (mapa != null) {
            CameraUpdate update = CameraUpdateFactory.newLatLngZoom(coordenada, 17);
            mapa.moveCamera(update);
        }
    }

}

Agora alteramos o Localizador:

public class Localizador implements GoogleApiClient.ConnectionCallbacks, LocationListener {

    private final GoogleApiClient client;

    // guardamos o fragment ao invés do mapa agora
    private final MapaFragment mapaFragment;

    // mudamos o tipo do segundo parâmetro
    public Localizador(Context context, MapaFragment mapaFragment){
        client = new GoogleApiClient.Builder(context)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .build();

        client.connect();

        // guardamos a referência para o fragment agora
        this.mapaFragment = mapaFragment;
    }

    // ... outros métodos continuam iguais

    @Override
    public void onLocationChanged(Location location) {
        LatLng coordenada = new LatLng(location.getLatitude(), location.getLongitude());

        // aqui usamos o método que implementamos no fragment
        mapaFragment.centralizaEm(coordenada);
    }
}

Vou alterar os exemplos desse exercício para refletir essa solução. Obrigado pelo aviso!

Olá novamente,

TInha esquecido de comentar sobre uma outra parte do seu código que provavelmente vai causar problemas. Dá uma olhadinha no método onCreate(...) da MapaAlunosActivity:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        // ... começo do método

        mapaFragment = new MapaFragment();

    // aqui você deve usar o mapaFragment já criado ao invés fazer new
        tx.replace(R.id.frame_mapa, mapaFragment);
        tx.commit();

        // ... resto do método
    }

Do jeito que estava ele iria criar dois fragments: um deles seria armazenado e o outro seria jogado na tela. O problema é que o que foi armazenado seria passado pro Localizador e quando ele precisasse atualizar a posição isso não seria refletido na tela.

Oi Jeferson,

Aparentemente era pra estar ok todos os problemas rs, mas agora que corrigi apareceu uma exception:

09-01 10:46:18.843 4052-4052/br.com.alura.agenda E/AndroidRuntime: FATAL EXCEPTION: main
                                                                   Process: br.com.alura.agenda, PID: 4052
                                                                   android.content.ActivityNotFoundException: Unable to find explicit activity class {br.com.alura.agenda/br.com.alura.agenda.MapaAlunosActivity}; have you declared this activity in your AndroidManifest.xml?
                                                                       at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1788)
                                                                       at android.app.Instrumentation.execStartActivity(Instrumentation.java:1512)
                                                                       at android.app.Activity.startActivityForResult(Activity.java:3810)
                                                                       at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:48)
                                                                       at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:75)
                                                                       at android.app.Activity.startActivityForResult(Activity.java:3761)
                                                                       at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:856)
                                                                       at android.app.Activity.startActivity(Activity.java:4091)
                                                                       at android.app.Activity.startActivity(Activity.java:4059)
                                                                       at br.com.alura.agenda.ListaAlunosActivity.onOptionsItemSelected(ListaAlunosActivity.java:172)
                                                                       at android.app.Activity.onMenuItemSelected(Activity.java:2940)
                                                                       at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:406)
                                                                       at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:195)
                                                                       at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:103)
                                                                       at android.support.v7.app.AppCompatDelegateImplV9.onMenuItemSelected(AppCompatDelegateImplV9.java:667)
                                                                       at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:810)
                                                                       at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152)
                                                                       at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:957)
                                                                       at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:947)
                                                                       at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:616)
                                                                       at android.support.v7.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:153)
                                                                       at android.view.View.performClick(View.java:4923)
                                                                       at android.view.View$PerformClick.run(View.java:20341)
                                                                       at android.os.Handler.handleCallback(Handler.java:815)
                                                                       at android.os.Handler.dispatchMessage(Handler.java:104)
                                                                       at android.os.Looper.loop(Looper.java:194)
                                                                       at android.app.ActivityThread.main(ActivityThread.java:5717)
                                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                                       at java.lang.reflect.Method.invoke(Method.java:372)
                                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
                                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)

Ele reclama do manifest.xml mais a activity já está registrada la:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="br.com.alura.agenda">

    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.INTERNET" />

    <!--
         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.ACCESS_COARSE_LOCATION" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity
            android:name=".ListaAlunosActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".FormularioActivity"
            android:label="@string/title_activity_formulario"/>

        <receiver
            android:name=".receiver.SmsReceiver"
            android:enabled="true">
            <intent-filter>
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>

        <activity android:name=".ProvasActivity" />
        <!--
             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=".MapaAlunosActivity"></activity>
    </application>

</manifest>

Se ajudar segue o código das outras classes:

MapaAvitivity:

package br.com.alura.agenda;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

//import com.google.android.gms.maps.SupportMapFragment;


public class MapaAlunosActivity extends AppCompatActivity {

    private static final int REQUEST_PERMISSOES = 1;
    private MapaFragment mapaFragment;

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

        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction tx = manager.beginTransaction();

        mapaFragment = new MapaFragment();

        tx.replace(R.id.frame_mapa, mapaFragment);
        tx.commit();

        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) {
                String[] permissoes = {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
                requestPermissions(permissoes, REQUEST_PERMISSOES);
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if(requestCode == REQUEST_PERMISSOES){

            if(grantResults[0] == PackageManager.PERMISSION_GRANTED &&
                    grantResults[1] == PackageManager.PERMISSION_GRANTED){

                new Localizador(this, mapaFragment);
            }
        }
    }
}

MapaFragment:

package br.com.alura.agenda;

import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;

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.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

import java.io.IOException;
import java.util.List;

import br.com.alura.agenda.dao.AlunoDAO;
import br.com.alura.agenda.modelo.Aluno;

/**
 * Created by Birbara on 31/08/2016.
 */
public class MapaFragment extends SupportMapFragment implements OnMapReadyCallback {

    private GoogleMap mapa;

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);

        getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {

        this.mapa = googleMap;

        LatLng posicaoDaEscola = pegaCoordenadaDoEndereco("Rua Vergueiro 3185, Vila Mariana, Sao Paulo");

        if (posicaoDaEscola != null){
            centralizaEm(posicaoDaEscola);
        }

        //adiciona local do aluno
        AlunoDAO dao = new AlunoDAO(getContext());
        for(Aluno aluno : dao.buscaAlunos()){
            LatLng coordenada = pegaCoordenadaDoEndereco(aluno.getEndereco());
            if(coordenada != null) {
                MarkerOptions marcador = new MarkerOptions();
                marcador.position(coordenada);
                marcador.title(aluno.getNome());
                marcador.snippet(String.valueOf(aluno.getNota()));
                mapa.addMarker(marcador);
            }
        }
        dao.close();

        new Localizador(getContext(), MapaFragment.this);
    }

    private LatLng pegaCoordenadaDoEndereco(String endereco) {

        try{
            Geocoder geocoder = new Geocoder(getContext());
            List<Address> resultados = geocoder.getFromLocationName(endereco, 1);

            if(!resultados.isEmpty()){
                LatLng posicao = new LatLng(resultados.get(0).getLatitude(),
                        resultados.get(0).getLongitude());
                return posicao;
            }

        }catch(IOException e){
            e.printStackTrace();
        }
        return null;
    }

    public void centralizaEm(LatLng coordenada){
        if(mapa != null){
            CameraUpdate update = CameraUpdateFactory.newLatLngZoom(coordenada, 17);
            mapa.moveCamera(update);
        }
    }
}

Localizador:

package br.com.alura.agenda;

import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;

import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
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.model.LatLng;

/**
 * Created by Birbara on 31/08/2016.
 */
public class Localizador implements GoogleApiClient.ConnectionCallbacks, LocationListener {

    private final GoogleApiClient client;
    private final MapaFragment mapaFragment;

    public Localizador(Context context, MapaFragment mapaFragment) {
        client = new GoogleApiClient.Builder(context)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .build();

        client.connect();

        this.mapaFragment = mapaFragment;
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {

        LocationRequest request = new LocationRequest();
        request.setSmallestDisplacement(50);
        request.setInterval(1000);
        request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        LocationServices.FusedLocationApi.requestLocationUpdates(client, request, this);
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onLocationChanged(Location location) {

        LatLng coordenada = new LatLng(location.getLatitude(), location.getLongitude());
        mapaFragment.centralizaEm(coordenada);
    }
}
solução!

Olá Lucas,

De acordo com o erro abaixo:

android.content.ActivityNotFoundException: Unable to find explicit activity class {br.com.alura.agenda/br.com.alura.agenda.MapaAlunosActivity}; have you declared this activity in your AndroidManifest.xml?

O Android tá dizendo que a MapaAlunosActivity não tá declarada no AndroidManifest.xml mas claramente ela está! Deve ser algum problema com o build da aplicação.

Tenta fazer um rebuild completo da aplicação. É só ir no menu Build > Clean Project e depois em Build > Rebuild project. Depois é só tentar rodar de novo, vamos ver se só isso resolve.

Ok Jeferson, muito obrigado, resolvido !!!!