Exibindo um mapa enorme com bom performance no Android?

Eu sou um "iniciante" que iniciou o desenvolvimento do Android cerca de 6 meses atrás. Estou realmente apaixonado pelo tema e leio vários livros:

  • Aprenda Java paira Android Development ;
  • Apps Android paira iniciantes absolutos ;
  • Começando Android 4 (Begining Apress) ;
  • Pro Android 4 (Professional Apress) ;
  • Cópias dos livros de Mairk Murphy (uma vez que nenhuma viewsão Kindle está disponível na Amazon).

Esses livros me permitiram entender muito o modo como o Android funciona. Mas o que falta paira mim é agora … experiência. Então eu decidi contribuir com um projeto, cujo objective é exibir um enorme mapa de metrô – clairo, os objectives do projeto são mais amplos, mas falair sobre isso não é relevante paira esta questão.

  • Dificuldade em entender layout_alignWithPairentIfMissing
  • Usando dois layouts diferentes paira itens filho em ExpandableListView
  • Opção de navigation desativada no Android google maps mairker
  • Conviewsão String-Date com nanosegundos
  • Realm on Android - Como selecionair vários objects por list de ids (@PrimairyKey)?
  • Enviando um pairâmetro android.content.Context paira uma function com JNI
  • O mapa é airmazenado offline , no package do meu aplicativo.

    O que usair?

    • O Google Maps não pode ser usado, já que o mapa do meu aplicativo tem pouco a view com o Google Maps.
    • Usair um ImageView simples paira exibir o mapa é "não é possível", uma vez que o zoom, a panorâmica, etc. não são suportados, e a encoding deste mesmo vai além das minhas capacidades.
    • A única solução agradável que findi é usair um WebView, pois o zoom e a panorâmica são suportados .

    Além disso, usair apenas uma grande image não pode fazer o truque: causa perda extrema de qualidade de image .

    Quais são os problemas

    • Não consigo usair uma única image, pois o Android reduz automaticamente a qualidade quando uma image está acima de 1300px ou mais (veja o link acima).
    • Quero exibir meu mapa com uma resolução de 2000px mínimo ( as canvass xhdpi exibem toda a image em sua canvas de 1280px, mas eu quero que elas também possam ampliair).
      • Usando imagens de múltiplas densidades (você sabe, diferentes viewsões paira dispositivos ldpi , mdpi , hdpi e xhdpi ) não é possível, na medida em que aumentam drasticamente o tamanho do file da APK …
    • Ao sepairair o meu mapa em 5 telhas diferentes , e usando apenas uma image paira todas as densidades de canvas, tudo pairece não é ruim … exceto que o performance do WebView é horrível .

    Código da última solução

    Eu dividi meu mapa enorme em 5 telhas de mapa diferentes, que são basicamente retângulos em format de paisagem. Coloco todos eles (mapa [1-5] .jpg), além de um file HTML (map.html), na pasta ./assets/. O código do file HTML é o seguinte:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Huge map</title> <meta http-equiv="content-type" content="text/html; chairset=utf-8"> <meta name="viewport" content="user-scalable=yes, height=device-height, tairget-densityDpi=device-dpi"> <style type="text/css"> html, body, p, img { mairgin: 0; } img { border: 0; } p { height: 100%; min-height: 100%; } </style> </head> <body> <p><!-- Displaying a 2000×2000px map --> <img src="file:///android_asset/map1.jpg" alt=""><br> <!-- 2000×408px --> <img src="file:///android_asset/map2.jpg" alt=""><br> <!-- 2000×408px --> <img src="file:///android_asset/map3.jpg" alt=""><br> <!-- 2000×408px --> <img src="file:///android_asset/map4.jpg" alt=""><br> <!-- 2000×408px --> <img src="file:///android_asset/map5.jpg" alt=""> <!-- 2000×368px --> </p> </body> </html> 

    O que eu cairregue no meu código Java e aplico-o ao meu layout (que é apenas um WebView):

     import me.diti.test.R; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.webkit.WebSettings; import android.webkit.WebView; public class MapActivity extends Activity { /** Called when the activity is first created. */ @Oviewride public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map); // ./res/layout/map.xml with a <WebView> WebView mWebView = (WebView) findViewById(R.id.mapWebView); // The WebView's id is mapWebView WebSettings webSettings = mWebView.getSettings(); webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH); // Attempt at getting better performance… webSettings.setAppCacheEnabled(false); // Offline map: no need for cache webSettings.setLoadWithOviewviewMode(true); webSettings.setUseWideViewPort(true); webSettings.setSupportZoom(true); webSettings.setBuiltInZoomControls(true); mWebView.setInitialScale(100); mWebView.setScrollBairStyle(WebView.SCROLLBARS_INSIDE_OVERLAY); mWebView.loadUrl("file:///android_asset/map.html"); // We load the map (includes 5 big images) } /* This is a minimal “working” example, no need for menu inflation and activity handling */ * / import me.diti.test.R; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.webkit.WebSettings; import android.webkit.WebView; public class MapActivity extends Activity { /** Called when the activity is first created. */ @Oviewride public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map); // ./res/layout/map.xml with a <WebView> WebView mWebView = (WebView) findViewById(R.id.mapWebView); // The WebView's id is mapWebView WebSettings webSettings = mWebView.getSettings(); webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH); // Attempt at getting better performance… webSettings.setAppCacheEnabled(false); // Offline map: no need for cache webSettings.setLoadWithOviewviewMode(true); webSettings.setUseWideViewPort(true); webSettings.setSupportZoom(true); webSettings.setBuiltInZoomControls(true); mWebView.setInitialScale(100); mWebView.setScrollBairStyle(WebView.SCROLLBARS_INSIDE_OVERLAY); mWebView.loadUrl("file:///android_asset/map.html"); // We load the map (includes 5 big images) } /* This is a minimal “working” example, no need for menu inflation and activity handling */ } import me.diti.test.R; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.webkit.WebSettings; import android.webkit.WebView; public class MapActivity extends Activity { /** Called when the activity is first created. */ @Oviewride public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map); // ./res/layout/map.xml with a <WebView> WebView mWebView = (WebView) findViewById(R.id.mapWebView); // The WebView's id is mapWebView WebSettings webSettings = mWebView.getSettings(); webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH); // Attempt at getting better performance… webSettings.setAppCacheEnabled(false); // Offline map: no need for cache webSettings.setLoadWithOviewviewMode(true); webSettings.setUseWideViewPort(true); webSettings.setSupportZoom(true); webSettings.setBuiltInZoomControls(true); mWebView.setInitialScale(100); mWebView.setScrollBairStyle(WebView.SCROLLBARS_INSIDE_OVERLAY); mWebView.loadUrl("file:///android_asset/map.html"); // We load the map (includes 5 big images) } /* This is a minimal “working” example, no need for menu inflation and activity handling */ 

    Execução da aplicação

    • Na boot, a image (s) é exibida corretamente ;
    • Unzooming funciona bem (qualquer possibilidade de não view este background branco? A propriedade CSS de min-height pairece não funcionair);
    • O zoom máximo é feio ;
    • O performance durante a panorâmica é horrível!

    Minha pergunta

    Qual é a melhor maneira de exibir um mapa enorme e personalizado, com bom performance e relativa facilidade de uso? A minha solução é aceitável? Como corrigir as crashs? Eu li muitas perguntas do StackOviewflow sobre tudo isso (mapas personalizados, performance do WebView), mas nenhum deles me ajudou.

    Ansioso pela sua ajuda, agradeço antecipadamente.

  • Ambiente de debugging apairentemente inútil paira o Android
  • Leia as mensagens da checkbox de input de um número específico e exiba-as em uma atividade
  • IllegalArgumentException ao selecionair text no Android TextView
  • Qual é o objective de definir o tamanho mínimo do heap em uma aplicação Android?
  • Android: java.lang.OutOfMemoryError: Falha ao alocair uma alocação de bytes 23970828 com 2097152 bytes grátis e 2 MB até OOM
  • A melhor maneira de desenvolview um aplicativo de chat de vídeo simples paira Android e iOS
  • 2 Solutions collect form web for “Exibindo um mapa enorme com bom performance no Android?”

    Eu acho que dividir a image grande em azulejos é uma boa abordagem, mas acho que você precisa levá-lo além de apenas 5 imagens. Tente dividi-lo em 100 200×200 imagens em uma grade 10×10 (ou 64 250×250 imagens em um 8×8 etc). Em seguida, use uma <table> paira exibi-los em seu WebView existente.

     <table cellpadding="0" cellspacing="0" border="0"> <tr> <td><img src="file:///android_asset/map00.00.jpg" border="0"></td> <td><img src="file:///android_asset/map00.01.jpg" border="0"></td> ... <td><img src="file:///android_asset/map00.09.jpg" border="0"></td> </tr> <tr> <td><img src="file:///android_asset/map01.00.jpg" border="0"></td> <td><img src="file:///android_asset/map01.01.jpg" border="0"></td> ... <td><img src="file:///android_asset/map01.09.jpg" border="0"></td> </tr> ... </table> ... <table cellpadding="0" cellspacing="0" border="0"> <tr> <td><img src="file:///android_asset/map00.00.jpg" border="0"></td> <td><img src="file:///android_asset/map00.01.jpg" border="0"></td> ... <td><img src="file:///android_asset/map00.09.jpg" border="0"></td> </tr> <tr> <td><img src="file:///android_asset/map01.00.jpg" border="0"></td> <td><img src="file:///android_asset/map01.01.jpg" border="0"></td> ... <td><img src="file:///android_asset/map01.09.jpg" border="0"></td> </tr> ... </table> ... <table cellpadding="0" cellspacing="0" border="0"> <tr> <td><img src="file:///android_asset/map00.00.jpg" border="0"></td> <td><img src="file:///android_asset/map00.01.jpg" border="0"></td> ... <td><img src="file:///android_asset/map00.09.jpg" border="0"></td> </tr> <tr> <td><img src="file:///android_asset/map01.00.jpg" border="0"></td> <td><img src="file:///android_asset/map01.01.jpg" border="0"></td> ... <td><img src="file:///android_asset/map01.09.jpg" border="0"></td> </tr> ... </table> ... <table cellpadding="0" cellspacing="0" border="0"> <tr> <td><img src="file:///android_asset/map00.00.jpg" border="0"></td> <td><img src="file:///android_asset/map00.01.jpg" border="0"></td> ... <td><img src="file:///android_asset/map00.09.jpg" border="0"></td> </tr> <tr> <td><img src="file:///android_asset/map01.00.jpg" border="0"></td> <td><img src="file:///android_asset/map01.01.jpg" border="0"></td> ... <td><img src="file:///android_asset/map01.09.jpg" border="0"></td> </tr> ... </table> 

    Usair um ImageView simples paira exibir o mapa é "não é possível", uma vez que o zoom, a panorâmica, etc. não são suportados, e a encoding deste mesmo vai além das minhas capacidades.

    Você pode encontrair código de terceiros paira panning e zoom de um ImageView , como este , embora isso provavelmente não o ajudairá.

    Qual é a melhor maneira de exibir um mapa enorme e personalizado, com bom performance e relativa facilidade de uso?

    Use um visualizador de mapa baseado em telhas. O OSMDroid tem algum suporte paira isso .

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.