Dicas Android: Anotando mapas com marcadores personalizados

slider_android

Problema

Além de exibir um mapa centrado em um local específico, o aplicativo precisa colocar uma anotação com um marcador mais visível no local.

Solução

Criar um ItemizedOverlay personalizado para o mapa, que inclui todos os pontos para marcar. ItemizedOverlay é uma classe base abstrata que lida com todo o desenho dos itens individuais em um MapView. Os itens em si são as instâncias de OverlayItem, que é uma classe de modelo que define o nome, o subtítulo, e marcador drawable para descrever o ponto no mapa.

Como Funciona

Vamos criar uma implementação de ItemizedOverlay que terá uma série de GeoPoints e desenhá-los no mapa utilizando o mesmo marcador drawable para cada um. Veja.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class LocationOverlay extends ItemizedOverlay<OverlayItem> {
 
	private List<GeoPoint> mItems;
 
	public LocationOverlay(Drawable marker) {
		super(boundCenterBottom(marker));
	}
 
	public void setItems(ArrayList<GeoPoint>items){
		mItems = items;
		populate();
	}
 
	@Override
	protected OverlayItem createItem(int i) {
		return new OverlayItem(mItems.get(i),null,null);
	}
 
	@Override
	public int size() {
		return mItems.size();
	}
 
	@Override
	public boolean onTap(int i) {
		return true;
	}
 
}

Nesta implementação, o construtor tem uma Drawable para representar o marcador colocado no mapa em cada local. Drawables que são usados ​​em sobreposições devem ter limites próprios aplicados a eles, e boundCenterBottom() é um método de conveniência que lida com isso para nós. Especificamente, aplica-se limites, de tal forma que o ponto no Drawable que toca o mapa de localização será no centro da linha inferior de pixels.

ItemizedOverlay tem dois métodos abstratos que devem ser substituídos: createItem(), que deve retornar um objeto do tipo declarado, e size(), que retorna o número de itens administrados. Este exemplo tem uma lista de GeoPoints e envolve todos em OverlayItems. O método de populate() deve ser chamado no overlay, logo que todos os dados estão presentes e prontos para exibição, que neste caso é no final de setItems().Vamos aplicar essa sobreposição para um mapa a desenhar três locais personalizados na cidade de Maringá-Pr, usando o ícone do aplicativo padrão como o marcador. Veja.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class PointMapsActivity extends MapActivity {
 
	MapView map;
	MapController controller;
 
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        map = (MapView)findViewById(R.id.map);
        controller = map.getController();
 
        ArrayList<GeoPoint> locais = new ArrayList<GeoPoint>();
        //Catedral de Maringá
        locais.add(new GeoPoint(-23414922,-51938077));
        //Parque do Ingá
        locais.add(new GeoPoint(-23424976,-51930056));
        //Teatro Municipal Reviver
        locais.add(new GeoPoint(-23423243,-51922245));
        LocationOverlay myOverlay =
        		new LocationOverlay(getResources().getDrawable(R.drawable.icon));
 
        myOverlay.setItems(locais);
        map.getOverlays().add(myOverlay);
        controller.setCenter(locais.get(0));
        controller.setZoom(15);
    }
 
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
}

Quando executar, essa Activity nos mostrará a seguinte tela.

Observe como o desenho da sombra projetada no marcador foi tratado por nós com MapView e o ItemizedOverlay.Mas, e se queremos personalizar cada item para que ele exiba uma imagem de marca diferente? Como poderíamos fazer isso? Definindo explicitamente marcador do item, um Drawable personalizado pode ser retornado para cada item. Neste caso, o Drawable fornecido para o construtor ItemizedOverlay é apenas um valor padrão a ser usado se não substituir por personalizadas existentes. Considere uma modificação para a implementação, mostrado no código a seguir.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class LocationOverlay extends ItemizedOverlay<OverlayItem> {
 
	private List<GeoPoint> mItems;
	private List<Drawable> mMarkers;
 
	public LocationOverlay(Drawable marker) {
		super(boundCenterBottom(marker));
	}
 
	public void setItems(ArrayList<GeoPoint>items, ArrayList<Drawable> drawables){
		mItems = items;
		mMarkers = drawables;
		populate();
	}
 
	@Override
	protected OverlayItem createItem(int i) {
		OverlayItem item = new OverlayItem(mItems.get(i),null,null);
		item.setMarker(boundCenterBottom(mMarkers.get(i)));
		return item;
 
	}
 
	@Override
	public int size() {
		return mItems.size();
	}
 
	@Override
	public boolean onTap(int i) {
		return true;
	}
 
}

Com essa modificação, o OverlayItems criados agora recebem uma imagem de marcador personalizado na forma de um Drawable correspondente ao índice do item em uma lista de imagens. Se o Drawable que você definiu tem estados, os estados pressionados e focados será exibida quando o item é selecionado ou tocada. Nosso exemplo modificado para usar a nova implementação parece com este código a seguir.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class PointMapsActivity extends MapActivity {
 
	MapView map;
	MapController controller;
 
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        map = (MapView)findViewById(R.id.map);
        controller = map.getController();
 
        ArrayList<GeoPoint> locais = new ArrayList<GeoPoint>();
        ArrayList<Drawable> images = new ArrayList<Drawable>();
 
        //Catedral de Maringá
        locais.add(new GeoPoint(-23425527,-51938295));
        images.add(getResources().getDrawable(R.drawable.cathedral));
        //Parque do Ingá
        locais.add(new GeoPoint(-23424976,-51930056));
        images.add(getResources().getDrawable(R.drawable.forest));
        //Teatro Municipal Reviver
        locais.add(new GeoPoint(-23423243,-51922245));
        images.add(getResources().getDrawable(R.drawable.theater));
 
        LocationOverlay myOverlay =
        		new LocationOverlay(getResources().getDrawable(R.drawable.icon));
 
        myOverlay.setItems(locais,images);
        map.getOverlays().add(myOverlay);
        controller.setCenter(locais.get(0));
        controller.setZoom(15);
    }
 
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
}

Agora nosso exemplo fornece uma imagem diferente para cada item que quiser mostrar no mapa. Especificamente, nós decidimos representar a real localização de diversos pontos turísticos da cidade com marcadores personalizados. Veja a figura abaixo.

Para torná-los interativos

Talvez você tenha notado o método OnTap() que foi definido na LocationOverlay, mas nunca foi utilizado. Outro recurso interessante da implementação base ItemizedOverlay é que ele lida com teste de clique e tem um método de conveniência quando um item específico que tocou, fazendo referência índice desse item. A partir deste método, você pode implementar outras funções, como mostrar um diálogo, iniciar uma nova atividade, ou qualquer outra ação que se encaixa no contexto do usuário tocando na marcação para mais informações. Bom espero que tenham gostado dessa dica e até a próxima.


Dicas Android: Mapear Localizações com Google Maps API

slider_android

Problema

Você gostaria de exibir um ou mais locais em um mapa para o usuário.

Solução

A maneira mais simples de mostrar ao usuário um mapa é criar uma intent com a localização de dados e passá-lo para o sistema Android para a execução de um aplicativo de mapeamento. Vamos olhar com mais profundidade este método para fazer uma série de tarefas diferentes em outra dica posterior. Além disso, os mapas podem ser incorporados dentro do seu aplicativo usando o MapView e MapActivity fornecidas pelo Google Maps SDK.

A API do Google Maps é um módulo add-on para o core do SDK, embora ainda sejam agrupados. Se você não tiver o Google APIs SDK, abra o SDK manager e você vai encontrar um pacote para cada nível de API listadas “Third-party Add-ons”.

No fim de utilizar o API do Google Maps na sua aplicação, uma chave de API deve primeiro ser obtida do Google. Esta chave é construída usando uma chave privada que é assinada com sua aplicação .
Sem uma chave de API, as classes de mapeamento podem ser utilizados, mas nenhuma parte do mapa será retornado para o aplicativo.

Se você estiver executando o código em um emulador para testar, para operar corretamente deve-se criar uma AVD com o SDK que inclui as APIs do Google para o mapeamento.

Com a chave API na mão e uma plataforma de testes adequado no lugar, você está pronto para começar.

Como Funciona

Para mostrar um mapa, basta criar uma instância de MapView dentro de um MapActivity. Um dos atributos necessários que devem ser passados ​​para o MapView em seu layout XML é a chave API que você obteve do Google. Ver o código.

1
2
3
4
5
6
7
8
<com.google.android.maps.MapView
    	android:id="@+id/map"
    	android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:enabled="true"
        android:clickable="true"
        android:apiKey="API_KEY_STRING_HERE"
/>

Nota: Ao adicionar MapView a um layout XML, o nome do pacote totalmente qualificado deve ser incluído porque a classe não existe no android.id.view ou android.widget.

Embora, MapView pode ser instanciado a partir do código, bem como, a chave API ainda é necessária como um parâmetro de construtor.
MapView mapa = new MapView (this,”API_KEY_STRING_HERE”);
Além disso, o manifesto do aplicativo deve declarar o seu uso da biblioteca Maps, que duplamente age como um filtro para Android Market para remover o aplicativo a partir de dispositivos que não têm esta capacidade.

Agora, vamos olhar um exemplo que coloca a última localização conhecida do usuário em um mapa e exibe.

Observe as permissões declaradas para INTERNET e ACCESS_FINE_LOCATION. Este último só é necessário porque este exemplo é ligar de volta para o LocationManager para obter o valor em cache local. O outro ingrediente-chave que devem estar presentes no manifesto é a tag <uses-library> referenciando do Google Maps API. Android requer este item corretamente vinculado a biblioteca externa para o seu aplicativo exexutar, mas também serve para outro propósito. A Declaração library é usada pelo Android Market para filtrar o aplicativo para que ele não pode ser instalado em dispositivos que não estão equipados com a biblioteca de mapeamento adequada. ver código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:text="Mapa com a sua localização"
    />
    <com.google.android.maps.MapView
    	android:id="@+id/map"
    	android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:enabled="true"
        android:clickable="true"
        android:apiKey="API_KEY_HERE"
    />
</LinearLayout>

Observe a localização da chave API que você deve digitar. Além disso, observe que o MapView não tem de ser a única coisa no layout de atividade, a despeito do fato que deve ser inflado dentro de um MapActivity. Ver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class DicaMapasActivity extends MapActivity {
 
	MapView map;
	MapController controller;
 
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        map = (MapView)findViewById(R.id.map);
        controller = map.getController();
 
        LocationManager manager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        Location location = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        int lat, lng;
        if (location != null){
        	//Converte para micrograus
        	lat = (int)(location.getLatitude() * 1000000);
        	lng = (int)(location.getLongitude() * 1000000);
        } else {
        	lat = -23426118;
        	lng = -51938210;
        }
        GeoPoint mapCenter = new GeoPoint(lat, lng);
        controller.setCenter(mapCenter);
        controller.setZoom(15);
    }
 
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
}

Esta Atividade leva a localizações do usuário mais recentes, e no pronto central do mapa, todo o controle do mapa é feito através de uma instância MapController, que obtemos chamando MapView.getController (), o controlador pode ser usado para fazer zoom, pan e de outra forma ajustar o mapa na tela, neste exemplo, usamos setCenter() do controlador e setZoom() para ajustar a visualização do mapa.

MapController.setCenter () toma um GeoPoint como parâmetro, que é levemente diferente do local que recebemos os serviços Android. A principal diferença é que GeoPoint expressa latitude e longitude em termos de micrograus (ou graus * 1E6) em vez de um valor decimal que representa graus inteiros. Portanto, nós, devemos converter os valores locais antes de aplicá-los ao mapa.

MapController.setZoom () permite que o mapa seja programaticamente ampliada para um nível específicado, entre 1 e 21. Por padrão, o mapa de zoom será nível 1, que a documentação do SDK define como sendo uma visão global, com cada nível crescente aumentado no mapa por dois. Veja:

 

Mapa de localização do usuário

A primeira coisa que provavelmente você vai notar é que o mapa não mostra nenhuma indicação no ponto de localização (como um alfinete). Nas próximas dicas criaremos essas anotações, e mostraremos como personalizá-los. Até a próxima.


Dicas Android: Integração de dispositivos com localização

slider_android

Problema

Você quer aproveitar a capacidade do dispositivo para informar sua localização física atual em um aplicativo.

Solução

Utilizar os serviços fornecidos pelo Android em background como LocationManager. Um dos benefícios mais poderosos que uma aplicação móvel pode frequentemente fornecer ao usuário é a capacidade de adicionar contextos, incluindo informações com base em onde eles estão localizados atualmente. As  aplicações podem solicitar ao LocationManager para fornecer atualizações de localização de um dispositivo seja feita regularmente ou apenas quando é detectado que o dispositivo se movimentou uma distância significativa.
Ao trabalhar com os serviços de localização do Android, alguns cuidados devem ser tomados para respeitar tanto a bateria do dispositivo e desejos do usuário. A obtenção de uma correta e refinada localização usando um dispositivo de GPS é um processo de uso intenso de energia, e pode rapidamente esgotar a bateria no dispositivo do usuário se for usada continuamente. Por esta razão, entre outras, o Android permite que o usuário desabilite certas fontes de dados de localização, como GPS do dispositivo. Estas definições devem ser observadas quando seu aplicativo decidir como irá obter localização.
Cada fonte de localização também vem com um grau de precisão. O GPS irá retornar uma localização mais exata (poucos metros), mas levam mais tempo para corrigir e utilizar mais energia, e que o local de rede normalmente irá ter uma precisão de poucos quilómetros, mas é devolvido muito mais rápido e usa menos energia. Considerar os requisitos da aplicação ao decidir quais as fontes de acesso, se a sua aplicação apenas deseja exibir informações sobre a cidade local, talvez correções GPS não são necessárias.
IMPORTANTE: Para usar os serviços de localização em uma aplicação, tenha em mente que android.permission.INTERNET ou android.permission.ACCESS_FINE_LOCATION deve ser declarado no manifesto do aplicativo. Se você declarar android.permission.ACCESS_FINE_LOCATION, você não precisa tanto, uma vez que inclui permissões coarse também.
Como Funciona 
Ao criar um monitor simples para localização do usuário em uma atividade ou serviço, existem algumas ações que precisamos considerar:
  1. Determinar se a fonte que queremos usar está ativada. Se não está, decidir se itá perguntar ao usuário para ativá-la ou tentar outra fonte.
  2. Registrar as  atualizações usando valores razoáveis ​​para a distância mínima e intervalo de atualização.
  1. Cancelar o registro para atualizações quando eles já não são necessários para conservar a energia do dispositivo.
No código abaixo, criamos uma atividade para buscar as atualizações de localização, embora seja visível para o usuário, e mostrar a atual localização na tela.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
public class DicaGPSActivity extends Activity {
 
	LocationManager manager;
	Location LocalAtual;
 
	TextView locationView;
 
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        locationView = new TextView(this);
        setContentView(locationView);
 
        manager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    }
 
	@Override
	protected void onResume() {
		super.onResume();
		if(!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
			//Pergunta ao usuário para habilitar o GPS
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setTitle("Location Manager");
			builder.setMessage("Nós queremos usar sua localização, mas o GPS está desativado.\n"
					+ "Podemos mudar essa configuração agora ?");
			builder.setPositiveButton("Sim", new DialogInterface.OnClickListener() {
 
				@Override
				public void onClick(DialogInterface arg0, int arg1) {
					//Permite o usuário mudar a configuração do GPS
					Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
					startActivity(intent);
				}
			});
			builder.setNegativeButton("Não", new DialogInterface.OnClickListener() {
 
				@Override
				public void onClick(DialogInterface arg0, int arg1) {
					//Não realiza a mudança de configuração
					finish();
				}
			});
			builder.create().show();
		}
 
		//Obtêm a uma localização cacheada, se existir
		LocalAtual = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		atualizaTela();
		//Registra as atualizações
		int minTime = 5000;
		float minDistance = 0;
		manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTime, minDistance, listener);
	}
 
	private void atualizaTela() {
		if(LocalAtual == null){
			locationView.setText("Determinando sua localização...");
		} else {
			locationView.setText(String.format("Sua localização:\n%.2f,%.2f", LocalAtual.getLatitude(),
					LocalAtual.getLongitude()));
		}
	}
 
	//Manipula as chamadas dos eventos de localização
	private LocationListener listener = new LocationListener() {
 
		@Override
		public void onLocationChanged(Location location) {
			LocalAtual = location;
			atualizaTela();
		}
 
		@Override
		public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
			// TODO Auto-generated method stub
 
		}
 
		@Override
		public void onProviderEnabled(String arg0) {
			// TODO Auto-generated method stub
 
		}
 
		@Override
		public void onProviderDisabled(String arg0) {
			// TODO Auto-generated method stub
 
		}
	};
 
	@Override
	protected void onPause() {
		super.onPause();
		manager.removeUpdates(listener);
	}
}

Neste exemplo escolhemos trabalhar estritamente com o GPS do aparelho para obter atualizações de localização. Porque é um elemento chave para a funcionalidade desta atividade, a primeira grande tarefa realizada após cada retorno é para verificar se o LocationManager.GPS_PROVIDER ainda está ativado. Se, por qualquer motivo, o usuário tenha desabilitado esse recurso, damos-lhes a oportunidade de corrigir esta situação, perguntando se eles gostariam de permitir GPS. Uma aplicação não tem a capacidade de fazer isso para o usuário, por isso, se eles concordarem lançamos uma atividade usando um Intent de ação como Settings.ACTION_LOCATION_SOURCE_SETTINGS, que traz as definições do dispositivo para que o usuário possa ativar o GPS.

Uma vez GPS está ativo e disponível, a Atividade registra um LocationListener para ser notificado das atualizações locais. O método LocationManager.requestLocationUpdates() tem dois parâmetros de maior interesse, além do tipo de provedor e listener de destino:

  1. minTime
  • O intervalo mínimo entre as atualizações, em milissegundos.
  • Configurando-o para não-zero permite que o provedor local possa descansar por cerca de período especificado antes de atualizar novamente.
  • Este é um parâmetro para poder conservar energia, e não deve ser definido para um valor mais baixo do que a taxa de atualização mínima aceitável.
  1. minDistance
  • A distância o dispositivo deve se mover antes que outra atualização possa ser enviada, em metros.
  • Definindo-o para não-zero vai bloquear as atualizações até que seja determinado que o dispositivo seja movido pelo menos isto.

No exemplo, nós pedimos que as atualizações sejam enviadas sem mais frequencia do que a cada cinco segundos, sem levar em conta se o local foi alterado significativamente ou não. Quando essas atualizações chegam, o método onLocationChanged() do listener registrado é chamado. Observe que um LocationListener também será notificado quando o status de mudanças diferentes provedores, embora nós não estamos utilizando os callbacks aqui.

NOTA: Se você está recebendo atualizações em um serviço ou operação em segundo plano ou outros, o Google recomenda que o intervalo de tempo mínimo deve ser nada menos do que 60.000 (60 segundos).

O exemplo mantém uma referência a correr para o mais recente local que recebeu. Inicialmente, este valor é definido como a última localização conhecida que o fornecedor tem em cache por getLastKnownLocation(), que pode retornar nulo se o provedor não tem um valor de local em cache. A cada atualização de entrada, o valor de localização é redefinir ea exibição da interface do usuário é atualizado para refletir a nova mudança.


Dicas WP7 – Escrevendo seu primeiro código para Windows Phone 7

windows-phone-7

Nesta seção, estaremos escrevendo código C# que o manipulador de evento click do botão irá popular o TextBox com o nome “textBox” com “Hello World !”. Para adicionar um comportamento para o botão OK, dê um duplo clique no botão OK na superfície de design do seu projeto. Visual Studio irá exibir MainPage.xaml.cs onde você pode ver o método btnOk_Click é adicionado automaticamente. Você irá adicionar código correto no próximo passo para manipular o evento clique de botão.

namespace HelloWorld
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();
            SupportedOrientations = SupportedPageOrientation.PortraitOrLandscape;
        }

        private void btnOk_Click(object sender, RoutedEventArgs e)
        {
            txtMessage.Text = "Hello World !";
        }
    }
}
  1. Em MainPage.xaml você notará que o botão manipulador de eventos Click é automaticamente adicionado ao botão OK.

    1
    
    <button name="btnOk"></button>
  2. IN MainPage.xaml.cs substituir o método btnOk_Click com o seguinte código .

    private void btnOk_Click(object sender, RoutedEventArgs e)
            {
                txtMessage.Text = "Hello World !";
            }

    Executando seu primeiro aplicativo Silverlight Windows Phone

    Sua aplicação Hello World está completa. Agora é hora de construir e rodar no emulador do Windows Phone 7.

    1. Para criar a solução, selecione Criar> Solução bulid no menu do Visual Studio.

    2. Para executar o aplicativo, selecione Debug> Start Debugging.

    3. Quando o emulador aparecer, clique em OK e você vai ver “Hello World !” como mostrado na figura abaixo.

    4. Clique no controle de rotação no emulador  do Windows Phone 7, como mostrado na figura abaixo.

    Observe no modo landscape que o texbox é automaticamente redimensionada, estendeu a fazer pleno uso da orientação paisagem do dispositivo, como mostrado na figura abaixo.

    1. Para interromper a depuração do aplicativo, selecione Debug> Stop Debugging.

    Por enquanto é isso, nas próximas dicas iremos nos aprofundar mais e nos divertir muito com essa plataforma mobile, até a próxima.


Dicas Android: Acessando uma API REST

slider_android

Problema

Sua aplicação precisa acessar um API RESTful sobre HTTP para interagir com os serviços web de um host remoto.

Solução

Use as classes Apache HTTP dentro de um AsyncTask. O Android inclui os componentes da biblioteca Apache HTTP , que fornece um método robusto de criação de conexões para remote APIs. A biblioteca Apache inclui classes para criar requisições GET, POST, PUT e DELETE  com facilidade, bem como fornecer suporte para SSL, o armazenamento de cookies, autenticação HTTP e outros requisitos que sua API específica pode ter na sua HttpClient.

REST significa Representational State Transfer, e é um estilo comum arquiitetural para serviços web hoje. RESTful APIs são tipicamente construídos usando verbos padrão do HTTP para criar solicitações de recursos remotos e as respostas são tipicamente retornadas em um formato de documentos estruturados, como XML, JSON, ou valores separados por vírgula (CVS).

Como Funciona

É um AsyncTask que pode processar qualquer HttpUriRequest e retornar a resposta string.

AsyncTask Processando HttpRequest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class RestTask extends AsyncTask {
 
	public static final String HTTP_RESPONSE = "httpResponse";
 
	private Context mContext;
	private HttpClient mClient;
	private String mAction;
 
	public RestTask(Context context, String action) {
		this.mContext = context;
		this.mAction = action;
		this.mClient = new DefaultHttpClient();
	}
 
	public RestTask(Context context, String action, HttpClient client) {
		mContext = context;
		mAction = action;
		mClient = client;
	}
 
	@Override
	protected String doInBackground(HttpUriRequest... params) {
 
		try {
			HttpUriRequest request = params[0];
			HttpResponse serverResponse = mClient.execute(request);
			BasicResponseHandler handler = new BasicResponseHandler();
			String response = handler.handleResponse(serverResponse);
			return response;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
 
	@Override
	protected void onPostExecute(String result) {
		Intent intent = new Intent(mAction);
		intent.putExtra(HTTP_RESPONSE, result);
		mContext.sendBroadcast(intent);
	}
 
}

O RestTask pode ser construído com ou sem parâmetros em HttpClient. O motivo para permitir que isto seja assim são várias requisições podem usar o objeto do mesmo cliente. Isto é extremamente útil se a sua API requer cookies para manter uma sessão ou se existe um conjunto específico de parâmetros necessários que são mais fáceis de configurar uma vez (como stores SSL), a tarefa tem um parâmetro para processar HttpUriRequest (como HttpGet, HttpPost , HttpPut, HttpDelete e são todas subclasses) e executá-las.

Uma BasicResponseHandler processa a resposta, que é uma classe de conveniência que abstrai a nossa tarefa de precisar verificar a resposta para erros. BasicResponseHandler irá devolver a resposta HTTP como uma string se o código de resposta é IXX ou 2XX, mas irá lançar uma HttpResponseException se o código de resposta foi de 300 ou superior.

A última peça importante desta classe existe em OnPostExecute (),. após isso a interação com a API está completa. Quando construído, o RestTask recebe um parâmetro String para ser a ação de um Intent que é transmitido de volta para todos os listerners com a resposta API encapsulados como um extra.
Este broadcast é o mecanismo de notificação de volta para o chamador da API que os dados estão prontos para processamento.

Agora vamos usar essa nova e poderosa ferramenta para criar algumas requisições básicas de API. Nos exemplos a seguir utilizamos a API REST Yahoo! Weather. Esta API tem dois parâmetros necessários para cada solicitação:

Visite http://developer.yahoo.com/weather/ para encontrar mais informações sobre esta API.

Exemplo GET

Uma requisição GET é a requisição mais simples e comum em muitas APIs públicas. Parâmetros que devem ser enviados com a requisição são codificadas numa string da URL em si, de modo que nenhum dado adicional deve ser fornecido. Vamos criar uma requisição GET para procurar por uma previsão do tempo de um local e tipo de grau.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class BuscaAPIActivity extends Activity {
 
	private static final String SEARCH_ACTION = "com.examples.rest.SEARCH";
 
	private static final String SEARCH_URI =  "http://weather.yahooapis.com/forecastrss?w=615702&u=c";
 
	private TextView result;
	private ProgressDialog progress;
 
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        result = new TextView(this);
        setContentView(result);
 
        try {
			String url = String.format(SEARCH_URI);
			HttpGet searchRequest = new HttpGet(new URI(url));
			RestTask task = new RestTask(this, SEARCH_ACTION);
			task.execute(searchRequest);
 
			progress = ProgressDialog.show(this, "Buscando", "Aguarde os resultados...", true);
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
 
	@Override
	protected void onResume() {
		super.onResume();
		registerReceiver(receiver, new IntentFilter(SEARCH_ACTION));
	}
 
	@Override
	protected void onPause() {
		super.onPause();
		unregisterReceiver(receiver);
	}
 
	private BroadcastReceiver receiver = new BroadcastReceiver() {
 
		@Override
		public void onReceive(Context context, Intent intent) {
			if (progress != null) {
				progress.dismiss();
			}
			String response = intent.getStringExtra(RestTask.HTTP_RESPONSE);
 
			result.setText(response);
		}
	};
}

No exemplo, criamos o tipo de solicitação HTTP que precisamos com a URL do que deseja se conectar (neste caso, uma solicitação GET para http://weather.yahooapis.com. A URL é armazenada como uma constante em formato de string, e os parâmetros necessários para a API Yahoo! Weather (w(WOEID) e u(units)) são adicionados em tempo de execução um pouco antes da requisição ser criada.

A RestTask é criado com uma string de ação única a ser transmitida após a conclusão, e a task é executada. O exemplo também define um BroadcastReceiver que irá registra-lo para a mesma ação que foi enviado para o RestTask. Quando a tarefa estiver concluída, este receptor vai pegar a transmissão e a resposta API para ser descompactado e processado. Vamos discutir a análise XML estruturado e respostas JSON como estas nos próximos posts, então por enquanto o exemplo simplesmente exibe a matéria-prima para a interface do usuário.


Powered by WordPress | Designed by: WordPress Themes | Thanks to best wordpress themes, Find WordPress Themes and Themes Directory

Ad Plugin made by Free Wordpress Themes