[Resolvido] Couldn't get connection factory client (MapView)

Olá a todos,
comecei a estudar android a algum tempo e impressionado com seus recursos decidi criar uma aplicação de estudo que utiliza-se mapView e que realiza-se a seguinte tarefa:
- Disponibilizar 4 campos de entrada para o usuário, sendo eles: latitude e longitude inicial e latitude e longitude final.
- Após o usuário entrar com os parâmetros (coordenadas iniciais e finais) e clicar no botão “Definir rota” o sistema deveria desenhar a rota entre os pontos solicitados.

Sendo assim, comecei a desenvolver a aplicação realizando todos os passos necessários para utilizar os recursos de forma correta, tais como:
Gerar a chave de acesso a api do maps:
- Localizei o certificado digital debug.keystore (como utilizo windows, localizei o arquivo no diretório “c:/documents and settings/<meu usuario>/.android/”)
- Entrei no prompt de comando e obtive o fingerprint (md5) do certificado digital. (para mais informações: https://developers.google.com/maps/documentation/android/mapkey)
- Entrei no site (https://developers.google.com/maps/documentation/android/mapkey) e enviei o fingerprint (md5) para obter a chave da api do maps.
- Inclui a chave no MapView.

Setar permissões de acesso ao AndroidManifest:
	- Inclui a permissão de acesso a internet: &lt;uses-permission android:name="android.permission.INTERNET"/&gt;

Neste momento, ja é para existir em minha aplicação o mapa do google… AQUI JA COMEÇA O PROBLEMA INEXPLICAVEL… o mapa aparece, mas junto com ele vem uma mensagem maldita no LogCat chamada "Couldn’t get connection factory client"
Ja pesquisei em tudo quanto é lugar e não encontrei uma definição exata para esta mensagem. Aqui no GUJ mesmo tem um usuário que passou por um problema semelhante, mas segundo ele resolveu incluindo
a permissão a internet, coisa que minha aplicação ja possui.
O problema não é somente a mensagem. O problema é que eu acredito que não consigo plotar nenhuma informação no mapa por conta deste erro. Todos os geoPoints que eu tento colocar no mapa não aparecem… a unica mensagem que possuo é "Couldn’t get connection factory client"
Acredito que este erro esta relacionado a minha chave, mas eu ja troquei de chave de tudo quanto é forma e ainda assim o problema persiste.

A aplicação ja possui o módulo pronto e ja esta buscando o kml na net, processando e montando os geoPoints com as coordenadas obtidas… Mas na hora de plotar no mapa a mensagem persiste: “Couldn’t get connection factory client” e nada além do mapa aparece.

Alguém ai sabe o que pode estar acontecendo?

O código de exemplo esta neste link http://www.4shared.com/zip/fGIxBoUo/DrawRoute.html?refurl=d1url (4shared) para download…

Desde ja agradeço a atenção.

:smiley: :smiley: :smiley:

Depois que postei, continuei fazendo testes e descobri outro fator interessante, apenas como complemento…

Estou utilizando o método abaixo para montar a URL que ira me retornar o KML com as informações da rota:

public String getUrl(double[] start, double[] end){
		StringBuffer urlString = new StringBuffer();
		urlString.append("http://maps.google.com/maps?f=d&hl=pt-BR");
		urlString.append("&saddr=");
		urlString.append(start[0] + "," + start[1]); //latitude e longitude inicial
		urlString.append("&daddr=");
		urlString.append(end[0] + "," + end[1]); //latitude e longitude final
		urlString.append("&ie=UTF8&0&om=0&output=kml");

		return urlString.toString();
	}

O interessante é que no começo dos meus testes a URL estava trazendo um arquivo .kml para download, e minha aplicação consumia este arquivo e mostrava no LogCat as coordenadas obtidas antes e depois de montar o array de GeoPoint. Porém, agora estou testando e a mesma retorna a seguinte informação: 07-27 16:30:35.073: I/ERRO(6208): unterminated entity ref (position:ENTITY_REF @1:802 in java.io.InputStreamReader@416beec0)

Então, resolvi recuperar o link e colocar no browser para ver o resultado, e adivinhem… no começo dos testes o mesmo link fazia o download do arquivo .kml, porém agora o link me leva para o maps.google.com e desenha a rota no mapa… muito estranho! Outro detalhe é que se trocamos o formato do parâmetro “output” do link de KML para JSON (no browser) é solicitado o download do arquivo como era feito antes com o KML.

O problema de consumir o JSON é que o mesmo não é tão completo quanto o KML que possui informações da rota…

Não tenho certeza mas tudo isso me leva a crer que há um limite permitido para consultas neste link… e que apartir deste limite em uma determinada janela de horários o google impede que seja feito o download do KML caso o limite seja ultrapassado… vou dar uma “googlada” para ver se consigo levantar mais informações. Caso encontre, volto a compartilhar.

:smiley: :smiley: :smiley:

Obrigado.

Olá Pessoal,

durante alguns testes percebi que o problema não esta relacionado a mensagem “Couldn’t get connection factory client”, pois consegui plotar um overlay no mapa mesmo com esta mensagem aparecendo.

Esta ocorrendo algo que ainda não consegui entender… logo no inicio, quando iniciei o desenvolvimento da app escrevi o método getUrl (descrito no do um ultimo post), utilizando o link “https://maps.google.com/maps?f=d&hl=en&saddr=latitude,longitude&daddr=latitude,longitude&ie=UTF8&om=0&output=kml” para obter o kml, gerar os GeoPoints e inseri-los na Overlay… com este link durante os testes conseguia obter as coordenadas juntamente com as informações do trajeto que eu precisava. Ou seja, durante os testes, quando eu colocava este link na URL de um browser qualquer, o mesmo solicitava o download do KML. Agora quando eu coloco o mesmo link o browser carrega a pagina do maps e desenha o trajato no mapa…

Alguém o que pode estar acontecendo?

Obrigado.

Olá a todos, após algumas horas de leitura e persistência consegui desenvolver a app e faze-la funcionar. :smiley: :smiley:
Segue minha solução:

Primeiro procurei entender como o google disponibiliza o arquivo KML para consumo e como o arquivo é montado para desenvolver o parser corretamente.
Então, durante minhas pesquisas encontrei este link que explica de forma resumida como as coisas funcionam - https://developers.google.com/maps/documentation/directions/

Depois refatorei o método getUrl da classe UrlMap responsável por retornar o link de acesso.

	public String getUrl(double[] start, double[] end){

		StringBuffer urlString = new StringBuffer();
		urlString.append(&quot;http://maps.googleapis.com/maps/api/directions/xml?&quot;);
		urlString.append(&quot;&origin=&quot;);
		urlString.append(start[0] + &quot;,&quot; + start[1]); //latitude e longitude inicial
		urlString.append(&quot;&destination=&quot;);
		urlString.append(end[0] + &quot;,&quot; + end[1]); //latitude e longitude final
		urlString.append(&quot;&sensor=false&quot;); 
		urlString.append(&quot;&region=br&quot;); 
		
		return urlString.toString();
	}

Então montei o método getConnection da classe UrlMap que é o responsável por realizar a conexão com a URL e retornar o InputStream obtido.

	public InputStream getConnection(String url){
		try{
			URL inUrl = new URL(url);
			URLConnection conn = inUrl.openConnection();
			return conn.getInputStream();
		}catch(IOException e){
			Log.w(&quot;UrlMap&quot;, &quot;getConnection =&gt; &quot; + e.getMessage());
		}
		return null;
	}

Com a conexão pronta montei o método getRoute da classe UrlMap que faz o parser do arquivo KML.

	public ArrayList&lt;GeoPoint&gt; getRoute(InputStream is) throws Exception{

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document doc = db.parse(is);
		
		NodeList list = doc.getElementsByTagName("overview_polyline").item(0).getChildNodes().item(1).getChildNodes();
		return decodePoly(list.item(0).getNodeValue());
	}

Neste momento percebi que iria precisar de um decodificador, pois os pontos que são resgatados do KML no nó <overview_polyline> estão criptografados
então, depois de algumas pesquisas consegui montar o método decodePoly da classe UrlMap que monta o ArrayList de GeoPoint apenas informando a string criptografada.

	private ArrayList&lt;GeoPoint&gt; decodePoly(String encoded) {
	
		ArrayList&lt;GeoPoint&gt; poly = new ArrayList&lt;GeoPoint&gt;();
	    int index = 0, len = encoded.length();
	    int lat = 0, lng = 0;

	    while (index &lt; len) {
	        int b, shift = 0, result = 0;
	        do {
	            b = encoded.charAt(index++) - 63;
	            result |= (b & 0x1f) &lt;&lt; shift;
	            shift += 5;
	        } while (b &gt;= 0x20);
	        int dlat = ((result & 1) != 0 ? ~(result &gt;&gt; 1) : (result &gt;&gt; 1));
	        lat += dlat;

	        shift = 0;
	        result = 0;
	        do {
	            b = encoded.charAt(index++) - 63;
	            result |= (b & 0x1f) &lt;&lt; shift;
	            shift += 5;
	        } while (b &gt;= 0x20);
	        int dlng = ((result & 1) != 0 ? ~(result &gt;&gt; 1) : (result &gt;&gt; 1));
	        lng += dlng;

	        GeoPoint p = new GeoPoint((int) (((double) lat / 1E5) * 1E6),
	             (int) (((double) lng / 1E5) * 1E6));
	        poly.add(p);
	    }
	    return poly;
	}

Neste momento ja temos os GeoPoints praticamente montados, para conseguir desenhá-los no mapa vamos precisar de uma outra classe (RouteOverlay) que extende Overlay para conseguirmos desenhar as linhas do trajeto.

	public class RouteOverlay extends Overlay{
	
		private GeoPoint gp1;
		private GeoPoint gp2;
		private int color;
		 
		public RouteOverlay(GeoPoint gp1, GeoPoint gp2, int color) {
			this.gp1 = gp1;
			this.gp2 = gp2;
			this.color = color;
		}
		@Override
		public void draw(Canvas canvas, MapView mapView, boolean shadow) {
			Projection projection = mapView.getProjection();
			Paint paint = new Paint();
			Point point = new Point();
			projection.toPixels(gp1, point);
			paint.setColor(color);
			Point point2 = new Point();
			projection.toPixels(gp2, point2);
			paint.setStrokeWidth(5);
			paint.setAlpha(50);
			canvas.drawLine(point.x, point.y, point2.x, point2.y, paint);
			super.draw(canvas, mapView, shadow);
		}
	}

Agora para concluir o projeto e conseguir desenhar uma rota entre dois pontos no mapa utilizando coordenadas, basta fazer as referências aos métodos criados
e associa-los corretamente na classe principal MainActivity:

public class MainActivity extends MapActivity {

	private MapView mapView;

	public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
		
		mapView = (MapView) findViewById(R.id.mapView);

		new Thread(){
        	public void run(){
				Bundle trajeto = new Bundle();
				
				//ponto inicial
				trajeto.putDouble(&quot;latIni&quot;,-22.74943);
				trajeto.putDouble(&quot;lonIni&quot;,-47.332735);
				
				//ponto final
				trajeto.putDouble(&quot;latFim&quot;,-22.711748);
				trajeto.putDouble(&quot;lonFim&quot;,-47.289133);
				
				Message message = new Message();
	    		message.setData(trajeto);
	    		handler.sendMessage(message);
			}
		}.start();
	}
	
	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}
	
	private Handler handler = new Handler(){
		@Override
		public void handleMessage(Message msg){
			UrlMap urlMap = new UrlMap();
			double inicio[] = {msg.getData().getDouble(&quot;latIni&quot;),msg.getData().getDouble(&quot;lonIni&quot;)};
			double fim[] = {msg.getData().getDouble(&quot;latFim&quot;),msg.getData().getDouble(&quot;lonFim&quot;)};
			try{
				ArrayList&lt;GeoPoint&gt; geoPoints = urlMap.getRoute(urlMap.getConnection(urlMap.getUrl(inicio, fim)));
				List&lt;Overlay&gt; overlays = mapView.getOverlays();
				for (int i = 1; i &lt; geoPoints.size(); i++)
					overlays.add(new RouteOverlay(geoPoints.get(i - 1), geoPoints.get(i), Color.BLUE));
				
				mapView.getController().setCenter(geoPoints.get(0));
				mapView.getController().setZoom(16);
				
			}catch(Exception e){
				Log.w(&quot;MainActivity&quot;, &quot;handleMessage =&gt; &quot; + e.getMessage());
			}
		}
	};
}

Esta solução não resolveu o problema da mensagem “Couldn’t get connection factory client”:frowning:

Mas fez com que minha aplicação desenha-se a rota que eu estava esperando. :wink:

Segue aqui alguns links que eu utilizei como referência:
https://developers.google.com/maps/documentation/directions/
https://developers.google.com/maps/documentation/utilities/polylinealgorithm


http://blog.synyx.de/2010/06/routing-driving-direc...2��-part-2-draw-the-route/

Segue o link do exemplo completo para download: http://www.4shared.com/zip/1teAPLXb/DrawRoute.html

Valeu, abraços.

Fala amigo,

estou com o mesmo problema que vc estava em relacao ao mapa, mas ao contrario de vc o meu mapa nao aparece, apenas os quadrados, sabe como resolver? ja coloquei permissao e ja troquei a chave e nada funciona.

Abs