<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CE8NSH48eCp7ImA9WhRbGEo.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661</id><updated>2012-02-10T03:21:39.070-08:00</updated><category term="1.5" /><category term="Hospedagem Java Free" /><category term="Flipout" /><category term="Habilitar" /><category term="BADA" /><category term="Java ME" /><category term="Apple" /><category term="Curso" /><category term="Route" /><category term="Ceará" /><category term="MotoBlur" /><category term="BroadcastReceiver" /><category term="BD" /><category term="MTJ" /><category term="Notícias" /><category term="eXtreme Go Horse Process" /><category term="Eventos" /><category term="Honeycomb" /><category term="Se meu código falasse" /><category term="Apache" /><category term="excluir" /><category term="tecdam" /><category term="Compilador" /><category term="Copiar" /><category term="Auto complete" /><category term="Fail" /><category term="i18n" /><category term="deprecated" /><category term="Helios" /><category term="Complexo" /><category term="Unbuntu" /><category term="Ler em voz alta" /><category term="Empreenderorismo" /><category term="AttributeSet" /><category term="Shop4Apps" /><category term="Quatro cantos" /><category term="SDK" /><category term="panic" /><category term="gradiente" /><category term="Bluetooth" /><category term="Som" /><category term="mp3" /><category term="Conversão" /><category term="Rota" /><category term="Tradutor" /><category term="KSOAP" /><category term="Charm" /><category term="2.1" /><category term="BaseAdapter" /><category term="Microsoft" /><category term="reflect" /><category term="Silvio Meira" /><category term="Xcode" /><category term="RadioButton" /><category term="RemoteViews" /><category term="Defy" /><category term="Gestures" /><category term="Wallpaper" /><category term="Erro" /><category term="Diretório" /><category term="AudioManager" /><category term="Leopard" /><category term="Swing" /><category term="AsyncTask" /><category term="Audio" /><category term="Ice Cream Sandwich" /><category term="devmedia" /><category term="2.2" /><category term="Impressora" /><category term="Treinamento" /><category term="Pulha virtual" /><category term="orientation" /><category term="Complex Data" /><category term="Home" /><category term="Busca" /><category term="Courier" /><category term="ConnectivityManager" /><category term="Vivo" /><category term="resolução" /><category term="Cloud" /><category term="Gallery" /><category term="Emulador" /><category term="driver" /><category term="Orientação" /><category term="linuxfi" /><category term="Recife" /><category term="Scroll" /><category term="Gesture" /><category term="pdu" /><category term="ICS" /><category term="espaço" /><category term="mcc" /><category term="Nordeste" /><category term="widgets" /><category term="Porto Digital" /><category term="Touch" /><category term="Padrões" /><category term="Javadoc" /><category term="PreferenceActivity" /><category term="sexto sentido" /><category term="Galeria" /><category term="Samsung" /><category term="máscara" /><category term="Trailer" /><category term="tela" /><category term="Ant" /><category term="TabActivity" /><category term="Galaxy" /><category term="Spice" /><category term="path" /><category term="Download" /><category term="display" /><category term="Projeto" /><category term="Voice" /><category term="interceptando" /><category term="Intents Nativas" /><category term="LWUIT" /><category term="AVD" /><category term="HTTP" /><category term="Lexer" /><category term="Gestos" /><category term="Flash" /><category term="passando objetos" /><category term="faculdade" /><category term="Parser" /><category term="Jersey" /><category term="Status" /><category term="Cariri" /><category term="Adobe" /><category term="camera" /><category term="NotificationManager" /><category term="Top" /><category term="XML" /><category term="Java Free Host" /><category term="state" /><category term="style" /><category term="Listener" /><category term="RESTful" /><category term="Nexus" /><category term="printscreen" /><category term="digits Mapas" /><category term="FilterResults" /><category term="drawable" /><category term="acender" /><category term="configChanges" /><category term="Papel de parede" /><category term="Interface Builder" /><category term="shape" /><category term="Twitter" /><category term="Patch" /><category term="chamada" /><category term="Reader" /><category term="saveInstanceState" /><category term="Fonte" /><category term="PhoneGap" /><category term="Froyo" /><category term="Code Assist" /><category term="nglauber" /><category term="browser" /><category term="JUnit" /><category term="Book" /><category term="MotoCliq" /><category term="ContactsContract" /><category term="mercado de trabalho" /><category term="Especialização" /><category term="Custom" /><category term="MediaPlayer" /><category term="Thread" /><category term="9.png" /><category term="Alert" /><category term="Acelerômetro" /><category term="Palestra" /><category term="Java" /><category term="Search" /><category term="Air" /><category term="API" /><category term="Mapas" /><category term="Command" /><category term="SOAP" /><category term="Filme" /><category term="Pós Graduação" /><category term="incluir" /><category term="Java Magazine" /><category term="Arquiteturais" /><category term="iOS2Droid" /><category term="Overlay" /><category term="debug.keystore" /><category term="Java Web" /><category term="cores" /><category term="programaticamente" /><category term="Notificação" /><category term="Dock" /><category term="iPad" /><category term="GoogleMaps" /><category term="Pernambuco" /><category term="Nine" /><category term="Exemplo" /><category term="Redes" /><category term="J2ME" /><category term="Fragment" /><category term="KML" /><category term="Animação" /><category term="sms" /><category term="Print" /><category term="telefone" /><category term="Market" /><category term="tridimensional" /><category term="mnc" /><category term="SQLite" /><category term="Configurações" /><category term="Dead Pixel" /><category term="Feed" /><category term="RUP" /><category term="spam" /><category term="Flex" /><category term="capturando" /><category term="Jaboatão" /><category term="Atualização" /><category term="iOS" /><category term="EATJ" /><category term="Service" /><category term="CAD" /><category term="PDF" /><category term="iATKOS" /><category term="Testes Unitários" /><category term="Antenna" /><category term="Livro" /><category term="recebendo" /><category term="mkdir" /><category term="App Inventor" /><category term="Netbeans" /><category term="Tomcat" /><category term="iPhone" /><category term="Universidade Católica de Pernambuco" /><category term="G1" /><category term="Eclipse" /><category term="Scrum" /><category term="EditText" /><category term="PX" /><category term="unibratec" /><category term="Parcelable" /><category term="wakelock" /><category term="XMLVM" /><category term="Desabilitar" /><category term="reflection" /><category term="Sprite" /><category term="TabHost" /><category term="OAuth" /><category term="ListActivity" /><category term="Especializa" /><category term="ADT" /><category term="inovação" /><category term="emptyView" /><category term="mask" /><category term="Acrobat" /><category term="Imprimir" /><category term="Tutorial" /><category term="XNA" /><category term="Waldez Luiz Ludwig" /><category term="enviando" /><category term="Expressão Regular" /><category term="Tablets" /><category term="JSON" /><category term="artigo" /><category term="masked" /><category term="Estilos" /><category term="ListView" /><category term="screen" /><category term="Banco de Dados" /><category term="res" /><category term="Java4Ever" /><category term="Live Wallpaper" /><category term="Dialog" /><category term="PVMFErrNotSupported" /><category term="Motorola" /><category term="Splash" /><category term="Foto" /><category term="SDcard" /><category term="Google" /><category term="JDBC" /><category term="CESAR" /><category term="LinearLayout" /><category term="Alarme" /><category term="Database" /><category term="AppWidgetProvider" /><category term="Linux" /><category term="Dissertação" /><category term="20" /><category term="JPopupMenu" /><category term="Unicap" /><category term="João Pessoa" /><category term="Elips" /><category term="Loading" /><category term="install" /><category term="SharedPreferences" /><category term="Dicas" /><category term="4" /><category term="Tamanho da Tela" /><category term="Adapter" /><category term="Reconhecimento" /><category term="Multiple" /><category term="licões" /><category term="DownloadManager" /><category term="4.0" /><category term="Milestone" /><category term="Personalizada" /><category term="OSX86" /><category term="ViewHolder" /><category term="ANTLR" /><category term="DIP" /><category term="location" /><category term="Ah if my Code could talk" /><category term="RSS" /><category term="Axis" /><category term="Mac" /><category term="Java SE" /><category term="PC" /><category term="82" /><category term="Twitter4J" /><category term="Page" /><category term="Lento" /><category term="UFPE" /><category term="Android 2.0" /><category term="TabWidget" /><category term="WebMobile" /><category term="Lion" /><category term="MySQL" /><category term="WTK" /><category term="Sandwich" /><category term="Web Services" /><category term="Interpolator" /><category term="Avançado" /><category term="Intents" /><category term="Regex" /><category term="Filter" /><category term="Maps" /><category term="View" /><category term="Multi-Touch" /><category term="Guararapes" /><category term="CIn" /><category term="GPS" /><category term="eficiente" /><category term="selector" /><category term="screenshot" /><category term="Teclado Virtual" /><category term="Activity" /><category term="33" /><category term="lessons" /><category term="XP" /><category term="Problema" /><category term="Titanium" /><category term="XGHP" /><category term="contatos" /><category term="PreferenceScreen" /><category term="Cream" /><category term="3G" /><category term="Programming" /><category term="CDT" /><category term="real" /><category term="recursos" /><category term="AlertDialog" /><category term="Objective-C" /><category term="Comando" /><category term="Hospedagem Java Grátis" /><category term="34" /><category term="Android" /><category term="Animation" /><category term="TODO" /><category term="Mobile" /><category term="AutoCompleteTextView" /><category term="programatically" /><category term="JTable" /><category term="XGH" /><category term="Compatibility" /><category term="Sensores" /><category term="layout_weight" /><category term="REST" /><category term="peso" /><category term="JSR" /><category term="SoundPool" /><category term="Paraíba" /><category term="Instalação" /><category term="Web Service" /><category term="Slice" /><category term="9" /><category term="keytool" /><category term="Horizontal" /><category term="ligar" /><category term="Recognition" /><category term="3D" /><category term="Hackintosh" /><category term="Mestrado" /><category term="Cupcake" /><category term="Axis2" /><category term="Ice" /><title>debug is on the table</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://nglauber.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://nglauber.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>146</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/DebugIsOnTheTable" /><feedburner:info uri="debugisonthetable" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CUINSX45fip7ImA9WhRbFU4.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-1067382577089724288</id><published>2012-02-03T08:31:00.000-08:00</published><updated>2012-02-06T05:06:38.026-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-06T05:06:38.026-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="artigo" /><category scheme="http://www.blogger.com/atom/ns#" term="devmedia" /><category scheme="http://www.blogger.com/atom/ns#" term="Java Magazine" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="Ice Cream Sandwich" /><category scheme="http://www.blogger.com/atom/ns#" term="ICS" /><category scheme="http://www.blogger.com/atom/ns#" term="4.0" /><title>Artigo "Android 4: Ice Cream Sandwich"</title><content type="html">&lt;a href="http://www.devmedia.com.br/resumo/default.asp?ed=100&amp;amp;site=6"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 199px; height: 271px;" src="http://3.bp.blogspot.com/-4qiRpqj7kKY/TywOR8cRsAI/AAAAAAAAAks/4wAVgYIQXzQ/s400/capaJava100_G.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5704950529416867842" /&gt;&lt;/a&gt;Olá povo,&lt;br /&gt;&lt;br /&gt;A revista &lt;a href="http://www.devmedia.com.br/resumo/default.asp?ed=100&amp;amp;site=6"&gt;Java Magazine&lt;/a&gt; deste mês, traz em sua edição comemorativa de número 100, a primeira de duas matérias sobre a nova versão da plataforma Android. O texto foi escrito por mim e pelo meu colega Bruno Vinícius.&lt;br /&gt;&lt;br /&gt;O Ice Cream Sandwich, como é denominada a nova versão, veio para unificar os smartphones e tablets Android. Neste artigo, apresentamos as novas APIs da versão 4.0 do sistema operacional da Google, que vieram para ajudar a encarar de frente e superar seus concorrentes. As várias melhorias de desempenho e diversas novas funcionalidades para os usuários e desenvolvedores, também são descritas no texto.&lt;br /&gt;&lt;br /&gt;A segunda parte da matéria deverá sair em março.&lt;br /&gt;Espero que vocês gostem.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-1067382577089724288?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/177Me_60citwi_mHxyqk6bl6JRM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/177Me_60citwi_mHxyqk6bl6JRM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/177Me_60citwi_mHxyqk6bl6JRM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/177Me_60citwi_mHxyqk6bl6JRM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/VkAEf723q24" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=1067382577089724288" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/1067382577089724288?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/1067382577089724288?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/VkAEf723q24/artigo-android-4-ice-cream-sandwich.html" title="Artigo &quot;Android 4: Ice Cream Sandwich&quot;" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-4qiRpqj7kKY/TywOR8cRsAI/AAAAAAAAAks/4wAVgYIQXzQ/s72-c/capaJava100_G.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2012/02/artigo-android-4-ice-cream-sandwich.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8DRHsycSp7ImA9WhRbEU0.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-3245925770550837908</id><published>2012-01-31T05:18:00.000-08:00</published><updated>2012-02-01T05:44:35.599-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-01T05:44:35.599-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Honeycomb" /><category scheme="http://www.blogger.com/atom/ns#" term="Compatibility" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="Fragment" /><title>Fragmentos para todos</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Uma das novidades do Android 3 (Honeycomb), foi a adição do conceito de Fragments. Com essa versão foi escrita exclusivamente para tablets, os "fragmentos" permitem a separação de uma Activity em pedaços de modo a aproveitar os grande tamanho de tela desse tipo de dispositivo. Os Fragments funcionam como sub-activities (dentro de uma Activity), e têm seu próprio ciclo de vida, tratando também os eventos dos componentes nele contidos.&lt;br /&gt;&lt;br /&gt;Você pode estar se perguntando: ótimo, mas isso é só pro Android 3 ou superior, então não roda no 2.x. Você estaria certo se a Google não tivesse disponibilizado uma API de compatibilidade, que permite usufruir de alguns recursos do Honeycomb em aparelhos 1.6 (Donut) ou superior. Essa biblioteca está disponível no Android SDK Manager, o mesmo lugar onde você baixa os pacotes necessários para o desenvolvimento Android. Essa API é basicamente um JAR que deve ser adicionado no seu projeto Android.&lt;br /&gt;&lt;br /&gt;A Figura abaixo mostra a opção para baixar a API de compatibilidade no Android SDK Manager.&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-0r4Rwh4YiV0/TyKpVKDSwfI/AAAAAAAAAkU/vtM7TO7PNNM/s1600/Screen%2Bshot%2B2012-01-27%2Bat%2B10.46.46%2BAM.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 307px;" src="http://3.bp.blogspot.com/-0r4Rwh4YiV0/TyKpVKDSwfI/AAAAAAAAAkU/vtM7TO7PNNM/s400/Screen%2Bshot%2B2012-01-27%2Bat%2B10.46.46%2BAM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5702306259144983026" /&gt;&lt;/a&gt;&lt;br /&gt;Uma vez baixado, o JAR vá até a pasta do SDK e procure pelo arquivo android-support-v4.jar. Ele pode estar na pasta extras/android/compatibility/v4 ou android-compatibility/v4 (dependendo do S.O.).&lt;br /&gt;Crie um novo projeto Android selecionando a versão 1.6 ou superior, e na raiz do projeto, crie uma pasta lib. Copie o JAR para essa pasta e depois adicione-o ao Build-Path do projeto (botão direito sobre JAR, Build Path &amp;gt; Add to build path). Em seguida, clique com o botão direito sobre o projeto e clique em propriedades. Por fim, selecione Java Build Path e na aba Order and Export, marque o android-support-v4.jar.&lt;br /&gt;&lt;br /&gt;Antes de começarmos a codificar, vou explicar como será o exemplo. Será uma aplicação clássica de Fragments, onde teremos uma lista, e ao clicar em um dos elementos dessa lista, os detalhes daquele item serão exibidos. Como exemplo, listarei as versões do Android e ao clicar, exibir os detalhes da respectiva versão.&lt;br /&gt;&lt;br /&gt;Vou começar criando o layout principal da aplicação. Crie o arquivo &lt;b&gt;res/layout/titles.xml&lt;/b&gt; e deixe-o conforme abaixo:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;LinearLayout &lt;br /&gt;  xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt;  android:layout_width="fill_parent"&lt;br /&gt;  android:layout_height="fill_parent"&lt;br /&gt;  android:orientation="horizontal" &amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;fragment&lt;br /&gt;    android:id="@+id/titles"&lt;br /&gt;    android:layout_width="0px"&lt;br /&gt;    android:layout_height="fill_parent" &lt;br /&gt;    android:layout_weight="1"&lt;br /&gt;    class="ngvl.android.fragments2.TitlesFragment" /&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;FrameLayout&lt;br /&gt;    android:id="@+id/details"&lt;br /&gt;    android:layout_width="0px"&lt;br /&gt;    android:layout_height="fill_parent"&lt;br /&gt;    android:layout_weight="1" /&amp;gt;&lt;br /&gt;&amp;lt;/LinearLayout&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Aqui temos um LinearLayout horizontal com um Fragment que está apontando para a classe TitlesFragment e está ocupando metade da tela (determinado pela propriedade layout_weight). E um FrameLayout para exibir os detalhes da opção selecionada.&lt;br /&gt;&lt;br /&gt;O arquivo acima dará erro porque não criamos a classe TitlesFragment. Ela é mostrada abaixo:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class TitlesFragment extends ListFragment {&lt;br /&gt;&lt;br /&gt;  private final String EXTRA_INDEX = "index";&lt;br /&gt;  private int selectedIndex;&lt;br /&gt; &lt;br /&gt;  @Override&lt;br /&gt;  public void onActivityCreated(&lt;br /&gt;    Bundle savedInstanceState) {&lt;br /&gt;    super.onActivityCreated(savedInstanceState);&lt;br /&gt;  &lt;br /&gt;    ListView lv = getListView();&lt;br /&gt;  &lt;br /&gt;    setListAdapter(&lt;br /&gt;      new ArrayAdapter&amp;lt;String&amp;gt;(&lt;br /&gt;      getActivity(),&lt;br /&gt;      android.R.layout.simple_list_item_checked,&lt;br /&gt;      Dados.titles));&lt;br /&gt;  &lt;br /&gt;    lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);&lt;br /&gt;  &lt;br /&gt;    if (savedInstanceState != null){&lt;br /&gt;      selectedIndex = &lt;br /&gt;        savedInstanceState.getInt(EXTRA_INDEX);&lt;br /&gt;      lv.setSelection(selectedIndex);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (isDualPane()){&lt;br /&gt;      showDetails(selectedIndex);&lt;br /&gt;    } else {&lt;br /&gt;      getActivity().findViewById(&lt;br /&gt;        R.id.details).setVisibility(View.GONE);&lt;br /&gt;    }&lt;br /&gt;  &lt;br /&gt;    lv.setItemChecked(selectedIndex, true);  &lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private void showDetails(int index) {&lt;br /&gt;    selectedIndex = index;&lt;br /&gt;  &lt;br /&gt;    if (isDualPane()) {  &lt;br /&gt;      DetailsFragment details = &lt;br /&gt;        (DetailsFragment)getFragmentManager()&lt;br /&gt;          .findFragmentById(R.id.details);&lt;br /&gt;   &lt;br /&gt;      if (details == null || &lt;br /&gt;        details.getShowIndex() != index){&lt;br /&gt;&lt;br /&gt;        details = DetailsFragment.newInstance(index);&lt;br /&gt;    &lt;br /&gt;        FragmentTransaction fragTrans =&lt;br /&gt;          getFragmentManager().beginTransaction();&lt;br /&gt;        fragTrans.replace(R.id.details, details);&lt;br /&gt;        fragTrans.setTransition(&lt;br /&gt;          FragmentTransaction.TRANSIT_FRAGMENT_FADE);&lt;br /&gt;        fragTrans.commit();&lt;br /&gt;      }&lt;br /&gt;    } else {&lt;br /&gt;      Intent it = new Intent(getActivity(), &lt;br /&gt;        DetailsActivity.class);&lt;br /&gt;&lt;br /&gt;      it.putExtra(EXTRA_INDEX, index);&lt;br /&gt;      startActivity(it);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  @Override&lt;br /&gt;  public void onSaveInstanceState(Bundle outState) {&lt;br /&gt;    super.onSaveInstanceState(outState);&lt;br /&gt;    outState.putInt(EXTRA_INDEX, selectedIndex);&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  @Override&lt;br /&gt;  public void onListItemClick(ListView l, &lt;br /&gt;    View v, int position, long id) {&lt;br /&gt;    super.onListItemClick(l, v, position, id);&lt;br /&gt;    showDetails(position);&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  private boolean isDualPane(){&lt;br /&gt;    Configuration config =&lt;br /&gt;      getActivity().getResources().getConfiguration();&lt;br /&gt;&lt;br /&gt;    return config.orientation == &lt;br /&gt;      Configuration.ORIENTATION_LANDSCAPE;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Nosso fragmento herda de ListFragment, que é bem similar a classe ListActivity, e exibe informações em formato de lista. Então, no método onActivityCreated (o nome por sí só já diz o que ele faz :) obtemos a referência para a ListView e setamos um Adapter para ela. Os dados que são passados para esse Adapter vêm de um array de Strings contendo as versões do Android definidos na classe Dados. &lt;u&gt;Parte&lt;/u&gt; dessa classe é mostrada abaixo:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class Dados {&lt;br /&gt;  static public String[] titles = {&lt;br /&gt;    "Android 1.5",&lt;br /&gt;    "Android 1.6",&lt;br /&gt;    // Mais itens aqui&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  static public String[] description = {&lt;br /&gt;    "Primeira versão do Android, Cupcake",&lt;br /&gt;    "Donut já suporta Fragments",&lt;br /&gt;    // Mais descrições aqui&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Em seguida, verificamos se existe um estado salvo da nossa Activity. Quando entramos a primeira vez, esse estado estará vazio, mas quando girarmos o aparelho, o método onSaveInstance será chamado e nós salvaremos a posição da lista que está checada. Se já existir um estado saldo, marcamos a opção que estava selecionada antes de girar o aparelho e fazemos o scroll até ela.&lt;br /&gt;Logo após, verificamos se a aplicação é dualPane (dois painéis) esse método (que está no fim da classe) verifica se a orientação do aparelho está como landscape. Em caso positivo exibiremos a lista e os detalhes no mesmo momento, caso contrário exibiremos apenas a lista, então ocultamos o FrameLayout de detalhes.&lt;br /&gt;O método showDetails verifica se a tela é dualPane, em caso positivo, instancia o fragmento de detalhes e o exibe utilizando a class FragmentTransition. Caso não seja dualPane, ou seja, está em Portrait, exibimos a Activity de detalhes.&lt;br /&gt;&lt;br /&gt;Com a utilização de Fragments, a Activity passa a controlar o Fragment, e o Fragment trata eventos de UI. Com isso a Activity fica bem simples como podemos ver abaixo:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class TitleActivity extends FragmentActivity {&lt;br /&gt;  @Override&lt;br /&gt;  public void onCreate(Bundle savedInstanceState) {&lt;br /&gt;    super.onCreate(savedInstanceState);&lt;br /&gt;    setContentView(R.layout.titles);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;O único detalhe é que essa clase herda de FragmentActivity. Lembrando que ela é uma classe da API de compatibilidade, no Android 3.x podemos continuar usando Activity mesmo. Agora vamos analisar o fragmento de detalhes&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class DetailsFragment extends Fragment {&lt;br /&gt;&lt;br /&gt;  private static final String EXTRA_INDEX = "index";&lt;br /&gt; &lt;br /&gt;  public static DetailsFragment newInstance(int index) {&lt;br /&gt;    DetailsFragment fragment = new DetailsFragment();&lt;br /&gt;  &lt;br /&gt;    Bundle params = new Bundle();&lt;br /&gt;    params.putInt(EXTRA_INDEX, index);&lt;br /&gt;    fragment.setArguments(params);&lt;br /&gt;  &lt;br /&gt;    return fragment;&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  public int getShowIndex() {&lt;br /&gt;    return getArguments().getInt(EXTRA_INDEX);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public View onCreateView(LayoutInflater inflater,&lt;br /&gt;    ViewGroup container, Bundle savedInstanceState) {&lt;br /&gt;  &lt;br /&gt;    TextView txt = new TextView(getActivity());&lt;br /&gt;    txt.setText(Dados.description[getShowIndex()]);&lt;br /&gt;  &lt;br /&gt;    return txt;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A classe tem um Factory Method (chamado newInstance) que cria um DetailsFragment já passando os "extras" necessários. O método onCreateView define o que será exibido no Fragment, para simplificar, criamos apenas um TextView, mas você poderia usar o parâmetro inflater para carregar um arquivo de Layout que desejasse.&lt;br /&gt;Por fim, vamos mostrar a Activity de detalhes.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class DetailsActivity extends FragmentActivity {&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  protected void onCreate(Bundle savedInstanceState) {&lt;br /&gt;    super.onCreate(savedInstanceState);&lt;br /&gt;  &lt;br /&gt;    if (isDualPane()){&lt;br /&gt;      finish();&lt;br /&gt;      return;&lt;br /&gt;   &lt;br /&gt;    } else if (savedInstanceState == null) {&lt;br /&gt;  &lt;br /&gt;      DetailsFragment details = new DetailsFragment();&lt;br /&gt;      details.setArguments(getIntent().getExtras());&lt;br /&gt;   &lt;br /&gt;      getSupportFragmentManager()&lt;br /&gt;        .beginTransaction()&lt;br /&gt;        .add(android.R.id.content, details)&lt;br /&gt;        .commit();&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  private boolean isDualPane(){&lt;br /&gt;    Configuration config =&lt;br /&gt;      getResources().getConfiguration();&lt;br /&gt;&lt;br /&gt;    return config.orientation ==&lt;br /&gt;      Configuration.ORIENTATION_LANDSCAPE;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Nessa Activity, basicamente verificamos se a orientação é landscape, em caso positivo, essa Activity é fechada, e consequentemente a TitlesActivity é exibida mostrando os títulos e os detalhes do mesmo. Já se Activity não é dual pane (ou seja, é portrait) e foi passado o índice para ela, carregamos o Fragment e o adicionamos à tela.&lt;br /&gt;&lt;br /&gt;A imagem abaixo mostra nossa aplicação rodando em landscape.&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-jsFqANKEfrw/Tyk0wS440PI/AAAAAAAAAkg/mvYzVAr9OyU/s1600/device-2012-02-01-095144.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 240px;" src="http://1.bp.blogspot.com/-jsFqANKEfrw/Tyk0wS440PI/AAAAAAAAAkg/mvYzVAr9OyU/s400/device-2012-02-01-095144.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5704148407350251762" /&gt;&lt;/a&gt;&lt;br /&gt;Esse artigo foi baseado &lt;a href="http://android-developers.blogspot.com/2011/02/android-30-fragments-api.html"&gt;nesse post&lt;/a&gt; do Blog do Android Developers.&lt;br /&gt;&lt;br /&gt;Qualquer dúvida, deixem seus comentários,&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-3245925770550837908?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/YHvWSBy3srKBDfqXO770n6kfzOs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YHvWSBy3srKBDfqXO770n6kfzOs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/YHvWSBy3srKBDfqXO770n6kfzOs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YHvWSBy3srKBDfqXO770n6kfzOs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/My36lV-uLGc" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=3245925770550837908" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/3245925770550837908?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/3245925770550837908?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/My36lV-uLGc/fragmentos-para-todos.html" title="Fragmentos para todos" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-0r4Rwh4YiV0/TyKpVKDSwfI/AAAAAAAAAkU/vtM7TO7PNNM/s72-c/Screen%2Bshot%2B2012-01-27%2Bat%2B10.46.46%2BAM.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2012/01/fragmentos-para-todos.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUDRno5eSp7ImA9WhRVGE8.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-8820935498819824213</id><published>2012-01-14T18:50:00.000-08:00</published><updated>2012-01-17T11:24:37.421-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-17T11:24:37.421-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Air" /><category scheme="http://www.blogger.com/atom/ns#" term="Adobe" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="iOS" /><category scheme="http://www.blogger.com/atom/ns#" term="Flex" /><category scheme="http://www.blogger.com/atom/ns#" term="Flash" /><title>Android + iOS = Adobe Air</title><content type="html">&lt;a href="http://1.bp.blogspot.com/-Wx-0I4vRCFc/TxXKjVOE-dI/AAAAAAAAAkA/961Ogf561uI/s1600/adobe-air-1a.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 200px; height: 175px;" src="http://1.bp.blogspot.com/-Wx-0I4vRCFc/TxXKjVOE-dI/AAAAAAAAAkA/961Ogf561uI/s400/adobe-air-1a.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5698683611847653842" /&gt;&lt;/a&gt;Olá povo,&lt;br /&gt;&lt;br /&gt;Atualmente a disputa entre as plataformas para dispositivos móveis está bastante acirrada. Android e iOS travam uma verdadeira batalha pela preferência dos usuários, tanto no mercado de tablets quanto de smartphones. E nós, como desenvolvedores, temos de estar atentos a essa peleja.&lt;br /&gt;Imagine que você recebe uma demanda de um projeto em que um dos requisitos, é rodar em iOS e Android. Nesse caso, o primeiro pensamento normalmente é: "putz! vou ter que fazer duas aplicações?".&lt;br /&gt;Quem me conhece, sabe que meu projeto de mestrado foi o desenvolvimento de uma ferramenta que traduz aplicações iOS para Android. Mas infelizmente ela ainda está longe de ficar pronta :( Mesmo assim, durante as pesquisas do mestrado, analisei algumas ferramentas "concorrentes" da minha como o PhoneGap e Titanium. Entretanto, dentre todas, a que gostei mais foi o Adobe Air. Entre os pontos positivos da tecnologia estão: a produtividade, utilizando uma ferramenta RAD com diversos recursos; a linguagem de programação é dinâmica e bastante fácil de aprender; e o aspecto visual que se mantém igual no Android e no iOS.&lt;br /&gt;&lt;br /&gt;A aplicação é desenvolvida em Flex e/ou ActionScrpit com o Flash Builder (ou Flash Professional CS5). Nesse post, vou mostrar como iniciar o desenvolvimento e fazer o bom e velho "Hello World". Para começar, você precisa fazer o download do Flash Builder 4.6 no site da Adobe. Ele é uma IDE baseada em Eclipse, onde você pode baixar um trial de 60 dias, e após esse tempo deve ser adquirido. Faça o download e instale o Flash Builder Trial no seu computador e vamos começar a brincadeira :)&lt;br /&gt;&lt;br /&gt;Acesse o menu File &amp;gt; New &amp;gt; Flex Mobile Project. Na janela exibida abaixo, digite o nome do projeto e o local onde o projeto será salvo e clique em Next.&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-z7Hkgo5JpOw/TxNfNoxIgDI/AAAAAAAAAis/Eat9J5dn1Eo/s1600/Screen%2Bshot%2B2012-01-15%2Bat%2B8.23.14%2BPM.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 318px;" src="http://4.bp.blogspot.com/-z7Hkgo5JpOw/TxNfNoxIgDI/AAAAAAAAAis/Eat9J5dn1Eo/s400/Screen%2Bshot%2B2012-01-15%2Bat%2B8.23.14%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5698002641440243762" /&gt;&lt;/a&gt;&lt;br /&gt;Na próxima janela do assistente, selecionamos para quais plataformas iremos desenvolver: iOS, Android e/ou BlackBerry. Deixei aqui Android e iOS. Na aba "Application Template" selecionamos o formato de aplicação que devemos desenvolver, aqui deixei uma aplicação Blank. As outras opções permitem criar aplicações que naveguem entre telas ou com abas respectivamente.&lt;br /&gt;Na aba "Permission", selecionamos as permissões necessárias para acessar recursos de aplicações Android (para iOS ela não é usada). E em "Platform Settings", selecionamos para quais aparelhos iOS iremos desenvolver (iPad, iPod, iPhone).&lt;br /&gt;Na seção "Application settings", marcamos se a aplicação deve mudar de orientação (portrait e landscape) automaticamente; se será tela cheia; e se a aplicação será esticada para se ajustar a telas de diferentes densidades. Deixe as configurações como abaixo e clique em Next.&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-ADnHClmupq8/TxNfsPiKsSI/AAAAAAAAAi8/CfnLvISIAs8/s1600/Screen%2Bshot%2B2012-01-15%2Bat%2B8.25.33%2BPM.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 361px; height: 400px;" src="http://4.bp.blogspot.com/-ADnHClmupq8/TxNfsPiKsSI/AAAAAAAAAi8/CfnLvISIAs8/s400/Screen%2Bshot%2B2012-01-15%2Bat%2B8.25.33%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5698003167242531106" /&gt;&lt;/a&gt;&lt;br /&gt;Na próxima tela poderíamos selecionar se estamos utilizando alguma tecnologia servidor. Mas como não é o caso, clique em Next.&lt;br /&gt;Na última tela do assistente, vamos deixar as opções padrão, exceto pelo campo Application ID, onde preencheremos com o esquema similar ao que usamos em Java. ex:"ngvl.air.exemploblog".  Outro campo interessante dessa tela, é o "Main Application File" onde definimos o arquivo que será o ponto de partida da nossa aplicação. Aqui, deixamos HelloWorldBlog.mxml e clicamos em Finish.&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-q7z6IK1QNDY/TxNisyG6ycI/AAAAAAAAAjE/zvt3j4c9oh0/s1600/Screen%2Bshot%2B2012-01-15%2Bat%2B8.36.50%2BPM.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 381px; height: 400px;" src="http://3.bp.blogspot.com/-q7z6IK1QNDY/TxNisyG6ycI/AAAAAAAAAjE/zvt3j4c9oh0/s400/Screen%2Bshot%2B2012-01-15%2Bat%2B8.36.50%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5698006475058366914" /&gt;&lt;/a&gt;&lt;br /&gt;Ao iniciar o projeto, o arquivo HelloWorldBlog.mxml é aberto em modo texto, mas vamos primeiro edita-lo no modo design. Para tal, clique no botão na parte superior do editor de código, e no combo "Device" selecione um aparelho de sua preferência.&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-uF5BGzV8blE/TxNj0zj4p6I/AAAAAAAAAjQ/OyyRyC8preI/s1600/Screen%2Bshot%2B2012-01-15%2Bat%2B8.45.19%2BPM.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 46px;" src="http://1.bp.blogspot.com/-uF5BGzV8blE/TxNj0zj4p6I/AAAAAAAAAjQ/OyyRyC8preI/s400/Screen%2Bshot%2B2012-01-15%2Bat%2B8.45.19%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5698007712398878626" /&gt;&lt;/a&gt;&lt;br /&gt;Na paleta de componentes, localizada do lado esquerdo, arraste para a tela de design: um Label, um TextInput e um Button. De um duplo-clique nos componentes Label e Button para alterar o texto. E deixe conforme abaixo:&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-HWb2VcqAki4/TxNk6P6jyJI/AAAAAAAAAjc/fDH3CNR66tA/s1600/Screen%2Bshot%2B2012-01-15%2Bat%2B8.49.53%2BPM.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 207px;" src="http://1.bp.blogspot.com/-HWb2VcqAki4/TxNk6P6jyJI/AAAAAAAAAjc/fDH3CNR66tA/s400/Screen%2Bshot%2B2012-01-15%2Bat%2B8.49.53%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5698008905421146258" /&gt;&lt;/a&gt;&lt;br /&gt;Agora vá para o modo Source e deixe conforme abaixo;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;s:Application&lt;br /&gt; xmlns:fx="http://ns.adobe.com/mxml/2009"&lt;br /&gt; xmlns:s="library://ns.adobe.com/flex/spark"&lt;br /&gt; applicationDPI="160"&amp;gt;&lt;br /&gt; &lt;br /&gt; &amp;lt;fx:Script&amp;gt;&lt;br /&gt;   &amp;lt;![CDATA[&lt;br /&gt;   protected function botaoFilhaoClick(&lt;br /&gt;     event:MouseEvent):void&lt;br /&gt;   {&lt;br /&gt;     lblTexto.text = edtTexto.text;&lt;br /&gt;   }&lt;br /&gt;   ]]&amp;gt;&lt;br /&gt; &amp;lt;/fx:Script&amp;gt;&lt;br /&gt; &amp;lt;fx:Declarations&amp;gt;&lt;br /&gt; &amp;lt;/fx:Declarations&amp;gt;&lt;br /&gt; &amp;lt;s:Label&lt;br /&gt;   id="lblTexto"&lt;br /&gt;   x="39" y="48"&lt;br /&gt;   text="Olá mundo Adobe Air"/&amp;gt;&lt;br /&gt; &amp;lt;s:TextInput&lt;br /&gt;   id="edtTexto"&lt;br /&gt;   x="39" y="71"/&amp;gt;&lt;br /&gt; &amp;lt;s:Button&lt;br /&gt;   x="39" y="112"&lt;br /&gt;   label="Vai filhão!"&lt;br /&gt;   click="botaoFilhaoClick(event)"/&amp;gt;&lt;br /&gt;&amp;lt;/s:Application&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Em seguida, clique com o botão direito sobre o projeto e selecione Run As... &amp;gt; Mobile Application. Aparecerá a janela abaixo.  Selecione a plataforma que deseja testar (aqui usei Android)  e em Launch Method você pode escolher entre rodar em um simulador ou em um dispositivo real. Aqui, selecionei para rodar no Desktop, e então o emulador com o tamanho de tela do Motorola Defy +. Clique em Run.&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-E5ZMBh5_8Ew/TxNnTFdAZyI/AAAAAAAAAjo/jhT03yaaJpQ/s1600/Screen%2Bshot%2B2012-01-15%2Bat%2B9.00.18%2BPM.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 400px;" src="http://2.bp.blogspot.com/-E5ZMBh5_8Ew/TxNnTFdAZyI/AAAAAAAAAjo/jhT03yaaJpQ/s400/Screen%2Bshot%2B2012-01-15%2Bat%2B9.00.18%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5698011531132823330" /&gt;&lt;/a&gt;&lt;br /&gt;A figura abaixo mostra nossa aplicação em execução no simulador do Adobe Air. Ao clicar no botão, o texto digitado na caixa de texto é exibido no Label.&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-5IG5_pQjS9s/TxOK_PTr4qI/AAAAAAAAAj0/tnQYyJ_kUY0/s1600/Screen%2Bshot%2B2012-01-15%2Bat%2B11.32.16%2BPM.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 175px;" src="http://1.bp.blogspot.com/-5IG5_pQjS9s/TxOK_PTr4qI/AAAAAAAAAj0/tnQYyJ_kUY0/s400/Screen%2Bshot%2B2012-01-15%2Bat%2B11.32.16%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5698050772599300770" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Bem povo, esse é apenas um pontapé inicial. Espero colocar mais posts sobre Adobe Air aqui no blog. Aproveito para agradecer ao meu grande amigo &lt;a href="http://www.tips4dev.com"&gt;Eric Cavalcanti&lt;/a&gt;(&lt;a href="https://twitter.com/ericoc"&gt;@ericoc&lt;/a&gt;), com quem tive aulas de Adobe Air e me ajudou a iniciar nessa tecnologia.&lt;br /&gt;&lt;br /&gt;Dúvidas? Deixem seus comentários.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-8820935498819824213?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/O4rnmnDmtT15p5XtDcuAbqF9mPg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/O4rnmnDmtT15p5XtDcuAbqF9mPg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/O4rnmnDmtT15p5XtDcuAbqF9mPg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/O4rnmnDmtT15p5XtDcuAbqF9mPg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/9YyZ4vA50Jc" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=8820935498819824213" title="5 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/8820935498819824213?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/8820935498819824213?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/9YyZ4vA50Jc/android-ios-adobe-air.html" title="Android + iOS = Adobe Air" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-Wx-0I4vRCFc/TxXKjVOE-dI/AAAAAAAAAkA/961Ogf561uI/s72-c/adobe-air-1a.jpg" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2012/01/android-ios-adobe-air.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8AQn0zfip7ImA9WhRWFU0.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-6548834157083014636</id><published>2012-01-02T01:00:00.000-08:00</published><updated>2012-01-02T04:54:03.386-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-02T04:54:03.386-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="AppWidgetProvider" /><category scheme="http://www.blogger.com/atom/ns#" term="widgets" /><category scheme="http://www.blogger.com/atom/ns#" term="Service" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><title>Widgets + Service</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Eu já coloquei aqui no blog dois posts sobre widgets (veja &lt;a href="http://nglauber.blogspot.com/2010/10/android-widgets-2.html"&gt;aqui&lt;/a&gt; e &lt;a href="http://nglauber.blogspot.com/2009/10/android-widgets.html"&gt;aqui&lt;/a&gt;), mas para quem não os viu, um AppWidget é uma aplicação que roda na HomeScreen dos aparelhos Android. E um dos grandes problemas ao se desenvolver esse tipo de aplicação é que o tratamento dos eventos que são disparados por ele. Eles podem ser feitos com uma subclasse de AppWidgetProvider (que herda de BroadcastReceiver), entretanto eles não mantêm estado. Por ser um BroadcastReceiver, o seu programa só interage com ele durante a execução do método onReceive.&lt;br /&gt;&lt;br /&gt;Alguns colegas de trabalho (que não vou citar nomes :) usam classes com atributos estáticos para manter os estado dos AppWidgets. Mas digamos que essa não é a maneira mais elegante :) Por isso, hoje vou mostrar como integrá-los com o componente Service do Android.&lt;br /&gt;&lt;br /&gt;O componente Service permite a sua execução em segundo plano mesmo que não haja nenhuma tela da aplicação aberta. Seu ciclo de vida inicia quando é disparada uma Intent para a classe do serviço utilizando o método startService. Caso o serviço ainda não esteja sendo executado, o mesmo será iniciado e ficará ativo até que o método stopService seja chamado ou que o próprio serviço chame o método stopSelf.&lt;br /&gt;&lt;br /&gt;Tendo em vista essa característica do serviço, vou utilizá-lo nesse exemplo para guardar o estado do widget, que ficará fazendo chamadas ao serviço para obter informações e se atualizar. Nosso exemplo será um widget que mostrará alguns links favoritos que nós poderemos passar clicando nos botões de navegação.&lt;br /&gt;&lt;br /&gt;Vamos começar pelo código do Service, que está na classe MeuServico&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class MeuServico extends Service {&lt;br /&gt;&lt;br /&gt;  // Sites favoritos&lt;br /&gt;  private String[] sites = {&lt;br /&gt;    "nglauber.blogspot.com",&lt;br /&gt;    "developer.android.com",&lt;br /&gt;    "www.unibratec.edu.br",&lt;br /&gt;    "www.especializa.com.br",&lt;br /&gt;    "www.cesar.edu.br" };&lt;br /&gt;&lt;br /&gt;  // índice do site que deve ser mostrado no widget&lt;br /&gt;  private int indice;&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public int onStartCommand(Intent intent, int flags, &lt;br /&gt;    int startId) {&lt;br /&gt;    // O Widget vai chamar esse método cada vez que &lt;br /&gt;    // clicarmos no botão&lt;br /&gt;    // Obtendo o botão clicado (próx. ou ant.)&lt;br /&gt;    String acao = intent.getStringExtra(&lt;br /&gt;      MeuWidget.EXTRA_ACAO);&lt;br /&gt;&lt;br /&gt;    // Se foi próximo, incrementa o índice&lt;br /&gt;    if (MeuWidget.ACAO_PROXIMO.equals(acao)) {&lt;br /&gt;      indice++;&lt;br /&gt;&lt;br /&gt;      if (indice &amp;gt; sites.length - 1) {&lt;br /&gt;        indice = 0;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;    // Se foi anterior, decrementa o índice &lt;br /&gt;    }else if(MeuWidget.ACAO_ANTERIOR.equals(acao)){&lt;br /&gt;      indice--;&lt;br /&gt;      if (indice &amp;lt; 0) {&lt;br /&gt;         indice = sites.length - 1;       &lt;br /&gt;      }     &lt;br /&gt;    }     &lt;br /&gt;    // Se veio alguma ação, atualize o widget&lt;br /&gt;    if (acao != null) {&lt;br /&gt;      RemoteViews views = new RemoteViews(&lt;br /&gt;        this.getPackageName(), R.layout.main);&lt;br /&gt;&lt;br /&gt;      // Atualizando TextView pra exibir o site&lt;br /&gt;      views.setTextViewText(&lt;br /&gt;        R.id.txtSite, sites[indice]);&lt;br /&gt;&lt;br /&gt;      // ID do widget que deve ser atualizado&lt;br /&gt;      int appWidgetId = intent.getIntExtra(&lt;br /&gt;        AppWidgetManager.EXTRA_APPWIDGET_ID,&lt;br /&gt;        AppWidgetManager.INVALID_APPWIDGET_ID);&lt;br /&gt;&lt;br /&gt;      // Obtendo a instância do AppWidgetManager&lt;br /&gt;      // para atualizar o Widget&lt;br /&gt;      AppWidgetManager appWidgetManager = &lt;br /&gt;        AppWidgetManager.getInstance(this);&lt;br /&gt;&lt;br /&gt;      // atualiza o widget&lt;br /&gt;      appWidgetManager.updateAppWidget(&lt;br /&gt;        appWidgetId, views);&lt;br /&gt;    } &lt;br /&gt;    &lt;br /&gt;    return super.onStartCommand(&lt;br /&gt;      intent, flags, startId);   &lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override   &lt;br /&gt;  public IBinder onBind(Intent arg0) {&lt;br /&gt;    // Não usado aqui&lt;br /&gt;    return null;&lt;br /&gt;  } &lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;O código acima, cria um serviço que tem uma lista de links favoritos, e um índice que controlará qual link deve ser exibido. O widget então fará requisições ao serviço, que serão tratadas pelo método onStartCommand, que mostrará um link da lista baseado na posição do array. &lt;br /&gt;É importante ter em mente que o widget não roda no processo da nossa aplicação, e sim da HomeScreen, então para ter acesso aos componentes gráficos usamos a classe RemoteViews e atualizamos o seu conteúdo com a classe AppWidgetManager.&lt;br /&gt;&lt;br /&gt;Uma vez que o Service está pronto, vamos começar a criar o widget. Assim como uma Activity, ele terá um arquivo de layout. Utilizei o próprio res/layout/main.xml que é criado com o projeto. Ele ficou conforme abaixo:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;  &amp;lt;LinearLayout &lt;br /&gt;    xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt;    android:layout_width="fill_parent"&lt;br /&gt;    android:layout_height="fill_parent"&lt;br /&gt;    android:orientation="horizontal"&lt;br /&gt;    android:background="#000000"&lt;br /&gt;    android:layout_margin="20dp"&amp;gt;&lt;br /&gt;  &amp;lt;Button&lt;br /&gt;    android:id="@+id/btnAnterior"&lt;br /&gt;    android:layout_width="wrap_content"&lt;br /&gt;    android:layout_height="fill_parent"&lt;br /&gt;    android:text="&amp;lt;" /&amp;gt;&lt;br /&gt;  &amp;lt;TextView&lt;br /&gt;    android:id="@+id/txtSite"&lt;br /&gt;    android:layout_width="wrap_content"&lt;br /&gt;    android:layout_height="wrap_content"&lt;br /&gt;    android:gravity="center"&lt;br /&gt;    android:layout_gravity="center"&lt;br /&gt;    android:layout_weight="1"&lt;br /&gt;    android:text="Clique para navegar nos favoritos"/&amp;gt;&lt;br /&gt;  &amp;lt;Button&lt;br /&gt;    android:id="@+id/btnProximo"&lt;br /&gt;    android:layout_width="wrap_content"&lt;br /&gt;    android:layout_height="fill_parent"&lt;br /&gt;    android:text="&amp;gt;" /&amp;gt;&lt;br /&gt;&amp;lt;/LinearLayout&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Nada de especial no Layout acima, então vamos ver como fica o código do Widget.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class MeuWidget extends AppWidgetProvider {&lt;br /&gt;  public static final String EXTRA_ACAO = "acao";&lt;br /&gt;  public static final String ACAO_ANTERIOR="anterior";&lt;br /&gt;  public static final String ACAO_PROXIMO = "proximo";&lt;br /&gt; &lt;br /&gt;  @Override&lt;br /&gt;  public void onUpdate(Context context,&lt;br /&gt;    AppWidgetManager appWidgetManager, &lt;br /&gt;    int[] appWidgetIds) {&lt;br /&gt;&lt;br /&gt;    super.onUpdate(context, &lt;br /&gt;      appWidgetManager, appWidgetIds);&lt;br /&gt;&lt;br /&gt;    // As view estão na aplicação Home e não na &lt;br /&gt;    // nossa. Por isso, para obter as referências &lt;br /&gt;    // dos componentes é usada a classe RemoteViews&lt;br /&gt;    RemoteViews views = new RemoteViews(&lt;br /&gt;      context.getPackageName(), R.layout.main);&lt;br /&gt;&lt;br /&gt;    // Esse método recebe a lista dos widgets que &lt;br /&gt;    // devem ser atualizados, pois podem haver várias &lt;br /&gt;    // instâncias do mesmo na Home. &lt;br /&gt;    // Então devemos atualizar todos.  &lt;br /&gt;    for (int i = 0; i &amp;lt; appWidgetIds.length; i++){&lt;br /&gt;      // Configurando evento dos botões&lt;br /&gt;      setButtonClicks(context, appWidgetIds[i], views);&lt;br /&gt;    }&lt;br /&gt;    appWidgetManager.updateAppWidget(&lt;br /&gt;      appWidgetIds, views);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private void setButtonClicks(&lt;br /&gt;    Context context, int appWidgetId,&lt;br /&gt;    RemoteViews views) {&lt;br /&gt;    // Os eventos de click só podem disparar &lt;br /&gt;    // PendingIntents. No nosso caso, &lt;br /&gt;    // dispararemos PendingIntents para o nosso&lt;br /&gt;    // serviço. Para setar o evento, passa o id &lt;br /&gt;    // do componentes e a PendingIntent&lt;br /&gt;    views.setOnClickPendingIntent(&lt;br /&gt;      R.id.btnProximo,&lt;br /&gt;      servicePendingIntent(&lt;br /&gt;        context, ACAO_PROXIMO, appWidgetId));&lt;br /&gt;  &lt;br /&gt;    views.setOnClickPendingIntent(&lt;br /&gt;      R.id.btnAnterior,&lt;br /&gt;      servicePendingIntent(&lt;br /&gt;        context, ACAO_ANTERIOR, appWidgetId));&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private PendingIntent servicePendingIntent(&lt;br /&gt;    Context ctx, String acao, int appWidgetId){&lt;br /&gt;&lt;br /&gt;    // Criando a Intent para chamar o serviço&lt;br /&gt;    Intent serviceIntent = new Intent(&lt;br /&gt;      ctx, MeuServico.class);&lt;br /&gt;&lt;br /&gt;    // Passando a ação (proximo ou anterior)&lt;br /&gt;    serviceIntent.putExtra(EXTRA_ACAO, acao);&lt;br /&gt;&lt;br /&gt;    // Passando o ID do widget que clicou&lt;br /&gt;    serviceIntent.putExtra(&lt;br /&gt;      AppWidgetManager.EXTRA_APPWIDGET_ID, &lt;br /&gt;      appWidgetId);&lt;br /&gt;&lt;br /&gt;    // O requestId da PendingIntent deve ser único,&lt;br /&gt;    // então gero um número aleatório&lt;br /&gt;    int requestId = new Random().nextInt();&lt;br /&gt;&lt;br /&gt;    // criando a PendingIntent para o serviço&lt;br /&gt;    PendingIntent pit = PendingIntent.getService(&lt;br /&gt;      ctx, requestId, serviceIntent, 0);&lt;br /&gt;    return pit;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No código acima, o método onUpdate é chamado quando o widget é adicionado à tela. Note que a referência aos componentes é feita através da classe RemoteViews, este é outro conceito que não deve ser esquecido: o widget roda na aplicação Home, logo, essas Views lá. Outro detalhe interessante é que os componentes só podem disparar PendingIntents ao serem clicados. E no nosso caso, essas PendingIntents estão chamando o Service, mudando apenas os parâmetros que são passados (próximo e anterior).&lt;br /&gt;&lt;br /&gt;Agora vamos criar o arquivo de configuração do widget. Na pasta res, crie a pasta xml (minúsculo) e adicione o arquivo meuwidget.xml e coloque o conteúdo abaixo:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;appwidget-provider &lt;br /&gt;  xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt;  android:initialLayout="@layout/main"&lt;br /&gt;  android:minHeight="72dp"&lt;br /&gt;  android:minWidth="294dp" &amp;gt;&lt;br /&gt;&amp;lt;/appwidget-provider&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Assim como todo BroadcastReceiver ele deve ser declarado no AndroidManifest.xml, só que ele deve tratar a ação APPWIDGET_UPDATE e deve ter uma tag meta-data referenciando o arquivo de configuração que criamos anteriormente.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;manifest &lt;br /&gt;  xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt;  package="br.edu.cesar.aula12"&lt;br /&gt;  android:versionCode="1"&lt;br /&gt;  android:versionName="1.0" &amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;uses-sdk android:minSdkVersion="10" /&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;application&lt;br /&gt;    android:icon="@drawable/ic_launcher"&lt;br /&gt;    android:label="@string/app_name" &amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;receiver &lt;br /&gt;    android:name="MeuWidget" &lt;br /&gt;    android:label="Meu Widget"&amp;gt;&lt;br /&gt;    &amp;lt;!-- IntentFilter obrigatória &lt;br /&gt;    para todo widget --&amp;gt;&lt;br /&gt;    &amp;lt;intent-filter&amp;gt;&lt;br /&gt;      &amp;lt;action &lt;br /&gt;      android:name="android.appwidget.action.APPWIDGET_UPDATE"/&amp;gt;&lt;br /&gt;    &amp;lt;/intent-filter&amp;gt;&lt;br /&gt;    &amp;lt;!-- Arquivo de configuração do widget --&amp;gt;&lt;br /&gt;    &amp;lt;meta-data android:resource="@xml/meuwidget"&lt;br /&gt;      android:name="android.appwidget.provider"/&amp;gt;&lt;br /&gt;  &amp;lt;/receiver&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!-- Meu Serviço --&amp;gt;&lt;br /&gt;  &amp;lt;service android:name="MeuServico"/&amp;gt;&lt;br /&gt;  &amp;lt;/application&amp;gt;&lt;br /&gt;&amp;lt;/manifest&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Mande rodar a aplicação. Nada irá aparecer, pois você não tem nenhuma Activity no projeto. Para ver se o Widget está funcionando, dê um clique-longo na Home ou clique na tecla "Menu" e em seguida, selecione "Add". No pop-up que for exibido, selecione "Widgets", e depois "Meu Widget". A mensagem inicial do widget será exibida, depois é clicar nos botões para ver o resultado.&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-DcpXs1wirXg/TrXRMWPEa_I/AAAAAAAAAgE/DoZLgSDhZhc/s1600/device-2011-11-05-211342.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 214px; height: 320px;" src="http://1.bp.blogspot.com/-DcpXs1wirXg/TrXRMWPEa_I/AAAAAAAAAgE/DoZLgSDhZhc/s320/device-2011-11-05-211342.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5671669315800427506" /&gt;&lt;/a&gt;&lt;br /&gt;Como vocês observaram dexei o código comentado, mas quem tiver dúvidas, deixem seus comentários.&lt;br /&gt;&lt;br /&gt;4br4ç0s,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-6548834157083014636?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/I4LdIv4zgs7siTz2juqG0GeiwHU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/I4LdIv4zgs7siTz2juqG0GeiwHU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/I4LdIv4zgs7siTz2juqG0GeiwHU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/I4LdIv4zgs7siTz2juqG0GeiwHU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/40STf-vStwQ" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=6548834157083014636" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/6548834157083014636?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/6548834157083014636?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/40STf-vStwQ/widgets-service.html" title="Widgets + Service" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-DcpXs1wirXg/TrXRMWPEa_I/AAAAAAAAAgE/DoZLgSDhZhc/s72-c/device-2011-11-05-211342.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2012/01/widgets-service.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4AQng-fCp7ImA9WhRXFks.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-9023989282001264771</id><published>2011-12-23T07:00:00.000-08:00</published><updated>2011-12-23T11:19:03.654-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-23T11:19:03.654-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="CESAR" /><category scheme="http://www.blogger.com/atom/ns#" term="devmedia" /><category scheme="http://www.blogger.com/atom/ns#" term="tecdam" /><category scheme="http://www.blogger.com/atom/ns#" term="Especializa" /><category scheme="http://www.blogger.com/atom/ns#" term="linuxfi" /><category scheme="http://www.blogger.com/atom/ns#" term="unibratec" /><category scheme="http://www.blogger.com/atom/ns#" term="nglauber" /><title>Agradecimento</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Esse será o último post de 2011. Um ano fantástico para mim, Graças a Deus! Consegui atingir vários objetivos, e por isso resolvi agradecer a todos que acreditaram em mim e no meu trabalho.&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://www.cesar.org.br/" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 100px; height: 53px;" src="http://3.bp.blogspot.com/-sDLLWI1I98A/TvKacSCZ6fI/AAAAAAAAAhY/Re9zgTmPE3M/s400/logo_cesar.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5688779089991297522" /&gt;&lt;/a&gt;&lt;div&gt;Primeiramente ao CESAR, onde trabalho desde 2006, e me dá a oportunidade de aprender muito todos os dias. Mexer com diversas tecnologias e em um ambiente diferenciado, são coisas que me faz gostar e querer continuar nesse time fantástico.&lt;div&gt;&lt;br /&gt;&lt;a href="http://www.especializa.com.br/" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 190px; height: 80px;" src="http://4.bp.blogspot.com/-_3pFIzabUUc/TvKbRl1xECI/AAAAAAAAAhk/vtQccjl_kzA/s400/marca_topo.gif" border="0" alt="" id="BLOGGER_PHOTO_ID_5688780005840064546" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;Um agradecimento Especial a Especializa :) onde dei os primeiros paços como instrutor. Foi uma grande escola, e continua sendo uma satisfação ministrar cursos em uma instituição que tem como meta, formar especialistas com cursos de qualidade.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;a href="http://www.linuxfi.com.br/" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 205px; height: 73px;" src="http://4.bp.blogspot.com/-eSbpiVB59gA/TvKcnCUj0qI/AAAAAAAAAhw/EprnmTRlmG4/s400/Screen%2Bshot%2B2011-12-22%2Bat%2B12.00.49%2BAM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5688781473774293666" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;A LinuxFi me permitiu conhecer a bela capital da Paraíba. E tive a satisfação de ministrar o primeiro curso de Android de João Pessoa. Depois tive a oportunidade de voltar, e espero voltar mais vezes :)&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://www.cesar.edu.br/" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 112px; height: 101px;" src="http://3.bp.blogspot.com/-XK8zSc9VGaM/TvKd4kE838I/AAAAAAAAAh8/JYM5xJG3PTw/s400/logo_edu_rodape.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5688782874405035970" /&gt;&lt;/a&gt;&lt;div&gt;Após terminar o mestrado no CESAR.edu, tive a felicidade de iniciar minha carreira como professor universitário na própria instituição. Dando aulas de Java ME e Android na pós-graduação em &lt;i&gt;Tecnologias para Desenvolvimento de Aplicações Móveis&lt;/i&gt;, aprendi muito com meus alunos, e isso gerou muitos posts aqui do blog :)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://www.unibratec.edu.br/" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 225px; height: 53px;" src="http://2.bp.blogspot.com/-aCK20zZ1wQo/TvKfbYPUxoI/AAAAAAAAAiI/HgjdE0d4IXk/s400/Screen%2Bshot%2B2011-12-22%2Bat%2B12.12.49%2BAM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5688784572034369154" /&gt;&lt;/a&gt;&lt;div&gt;Esse é o meu mais novo desafio. Esse ano eu comecei a ministrar a disciplina de Programação Móvel no curso de Análise e Desenvolvimento de Software (ADS) na Unibratec. Totalmente diferente de cursos isolados e de pós-graduação, está sendo bem gratificante e desafiador.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://www.devmedia.com.br/" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 250px; height: 50px;" src="http://1.bp.blogspot.com/-AR5TVwjASaU/TvKhvBQIe1I/AAAAAAAAAiU/PragoeaBaH0/s400/LOGODEVMEDIA.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5688787108484381522" /&gt;&lt;/a&gt;&lt;div&gt;Venho escrevendo matérias para as revistas Java Magazine e Mobile Magazine da DevMedia. Essa parceria tem me ajudado a escrever melhor (inclusive aqui pro blog) e falar melhor também durante as aulas. Além é claro de me forçar a estudar para enriquecer as aulas.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Para finalizar, agradeço a todos vocês. Colegas de trabalho, Alunos, Leitores do Blog e/ou dos meus artigos. Espero contar com todos vocês em 2012.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;8045 F35745!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;4br4ç05,&lt;/div&gt;&lt;div&gt;nglauber&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-9023989282001264771?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HRjMGsHRZQORWNY0WMJ8imwZ2LE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HRjMGsHRZQORWNY0WMJ8imwZ2LE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HRjMGsHRZQORWNY0WMJ8imwZ2LE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HRjMGsHRZQORWNY0WMJ8imwZ2LE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/N6s5283EBnM" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=9023989282001264771" title="2 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/9023989282001264771?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/9023989282001264771?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/N6s5283EBnM/agradecimento.html" title="Agradecimento" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-sDLLWI1I98A/TvKacSCZ6fI/AAAAAAAAAhY/Re9zgTmPE3M/s72-c/logo_cesar.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/12/agradecimento.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAMSXk7cSp7ImA9WhRVEUs.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-5310517441974819756</id><published>2011-12-12T07:56:00.000-08:00</published><updated>2012-01-09T18:49:48.709-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-09T18:49:48.709-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="KML" /><category scheme="http://www.blogger.com/atom/ns#" term="Maps" /><category scheme="http://www.blogger.com/atom/ns#" term="Overlay" /><category scheme="http://www.blogger.com/atom/ns#" term="Google" /><category scheme="http://www.blogger.com/atom/ns#" term="Route" /><category scheme="http://www.blogger.com/atom/ns#" term="Rota" /><category scheme="http://www.blogger.com/atom/ns#" term="Mapas" /><title>Google Maps: Traçando Rotas</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;A API do Google Maps disponível para Android é muito bacana, e incorporar esse recurso na sua aplicação pode ser um bom atrativo. Em um dos projetos que trabalhei, precisava mostrar a rota entre dois pontos no mapa, mas infelizmente não há uma API pronta para isso. Entretanto, o site do Google Maps disponibiliza uma URL onde você pode informar as latitudes e longitudes de origem e destino e obter um XML com a rota entre os dois pontos.&lt;br /&gt;&lt;br /&gt;Nesse arquivo, temos uma lista com as coordenadas geográficas que devem ser percorridas desde o ponto de partida até o  destino. Com essas coordenadas lidas do XML, criamos uma lista de GeoPoints que devem ser desenhadas em uma MapView através de uma subclasse de Overlay.&lt;br /&gt;&lt;br /&gt;Não vou detalhar muito a configuração do Google Maps no Android pois já falei &lt;a href="http://nglauber.blogspot.com/2009/09/google-maps-com-android-15.html"&gt;nesse post aqui&lt;/a&gt;. Também não vou entrar em detalhes sobre leitura de XML pois falei &lt;a href="http://nglauber.blogspot.com/2011/11/lendo-rss-no-android.html"&gt;nesse post aqui&lt;/a&gt;. E se você tiver dúvidas sobre AsyncTask, dê uma olhada &lt;a href="http://nglauber.blogspot.com/2011/06/tarefas-assincronas-no-android.html"&gt;nesse post&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Vou começar pelo código da Activity mostrado abaixo. No onCreate pegamos a instância de MapView e habilitamos o botão de Zoom através do método setBuiltInZoomControls e definimos um zoom padrão. Em seguida iniciamos a AsyncTask passando a MapView no construtor e informando a latitude e longitude de origem e destino. O método isRouteDisplayed é herdado da classe MapActivity e informa ao servidor do Google Maps se estamos exibindo informações de rota. Já que esse é o nosso propósito, retornamos true.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class TesteRotaMapaActivity extends MapActivity {&lt;br /&gt;&lt;br /&gt;  private MapView mapView;&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public void onCreate(Bundle savedInstanceState) {&lt;br /&gt;    super.onCreate(savedInstanceState);&lt;br /&gt;    setContentView(R.layout.main);&lt;br /&gt;    &lt;br /&gt;    mapView = (MapView)findViewById(R.id.mapa);&lt;br /&gt;    mapView.setBuiltInZoomControls(true);&lt;br /&gt;    mapView.getController().setZoom(8);&lt;br /&gt;    &lt;br /&gt;    new RotaAsyncTask(mapView).execute(&lt;br /&gt;      // Latitude, Logintude de Origem&lt;br /&gt;      -8.282503, -35.981941,&lt;br /&gt;      // Latitude, Longitude de Destino&lt;br /&gt;      -8.062969, -34.87215);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  protected boolean isRouteDisplayed() {&lt;br /&gt;    return true;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A classe RotaAsyncTask é quem faz o trabalho de acessar o site do Google Maps, baixar o XML com a informação da rota.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class RotaAsyncTask extends&lt;br /&gt;  AsyncTask&amp;lt;Double, Void, List&amp;lt;GeoPoint&amp;gt;&amp;gt;{&lt;br /&gt;&lt;br /&gt;  private ProgressDialog dialog;&lt;br /&gt;  private MapView mapView;&lt;br /&gt;&lt;br /&gt;  public RotaAsyncTask(MapView mapa) {&lt;br /&gt;    mapView = mapa;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  protected void onPreExecute() {&lt;br /&gt;    super.onPreExecute();&lt;br /&gt;    dialog = ProgressDialog.show(&lt;br /&gt;      mapView.getContext(), "Aguarde", &lt;br /&gt;      "Calculando rota");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  protected List&amp;lt;GeoPoint&amp;gt; doInBackground(&lt;br /&gt;    Double... params) {&lt;br /&gt;&lt;br /&gt;    // Formatando a URL com a latitude e longitude&lt;br /&gt;    // de origem e destino.&lt;br /&gt;    String urlRota = String.format(Locale.US,&lt;br /&gt;      "http://maps.google.com/maps?f=d&amp;amp;hl=en&amp;"+&lt;br /&gt;      "amp;saddr=%f,%f&amp;amp;daddr=%f,%f&amp;amp;ie=UTF8&amp;"+&lt;br /&gt;      "amp;0&amp;amp;om=0&amp;amp;output=kml",&lt;br /&gt;    params[0], params[1], params[2], params[3]);&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;      // Estabelecendo a conexão com o servidor&lt;br /&gt;      URL url = new URL(urlRota);&lt;br /&gt;      HttpURLConnection conexao = (HttpURLConnection)&lt;br /&gt;        url.openConnection();&lt;br /&gt;      conexao.connect();&lt;br /&gt;&lt;br /&gt;      // Obtendo a lista de GeoPoints&lt;br /&gt;      InputStream is = conexao.getInputStream();&lt;br /&gt;      return getGeoPoints(is);&lt;br /&gt; &lt;br /&gt;    } catch (Exception e) {&lt;br /&gt;      e.printStackTrace();&lt;br /&gt;    }&lt;br /&gt;    return null;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  protected void onPostExecute(List&amp;lt;GeoPoint&amp;gt; result) {&lt;br /&gt;    super.onPostExecute(result);&lt;br /&gt;    if (result != null) {&lt;br /&gt;      // Pega o GeoPoint do meio da lista p/ dar zoom&lt;br /&gt;      GeoPoint p1 = result.get(result.size()/2);&lt;br /&gt;&lt;br /&gt;      // Cria o Overlay que vai desenhar a Rota&lt;br /&gt;      RotaOverlay overlay = new RotaOverlay(result);&lt;br /&gt;      mapView.getOverlays().add(overlay);&lt;br /&gt;&lt;br /&gt;      // Centraliza no meio da rota&lt;br /&gt;      mapView.getController().animateTo(p1);&lt;br /&gt;    }&lt;br /&gt;    dialog.dismiss();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private List&amp;lt;GeoPoint&amp;gt; getGeoPoints(InputStream is){&lt;br /&gt;    try {&lt;br /&gt;      // Cria o documento XML&lt;br /&gt;      DocumentBuilderFactory factory =&lt;br /&gt;        DocumentBuilderFactory.newInstance();&lt;br /&gt;&lt;br /&gt;      DocumentBuilder builder = &lt;br /&gt;        factory.newDocumentBuilder();&lt;br /&gt;      Document xmlDocument = builder.parse(is);&lt;br /&gt;&lt;br /&gt;      // Procura a TAG com a String que tem &lt;br /&gt;      // todas as coordenadas&lt;br /&gt;      Node coordenadasXML =&lt;br /&gt;        xmlDocument.getElementsByTagName(&lt;br /&gt;          "LineString").item(0);&lt;br /&gt;&lt;br /&gt;      // Guarda o conteúdo da TAG&lt;br /&gt;      String coordenadasStr = &lt;br /&gt;        coordenadasXML.getTextContent();&lt;br /&gt;&lt;br /&gt;      //Cada coordenada é separada por espaço.&lt;br /&gt;      //Aqui eu quebro para pegar todas as coordenadas&lt;br /&gt;      String[] coordenadasArrayStr = &lt;br /&gt;        coordenadasStr.split(" ");&lt;br /&gt;&lt;br /&gt;      // Será montada uma lista de GeoPoints&lt;br /&gt;      // a partir da lista de strings&lt;br /&gt;      List&amp;lt;GeoPoint&amp;gt; geoPoints = &lt;br /&gt;        new ArrayList&amp;lt;GeoPoint&amp;gt;();&lt;br /&gt;&lt;br /&gt;      int length = coordenadasArrayStr.length;&lt;br /&gt;      for (int i = 0; i &amp;lt; length; i++) {&lt;br /&gt;        // Cada coordenada tem a latitude e longitude&lt;br /&gt;        // separado por vírgula&lt;br /&gt;        String[] long_lat = &lt;br /&gt;          coordenadasArrayStr[i].split(",");&lt;br /&gt;&lt;br /&gt;        // Criando o GeoPoint&lt;br /&gt;        GeoPoint gp = new GeoPoint(&lt;br /&gt;          (int)&lt;br /&gt;          (Double.parseDouble(long_lat[1]) * 1E6),&lt;br /&gt;          (int)&lt;br /&gt;          (Double.parseDouble(long_lat[0]) * 1E6));&lt;br /&gt;        // Adicionando na lista&lt;br /&gt;        geoPoints.add(gp);&lt;br /&gt;      }&lt;br /&gt;      return geoPoints;&lt;br /&gt;&lt;br /&gt;    } catch (Exception e){&lt;br /&gt;      e.printStackTrace();&lt;br /&gt;    }&lt;br /&gt;    return null;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;O código acima está comentado. Então vou partir pra classe overlay que é bem simples. Ela recebe a lista de GeoPoints obtida na classe acima e desenha cada uma.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class RotaOverlay extends Overlay {&lt;br /&gt;  private Paint paint;&lt;br /&gt;  private List&amp;lt;GeoPoint&amp;gt; geoPoints;&lt;br /&gt;&lt;br /&gt;  public RotaOverlay(List&amp;lt;GeoPoint&amp;gt; geoPoints) {&lt;br /&gt;    this.geoPoints = geoPoints;&lt;br /&gt;    this.paint = new Paint();&lt;br /&gt;    this.paint.setColor(Color.RED);&lt;br /&gt;    this.paint.setStrokeWidth(5);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public void draw(Canvas canvas, MapView mapView,&lt;br /&gt;    boolean shadow) {&lt;br /&gt;    super.draw(canvas, mapView, shadow);&lt;br /&gt;&lt;br /&gt;    // Esse objeto converte GeoPoint em Point&lt;br /&gt;    //  para poder desenhar na tela&lt;br /&gt;    Projection proj = mapView.getProjection();&lt;br /&gt;&lt;br /&gt;    Point ponto1, ponto2;&lt;br /&gt;    for (int i = 0; i &amp;lt; geoPoints.size() - 1; i++) {&lt;br /&gt;      ponto1 = proj.toPixels(geoPoints.get(i), null);&lt;br /&gt;      ponto2 = proj.toPixels(geoPoints.get(i+1),null);&lt;br /&gt;&lt;br /&gt;      // Desenha uma linha de um ponto a outro  &lt;br /&gt;      canvas.drawLine(ponto1.x, ponto1.y,&lt;br /&gt;        ponto2.x, ponto2.y, paint);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A imagem abaixo mostra nossa aplicação em execução.&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-W4o3kV00AKM/TriqsfFnarI/AAAAAAAAAgc/iRKZVfBRMuw/s1600/device-2011-11-08-010608.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 214px; height: 320px;" src="http://3.bp.blogspot.com/-W4o3kV00AKM/TriqsfFnarI/AAAAAAAAAgc/iRKZVfBRMuw/s320/device-2011-11-08-010608.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5672471411909159602" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Qualquer dúvida, deixem seus comentários.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-5310517441974819756?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/73lZCenaWlv_VUhJBb4P-gmx9Qc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/73lZCenaWlv_VUhJBb4P-gmx9Qc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/73lZCenaWlv_VUhJBb4P-gmx9Qc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/73lZCenaWlv_VUhJBb4P-gmx9Qc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/pOKqKOHeHUA" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=5310517441974819756" title="4 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/5310517441974819756?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/5310517441974819756?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/pOKqKOHeHUA/google-maps-tracando-rotas.html" title="Google Maps: Traçando Rotas" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-W4o3kV00AKM/TriqsfFnarI/AAAAAAAAAgc/iRKZVfBRMuw/s72-c/device-2011-11-08-010608.png" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/10/google-maps-tracando-rotas.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQBSXYzfCp7ImA9WhRQEU4.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-6471828806717789096</id><published>2011-12-05T16:50:00.001-08:00</published><updated>2011-12-05T17:02:38.884-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-05T17:02:38.884-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="display" /><category scheme="http://www.blogger.com/atom/ns#" term="Tamanho da Tela" /><category scheme="http://www.blogger.com/atom/ns#" term="resolução" /><category scheme="http://www.blogger.com/atom/ns#" term="tela" /><title>Resoluções de Tela</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Frequentemente nas aulas de Android o pessoal tem dificuldade de lembrar as diversas resoluções de tela disponíveis para os smartphones e tablets atuais. Hoje meu colega de trabalho André mandou uma imagem com os tamanhos e siglas que as representam.&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-WVu6LSyN5FE/Tt1npqJBMpI/AAAAAAAAAgw/xnL4c71uAM4/s1600/resolutions.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 321px;" src="http://3.bp.blogspot.com/-WVu6LSyN5FE/Tt1npqJBMpI/AAAAAAAAAgw/xnL4c71uAM4/s400/resolutions.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5682812270195847826" /&gt;&lt;/a&gt;&lt;br /&gt;No Android, a grande maioria dos dispositivos utilizam as resoluções: QVGA, HVGA, WVGA e WXGA.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:85%;"&gt;&lt;i&gt;Fonte: &lt;a href="http://samuelvarela.wordpress.com/2009/03/20/resolucao-de-tela-vga-qvga-etc/"&gt;http://samuelvarela.wordpress.com/2009/03/20/resolucao-de-tela-vga-qvga-etc/&lt;/a&gt;&lt;/i&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-6471828806717789096?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QW3_Ol7ucLyP3eSppfSXZWfhkuQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QW3_Ol7ucLyP3eSppfSXZWfhkuQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QW3_Ol7ucLyP3eSppfSXZWfhkuQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QW3_Ol7ucLyP3eSppfSXZWfhkuQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/_1XUBT7kqyE" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=6471828806717789096" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/6471828806717789096?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/6471828806717789096?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/_1XUBT7kqyE/resolucoes-de-tela.html" title="Resoluções de Tela" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-WVu6LSyN5FE/Tt1npqJBMpI/AAAAAAAAAgw/xnL4c71uAM4/s72-c/resolutions.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/12/resolucoes-de-tela.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEHQno7cSp7ImA9WhRRFUw.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-5730981437490815999</id><published>2011-11-28T06:00:00.000-08:00</published><updated>2011-11-28T12:53:53.409-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-28T12:53:53.409-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="RSS" /><category scheme="http://www.blogger.com/atom/ns#" term="XML" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="Feed" /><title>Lendo RSS no Android</title><content type="html">&lt;a href="http://2.bp.blogspot.com/-zwDSECnKrnk/Trczi7WlitI/AAAAAAAAAgQ/prODFioelzg/s1600/androinica-rss-market.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 200px; height: 186px;" src="http://2.bp.blogspot.com/-zwDSECnKrnk/Trczi7WlitI/AAAAAAAAAgQ/prODFioelzg/s200/androinica-rss-market.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5672058930837424850" /&gt;&lt;/a&gt;Olá povo,&lt;br /&gt;&lt;br /&gt;A tecnologia RSS tornou-se uma forma padrão que os sites encontraram para compartilhar suas informações. Com ele, os usuários podem visualizar seu conteúdo de forma padronizada, uma vez que utiliza o formato XML. Sendo assim, vou mostrar nesse post como ler um RSS com Android. Mas o código utilizado aqui pode ser utilizado para qualquer XML.&lt;br /&gt;&lt;br /&gt;Vou começar criando a classe que vai representar uma notícia do RSS. Ela tem basicamente um título, um resumo da notícia e um link para notícia completa.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;class Noticia {&lt;br /&gt;  String titulo;&lt;br /&gt;  String descricao;&lt;br /&gt;  String link;&lt;br /&gt; &lt;br /&gt;  public Noticia(String t, String d, String l) {&lt;br /&gt;    titulo = t;&lt;br /&gt;    descricao = d;&lt;br /&gt;    link = l;&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  @Override&lt;br /&gt;  public String toString() {&lt;br /&gt;    return titulo;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Simplifiquei ao máximo a classe aqui, não coloquei nem os GETs nem os SETs. Implementei apenas o método toString() pois o mesmo é utilizado pelo Adapter (que veremos em seguida) para exibir a notícia.&lt;br /&gt;&lt;br /&gt;Agora vamos ver o código da Activity.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class LeitorRSSActivity extends ListActivity {&lt;br /&gt;&lt;br /&gt;  List&amp;lt;Noticia&amp;gt; news;&lt;br /&gt;  ArrayAdapter&amp;lt;Noticia&amp;gt; adapter;&lt;br /&gt; &lt;br /&gt;  @Override&lt;br /&gt;  public void onCreate(Bundle savedInstanceState) {&lt;br /&gt;    super.onCreate(savedInstanceState);&lt;br /&gt;&lt;br /&gt;    news = new ArrayList&amp;lt;Noticia&amp;gt;();&lt;br /&gt;    adapter = new ArrayAdapter&amp;lt;Noticia&amp;gt;(&lt;br /&gt;    this, android.R.layout.simple_list_item_1, news);&lt;br /&gt;    setListAdapter(adapter);&lt;br /&gt;&lt;br /&gt;    // Criando AsyncTask que buscará o RSS da globo&lt;br /&gt;    new RssAsyncTask().execute(&lt;br /&gt;      "http://g1.globo.com/dynamo/rss2.xml");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // Método que lê o XML do RSS&lt;br /&gt;  private List&amp;lt;Noticia&amp;gt; readXML(InputStream is){&lt;br /&gt;    List&amp;lt;Noticia&amp;gt; noticias =&lt;br /&gt;      new ArrayList&amp;lt;Noticia&amp;gt;();&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;      // Criando os objetos que representam o XML&lt;br /&gt;      DocumentBuilderFactory factory =&lt;br /&gt;        DocumentBuilderFactory.newInstance();&lt;br /&gt;&lt;br /&gt;      DocumentBuilder builder = &lt;br /&gt;        factory.newDocumentBuilder();&lt;br /&gt;      Document xmlDocument = builder.parse(is);&lt;br /&gt;   &lt;br /&gt;      // Cada notícia é representada pela tag &amp;lt;item&amp;gt;&lt;br /&gt;      // Aqui obtemos a lista de nós com essa tag&lt;br /&gt;      NodeList posts = &lt;br /&gt;        xmlDocument.getElementsByTagName("item");&lt;br /&gt;&lt;br /&gt;      // Vamos iterar sobre a lista de itens&lt;br /&gt;      String titulo = null, descricao = null, &lt;br /&gt;        link = null;&lt;br /&gt;&lt;br /&gt;      for (int i = 0; i &amp;lt; posts.getLength(); i++) {&lt;br /&gt;        Node post = posts.item(i);&lt;br /&gt;&lt;br /&gt;        // Cada nó ITEM tem os filhos:&lt;br /&gt;        // TITLE, DESCRIPTION e LINK&lt;br /&gt;        NodeList postInfo = post.getChildNodes();&lt;br /&gt;        for (int j = 0; j &amp;lt; postInfo.getLength(); j++){&lt;br /&gt;          Node info = postInfo.item(j);&lt;br /&gt;&lt;br /&gt;          if ("title".equals(info.getNodeName())){&lt;br /&gt;            titulo = info.getTextContent();&lt;br /&gt;&lt;br /&gt;          } else if ("link".equals(&lt;br /&gt;            info.getNodeName())){&lt;br /&gt;            link = info.getTextContent();&lt;br /&gt;      &lt;br /&gt;          } else if ("description".equals(&lt;br /&gt;            info.getNodeName())){&lt;br /&gt;            descricao = info.getTextContent();&lt;br /&gt;          }&lt;br /&gt;        }&lt;br /&gt;        // Com as informações das tags, criamos o&lt;br /&gt;        // objeto notícia e adicionamos na lista&lt;br /&gt;        noticias.add(&lt;br /&gt;          new Noticia(titulo, descricao, link));&lt;br /&gt;      }&lt;br /&gt;    } catch (Throwable e) {&lt;br /&gt;      e.printStackTrace();&lt;br /&gt;    }&lt;br /&gt;    return noticias;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // A AsyncTask realiza a comunicação em background&lt;br /&gt;  class RssAsyncTask extends&lt;br /&gt;    AsyncTask&amp;lt;String, Void, List&amp;lt;Noticia&amp;gt;&amp;gt;{&lt;br /&gt;&lt;br /&gt;    ProgressDialog dialog;&lt;br /&gt; &lt;br /&gt;    @Override&lt;br /&gt;    protected void onPreExecute() {&lt;br /&gt;      super.onPreExecute();&lt;br /&gt;      // Antes de baixaro XML, mostra o dialog&lt;br /&gt;      dialog = ProgressDialog.show(&lt;br /&gt;        LeitorRSSActivity.this, &lt;br /&gt;        "Aguarde", "Baixando RSS");&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    @Override&lt;br /&gt;    protected List&amp;lt;Noticia&amp;gt; doInBackground(&lt;br /&gt;      String... params) {&lt;br /&gt;&lt;br /&gt;      List&amp;lt;Noticia&amp;gt; lista = null;&lt;br /&gt;      HttpURLConnection conexao = null;&lt;br /&gt;      InputStream is = null;&lt;br /&gt;   &lt;br /&gt;      try {&lt;br /&gt;        URL url = new URL(params[0]);&lt;br /&gt;        conexao = (HttpURLConnection)&lt;br /&gt;          url.openConnection();&lt;br /&gt;        conexao.connect();&lt;br /&gt;    &lt;br /&gt;        is = conexao.getInputStream();&lt;br /&gt;        lista = readXML(is);&lt;br /&gt;&lt;br /&gt;      } catch (Throwable t){&lt;br /&gt;        t.printStackTrace();&lt;br /&gt;      } finally {&lt;br /&gt;        try {&lt;br /&gt;          if (is != null) is.close();&lt;br /&gt;          if (conexao != null) conexao.disconnect();&lt;br /&gt;        } catch (Throwable t){&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;      return lista;&lt;br /&gt;    }&lt;br /&gt;  &lt;br /&gt;    @Override&lt;br /&gt;    protected void onPostExecute(List&amp;lt;Noticia&amp;gt; result){&lt;br /&gt;      super.onPostExecute(result);&lt;br /&gt;      dialog.dismiss();&lt;br /&gt;      news.addAll(result);&lt;br /&gt;      adapter.notifyDataSetChanged();&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Quem tiver dúvida sobre AsyncTask, dá uma olhada &lt;a href="http://nglauber.blogspot.com/2011/06/tarefas-assincronas-no-android.html"&gt;aqui&lt;/a&gt;, ou deixem seus comentários.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-5730981437490815999?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/j9JzEhWWQIp6XULxX0GCyhMkY8s/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/j9JzEhWWQIp6XULxX0GCyhMkY8s/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/j9JzEhWWQIp6XULxX0GCyhMkY8s/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/j9JzEhWWQIp6XULxX0GCyhMkY8s/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/O8qiz7nvfR4" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=5730981437490815999" title="4 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/5730981437490815999?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/5730981437490815999?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/O8qiz7nvfR4/lendo-rss-no-android.html" title="Lendo RSS no Android" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-zwDSECnKrnk/Trczi7WlitI/AAAAAAAAAgQ/prODFioelzg/s72-c/androinica-rss-market.png" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/11/lendo-rss-no-android.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QGRX09fSp7ImA9WhRSGEU.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-7444108336393930772</id><published>2011-11-21T07:00:00.000-08:00</published><updated>2011-11-21T06:22:04.365-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-21T06:22:04.365-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Maps" /><category scheme="http://www.blogger.com/atom/ns#" term="location" /><category scheme="http://www.blogger.com/atom/ns#" term="Listener" /><category scheme="http://www.blogger.com/atom/ns#" term="GPS" /><category scheme="http://www.blogger.com/atom/ns#" term="Google" /><category scheme="http://www.blogger.com/atom/ns#" term="Mapas" /><title>Google Maps e GPS</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;&lt;a href="http://nglauber.blogspot.com/2009/09/google-maps-com-android-15.html"&gt;Nesse post de 2009&lt;/a&gt; mostrei como fazer um "Hello World" com a API do Google Maps. Agora vamos incrementar um pouco esse exemplo colocando uma imagem para indicar o seu local baseado na posição GPS.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pré-requisitos&lt;/b&gt;&lt;br /&gt;A configuração inicial para obter a chave e exibir o mapa na tela é idêntica a apresentada no post de dois anos atrás, mas caso não consiga gerar a chave, dê uma olhada &lt;a href="http://nglauber.blogspot.com/2011/04/android-dicas-2.html"&gt;nesse post aqui (Dica 5)&lt;/a&gt;. Outra ressalva é que, caso você esteja usando o emulador para testar sua aplicação, certifique-se de que ele esteja usando a "Google APIs" no "Android AVD Manager" conforme a figura abaixo:&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 106px;" src="http://4.bp.blogspot.com/-MsfllgsYxSo/Tq3a4kj2jmI/AAAAAAAAAeY/QrSr__aWSxg/s320/Screen%2Bshot%2B2011-10-30%2Bat%2B8.15.29%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5669428171350904418" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;O código do Overlay&lt;/b&gt;&lt;br /&gt;Uma coordenada geográfica é representada pela classe GeoPoint. Ela tem a latitude e longitude de um ponto no mapa. Entretanto essa classe não é visual, ou seja, ela não serve para enxergarmos o ponto no mapa. Quando queremos adicionar no mapa alguma indicação para uma coordenada geográfica, devemos utilizar a classe Overlay, que é uma subclasse de View. O código abaixo cria um Overlay que desenhará uma imagem em um dado ponto no mapa (representado por um GeoPoint).&lt;br /&gt;&lt;pre name="code" class="java"&gt;public class MeuOverlay extends Overlay {&lt;br /&gt;&lt;br /&gt; private Bitmap imagem;&lt;br /&gt; private GeoPoint geopoint;&lt;br /&gt; &lt;br /&gt; public MeuOverlay(Bitmap img ) {&lt;br /&gt;   imagem = img;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void setGeopoint(GeoPoint geopoint) {&lt;br /&gt;   this.geopoint = geopoint;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @Override&lt;br /&gt; public void draw(Canvas canvas, MapView mapView,&lt;br /&gt;   boolean shadow) {&lt;br /&gt;   super.draw(canvas, mapView, shadow);&lt;br /&gt;&lt;br /&gt;   if (geopoint != null){&lt;br /&gt;     Point pontoNaTela = mapView.getProjection()&lt;br /&gt;       .toPixels(geopoint, null);&lt;br /&gt;   &lt;br /&gt;     canvas.drawBitmap(imagem,&lt;br /&gt;       pontoNaTela.x - (imagem.getWidth() / 2),&lt;br /&gt;       pontoNaTela.y - (imagem.getHeight()), null);&lt;br /&gt;   }&lt;br /&gt; } &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Essa classe tem dois atributos: um Bitmap e um GeoPoint. O Bitmap será a imagem que desenharemos para representar a o ponto no mapa; já o GeoPoint, como o próprio nome diz, é um ponto geográfico, que obteremos a partir da posição do GPS.&lt;br /&gt;No método draw() é desenhado o ponto no mapa. Inicialmente checamos se o GeoPoint foi setado, em caso positivo, convertemos essa coordenada geográfica em um ponto na tela, que é representado pela classe Point. Quem faz essa conversão é a classe Projection obtida através do método getProjection() do MapView recebido como parâmetro do método. Depois, é só desenhar a imagem na tela. O cálculo feito na chamada do método é para que a imagem fique imediatamente acima do ponto geográfico.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;O arquivo de layout&lt;/b&gt;&lt;br /&gt;O arquivo de layout não tem nada de mais, apenas a declaração da MapView com a API key (veja no post de 2009 como obter a sua API key).&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;LinearLayout&lt;br /&gt;xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt; android:layout_width="fill_parent"&lt;br /&gt; android:layout_height="fill_parent"&lt;br /&gt; android:orientation="vertical"&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;TextView&lt;br /&gt;   android:layout_width="fill_parent"&lt;br /&gt;   android:layout_height="wrap_content"&lt;br /&gt;   android:text="Exemplo GPS e MapActivity" /&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;com.google.android.maps.MapView&lt;br /&gt;   android:id="@+id/mapa"&lt;br /&gt;   android:layout_width="fill_parent"&lt;br /&gt;   android:layout_height="fill_parent"&lt;br /&gt;   android:clickable="true"&lt;br /&gt;   android:apiKey="SUA_API_KEY" /&amp;gt;&lt;br /&gt;&amp;lt;/LinearLayout&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;A Activity&lt;/b&gt;&lt;br /&gt;O código abaixo representa a Activity da aplicação e está todo comentado e só vou fazer alguns comentários no final. A nossa classe herda de MapActivity e implementa a interface LocationListener, que é utilizada para receber as notificações do GPS.&lt;br /&gt;&lt;pre name="code" class="java"&gt;public class Aula09Activity extends MapActivity&lt;br /&gt; // Interface que tem os métodos para tratar&lt;br /&gt; // os eventos do GPS&lt;br /&gt; implements LocationListener {&lt;br /&gt;&lt;br /&gt; private MapView mapa;&lt;br /&gt; private MapController controller;&lt;br /&gt; private MeuOverlay overlay;&lt;br /&gt; private LocationManager locationManager;&lt;br /&gt; &lt;br /&gt; @Override&lt;br /&gt; public void onCreate(Bundle savedInstanceState) {&lt;br /&gt;   super.onCreate(savedInstanceState);&lt;br /&gt;   setContentView(R.layout.main);&lt;br /&gt;   // O LocationManager vai registrar e desregistrar&lt;br /&gt;   // a classe para ouvir eventos do GPS&lt;br /&gt;   locationManager = (LocationManager)&lt;br /&gt;     getSystemService(LOCATION_SERVICE);&lt;br /&gt;&lt;br /&gt;   // Configurando a MapView&lt;br /&gt;   mapa = (MapView)findViewById(R.id.mapa);&lt;br /&gt;   // Habilita os botões de Zoom&lt;br /&gt;   mapa.setBuiltInZoomControls(true);&lt;br /&gt;   // Mostra em modo satélite&lt;br /&gt;   mapa.setSatellite(true);&lt;br /&gt;&lt;br /&gt;   // O MapController 'controla' o mapa :)&lt;br /&gt;   controller = mapa.getController();&lt;br /&gt;   controller.setZoom(17);&lt;br /&gt;&lt;br /&gt;   // Cria a imagem que vai representar o Overlay&lt;br /&gt;   Bitmap marcador = BitmapFactory.decodeResource(&lt;br /&gt;      getResources(), R.drawable.ponto);&lt;br /&gt;&lt;br /&gt;   // Cria o Overlay e adiciona ao mapView&lt;br /&gt;   overlay = new MeuOverlay(marcador);&lt;br /&gt;   mapa.getOverlays().add(overlay);&lt;br /&gt;&lt;br /&gt;   // Determinando um ponto inicial&lt;br /&gt;   int latitude  = (int)(-8.058698 * 1E6);&lt;br /&gt;   int longitude = (int)(-34.872129 * 1E6);&lt;br /&gt;&lt;br /&gt;   GeoPoint geopoint = new GeoPoint(latitude, longitude);&lt;br /&gt;   controller.setCenter(geopoint);&lt;br /&gt;   overlay.setGeopoint(geopoint);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; protected void onResume() {&lt;br /&gt;   super.onResume();&lt;br /&gt;   // Registrando a Activity para receber notificações&lt;br /&gt;   // de mudança na posição GPS&lt;br /&gt;   locationManager.requestLocationUpdates(&lt;br /&gt;     LocationManager.GPS_PROVIDER, 0, 0, this);&lt;br /&gt;  &lt;br /&gt;   locationManager.requestLocationUpdates(&lt;br /&gt;     LocationManager.NETWORK_PROVIDER, 0, 0, this);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; protected void onPause() {&lt;br /&gt;   super.onPause();&lt;br /&gt;   // Desregistrando a Activity para receber&lt;br /&gt;   // notificações de mudança na posição GPS&lt;br /&gt;   locationManager.removeUpdates(this);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @Override&lt;br /&gt; protected boolean isRouteDisplayed() {&lt;br /&gt;   return false;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @Override&lt;br /&gt; public void onLocationChanged(Location location) {&lt;br /&gt;   // Método chamado quando a posição GPS muda&lt;br /&gt;   int latitude  = (int)(location.getLatitude() * 1E6);&lt;br /&gt;   int longitude = (int)(location.getLongitude() * 1E6);&lt;br /&gt;&lt;br /&gt;   GeoPoint geopoint = new GeoPoint(latitude, longitude);&lt;br /&gt;   overlay.setGeopoint(geopoint);&lt;br /&gt;   controller.animateTo(geopoint);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public void onProviderDisabled(String provider) {&lt;br /&gt;   // Método chamado quando o GPS é desabilitado&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public void onProviderEnabled(String provider) {&lt;br /&gt;   // Método chamado quando o GPS é habilitado&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public void onStatusChanged(String provider,&lt;br /&gt;   int status, Bundle extras) {&lt;br /&gt;   // Método chamado quando o status do GPS muda.&lt;br /&gt;   // Pode ser: OUT_OF_SERVICE,&lt;br /&gt;   // TEMPORARILY_UNAVAILABLE e AVAILABLE&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No código acima fazemos algumas inicializações no método onCreate. A classe LocationManager é responsável por registrar uma classe para "ouvir" os eventos de GPS (definidos na interface LocationListener que nossa Activity está implementando). Para criar um GeoPoint devemos passar a latitude e longitude em microdegrees, para tal devemos multiplicar os valores por 1.000.000 ou em notação científica 1E6 (10 elevado a 6).&lt;br /&gt;No método onResume registramos nossa classe para ouvir os eventos do GPS. O método requestLocationUpdates recebe como parâmetros:&lt;br /&gt;- o provedor de informações de posição GPS: aqui podemos utilizar o GPS do telefone, que demora mais a obter os dados, porém eles são mais precisos; e o da rede de dados, que obtém a posição baseado no esquema de triangulação de antenas da operadora de telefonia;&lt;br /&gt;- a distância mínima em metros na posição GPS;&lt;br /&gt;- o intervalo de tempo em milisegundos para receber a atualização;&lt;br /&gt;- o objeto de uma classe que implemente a interface LocationListener (no nosso caso, a própria Activity).&lt;br /&gt;No método onPause, desregistramos nossa classe para não ouvir mais os eventos de GPS. Isso evitará que ao sair da aplicação o Android tente ficar enviando as coordenadas mesmo com a aplicação inativa.&lt;br /&gt;O método onLocationChanged é o mais importante, pois a cada vez que a posição GPS muda, esse método é chamado pelo Android. A partir do objeto Location que vem como parâmetro, obtemos a latitude e longitude para atualizarmos a posição do Overlay.&lt;br /&gt;&lt;b&gt;AndroidManifest.xml&lt;/b&gt;&lt;br /&gt;No manifest, adicionamos as permissões INTERNET e ACCESS_FINE_LOCATION para podermos utilizar o Google Maps e obter a posição GPS respectivamente. Outra informação relevante é a tag &amp;lt;uses-library&amp;gt; que adicionamos para usar a API do Google Maps, uma vez que ela não é "padrão" da plataforma Android.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;manifest&lt;br /&gt;xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt;package="br.edu.cesar.aula09"&lt;br /&gt;android:versionCode="1"&lt;br /&gt;android:versionName="1.0" &amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;uses-sdk android:minSdkVersion="10" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;uses-permission&lt;br /&gt;android:name="android.permission.INTERNET" /&amp;gt;&lt;br /&gt;&amp;lt;uses-permission&lt;br /&gt;android:name="android.permission.ACCESS_FINE_LOCATION" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;application&lt;br /&gt;android:icon="@drawable/ic_launcher"&lt;br /&gt;android:label="@string/app_name" &amp;gt;&lt;br /&gt;&amp;lt;activity&lt;br /&gt;android:label="@string/app_name"&lt;br /&gt;android:name=".Aula09Activity" &amp;gt;&lt;br /&gt;&amp;lt;intent-filter &amp;gt;&lt;br /&gt;  &amp;lt;action&lt;br /&gt;    android:name="android.intent.action.MAIN" /&amp;gt;&lt;br /&gt;  &amp;lt;category&lt;br /&gt;    android:name="android.intent.category.LAUNCHER" /&amp;gt;&lt;br /&gt;&amp;lt;/intent-filter&amp;gt;&lt;br /&gt;&amp;lt;/activity&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;uses-library&lt;br /&gt;android:name="com.google.android.maps"/&amp;gt;&lt;br /&gt;&amp;lt;/application&amp;gt;&lt;br /&gt;&amp;lt;/manifest&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Para testar o código da aplicação, você deve habilitar as opções de GPS no dispositivo através da opção Settings &amp;gt; Location &amp;amp; Security &amp;gt; My Location. Notem que temos duas opções nessa seção: GPS satélites e redes móveis. A primeira é mais precisa, porém demora mais; já a segunda obtém a posição baseada triangulação entre as distâncias das redes de telefonia ou wireless.&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 214px; height: 320px;" src="http://3.bp.blogspot.com/-BmqacjAKjBk/Tq3lk-do13I/AAAAAAAAAek/KYZdfcJuheo/s320/device-2011-10-30-205845.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5669439929334683506" /&gt;&lt;br /&gt;Mas se você estiver usando o emulador, use a aba "Emulator control" da perspectiva DDMS do Eclipse (para exibir, acesse Window &amp;gt; Open perspective &amp;gt; DDMS).&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 199px; height: 191px;" src="http://3.bp.blogspot.com/-bTjFnMH6th8/Tq3p94Pc9cI/AAAAAAAAAew/uH-CdLtA8Kw/s320/Screen%2Bshot%2B2011-10-30%2Bat%2B9.20.30%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5669444755207812546" /&gt;&lt;br /&gt;Digite uma coordena válida e clique em "Send". Para ober uma posição, vá no Google Maps, clique com o botão direito e selecione "O que há aqui? | What's here?". Na barra de busca, ficará a latitude e a longitude, aí é só copiar e testar.&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 214px; height: 320px;" src="http://2.bp.blogspot.com/-LMD_l4p1yLg/Tq3p-A5CseI/AAAAAAAAAfA/3ucLh3G2KiU/s320/device-2011-10-30-212009.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5669444757529735650" /&gt;&lt;br /&gt;Qualquer dúvida, deixem seus comentários.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-7444108336393930772?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/tiVJ8C3BnD4JTEPZU-Dtcxd4UPE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tiVJ8C3BnD4JTEPZU-Dtcxd4UPE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/tiVJ8C3BnD4JTEPZU-Dtcxd4UPE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tiVJ8C3BnD4JTEPZU-Dtcxd4UPE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/l4p_ALfVLCc" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=7444108336393930772" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/7444108336393930772?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/7444108336393930772?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/l4p_ALfVLCc/google-maps-e-gps.html" title="Google Maps e GPS" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-MsfllgsYxSo/Tq3a4kj2jmI/AAAAAAAAAeY/QrSr__aWSxg/s72-c/Screen%2Bshot%2B2011-10-30%2Bat%2B8.15.29%2BPM.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/10/google-maps-e-gps.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QGQHo7eyp7ImA9WhRTF0s.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-1991996280987469220</id><published>2011-11-08T07:00:00.000-08:00</published><updated>2011-11-08T07:15:21.403-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-08T07:15:21.403-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="FilterResults" /><category scheme="http://www.blogger.com/atom/ns#" term="Filter" /><category scheme="http://www.blogger.com/atom/ns#" term="Custom" /><category scheme="http://www.blogger.com/atom/ns#" term="AutoCompleteTextView" /><category scheme="http://www.blogger.com/atom/ns#" term="Personalizada" /><title>AutoCompleteTextView personalizado</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Estou com um monte de posts legais pra publicar, mas infelizmente (pra variar) estou sem tempo. São coisas que precisei fazer nos projetos que trabalhei, e que gosto de compartilhar com quem lê o blog. Além do mais, me serve como fonte de consulta para uma uso posterior. Afinal de contas, é pra isso que serve o blog (pelo menos pra mim).&lt;br /&gt;&lt;br /&gt;Hoje vou mostrar como criar uma consulta personalizada para o componente AutoCompleteTextView. Esse componente é utilizado quando você tem uma lista de valores, e ao invés de selecioná-lo em uma lista, você digita parte do texto e os resultados vão sendo exibidos em uma lista (estilo drop-down) abaixo do componente. Este componente já conta com um mecanismo de busca padrão, entretanto a necessidade de personalizá-lo surgiu quando precisei realizar a busca por nomes de cidades. O cliente solicitou que a acentuação fosse ignorada, ou seja, quando eu digitasse "sao" era para aparecer "São Paulo" nos resultados.&lt;br /&gt;&lt;br /&gt;Vamos à implementação! Primeiro vou mostrar o método que substitui os caracteres acentuados pelos mesmos não acentuados.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;public static String[] REPLACES = &lt;br /&gt;  { "a", "e", "i", "o", "u", "c" };&lt;br /&gt;&lt;br /&gt;public static Pattern[] PATTERNS = null;&lt;br /&gt; &lt;br /&gt;public static void compilePatterns() {&lt;br /&gt; PATTERNS = new Pattern[REPLACES.length];&lt;br /&gt; PATTERNS[0] = Pattern.compile(&lt;br /&gt;   "[âãáàä]", Pattern.CASE_INSENSITIVE);&lt;br /&gt; PATTERNS[1] = Pattern.compile(&lt;br /&gt;   "[éèêë]", Pattern.CASE_INSENSITIVE);&lt;br /&gt; PATTERNS[2] = Pattern.compile(&lt;br /&gt;   "[íìîï]", Pattern.CASE_INSENSITIVE);&lt;br /&gt; PATTERNS[3] = Pattern.compile(&lt;br /&gt;   "[óòôõö]", Pattern.CASE_INSENSITIVE);&lt;br /&gt; PATTERNS[4] = Pattern.compile(&lt;br /&gt;   "[úùûü]", Pattern.CASE_INSENSITIVE);&lt;br /&gt; PATTERNS[5] = Pattern.compile(&lt;br /&gt;   "[ç]", Pattern.CASE_INSENSITIVE);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static String removeAcentos(String text) {&lt;br /&gt; if (PATTERNS == null) {&lt;br /&gt;   compilePatterns();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; String result = text;&lt;br /&gt; for (int i = 0; i &amp;lt; PATTERNS.length; i++) {     &lt;br /&gt;   Matcher matcher = PATTERNS[i].matcher(result);     &lt;br /&gt;   result = matcher.replaceAll(REPLACES[i]);   &lt;br /&gt;  }   &lt;br /&gt;  return result.toUpperCase(); &lt;br /&gt;} &lt;/pre&gt;&lt;br /&gt;O código acima, utiliza as classes Pattern e Matcher para checar a presença de caracteres acentuados e substitui-los pelos caracteres correspondentes sem acentuação. Observe que só são sendo tratadas as vogais e o cedilha, para textos em outros idiomas você deve fazer os ajustes necessários (como o 'ñ' do espanhol).&lt;br /&gt;&lt;br /&gt;Para que um AutoCompleteTextView faça a busca, é necessário definir um Adapter com os dados que ele irá filtrar para exibir. Para fazer nossa busca personalizada (ignorando acentuação) devemos criar nosso Adapter e sobrescrever o método getFilter(). Esse método deve retornar um objeto da classe android.widget.Filter que representa o resultado da busca.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;public class MeuAutoCompleteAdapter&lt;br /&gt;  extends ArrayAdapter&amp;lt;String&amp;gt;&lt;br /&gt;  implements Filterable {&lt;br /&gt;&lt;br /&gt;  private List&amp;lt;String&amp;gt; listaCompleta;&lt;br /&gt;  private List&amp;lt;String&amp;gt; resultados;&lt;br /&gt;  private Filter meuFiltro;&lt;br /&gt;&lt;br /&gt;  public MeuAutoCompleteAdapter(&lt;br /&gt;    Context ctx, int layout,&lt;br /&gt;    List&amp;lt;String&amp;gt; textos) { &lt;br /&gt;&lt;br /&gt;    super(ctx, layout, textos);&lt;br /&gt;    this.listaCompleta = textos;&lt;br /&gt;    this.resultados = listaCompleta;&lt;br /&gt;    this.meuFiltro = new MeuFiltro();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public int getCount() {&lt;br /&gt;    return resultados.size();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public String getItem(int position) {&lt;br /&gt;    if (resultados != null&lt;br /&gt;      &amp;amp;&amp;amp; resultados.size() &amp;gt; 0&lt;br /&gt;      &amp;amp;&amp;amp; position &amp;lt; resultados.size()){        &lt;br /&gt;      return resultados.get(position);      &lt;br /&gt;    } else {        &lt;br /&gt;      return null;     &lt;br /&gt;    }   &lt;br /&gt;  }     &lt;br /&gt;&lt;br /&gt;  @Override   &lt;br /&gt;  public Filter getFilter() {     &lt;br /&gt;    return meuFiltro;   &lt;br /&gt;  }    &lt;br /&gt;&lt;br /&gt;  private class MeuFiltro extends Filter {&lt;br /&gt;    @Override&lt;br /&gt;    protected FilterResults performFiltering(&lt;br /&gt;      CharSequence constraint) {&lt;br /&gt;&lt;br /&gt;      FilterResults filterResults = &lt;br /&gt;        new FilterResults();&lt;br /&gt;&lt;br /&gt;      ArrayList&amp;lt;String&amp;gt; temp = &lt;br /&gt;        new ArrayList&amp;lt;String&amp;gt;();&lt;br /&gt;          &lt;br /&gt;      if (constraint != null) {&lt;br /&gt;        String term = removeAcentos(&lt;br /&gt;          constraint.toString().trim().toLowerCase());&lt;br /&gt;            &lt;br /&gt;        String placeStr;&lt;br /&gt;        for (String p : listaCompleta) {&lt;br /&gt;          placeStr = removeAcentos(p.toLowerCase());&lt;br /&gt;                &lt;br /&gt;          if ( placeStr.indexOf(term) &amp;gt; -1){&lt;br /&gt;            temp.add(p);&lt;br /&gt;          }&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;      filterResults.values = temp;&lt;br /&gt;      filterResults.count = temp.size();&lt;br /&gt;      return filterResults;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @SuppressWarnings("unchecked")&lt;br /&gt;    @Override&lt;br /&gt;    protected void publishResults(&lt;br /&gt;      CharSequence contraint,&lt;br /&gt;      FilterResults filterResults) {&lt;br /&gt;&lt;br /&gt;      resultados = (ArrayList&amp;lt;String&amp;gt;) &lt;br /&gt;        filterResults.values;&lt;br /&gt;&lt;br /&gt;      notifyDataSetChanged();&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A classe acima tem duas listas de strings: a original e a que serve como resultado da busca. Note que os métodos getCount e getItem trabalha em cima da lista dos resultados. O outro atributo da classe é da classe MeuFiltro, e esse atributo é retornado no método getFilter.&lt;br /&gt;A classe interna MeuFiltro faz a nossa busca personalizada. O filtro é realizado no método performFiltering, que retorna um objeto da classe android.widget.Filter.FilterResults que contém o resultado da busca e o total de registros encontrados. Esse resultado é passado para o método publishResults que seta o resultado da busca no atributo resultados, e logo após atualiza o adapter através do método notifyDatasetChanged.&lt;br /&gt;&lt;br /&gt;Agora vamos ver como usar esse nosso adapter.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;List&amp;lt;String&amp;gt; cidade = new ArrayList&amp;lt;String&amp;gt;();&lt;br /&gt;cidade.add("Recife");&lt;br /&gt;cidade.add("São Paulo");&lt;br /&gt;cidade.add("Santos");&lt;br /&gt;cidade.add("Santa Cruz");&lt;br /&gt;&lt;br /&gt;MeuAutoCompleteAdapter adapter = &lt;br /&gt;  new MeuAutoCompleteAdapter(&lt;br /&gt;     contexto, &lt;br /&gt;     android.R.layout.simple_dropdown_item_1line, &lt;br /&gt;     cidade);&lt;br /&gt;&lt;br /&gt;AutoCompleteTextView actv = (AutoCompleteTextView)&lt;br /&gt;  findViewById(R.id.autoCompleteTextView1);&lt;br /&gt;actv.setAdapter(adapter);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O resultado é exibido na figura abaixo:&lt;br /&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 214px; height: 320px;" src="http://2.bp.blogspot.com/-t9QEjpr23vs/TpNGecYzIfI/AAAAAAAAAcE/OyaP7lH2IxA/s320/device-2011-10-10-162538.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5661946645365072370" /&gt;&lt;br /&gt;&lt;br /&gt;Qualquer dúvida, deixem seus comentários.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-1991996280987469220?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/uy8gQtbIC2volVp1RpRMx0u5u34/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uy8gQtbIC2volVp1RpRMx0u5u34/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/uy8gQtbIC2volVp1RpRMx0u5u34/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uy8gQtbIC2volVp1RpRMx0u5u34/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/KQiQOM6zMhw" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=1991996280987469220" title="3 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/1991996280987469220?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/1991996280987469220?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/KQiQOM6zMhw/autocompletetextview-personalizado.html" title="AutoCompleteTextView personalizado" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-t9QEjpr23vs/TpNGecYzIfI/AAAAAAAAAcE/OyaP7lH2IxA/s72-c/device-2011-10-10-162538.png" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/11/autocompletetextview-personalizado.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8MR34-fyp7ImA9WhRTFE0.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-4167173815512219712</id><published>2011-11-04T07:00:00.000-07:00</published><updated>2011-11-04T04:58:06.057-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-04T04:58:06.057-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Download" /><category scheme="http://www.blogger.com/atom/ns#" term="DownloadManager" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><title>Baixe arquivos com o DownloadManager</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Frequentemente alunos e colegas me perguntam qual é um bom livro sobre Android. E normalmente eu costumo indicar o livro do &lt;a href="http://www.livroandroid.com.br/"&gt;Ricardo Lecheta, Google Android (Editora Novatec)&lt;/a&gt;, ou o &lt;a href="http://www.wrox.com/WileyCDA/WroxTitle/Professional-Android-Application-Development.productCd-0470565527.html"&gt;Professional Android 2, do Reto Meyer&lt;/a&gt;. Vou adicionar nessa lista o &lt;a href="http://www.amazon.com/Pro-Android-3-Satya-Komatineni/dp/1430232226"&gt;Pro Android 2 da Editora Apress&lt;/a&gt;. Estava folheando esse livro quando achei um exemplo bem bacana: utilizar a classe DownloadManager para baixar arquivos. A utilização dela é bem simples, como podemos observar no exemplo abaixo:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class ExDownldMngrActivity &lt;br /&gt;  extends Activity {&lt;br /&gt;&lt;br /&gt;  private DownloadManager dm;&lt;br /&gt;  private MeuReceiver receiver;&lt;br /&gt;  private ImageView imgView;&lt;br /&gt;  private long downloadId;&lt;br /&gt; &lt;br /&gt;  @Override&lt;br /&gt;  protected void onCreate(Bundle savedInstanceState) {&lt;br /&gt;    super.onCreate(savedInstanceState);&lt;br /&gt;    setContentView(R.layout.ex_dwnldmngr);&lt;br /&gt;  &lt;br /&gt;    imgView = (ImageView)findViewById(&lt;br /&gt;      R.id.imageView1);&lt;br /&gt;  &lt;br /&gt;    dm = (DownloadManager)&lt;br /&gt;      getSystemService(DOWNLOAD_SERVICE);&lt;br /&gt;  &lt;br /&gt;    receiver = new MeuReceiver();&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  @Override&lt;br /&gt;  protected void onResume() {&lt;br /&gt;    super.onResume();&lt;br /&gt;&lt;br /&gt;    IntentFilter filter = new IntentFilter(&lt;br /&gt;      DownloadManager.&lt;br /&gt;        ACTION_DOWNLOAD_COMPLETE);&lt;br /&gt;&lt;br /&gt;    registerReceiver(receiver, filter);&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  @Override&lt;br /&gt;  protected void onDestroy() {&lt;br /&gt;    super.onDestroy();&lt;br /&gt;    unregisterReceiver(receiver);&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  public void baixarArquivoClick(View v){&lt;br /&gt;    String url = "http://developer.android.com/assets/"+&lt;br /&gt;      "images/home/honeycomb-android.png";&lt;br /&gt;&lt;br /&gt;    DownloadManager.Request request = &lt;br /&gt;      new DownloadManager.Request(Uri.parse(url));&lt;br /&gt;    request.setTitle("Meu download");&lt;br /&gt;    request.setDescription("Logo do Android");&lt;br /&gt;    request.setAllowedNetworkTypes(Request.NETWORK_MOBILE);&lt;br /&gt;  &lt;br /&gt;    downloadId = dm.enqueue(request);&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  private class MeuReceiver extends BroadcastReceiver {&lt;br /&gt;    @Override&lt;br /&gt;    public void onReceive(Context context, Intent intent) {&lt;br /&gt;      long id = intent.getLongExtra(&lt;br /&gt;        DownloadManager.EXTRA_DOWNLOAD_ID, -1);&lt;br /&gt;&lt;br /&gt;      if (id == downloadId) {&lt;br /&gt;        try {&lt;br /&gt;          FileDescriptor fd = dm.openDownloadedFile(&lt;br /&gt;            downloadId).getFileDescriptor();&lt;br /&gt;&lt;br /&gt;          Bitmap image = &lt;br /&gt;            BitmapFactory.decodeFileDescriptor(fd);&lt;br /&gt;     &lt;br /&gt;          imgView.setImageBitmap(image);&lt;br /&gt;&lt;br /&gt;        } catch (FileNotFoundException e) {&lt;br /&gt;          e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Na classe acima, temos quatro atributos. O DownloadManager que realizará a solicitação de download. O atributo MeuReceiver receberá a notificação quando o download for concluído. No nosso exemplo, baixaremos uma imagem, e ela será exibida no ImageView declarado em seguida. O último atributo é o ID do download que a nossa aplicação iniciará. Esse atributo é importante para obtermos o arquivo que foi baixado.&lt;br /&gt;No onCreate fazemos as inicializações necessárias, inclusive, a do DownloadManager, através do método getSystemService. No método onResume, registramos o nosso BroadcastReceiver para ser chamado quando a ação ACTION_DOWNLOAD_COMPLETE for disparada. Essa ação é disparada quando o download do arquivo é concluído. E no onDestroy, desregistamos o nosso receiver.&lt;br /&gt;O método baixarArquivoClick é chamado quando o botão (que declarei no arquivo de layout) é clicado. Nesse método criamos um objeto da classe DownloadManager.Request passando a URL do arquivo. Em seguida, setamos o título e a descrição do download. Além disso, podemos restringir o tipo de rede usada para download, no nosso caso, informamos que podemos fazer com a rede de dados da operadora, mas poderíamos informar que o download só poderia ser feito via Wi-Fi.&lt;br /&gt;Finalmente, enviamos a requisição de download e armazenamos o id do download no atributo downloadId.&lt;br /&gt;Para tratar o fim do download, temos a classe MeuReceiver. Quando o download é concluído o método onReceive é chamado. Nosso broadcast será chamado mesmo se não for o nosso download que for concluído, então temos que checar se o id que foi concluído é igual ao atributo downloadId. Se for, obtemos o FileDescriptor do arquivo baixado, criamos a imagem e setamos no ImageView.&lt;br /&gt;&lt;br /&gt;Abaixo, temos a imagem da nossa aplicação em execução.&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 214px; height: 320px;" src="http://3.bp.blogspot.com/-OwC_yBPf0sc/TpY88zlD5EI/AAAAAAAAAck/3mMV5VPADgA/s320/device-2011-10-12-222013.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5662780596800447554" /&gt;&lt;br /&gt;&lt;br /&gt;4br4ços,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-4167173815512219712?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/SvtSHHV0OW2rn0uHPrQejQFL_Vc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SvtSHHV0OW2rn0uHPrQejQFL_Vc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/SvtSHHV0OW2rn0uHPrQejQFL_Vc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SvtSHHV0OW2rn0uHPrQejQFL_Vc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/ixF95911HwI" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=4167173815512219712" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/4167173815512219712?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/4167173815512219712?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/ixF95911HwI/baixe-arquivos-com-o-downloadmanager.html" title="Baixe arquivos com o DownloadManager" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-OwC_yBPf0sc/TpY88zlD5EI/AAAAAAAAAck/3mMV5VPADgA/s72-c/device-2011-10-12-222013.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/10/baixe-arquivos-com-o-downloadmanager.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcHQ3w9eyp7ImA9WhdaFkg.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-5166086493919334933</id><published>2011-10-26T07:00:00.000-07:00</published><updated>2011-10-26T10:27:12.263-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-26T10:27:12.263-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="saveInstanceState" /><category scheme="http://www.blogger.com/atom/ns#" term="Activity" /><category scheme="http://www.blogger.com/atom/ns#" term="orientation" /><category scheme="http://www.blogger.com/atom/ns#" term="state" /><category scheme="http://www.blogger.com/atom/ns#" term="configChanges" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="Orientação" /><title>Android: Tratando mudança de orientação</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Chegaram 4 novos estagiários aqui no projeto e coube "a minha pessoa" orientá-los. Durante a aula, o assunto enveredou para tratamento de mudança de orientação do aparelho (portrait e landscape | retrato e paisagem).&lt;br /&gt;Por padrão, ao girar o telefone o método onCreate é chamado novamente e com isso, dados que foram carregados dinamicamente (como itens de um ArrayList que estão preenchendo um ListView) são perdidos.&lt;br /&gt;&lt;br /&gt;Vejamos o exemplo abaixo:&lt;br /&gt;&lt;br /&gt;Arquivo de layout.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;LinearLayout&lt;br /&gt; xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt; android:layout_width="fill_parent"&lt;br /&gt; android:layout_height="fill_parent"&lt;br /&gt; android:orientation="vertical"&lt;br /&gt; android:background="#0000FF"&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;TextView&lt;br /&gt;   android:layout_width="fill_parent"&lt;br /&gt;   android:layout_height="wrap_content"&lt;br /&gt;   android:text="Digite o nome" /&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;EditText&lt;br /&gt;   android:id="@+id/editText1"&lt;br /&gt;   android:layout_width="fill_parent"&lt;br /&gt;   android:layout_height="wrap_content"/&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;Button&lt;br /&gt;   android:layout_width="wrap_content"&lt;br /&gt;   android:layout_height="wrap_content"&lt;br /&gt;   android:onClick="meuBotaoClick"&lt;br /&gt;   android:text="Adicionar" /&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;ListView&lt;br /&gt;   android:id="@+id/listView1"&lt;br /&gt;   android:layout_width="fill_parent"&lt;br /&gt;   android:layout_height="fill_parent" /&amp;gt;&lt;br /&gt;&amp;lt;/LinearLayout&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Classe da Activity&lt;br /&gt;&lt;pre name="code" class="java"&gt;public class TelaPrincipalActivity&lt;br /&gt; extends Activity {&lt;br /&gt;&lt;br /&gt; EditText edt;&lt;br /&gt; ArrayList&amp;lt;String&amp;gt; nomes;&lt;br /&gt; ArrayAdapter&amp;lt;String&amp;gt; adapter;&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public void onCreate(Bundle savedInstanceState) {&lt;br /&gt;   super.onCreate(savedInstanceState);&lt;br /&gt;   setContentView(R.layout.main);&lt;br /&gt;&lt;br /&gt;   edt = (EditText) findViewById(R.id.editText1);&lt;br /&gt;&lt;br /&gt;   ListView listView = (ListView) &lt;br /&gt;     findViewById(R.id.listView1);&lt;br /&gt;   adapter = new ArrayAdapter&amp;lt;String&amp;gt;(this,&lt;br /&gt;     android.R.layout.simple_list_item_1, nomes);&lt;br /&gt;&lt;br /&gt;   listView.setAdapter(adapter);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void meuBotaoClick(View v) {&lt;br /&gt;   nomes.add(edt.getText().toString());&lt;br /&gt;   edt.setText("");&lt;br /&gt;   adapter.notifyDataSetChanged();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No código acima, ao clicar no botão, o texto digitado no EditText é inserido na lista, e em seguida o adapter é atualizado através do método notifyDataSetChanged.&lt;br /&gt;O exemplo é bem simples, mas se você girarmos o aparelho os dados que estão sendo exibidos são perdidos, uma vez que a lista inicia vazia e (como já falei) o onCreate é chamado novamente.&lt;br /&gt;&lt;br /&gt;Para isso não acontecer você tem 3 alternativas:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1)Forçar uma orientação&lt;/b&gt;&lt;br /&gt;Na declaração da sua Activity, no AndroidManifest.xml, você pode usar a propriedade android:screenOrientation para manter sua aplicação em uma orientação específica (portrait/landscape).&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;activity&lt;br /&gt; android:name="TelaPrincipalActivity"&lt;br /&gt; android:screenOrientation="portrait" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2)Avisar o Android para não chamar o onCreate&lt;/b&gt;&lt;br /&gt;Essa é a melhor opção quando você quer utilizar a tela nas duas orientações e impedir que o Android chame o onCreate cada vez que você girar o aparelho. Para isso basta dizer que ao mudar a configuração (configChanges) de orientação, ele não recrie a Activity.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;activity&lt;br /&gt; android:name="TelaPrincipalActivity"&lt;br /&gt; android:configChanges="orientation|keyboardHidden"/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3) Salvar o estado da Activity&lt;/b&gt;&lt;br /&gt;A opção número dois é perfeita quando você quer usar o mesmo layout nas duas orientações. Mas, e se eu quiser usar layouts diferentes? Neste caso você dever permitir que a Activity seja recriada. Entretanto, devemos salvar seu estado com o método onSaveInstanceState e no onCreate recuperar esse estado.&lt;br /&gt;&lt;br /&gt;No exemplo que fiz os "estags", criei a pasta "layout-land" com o mesmo layout definido acima, só mudando o background (apenas para notarmos os diferentes layouts). Depois implementamos o método onSaveInstanceState para salvar os itens da lista.&lt;br /&gt;&lt;pre name="code" class="java"&gt;@Override&lt;br /&gt;protected void onSaveInstanceState(Bundle outState) {&lt;br /&gt; super.onSaveInstanceState(outState);&lt;br /&gt; outState.putStringArrayList("nomes", nomes);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Se vocês notaram, o método onSaveInstanceState usa um objeto da classe Bundle para salvar o estado. Esse estado é passado para o método onCreate da Activity como parâmetro, que utilizaremos para restaurar o seu estado.&lt;br /&gt;&lt;pre name="code" class="java"&gt;@Override&lt;br /&gt;public void onCreate(Bundle savedInstanceState) {&lt;br /&gt; super.onCreate(savedInstanceState);&lt;br /&gt; // Código já apresentado&lt;br /&gt; if (savedInstanceState != null) {&lt;br /&gt;   nomes = savedInstanceState.&lt;br /&gt;    getStringArrayList("nomes");&lt;br /&gt;&lt;br /&gt; } else {&lt;br /&gt;   nomes = new ArrayList&amp;lt;String&amp;gt;();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Com isso podemos ter, para a mesma tela, um layout diferente para cada orientação, desde que tenhamos os mesmos componentes (e com os mesmos ids).&lt;br /&gt;&lt;br /&gt;Ficou com dúvida? Deixe seu comentário.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-5166086493919334933?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HqgY7Cg1rBKI_dsUEhlchcEk0Cg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HqgY7Cg1rBKI_dsUEhlchcEk0Cg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HqgY7Cg1rBKI_dsUEhlchcEk0Cg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HqgY7Cg1rBKI_dsUEhlchcEk0Cg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/L-Q-RFCuiGs" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=5166086493919334933" title="3 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/5166086493919334933?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/5166086493919334933?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/L-Q-RFCuiGs/android-tratando-mudanca-de-orientacao.html" title="Android: Tratando mudança de orientação" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/10/android-tratando-mudanca-de-orientacao.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQDRHg6cSp7ImA9WhdaFEg.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-8346927500080297957</id><published>2011-10-24T04:00:00.000-07:00</published><updated>2011-10-24T04:39:35.619-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-24T04:39:35.619-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="peso" /><category scheme="http://www.blogger.com/atom/ns#" term="LinearLayout" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="layout_weight" /><title>Android: utilizando layout_weight</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Em todas as minhas turmas de Android, noto uma certa dificuldade em entender como funciona a propriedade layout_weight utilizada nos componentes inseridos dentro do LinearLayout. Por padrão, essa propriedade serve para definir como o espaço restante do layout deve ser distribuído pelos componentes. Mas esse comportamento pode variar de acordo com o valor definido na propriedade layout_width e layout_height. Observemos a figura abaixo:&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 214px; height: 320px;" src="http://2.bp.blogspot.com/-hXs6OqG5hVw/TpXOoHteAvI/AAAAAAAAAcY/0svD7m-V4-0/s320/device-2011-10-12-142937.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5662659295148114674" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;O layout acima é um LinearLayout vertical (orientation=vertical) com vários LinearLayout horizontal iguais, com 3 botões cada, e com os respectivos textos: "Um", "exemplo" e "de peso".&lt;br /&gt;&lt;br /&gt;Vamos ver como da linha está configurada:&lt;br /&gt;&lt;br /&gt;Linha1 - Nessa linha não fizemos nenhuma modificação, ou seja, está sem peso e com a largura e altura (layout_width e layout_height) definidos como wrap_content.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;LinearLayout&lt;br /&gt;android:layout_height="wrap_content"&lt;br /&gt;android:layout_width="match_parent"&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="Um"&lt;br /&gt;  android:layout_width="wrap_content"&lt;br /&gt;  android:layout_height="wrap_content"/&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="Exemplo"&lt;br /&gt;  android:layout_width="wrap_content"&lt;br /&gt;  android:layout_height="wrap_content"/&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="de peso"&lt;br /&gt;  android:layout_width="wrap_content"&lt;br /&gt;  android:layout_height="wrap_content"/&amp;gt;&lt;br /&gt;&amp;lt;/LinearLayout&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Linha 2 - Nesse linha, definimos pesos iguais para todos os botões. Notem que apesar dos pesos estarem iguais, os componentes não têm tamanhos iguais. Essa é a aplicação clássica do layout_weight. Como vimos na linha 1, sobrou um espaço entre o terceiro botão e a margem direita. Com os pesos iguais, o espaço restante é distribuído igualmente entre os componentes. Uma vez que o texto de um botão é maior que o outro, os botões ficam com larguras diferentes.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;LinearLayout&lt;br /&gt;android:layout_height="wrap_content"&lt;br /&gt;android:layout_width="match_parent"&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="Um"&lt;br /&gt;  android:layout_width="wrap_content"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="1"/&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="Exemplo"&lt;br /&gt;  android:layout_width="wrap_content"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="1"/&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="de peso"&lt;br /&gt;  android:layout_width="wrap_content"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="1"/&amp;gt;&lt;br /&gt;&amp;lt;/LinearLayout&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Linha 3 - Essa linha é similar a anterior, a diferença fica por conta da propriedade layout_width definida como 0dp. Como assim? Se setarmos a largura para zero, o componente não deveria aparecer certo? A resposta é sim, mas como estamos usando o peso, ele vai distribuir o espaço restante da tela igualmente para os 3 botões. Como os 3 botões estão com tamanho zero, o espaço restante (e que será dividido entre os componentes) é toda a tela.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;LinearLayout&lt;br /&gt;android:layout_height="wrap_content"&lt;br /&gt;android:layout_width="match_parent"&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="Um"&lt;br /&gt;  android:layout_width="0dp"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="1"/&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="Exemplo"&lt;br /&gt;  android:layout_width="0dp"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="1"/&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="de peso"&lt;br /&gt;  android:layout_width="0dp"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="1"/&amp;gt;&lt;br /&gt;&amp;lt;/LinearLayout&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Linha 4 - Igual a anterior, mas modificamos a proporção dos componentes. Os dois primeiros ocupam metade da tela, e o terceiro ocupa a outra metade.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;LinearLayout&lt;br /&gt;android:layout_height="wrap_content"&lt;br /&gt;android:layout_width="match_parent"&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="Um"&lt;br /&gt;  android:layout_width="0dp"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="1"/&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="Exemplo"&lt;br /&gt;  android:layout_width="0dp"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="1"/&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="de peso"&lt;br /&gt;  android:layout_width="0dp"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="2"/&amp;gt;&lt;br /&gt;&amp;lt;/LinearLayout&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Linha 5 - Essa linha usa uma outra utilidade do layout_weight, a de prioridade. No código abaixo os dois primeiros botões estão com a propriedade layout_width setada para match_parent (que é o mesmo que fill_parent), ou seja, devem ocupar toda a largura do seu pai. Se esses componentes não tivessem o peso setado, o primeiro botão ocuparia toda a tela, e os demais não apareceriam. Uma vez que definimos o peso, cada um deles divide a tela, mas e o terceiro? Como não foi definido peso para ele, ele tem peso zero, então, o componente com MENOR peso, tem MAIOR prioridade, então ele passa a aparecer. Note que o layout_width do terceiro botão está como wrap_content, se estivesse fill_parent, ele ocuparia toda a tela, uma vez que ele tem peso menor (zero).&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;LinearLayout&lt;br /&gt;android:layout_height="wrap_content"&lt;br /&gt;android:layout_width="match_parent"&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="Um"&lt;br /&gt;  android:layout_width="fill_parent"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="1"/&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="Exemplo"&lt;br /&gt;  android:layout_width="fill_parent"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="1"/&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="de peso"&lt;br /&gt;  android:layout_width="wrap_content"&lt;br /&gt;  android:layout_height="wrap_content"/&amp;gt;&lt;br /&gt;&amp;lt;/LinearLayout&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Linha 6 - Conforme explicado acima, todos os botões estão com a propriedade layout_width definidos como fill_parent, entretanto, o primeiro está com peso 2, enquanto os demais tem peso 1. Logo os com peso menor tem prioridade.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;LinearLayout&lt;br /&gt;android:layout_height="wrap_content"&lt;br /&gt;android:layout_width="match_parent"&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="Um"&lt;br /&gt;  android:layout_width="fill_parent"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="2"/&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="Exemplo"&lt;br /&gt;  android:layout_width="fill_parent"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="1"/&amp;gt;&lt;br /&gt;&amp;lt;Button&lt;br /&gt;  android:text="de peso"&lt;br /&gt;  android:layout_width="fill_parent"&lt;br /&gt;  android:layout_height="wrap_content"&lt;br /&gt;  android:layout_weight="1"/&amp;gt;&lt;br /&gt;&amp;lt;/LinearLayout&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Espero que agora fique mais claro a utilização do peso. Na dúvida, deixem seus comentários.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-8346927500080297957?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/dCM6VUoa4qB7Eo8b2p3xmL7CMR8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dCM6VUoa4qB7Eo8b2p3xmL7CMR8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/dCM6VUoa4qB7Eo8b2p3xmL7CMR8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dCM6VUoa4qB7Eo8b2p3xmL7CMR8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/ejFnJahF8uA" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=8346927500080297957" title="2 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/8346927500080297957?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/8346927500080297957?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/ejFnJahF8uA/android-utilizando-layoutweight.html" title="Android: utilizando layout_weight" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-hXs6OqG5hVw/TpXOoHteAvI/AAAAAAAAAcY/0svD7m-V4-0/s72-c/device-2011-10-12-142937.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/10/android-utilizando-layoutweight.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMBQHcyfip7ImA9WhRTFE4.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-6548749215700800528</id><published>2011-10-20T07:00:00.000-07:00</published><updated>2011-11-04T11:47:31.996-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-04T11:47:31.996-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PX" /><category scheme="http://www.blogger.com/atom/ns#" term="display" /><category scheme="http://www.blogger.com/atom/ns#" term="Conversão" /><category scheme="http://www.blogger.com/atom/ns#" term="acender" /><category scheme="http://www.blogger.com/atom/ns#" term="DIP" /><category scheme="http://www.blogger.com/atom/ns#" term="Fonte" /><category scheme="http://www.blogger.com/atom/ns#" term="install" /><category scheme="http://www.blogger.com/atom/ns#" term="location" /><category scheme="http://www.blogger.com/atom/ns#" term="wakelock" /><category scheme="http://www.blogger.com/atom/ns#" term="ligar" /><category scheme="http://www.blogger.com/atom/ns#" term="debug.keystore" /><category scheme="http://www.blogger.com/atom/ns#" term="Tamanho da Tela" /><category scheme="http://www.blogger.com/atom/ns#" term="Dicas" /><title>Android: Dicas 5</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Esse é mais um post da série de dicas de Android. Aproveitem e deixem seus comentários :)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dica 1 - Alterando a fonte dos componentes&lt;/b&gt;&lt;br /&gt;O Android, por padrão, tem apenas 3 fontes que podem ser utilizadas nos componentes visuais: sans, serif e monospace. Para utilizar cada uma delas, basta atribuir o valor desejado à propriedade android:typeface. Mas se quiser utilizar uma nova fonte, basta adicionar o arquivo *.ttf na pasta assets e carregá-la utilizando o código abaixo.&lt;br /&gt;&lt;pre name="code" class="java"&gt;Typeface typeface =&lt;br /&gt;Typeface.createFromAsset(getAssets(), "Aliens.ttf");&lt;br /&gt;&lt;br /&gt;TextView txt = (TextView)findViewById(R.id.textView1);&lt;br /&gt;txt.setTypeface(typeface);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Infelizmente, não achei uma forma de setar essa fonte no XML. Se alguém souber, deixe um comentário. Ah! A fonte que usei nesse exemplo foi baixada do site http://www.webpagepublicity.com/free-fonts.html.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dica 2 - Converter DIP (Density Independent Pixel) para Pixel&lt;/b&gt;&lt;br /&gt;Após ministrar duas aulas seguidas (em turmas diferentes) sobre Views personalizadas no Android, uma dúvida frequente foi como converter DIP para PX (pixel). Isso é especialmente útil para que a View rode corretamente em diferentes densidades de tela (LDPI, MDPI, HDPI e agora XHDPI). Para tal, pode-se utilizar o método applyDimension da classe TypeValue.&lt;br /&gt;&lt;pre name="code" class="java"&gt;Resources r = getResources();&lt;br /&gt;float valorEmDp = 14;&lt;br /&gt;float valorEmPixels = TypedValue.applyDimension(&lt;br /&gt;  TypedValue.COMPLEX_UNIT_DIP, valorEmDp,&lt;br /&gt;  r.getDisplayMetrics());&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dica 3 - Evitando acumular Toasts&lt;/b&gt;&lt;br /&gt;Um "bug" clássico que os engenheiros de teste do projeto em que eu trabalho levantam é sobre a utilização do Toast. Se você chamar o método show() dessa classe várias vezes seguidas, essas mensagens são acumuladas e ficam sendo exibidas sequencialmente. Um recurso que utilizo é criar um método separado, que verificará se já existe um Toast aberto, em caso positivo, ele o cancela para exibir um novo. Para tal, você deve criar um atributo da classe Toast (que abaixo chamo de 'toast') e utilizar o seguinte código:&lt;br /&gt;&lt;pre name="code" class="java"&gt;// Declare o atributo&lt;br /&gt;private static Toast toast;&lt;br /&gt;&lt;br /&gt;// Método&lt;br /&gt;public static void showToast(Context ctx, int res){&lt;br /&gt;  if (toast != null){&lt;br /&gt;    toast.cancel();&lt;br /&gt;    toast.setText(res);&lt;br /&gt;  } else {&lt;br /&gt;    toast = Toast.makeText(ctx, res, Toast.LENGTH_LONG);&lt;br /&gt;  }&lt;br /&gt;  toast.show();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dica 4 - Definindo onde instalar sua aplicação&lt;/b&gt;&lt;br /&gt;A partir da versão 2.2 (Froyo) é possível especificar onde sua aplicação pode ser instalada: cartão de memória ou memória interna. Por padrão, a aplicação será instalada na memória interna, mas você pode utilizar a propriedade android:installLocation da tag &amp;lt;manifest&amp;gt; do AndroidManifest.xml para um dos valores abaixo:&lt;br /&gt;&lt;u&gt;internalOnly&lt;/u&gt; - A aplicação só poderá ser instalada na memória interna (valor padrão).&lt;br /&gt;&lt;u&gt;auto&lt;/u&gt; - A aplicação é instalada na memória interna, mas poderá ser movida para o cartão de memória posteriormente ou quando a memória interna estiver cheia.&lt;br /&gt;&lt;u&gt;preferExternal&lt;/u&gt; - A aplicação deve ser instalada no cartão de memória preferencialmente, mas isso não é garantido.&lt;br /&gt;&lt;br /&gt;Exemplo:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;manifest&lt;br /&gt;xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt;android:installLocation="preferExternal"&lt;br /&gt;... &amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dica 5: Ativar/Acender a tela do aparelho&lt;/b&gt;&lt;br /&gt;&lt;a href="http://nglauber.blogspot.com/2010/10/notificacoes-personalizadas-no-android.html"&gt;Neste post&lt;/a&gt; eu mostrei como criar notificações no Android. Um recurso que pode ser utilizado juntamente com as notificações é acender/ligar a tela do aparelho. Para fazer isso, deve-se utilizar a classe PowerManager.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;// Obtém a instância do PowerManager&lt;br /&gt;PowerManager pm = (PowerManager)c.getSystemService(&lt;br /&gt;Context.POWER_SERVICE);&lt;br /&gt;&lt;br /&gt;// Liga o display do aparelho&lt;br /&gt;WakeLock wakeLock = pm.newWakeLock(&lt;br /&gt;  // Liga a tela&lt;br /&gt;  PowerManager.SCREEN_DIM_WAKE_LOCK |&lt;br /&gt;  // Após liberar a tela para apagar, &lt;br /&gt;  // mantém a tela ligada por um pouco&lt;br /&gt;  // mais de tempo&lt;br /&gt;  PowerManager.ON_AFTER_RELEASE,&lt;br /&gt;  // Tag para debug&lt;br /&gt;  "tag_para_debug");&lt;br /&gt;&lt;br /&gt;// Liga a tela por 10 segundos&lt;br /&gt;wakeLock.acquire(10000);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para usar o código acima, deve-se adicionar a permissão WAKE_LOCK no AndroidManifest.xml.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;uses-permission name="android.permission.WAKE_LOCK"/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dica 6: debug.keystore expirou&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Essa dica foi enviada pelo meu colega &lt;a href="http://twitter.com/RicardoGilson"&gt;Ricardo Gilson&lt;/a&gt;.&lt;br /&gt;Toda aplicação Android é assinada para ser instalada no dispositivo, por padrão, ela é assinada com uma assinatura de debug através do arquivo debug.keystore que fica na subpasta ".android" no diretório do usuário (C:\Users\usuario\.android ou /Users/usuario/.android). Depois de um certo tempo sem utilizar a máquina, a mensagem abaixo pode ser exibida ao tentar rodar uma aplicação:&lt;br /&gt;&lt;br /&gt;Error generating final archive: Debug Certificate expired on 24/09/2011.&lt;br /&gt;&lt;br /&gt;Para resolver o problema é só apagar o arquivo debug.keystore, dar um clean no projeto do Eclipse (menu Project &amp;gt; Clean) e tentar rodar novamente.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Dica 6: Habilite a aceleração de Hardware (por Fernado Fragoso)&lt;/b&gt;&lt;br /&gt;Habilitar a aceleração de hardware quando necessitar de manipulação de imagens, adicionar na tag application do AndroidManifest.xml.&lt;br /&gt;&lt;br /&gt;android:hardwareAccelerated="true"&lt;br /&gt;&lt;br /&gt;Faz uma diferença gigantesca! Valeu Fernando!&lt;br /&gt;&lt;br /&gt;Por hoje é só, qualquer dúvida ou sugestão, deixem seus comentários.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-6548749215700800528?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pwZt2Bw101_E_A0j216zOZUulpQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pwZt2Bw101_E_A0j216zOZUulpQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pwZt2Bw101_E_A0j216zOZUulpQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pwZt2Bw101_E_A0j216zOZUulpQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/hnz6pxRBJVw" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=6548749215700800528" title="8 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/6548749215700800528?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/6548749215700800528?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/hnz6pxRBJVw/android-dicas-5.html" title="Android: Dicas 5" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><thr:total>8</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/10/android-dicas-5.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcNRHYzeyp7ImA9WhdaEE8.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-4072308341124389690</id><published>2011-10-18T21:05:00.000-07:00</published><updated>2011-10-19T04:34:55.883-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-19T04:34:55.883-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cream" /><category scheme="http://www.blogger.com/atom/ns#" term="Sandwich" /><category scheme="http://www.blogger.com/atom/ns#" term="4" /><category scheme="http://www.blogger.com/atom/ns#" term="Nexus" /><category scheme="http://www.blogger.com/atom/ns#" term="Galaxy" /><category scheme="http://www.blogger.com/atom/ns#" term="Ice" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="ICS" /><category scheme="http://www.blogger.com/atom/ns#" term="4.0" /><title>Ice Cream Sandwich: O Android 4.0</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Fiquei acordado até as 02:00 para ver o lançamento do Android "Sanduíche de Sorvete". A apresentação mostrou as novidades da nova versão do S.O. no Galaxy Nexus da Samsung. Ao terminar a apresentação, foi anunciado que o SDK já estaria disponível. Então, não perdi tempo e já o atualizei juntamente com o plugin ADT (Android Development Tools). &lt;br /&gt;Sendo assim, antes de dormir, vou deixar uns screenshots de algumas novidades que tirei com o emulador novo :)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-ppU83tPa90I/Tp5Pkp8KFUI/AAAAAAAAAc8/E0hPIs11sIM/s1600/lock_screen.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 192px; height: 320px;" src="http://1.bp.blogspot.com/-ppU83tPa90I/Tp5Pkp8KFUI/AAAAAAAAAc8/E0hPIs11sIM/s320/lock_screen.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5665052872430720322" /&gt;&lt;/a&gt;Na tela de lock, é possível ir direto para câmera.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-LhNcwHjklmk/Tp5PkjbTm8I/AAAAAAAAAcw/GokAdg_eAWY/s1600/home_screen.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 192px; height: 320px;" src="http://2.bp.blogspot.com/-LhNcwHjklmk/Tp5PkjbTm8I/AAAAAAAAAcw/GokAdg_eAWY/s320/home_screen.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5665052870682319810" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-wfugFHWsul4/Tp5PlYPEN6I/AAAAAAAAAdU/zRC9V3I8Or8/s1600/launcher_widgets.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 192px; height: 320px;" src="http://2.bp.blogspot.com/-wfugFHWsul4/Tp5PlYPEN6I/AAAAAAAAAdU/zRC9V3I8Or8/s320/launcher_widgets.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5665052884858058658" /&gt;&lt;/a&gt;No Launcher, agora podemos adicionar Widgets. Inclusive os do Honeycomb.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-qvOGNsi0S8w/Tp5PlE6c-iI/AAAAAAAAAdI/njc2O_jkeTg/s1600/launcher_apps.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 192px; height: 320px;" src="http://1.bp.blogspot.com/-qvOGNsi0S8w/Tp5PlE6c-iI/AAAAAAAAAdI/njc2O_jkeTg/s320/launcher_apps.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5665052879671327266" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-pzkNOnlHoGY/Tp5Plim1cKI/AAAAAAAAAdk/bb6I2i7SNjU/s1600/hello.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 192px; height: 320px;" src="http://4.bp.blogspot.com/-pzkNOnlHoGY/Tp5Plim1cKI/AAAAAAAAAdk/bb6I2i7SNjU/s320/hello.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5665052887642108066" /&gt;&lt;/a&gt;Um Hello World pra ver se funciona mesmo :)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-nutQindKBiA/Tp5P0JskIjI/AAAAAAAAAds/qAxuQEevzmw/s1600/sdk_manager.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 229px;" src="http://1.bp.blogspot.com/-nutQindKBiA/Tp5P0JskIjI/AAAAAAAAAds/qAxuQEevzmw/s320/sdk_manager.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5665053138653291058" /&gt;&lt;/a&gt;&lt;br /&gt;O SDK Manager ficou de cara nova. Bem melhor! Ah! O Assistente de novo projeto do Eclipse também melhorou.&lt;br /&gt;&lt;br /&gt;Vou tentar atualizar esse post mais tarde.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-4072308341124389690?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3GGUUXi3H22N_5Tgtq3YnT39gqI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3GGUUXi3H22N_5Tgtq3YnT39gqI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3GGUUXi3H22N_5Tgtq3YnT39gqI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3GGUUXi3H22N_5Tgtq3YnT39gqI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/aOa9R_-Fv4U" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=4072308341124389690" title="2 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/4072308341124389690?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/4072308341124389690?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/aOa9R_-Fv4U/ice-cream-sandwich-o-android-40.html" title="Ice Cream Sandwich: O Android 4.0" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-ppU83tPa90I/Tp5Pkp8KFUI/AAAAAAAAAc8/E0hPIs11sIM/s72-c/lock_screen.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/10/ice-cream-sandwich-o-android-40.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4HQng5fCp7ImA9WhdaEUw.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-5071631152880850708</id><published>2011-10-07T18:58:00.000-07:00</published><updated>2011-10-20T05:48:53.624-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-20T05:48:53.624-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Top" /><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="lessons" /><category scheme="http://www.blogger.com/atom/ns#" term="licões" /><category scheme="http://www.blogger.com/atom/ns#" term="Dicas" /><category scheme="http://www.blogger.com/atom/ns#" term="20" /><title>20 dicas para programadores</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Conviver com pessoas mais experientes é uma coisa muito boa, pois você pode explorar o know-how dessas pessoas e crescer profissionalmente (e às vezes pessoalmente). Eu tenho a satisfação de ter  trabalhado, tido aulas e ter sido orientando por Luiz Eugênio Fernandes Tenório (left), um excelente profissional de desenvolvimento de software (senão o melhor que conheço).&lt;br /&gt;Em 21 de agosto de 2007, ele me mandou um email com um texto de &lt;a href="http://twitter.com/jdanylko"&gt;Jonathan Danylko&lt;/a&gt; que a muito tempo queria postar aqui no blog. É um conjunto de boas práticas, que um desenvolvedor de software pode seguir para melhorar a produtividade e a qualidade do seu trabalho. Adotei uma boa parte dessas dicas, e notei bons resultados através de feedbacks de gestores e colegas de trabalho. E por causa disso, resolvi compartilhar com vocês.&lt;div&gt;&lt;br /&gt;&lt;div&gt;O texto abaixo é uma tradução/adaptação minha (vixe!) do texto original em inglês disponível &lt;a href="http://www.dcs-media.com/Archive/20-20-top-20-programming-lessons-ive-learned-in-20-years-FH"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Defina quanto tempo você acha que deve gastar para resolver um problema.&lt;/b&gt; Já vi programadores sentarem na frente de um monitor por oito para resolver um problema. Defina uma tabela de tempo para si mesmo de 1 hora, 30 minutos, ou até mesmo 15 minutos. Se você não conseguir descobrir uma solução para seu problema dentro de seu prazo, peça ajuda ou pesquise seu problema na Internet em vez de tentar ser super-coder.&lt;/li&gt;&lt;li&gt;&lt;b&gt;As linguagens são similares.&lt;/b&gt; Com o tempo, você entenderá como uma linguagem funciona, então você vai notar semelhanças com outras linguagens. A linguagem que você escolher deve: te fornecer um nível de "conforto" adequado, a capacidade de produzir código eficiente (e limpo), e acima de tudo, se adequar ao projeto e vice-versa. &lt;/li&gt;&lt;li&gt;&lt;b&gt;Não exagere nos padrões de projeto.&lt;/b&gt; Pense duas vezes antes de usá-los, se houver uma solução mais simples (e que funcione), use-a. Um problema que necessita de um padrão de projeto como solução, será identificado naturalmente (obviamente depois de um certo tempo de experiência).&lt;/li&gt;&lt;li&gt;&lt;b&gt;Sempre faça backup do código. &lt;/b&gt;Quando eu era mais novo, por uma falha no disco rígido,  perdi um monte de código, e me senti horrível por causa do que tinha acontecido. A única vez que você não fizer backup dos dados, pode ser o momento onde você tem um prazo restrito com um cliente, e eles precisam do que você estava fazendo pra amanhã. Controle de código fonte/versão (CVS, SVN, GIT,...) também se aplica aqui.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Você não é o melhor em programação. &lt;/b&gt;Aceite isso. Eu sempre pensei que eu sabia muito sobre programação, mas sempre há alguém lá fora (ou do seu lado), melhor que você. Sempre. Aprenda com eles.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Aprenda a aprender mais.&lt;/b&gt; Como número cinco explicou, eu sempre tive uma revista ou livro na minha mão sobre computadores ou programação (pergunte aos meus amigos, eles vão confirmar). Verdade, há muita tecnologia lá fora, e manter-se com ela é um trabalho em tempo integral, mas se você tem uma maneira inteligente de receber novidades, você vai aprender sobre novas tecnologias a cada dia.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Mudanças são constantes. &lt;/b&gt;Seu conhecimento de tecnologia e/ou programação deve ser semelhante à forma como você trata investimentos: Diversifique. Não fique muito confortável com uma tecnologia particular. Se não houver suporte suficiente para aquela linguagem ou tecnologia, é bom você pode começar a atualizar o seu currículo imediatamente, e começar o seu período de treinamento. Minha regra geral: Conheça pelo menos duas ou três linguagens, assim, se uma morre, você tem outra para trabalhar enquanto você estuda uma nova para colocar no lugar.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Ajude os novatos.&lt;/b&gt; Oriente os desenvolvedores iniciantes sobre as boas técnicas de programação. Você nunca sabe... mas você pode ganhar pontos com isso, e vai se sentir mais confiante de ter, pessoalmente, treinado e preparado uma pessoa para seu próximo trabalho.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Simplifique o algoritmo.&lt;/b&gt; Codifique como um demônio, mas quando estiver tudo pronto, volte para otimizá-lo. Uma pequena melhoria no código aqui e ali, e você terá uma manutenção de código mais feliz  no longo prazo.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Documente seu código.&lt;/b&gt; Se a documentação é uma API de Web Service ou uma simples classe, documente do mesmo jeito. Eu tenho sido acusado de excesso de comentários no meu código, e isso é algo que eu me orgulho. Leva apenas um segundo para adicionar uma linha de comentário adicional para cada 3 linhas de código.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Teste, teste e teste.&lt;/b&gt; Eu sou um fã de testes de caixa preta. Quando sua rotina é concluída, o seu período de "selo de aprovação" começa. Se você tem um departamento de Quality Assurance, você pode estar falando mais para eles do que para seu gerente de projeto sobre os erros em seu código. Se você não testar seu código completamente, você pode desenvolver mais que código, e possivelmente uma má reputação.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Celebre todo sucesso.&lt;/b&gt; Se um programador feliz te pedir para vir ver sua obra extraordinária de código, mesmo que você já tenha visto um trecho de código como esse mais de 100 vezes em suas experiências, comemore o sucesso desse desenvolvedor.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Faça revisão de código frequentes.&lt;/b&gt; Em projetos e pessoalmente. Na empresa, você sempre terá as revisões de código de quão bem você codificou alguma coisa. Não olhar para isso como pessoas crucificando o seu estilo de codificação. Pense nisso como uma crítica construtiva. Quando estiver na revisão, pergunte: "Como eu poderia ter feito melhor?" Isto irá acelerar o seu aprendizado e torná-lo um programador melhor.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Relembre seu código antigo.&lt;/b&gt; Existem duas maneiras de olhar para código antigo: "Eu não posso acreditar que eu escrevi este código" e "Eu não posso acreditar que eu escrevi este código." A primeira afirmação é muitas vezes de nojo e perguntando como você pode melhorá-lo. Você ficaria surpreso como um código antigo pode ser ressuscitado em uma rotina possível e melhor, ou até mesmo um produto inteiro. A segunda declaração é de espanto e realização. Desenvolvedores têm suas conquistas de código, aquelas que eles concluíram e todos tomaram conhecimento.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Humor é necessário.&lt;/b&gt; Em meus 20 anos de desenvolvimento, eu nunca conheci um programador que não tem um senso de humor decente. Na verdade, nesta indústria, é uma exigência.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Cuidado com o programador sabe-tudo, programador possessivo e o programador inexperiente.&lt;/b&gt; O programador sabe-tudo tenta relegar você em vez de trabalhar como um membro da equipe. O programador possessivo cria o código e não quer partilhar com ninguém. E o programador inexperientes pede ajuda constantemente (a cada dez minutos) ao ponto que o código desenvolvido é seu, não dele.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Jamais um projeto será simples.&lt;/b&gt; Se alguém precisa de um site de 3 páginas com o Microsoft Access no início, ele acaba se tornando um site de 15 páginas com o SQL Server, um fórum e um CMS personalizado (Content Management System).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Nunca tome nada como garantido.&lt;/b&gt; Se você levar em um projeto simples, você pode pensar que uma determinada seção será fácil de concluir. Não pense, mesmo por um momento. Ao menos que você tenha uma classe, componente, ou um pedaço de código já codificados, testado exaustivamente e em produção. A partir de um projeto existente, não pense que será fácil.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Software nunca está acabado.&lt;/b&gt; Um colega programador me disse uma vez que o software nunca está acabado, está "temporariamente concluído". Bons conselhos. Se o cliente ainda está usando um programa que você escreveu e tem resistido ao teste do tempo, existem boas chances de você ainda estar atualizando-o, o que não é uma coisa ruim. Mantém seu  emprego.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;A paciência é definitivamente uma virtude.&lt;/b&gt; Quando os clientes, amigos ou membros da família usar um PC, ficam frustrados e partem para bater no computador. Eu continuo dizendo a todos: "você está controlando o computador, não o contrário". Você precisa ter um certo nível de paciência para programar computadores. Tão logo os programadores entendem o que fizeram de errado, eles dizem: "Ah, é por isso que estava acontecendo isso".&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Qualquer sugestão, deixem seus comentário.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-5071631152880850708?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/YiB1y2ouudQ6PRSR7HVgQiyOz0U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YiB1y2ouudQ6PRSR7HVgQiyOz0U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/YiB1y2ouudQ6PRSR7HVgQiyOz0U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/YiB1y2ouudQ6PRSR7HVgQiyOz0U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/OYlfLg8_1CA" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=5071631152880850708" title="2 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/5071631152880850708?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/5071631152880850708?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/OYlfLg8_1CA/20-dicas-para-programadores.html" title="20 dicas para programadores" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/10/20-dicas-para-programadores.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cDRX4-fCp7ImA9WhdUEk4.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-3878199413421565147</id><published>2011-09-28T10:29:00.000-07:00</published><updated>2011-09-28T10:31:14.054-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-28T10:31:14.054-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="AlertDialog" /><category scheme="http://www.blogger.com/atom/ns#" term="selector" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="Alert" /><category scheme="http://www.blogger.com/atom/ns#" term="Dialog" /><title>AlertDialog Personalizado no Android</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Ultimamente estou escrevendo post curtos, com soluções para problemas que as equipes onde eu trabalho/trabalhei têm/tiveram, e que ao meu ver poderiam ter sido feitas de outra forma. A última foi como personalizar o AlertDialog do Android, dependendo da versão do Android (e até do fabricante) o aspecto visual das mensagens que são exibidas para o usuário tem um visual diferente. Por causa disso, o pessoal de UX (&lt;i&gt;User eXperience&lt;/i&gt;) resolveu padronizar isso. Só que o pessoal estava usando uma Activity com o tema de diálogo.&lt;br /&gt;&lt;br /&gt;Eu não acho essa uma boa abordagem, uma vez que você mexe com o ciclo de vida da activity (métodos onCreate, onStart, onPause, ...) para exibir um simples dialog. &lt;a href="http://developer.android.com/guide/topics/ui/dialogs.html"&gt;Esse tutorial do site do Android Developers&lt;/a&gt; mostra como criar um dialog com o conteúdo personalizado.&lt;br /&gt;&lt;br /&gt;Sim, mas e se eu quiser mudar o background do título e dos botões? Nesse post vou mostrar como fazer isso. O código abaixo mostra como personalizar as 3 áreas de um AlertDialog: a barra de título, a área de conteúdo e parte inferior onde ficam os botões.&lt;br /&gt;&lt;pre name="code" class="java"&gt;// O parâmetro temTitulo deve ser informado,&lt;br /&gt;// pois não há como saber se o Dialog tem&lt;br /&gt;// título para mudar a imagem de background&lt;br /&gt;// do topo e do meio.&lt;br /&gt;public void mostraDialog(&lt;br /&gt; AlertDialog dialog, boolean temTitulo) {&lt;br /&gt;&lt;br /&gt; dialog.show();&lt;br /&gt; Resources res = dialog.getContext().getResources();&lt;br /&gt;&lt;br /&gt; // Pega a View do AlertDialog toda&lt;br /&gt; ViewGroup contentView = (ViewGroup)&lt;br /&gt;   dialog.findViewById(android.R.id.content);&lt;br /&gt;&lt;br /&gt; // Pega a ViewGroup com os filhos&lt;br /&gt; // (title, textView, customView e barra dos botões)&lt;br /&gt; ViewGroup contentChilds =&lt;br /&gt;   (ViewGroup)contentView.getChildAt(0);&lt;br /&gt;&lt;br /&gt; // Barra de título&lt;br /&gt; if (temTitulo)&lt;br /&gt;   contentChilds.getChildAt(0).setBackgroundDrawable(&lt;br /&gt;     res.getDrawable(R.drawable.box_top));&lt;br /&gt;&lt;br /&gt; // Layout onde fica o texto (mensagem) do dialog&lt;br /&gt; contentChilds.getChildAt(1).setBackgroundDrawable(&lt;br /&gt;   res.getDrawable(&lt;br /&gt;     temTitulo?&lt;br /&gt;     R.drawable.box_middle :&lt;br /&gt;     R.drawable.box_top));&lt;br /&gt;&lt;br /&gt; // Layout onde fica a View personalizada (quando usada)&lt;br /&gt; contentChilds.getChildAt(2).setBackgroundDrawable(&lt;br /&gt;   res.getDrawable(&lt;br /&gt;     temTitulo?&lt;br /&gt;     R.drawable.box_middle :&lt;br /&gt;     R.drawable.box_top));&lt;br /&gt;  &lt;br /&gt; // Layout dos botões&lt;br /&gt; // Se não colocar wrap_content, o botão fica cortado&lt;br /&gt; contentChilds.getChildAt(3).setLayoutParams(&lt;br /&gt;   new LinearLayout.LayoutParams(&lt;br /&gt;     LayoutParams.FILL_PARENT,&lt;br /&gt;     LayoutParams.WRAP_CONTENT));&lt;br /&gt;&lt;br /&gt; contentChilds.getChildAt(3).setBackgroundDrawable(&lt;br /&gt;   res.getDrawable(R.drawable.box_bottom));&lt;br /&gt;&lt;br /&gt; // Alterando botões&lt;br /&gt; Button btn = (Button)dialog.findViewById(&lt;br /&gt;   android.R.id.button1);&lt;br /&gt; if (btn != null){&lt;br /&gt;   btn.setTextColor(Color.WHITE);&lt;br /&gt;   btn.setBackgroundResource(&lt;br /&gt;     R.drawable.selector_botao_verde);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; btn = (Button)dialog.findViewById(&lt;br /&gt;   android.R.id.button2);&lt;br /&gt; if (btn != null){&lt;br /&gt;   btn.setTextColor(Color.WHITE);&lt;br /&gt;   btn.setBackgroundResource(&lt;br /&gt;     R.drawable.selector_botao_vermelho);&lt;br /&gt; }&lt;br /&gt; btn = (Button)dialog.findViewById(&lt;br /&gt;   android.R.id.button3);&lt;br /&gt; if (btn != null){&lt;br /&gt;   btn.setTextColor(Color.WHITE);&lt;br /&gt;   btn.setBackgroundResource(&lt;br /&gt;     R.drawable.selector_botao_vermelho);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Como todos devem/deveriam saber tudo que é exibido no Android contém objetos da classe View. A classe ViewGroup é uma implementação do padrão de projeto Composite, e como tal, herda de View e é composto de várias Views. Dessa forma, após exibir o Alert, pegamos a ViewGroup que representa o AlertDialog e obtemos cada um dos seus "filhos". O Alert é composto de 4 filhos: o primeiro contém a view com o título e o ícone; a segunda tem o texto do Alert; o terceiro pode conter uma view personalizada associada ao Alert; e o último contém os botões (no máximo 3: positivo, negativo e neutro). Nesse exemplo, pegamos cada filho e alteramos o seu background.&lt;br /&gt;&lt;br /&gt;As imagens de background utilizadas estão no formato 9.png que falei &lt;a href="http://nglauber.blogspot.com/2011/09/android-e-o-formato-9-patch.html"&gt;nesse post aqui&lt;/a&gt;. Mas um detalhe interessante, é que o background do botão é definido utilizando os drawable selector_botao_verde e selector_botao_vermelho. Esses dois arquivos, apesar de ficarem na pasta res/drawable, não são imagens. Na verdade eles são arquivos XML que descrevem as imagens que serão utilizadas pelos botões dependendo do seu estado. Abaixo temos o XML que descreve o botão verde.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;selector&lt;br /&gt;xmlns:android="http://schemas.android.com/apk/res/android"&amp;gt;&lt;br /&gt;&amp;lt;item&lt;br /&gt; android:drawable="@drawable/btn_verde"&lt;br /&gt; android:state_pressed="false"/&amp;gt;&lt;br /&gt;&amp;lt;item&lt;br /&gt; android:drawable="@drawable/btn_verde_pressionado"&lt;br /&gt; android:state_pressed="true" /&amp;gt;&lt;br /&gt;&amp;lt;/selector&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Notem que devemos ter (por uma questão de usabilidade) duas imagens: uma imagem para o botão não pressionado, e outra para ele pressionado. Isso dará a sensação que o usuário estará pressionando no botão. Essa prática pode ser adotada para todos os botões da sua aplicação (inclusive para o botão vermelho usado nesse post).&lt;br /&gt;&lt;br /&gt;Para utilizar o AlertDialog personalizado, basta criá-lo normalmente e passá-lo para o método que criamos anteriormente.&lt;br /&gt;&lt;pre name="code" class="java"&gt;AlertDialog.Builder builder =&lt;br /&gt; new AlertDialog.Builder(this)&lt;br /&gt;   .setTitle("Titulo")&lt;br /&gt;   .setMessage("Mensagem")&lt;br /&gt;   .setPositiveButton("Sim", null)&lt;br /&gt;   .setNegativeButton("Não", null);&lt;br /&gt;AlertDialog d = builder.create();&lt;br /&gt;mostraDialog(d, true);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Abaixo temos um exemplo do nosso Alert em funcionamento.&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 267px; height: 400px;" src="http://4.bp.blogspot.com/-vnw71JmnaCY/ToNYPGM-dgI/AAAAAAAAAb8/B-dH1rdAdGE/s400/device-2011-09-28-142454.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5657462573293794818" /&gt;&lt;br /&gt;Qualquer dúvida, deixem seus comentários.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-3878199413421565147?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Z0Cv80NMUsfRNCgbKC8hlEdZsM0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z0Cv80NMUsfRNCgbKC8hlEdZsM0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Z0Cv80NMUsfRNCgbKC8hlEdZsM0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z0Cv80NMUsfRNCgbKC8hlEdZsM0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/fKHC0P-2xUQ" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=3878199413421565147" title="2 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/3878199413421565147?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/3878199413421565147?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/fKHC0P-2xUQ/dialogos-personalizados-no-android.html" title="AlertDialog Personalizado no Android" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-vnw71JmnaCY/ToNYPGM-dgI/AAAAAAAAAb8/B-dH1rdAdGE/s72-c/device-2011-09-28-142454.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/09/dialogos-personalizados-no-android.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYDRXk-cSp7ImA9WhdUEEk.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-7781246091593995506</id><published>2011-09-26T07:22:00.000-07:00</published><updated>2011-09-26T07:26:14.759-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-26T07:26:14.759-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mask" /><category scheme="http://www.blogger.com/atom/ns#" term="masked" /><category scheme="http://www.blogger.com/atom/ns#" term="máscara" /><category scheme="http://www.blogger.com/atom/ns#" term="EditText" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><title>Máscara no EditText do Android</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Certo dia, um colega me perguntou se existia um EditText com máscara no Android. Apesar de ser uma coisa bem comum em aplicações Desktop, eu não conheço um meio fácil de obter o mesmo comportamento em Android. Na época, dei uma pesquisada e não achei o queria.&lt;br /&gt;Durante as aulas de Android na Unibratec um aluno me perguntou novamente, e fui pesquisar. Como não achei nada tão fácil, o jeito foi implementar um listener (observer) para quando o texto do EditText é alterado. A interface que faz isso no Android é a TextWatcher.&lt;br /&gt;O exemplo abaixo, mostra como fazer uma máscara para um campo de CEP. Passei como exercício para a turma, estender esse exemplo para CPF e CNPJ. Eles fizeram. E vocês?&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;final EditText edt = &lt;br /&gt;  (EditText)findViewById(R.id.editText1);&lt;br /&gt;&lt;br /&gt;edt.addTextChangedListener(new TextWatcher() {&lt;br /&gt;   &lt;br /&gt;boolean isUpdating;&lt;br /&gt;      &lt;br /&gt;@Override&lt;br /&gt;public void beforeTextChanged(&lt;br /&gt; CharSequence s, int start, int count, int after) {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public void onTextChanged(&lt;br /&gt; CharSequence s, int start, int before, int after) {&lt;br /&gt;&lt;br /&gt; // Quando o texto é alterado o onTextChange é chamado&lt;br /&gt; // Essa flag evita a chamada infinita desse método&lt;br /&gt; if (isUpdating){&lt;br /&gt;   isUpdating = false;&lt;br /&gt;   return;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; // Ao apagar o texto, a máscara é removida,&lt;br /&gt; // então o posicionamento do cursor precisa&lt;br /&gt; // saber se o texto atual tinha ou não, máscara   &lt;br /&gt; boolean hasMask =&lt;br /&gt;   s.toString().indexOf('.') &amp;gt; -1 ||&lt;br /&gt;   s.toString().indexOf('-') &amp;gt; -1;&lt;br /&gt;&lt;br /&gt; // Remove o '.' e '-' da String&lt;br /&gt; String str = s.toString()&lt;br /&gt;   .replaceAll("[.]", "")&lt;br /&gt;   .replaceAll("[-]", "");&lt;br /&gt;&lt;br /&gt; // as variáveis before e after dizem o tamanho&lt;br /&gt; // anterior e atual da String, se after &amp;gt; before&lt;br /&gt; // é pq está apagando&lt;br /&gt; if (after &amp;gt; before) {&lt;br /&gt;   // Se tem mais de 5 caracteres (sem máscara)&lt;br /&gt;   // coloca o '.' e o '-'&lt;br /&gt;   if (str.length() &amp;gt; 5) {&lt;br /&gt;     str =&lt;br /&gt;       str.substring(0, 2) + '.' +&lt;br /&gt;       str.substring(2, 5) + '-' +&lt;br /&gt;       str.substring(5);&lt;br /&gt;&lt;br /&gt;   // Se tem mais de 2, coloca só o ponto&lt;br /&gt;   } else if (str.length() &amp;gt; 2) {&lt;br /&gt;     str =&lt;br /&gt;       str.substring(0, 2) + '.' +&lt;br /&gt;       str.substring(2);&lt;br /&gt;   }&lt;br /&gt;   // Seta a flag pra evitar chamada infinita&lt;br /&gt;   isUpdating = true;&lt;br /&gt;   // seta o novo texto&lt;br /&gt;   edt.setText(str);&lt;br /&gt;   // seta a posição do cursor&lt;br /&gt;   edt.setSelection(edt.getText().length());&lt;br /&gt;&lt;br /&gt; } else {&lt;br /&gt;   isUpdating = true;&lt;br /&gt;   edt.setText(str);&lt;br /&gt;   // Se estiver apagando posiciona o cursor&lt;br /&gt;   // no local correto. Isso trata a deleção dos&lt;br /&gt;   // caracteres da máscara.&lt;br /&gt;   edt.setSelection(&lt;br /&gt;     Math.max(0, Math.min(&lt;br /&gt;       hasMask ? start - before : start,&lt;br /&gt;       str.length() ) ) );&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;   &lt;br /&gt;@Override&lt;br /&gt;public void afterTextChanged(Editable s) {&lt;br /&gt;}&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-7781246091593995506?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3MF9Sn0uGa3kItZmVC7ZOIKMlaA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3MF9Sn0uGa3kItZmVC7ZOIKMlaA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3MF9Sn0uGa3kItZmVC7ZOIKMlaA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3MF9Sn0uGa3kItZmVC7ZOIKMlaA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/Qovu4oedYDE" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=7781246091593995506" title="1 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/7781246091593995506?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/7781246091593995506?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/Qovu4oedYDE/mascara-no-edittext-do-android.html" title="Máscara no EditText do Android" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/09/mascara-no-edittext-do-android.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMNQ3w9fCp7ImA9WhdVFk4.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-1136026179905044999</id><published>2011-09-21T11:43:00.000-07:00</published><updated>2011-09-21T12:14:52.264-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-21T12:14:52.264-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="9.png" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="Slice" /><category scheme="http://www.blogger.com/atom/ns#" term="9" /><category scheme="http://www.blogger.com/atom/ns#" term="Nine" /><category scheme="http://www.blogger.com/atom/ns#" term="Patch" /><title>Android e o formato 9-Patch</title><content type="html">&lt;div&gt;&lt;p class="MsoNormal"&gt;&lt;i&gt;&lt;span style="font-size:9.0pt;line-height:115%"&gt;Por: Manuella Nejaim &lt;a href="http://twitter.com/manux"&gt;@manux&lt;/a&gt; | Nelson Glauber &lt;a href="http://twitter.com/nglauber"&gt;@nglauber&lt;/a&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;Olá povo,&lt;/div&gt;&lt;br /&gt;Nossa experiência em projetos Android nos mostrou que não são apenas os engenheiros de sistema (ou programadores) que precisam saber do que a plataforma é capaz. Os designers também precisam conhecer as facilidades que a plataforma da Google traz.&lt;br /&gt;É bastante comum em uma interface, termos um botão que aparece em vários contextos com diferentes dimensões. Nestes casos, os designers criavam várias imagens semelhantes, diferindo apenas o tamanho. Isso fazia com que a aplicação ficasse com o tamanho maior (em bytes) e muitas vezes causando problemas de memória devido ao tamanho e quantidade de imagens utilizadas.&lt;div&gt;&lt;br /&gt;Uma técnica que foi amplamente utilizada em aplicações Java ME foi a 9-slice, devido à escassez de recursos dos aparelhos dessa plataforma. Essa abordagem divide uma imagem maior em 9 imagens menores, conforme abaixo:&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;img src="http://4.bp.blogspot.com/-qs4Y0OPKuBw/TnoxlDRnoDI/AAAAAAAAAak/P7sMvnf2rBc/s320/image001.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5654886794721206322" style="cursor: pointer; width: 70px; height: 100px; " /&gt;&lt;/div&gt;&lt;span class="Apple-style-span"&gt;&lt;div style="text-align: center;"&gt;Imagem cortada para o 9-slice&lt;/div&gt;&lt;/span&gt;&lt;div&gt;&lt;br /&gt;Essa forma é bem interessante, pois as imagens (exceto as das quatro quinas) são idealizadas de modo a serem esticadas sem perder a qualidade. Entretanto, tinha-se o inconveniente gerenciar, para cada imagem “de botão”, nove imagens.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;O Android adota uma forma similar para aperfeiçoar a utilização do 9-slice chamada de 9-patch. Essa abordagem utiliza marcações feitas na imagem, indicando a área “esticável”, assim como as margens que devem ser preservadas.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-w8osOF4d7KA/TnoyNxfg9mI/AAAAAAAAAbM/bp5v9r38izY/s1600/image004.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://4.bp.blogspot.com/-w8osOF4d7KA/TnoyNxfg9mI/AAAAAAAAAbM/bp5v9r38izY/s320/image004.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5654887494322288226" style="cursor: pointer; width: 319px; height: 258px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span"&gt;&lt;div style="text-align: center;"&gt;Indicação das áreas de marcação de uma imagem 9-patch&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;Os benefícios da utilização deste recurso são claros: diminuição da quantidade de imagens, diminuição do peso da própria imagem, otimização para o porting, flexibilidade para a interface, dentre vários outros. Além disso, representa ganho de desempenho e qualidade no produto final, beneficiando engenheiros, designers e principalmente o usuário.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;As imagens precisam ser produzidas de forma adequada para adotar esse recurso, então existe a necessidade de colaboração dos designers de interface com os engenheiros para fazer uso dessa solução. Gerar imagens para o 9patch requer um mínimo de esforço, e a inclusão de uns dois passos a mais no trabalho de layout.&lt;br /&gt;Vale à pena salientar que esta solução se aplica elementos da interface como boxes, botões e inputs que de alguma forma apresentam um padrão gráfico que pode ser distorcido na horizontal e/ou vertical.&lt;br /&gt;Para gerar a imagem “9patched”, é preciso primeiro criá-la na ferramenta gráfica (como o Photoshop) e observar dois pontos:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;O primeiro ponto é que, a imagem gerada não pode ter degradês diagonais, apenas em 90 graus.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Ig4_mj2stjA/TnoyZAODRUI/AAAAAAAAAbU/fh2izd5Yt9M/s1600/image006.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://4.bp.blogspot.com/-Ig4_mj2stjA/TnoyZAODRUI/AAAAAAAAAbU/fh2izd5Yt9M/s400/image006.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5654887687254132034" style="cursor: pointer; width: 400px; height: 279px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span"&gt;&lt;div style="text-align: center;"&gt;Degradê do botão com ângulo de 90 graus&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;&lt;br /&gt;&lt;/span&gt;O segundo ponto, é gerar a imagem do botão nas dimensões mínimas que conservem a sua aparência, conforme a imagem abaixo:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-mEp-LWIQwkE/TnoymbBajoI/AAAAAAAAAbc/Ra7fQKjRyFY/s1600/image007.gif" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://4.bp.blogspot.com/-mEp-LWIQwkE/TnoymbBajoI/AAAAAAAAAbc/Ra7fQKjRyFY/s200/image007.gif" border="0" alt="" id="BLOGGER_PHOTO_ID_5654887917787188866" style="cursor: pointer; width: 200px; height: 86px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span"&gt;&lt;div style="text-align: center;"&gt;Aparência do botão normal&lt;/div&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-q1ABmA2PXqM/Tnoyv_3Cb9I/AAAAAAAAAbk/e6OQaTurDu0/s1600/image008.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://2.bp.blogspot.com/-q1ABmA2PXqM/Tnoyv_3Cb9I/AAAAAAAAAbk/e6OQaTurDu0/s200/image008.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5654888082294599634" style="cursor: pointer; width: 27px; height: 58px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span"&gt;&lt;div style="text-align: center;"&gt;Imagem exportada do botão cortado para fazer o 9patch&lt;/div&gt;&lt;/span&gt;&lt;br /&gt;Uma vez criada a imagem, utilizaremos o draw9patch, uma ferramenta que vem com o Android SDK, onde podemos realizar as marcações para tornar uma imagem comum em uma imagem “9-patched”. Ao baixar e instalar o SDK do Android, a ferramenta encontra-se no diretório tools. Dentro dessa pasta, basta executar o arquivo draw9patch.bat (no Windows, no Linux e Mac o nome é similar). Após executar a aplicação, basta arrastar a imagem original para dentro do programa (ou carrega-la a partir do menu File).&lt;br /&gt;A imagem exportada é aberta no draw9patch e ao lado direito serão apresentadas 3 variações dela esticada na horizontal e na vertical.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-yVmCOUEz_cg/Tnoy_05m5sI/AAAAAAAAAbs/XIvo9o9OAlM/s1600/image010.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://2.bp.blogspot.com/-yVmCOUEz_cg/Tnoy_05m5sI/AAAAAAAAAbs/XIvo9o9OAlM/s400/image010.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5654888354230494914" style="cursor: pointer; width: 400px; height: 234px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span"&gt;&lt;div style="text-align: center;"&gt;Tela do draw9patch&lt;/div&gt;&lt;/span&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;A imagem ganha automaticamente uma margem externa de 1 pixel de cada lado. Nessa área é que fazemos a marcação na imagem “pintando-a” com o clique. Para remover a marcação de uma área, pressione a tecla Shift enquanto pinta.&lt;/div&gt;&lt;div&gt;A linha do topo refere-se à largura do botão, indicando os limites pra distorcer o botão horizontalmente. A margem lateral esquerda refere-se à altura do botão, onde ele esticará verticalmente. A margem inferior e direita serve para indicar o padding, ou seja, margem interna do botão, onde entra o conteúdo. E por fim, no lado direito temos o padding vertical da imagem.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Na parte inferior da tela do draw9patch encontramos as opções de zoom para a área de marcação e para o preview das distorções. Existem também botões Show lock para acionar o “travamento” da imagem em si (marcado por padrão), Show content para exibição da área de conteúdo definida pelo padding (desmarcada por padrão) e a opção Show patches que mostra os “cortes” que formam a imagem por completo (desmarcada por padrão).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Após realizar as alterações desejadas, o arquivo que será salvo terá a extensão *.9.png. e pode ser usado como imagem de background de componentes do Android como Button, EditText, etc.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;manux | nglauber&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-1136026179905044999?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/q_VxH_Em0bQ0JhRZ9cm0vEedui8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/q_VxH_Em0bQ0JhRZ9cm0vEedui8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/q_VxH_Em0bQ0JhRZ9cm0vEedui8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/q_VxH_Em0bQ0JhRZ9cm0vEedui8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/RHYt--8ZYxk" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=1136026179905044999" title="3 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/1136026179905044999?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/1136026179905044999?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/RHYt--8ZYxk/android-e-o-formato-9-patch.html" title="Android e o formato 9-Patch" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-qs4Y0OPKuBw/TnoxlDRnoDI/AAAAAAAAAak/P7sMvnf2rBc/s72-c/image001.png" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/09/android-e-o-formato-9-patch.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0IAQHY5fSp7ImA9WhdVFkQ.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-5374457857575086273</id><published>2011-09-19T10:41:00.000-07:00</published><updated>2011-09-22T05:45:41.825-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-22T05:45:41.825-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Home" /><category scheme="http://www.blogger.com/atom/ns#" term="View" /><category scheme="http://www.blogger.com/atom/ns#" term="Page" /><category scheme="http://www.blogger.com/atom/ns#" term="Horizontal" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="Scroll" /><title>PageScroll</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Certo dia, assisti uma apresentação de Silvio Meira em que ele falou que nós, como desenvolvedores, tínhamos sempre que olhar para uma aplicação e pensar: "como esses caras [desenvolvedores] fizeram isso?". Às vezes, utilizamos a aplicação sem notarmos coisas simples que poderíamos incorporar aos nossos próprios aplicativos (cuidado com as patentes :p).&lt;br /&gt;&lt;br /&gt;Pois bem. Eu achei interessante na aplicação do TweetDeck, a forma com que ele alternava entre a Timeline e as Mentions, apenas rolando da tela na horizontal. Similar ao que é feito na home screen do próprio Android para alternar entre os "desktops".&lt;br /&gt;&lt;br /&gt;Achava que o Android já tivesse um componente para fazer isso, mas não achei. Tentei fazer com um Gallery, mas o resultado não ficou legal. Finalmente, achei um componente chamado HorizontalPager, disponível em &lt;a href="http://code.google.com/p/deezapps-widgets/"&gt;http://code.google.com/p/deezapps-widgets/&lt;/a&gt;. Distribuído sobre licença Apache, ele realiza o comportamento que eu queria e pode ser incorporado ao seu projeto sem culpa :)&lt;br /&gt;&lt;br /&gt;Disponibilizei um projeto que utiliza "esse carinha" &lt;a href="https://sites.google.com/site/nglaubervasc/TestePageScroll.zip"&gt;neste link&lt;/a&gt;. E Abaixo temos um screenshot do mesmo.&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 192px; height: 320px;" src="http://1.bp.blogspot.com/-Z3i7kL3bQlM/TneGhJETAqI/AAAAAAAAAac/x3hKyggzvlY/s320/device-2011-09-19-150419.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5654135761114694306" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;EDITADO&lt;/b&gt;&lt;br /&gt;Depois de publicar esse post, recebi a dica de &lt;a href="http://twitter.com/acvilarim"&gt;@acvilarim&lt;/a&gt; que existe uma outra forma de obter esse mesmo comportamento com a API do próprio Android: utilizando as classes ViewPager e PagerAdapter. Entretanto essas classes estão em uma biblioteca separada que provê compatibilidade da versão 1.6 em diante com o Honeycomb (3.x). Para instalá-la, você pode seguir esse tutorial &lt;a href="http://developer.android.com/sdk/compatibility-library.html"&gt;aqui&lt;/a&gt;. &lt;div&gt;Meu colega &lt;a href="http://twitter.com/malvesinfo"&gt;Marcelo Alves&lt;/a&gt; me indicou &lt;a href="http://android-developers.blogspot.com/2011/08/horizontal-view-swiping-with-viewpager.html"&gt;esse artigo&lt;/a&gt; para começar a mexer com o ViewPager e o PagerAdapter. De qualquer forma, postei &lt;a href="https://sites.google.com/site/nglaubervasc/ViewSwinpping.zip"&gt;aqui&lt;/a&gt; um exemplo que fiz idêntico ao anterior, mas usando essa API.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-5374457857575086273?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Z8WoTQRiESqeF8g-zNskAtq08o8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z8WoTQRiESqeF8g-zNskAtq08o8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Z8WoTQRiESqeF8g-zNskAtq08o8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z8WoTQRiESqeF8g-zNskAtq08o8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/XP5TsqF8NpQ" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=5374457857575086273" title="5 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/5374457857575086273?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/5374457857575086273?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/XP5TsqF8NpQ/pagescroll.html" title="PageScroll" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-Z3i7kL3bQlM/TneGhJETAqI/AAAAAAAAAac/x3hKyggzvlY/s72-c/device-2011-09-19-150419.png" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/09/pagescroll.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUGSHg_fyp7ImA9WhdWF0w.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-7220592565732818698</id><published>2011-09-08T05:53:00.000-07:00</published><updated>2011-09-10T21:10:29.647-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-10T21:10:29.647-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Tutorial" /><category scheme="http://www.blogger.com/atom/ns#" term="OAuth" /><category scheme="http://www.blogger.com/atom/ns#" term="API" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="Twitter" /><category scheme="http://www.blogger.com/atom/ns#" term="Twitter4J" /><category scheme="http://www.blogger.com/atom/ns#" term="Exemplo" /><title>Twitter API no Android</title><content type="html">Olá povo,&lt;br /&gt;&lt;br /&gt;Nunca me interessei em testar APIs para redes sociais por dois motivos: não gosto muito dessa febre; e pensava que era bem trivial ao ponto de ter milhões de tutoriais por aí. Grande engano. Quando fui adicionar suporte ao Twitter em uma aplicação que estou trabalhando, notei que existem algumas etapas 'chatinhas' para realizar essa integração. Não sei se a forma que estou utilizando aqui é a melhor, inclusive, se vocês tiverem sugestões, deixem seus comentários :)&lt;br /&gt;&lt;br /&gt;Sem mais "delongas", vamos começar! Nesse post, vou mostrar como realizar o processo de autenticação no Twitter e 'twitar' uma mensagem. Para começar, obviamente você deve ter uma conta comum no Twitter. Para ter acesso aos recursos da API, você (como desenvolvedor) deverá cadastrar sua aplicação no site &lt;b&gt;https://dev.twitter.com&lt;/b&gt;. Esse cadastro servirá para a equipe do Twitter saber qual aplicação (e consequentemente o login) responsável pelo cliente que está acessando o Twitter. Isso é similar ao que é feito quando utilizamos a API de Mapas do Google, onde você deve usar sua conta do Google para obter uma chave, para então utilizar o serviço.&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 261px; height: 400px;" src="http://2.bp.blogspot.com/-w8Im2e6Xnmk/TmjmWZc-b2I/AAAAAAAAAYw/J34O501VFr4/s400/Screen%2Bshot%2B2011-09-08%2Bat%2B12.57.04%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5650019005000216418" /&gt;&lt;br /&gt;&lt;br /&gt;O cadastro é bem simples, basta informar: o nome da aplicação, descrição da mesma, URL para contato e uma URL de callback. Este último é mais importante para aplicações web, onde após efetuar o login, a chave de acesso será direcionada.&lt;br /&gt;Uma vez cadastrada, serão geradas alguma informações que serão utilizadas para integração da nossa aplicação com o Twitter. Nós precisaremos da "Consumer Key" e "Consumer Secret".&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Como funciona a autenticação no Twitter?&lt;/b&gt;&lt;br /&gt;Até meados do segundo semestre de 2010, o acesso ao twitter funcionava basicamente passando o login e a senha em texto plano. Por motivos óbvios de segurança, essa forma foi descontinuada, e passou-se a utilizar a forma de autenticação &lt;b&gt;OAuth&lt;/b&gt;. Esse processo é ilustrado na figura abaixo:&lt;br /&gt;&lt;a href="https://dev.twitter.com/sites/default/files/images_documentation/oauth_diagram.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 824px; height: 548px;" src="https://dev.twitter.com/sites/default/files/images_documentation/oauth_diagram.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;Não vou entrar em muitos detalhes sobre esse protocolo, mas basicamente o cliente envia um solicitação de acesso utilizando a consumerKey e consumerSecret para o servidor, o servidor então retorna uma URL para que o usuário se autentique. Nesse momento o usuário insere seu usuário e senha do Twitter. Uma vez passadas essas informações, o servidor valida esses dados e gera um token de acesso, que será usada para toda a comunicação com o Twitter. Esse tone deve ser salvo no cliente para que ele possa se comunicar com o servidor sem ter passar o login e a senha a cada transacção. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Mãos à obra!&lt;/b&gt;&lt;br /&gt;De posse do conceito sobre a autenticação do Twitter, vamos implementar nosso exemplo. Ele constará de apenas uma tela, onde o usuário poderá fazer o login/logout no Twitter e atualizar o seu status a partir da mesma. A tela da aplicação é exibida abaixo:&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 267px; height: 400px;" src="http://2.bp.blogspot.com/-KHcmmjzUJlo/TmkGkkak1AI/AAAAAAAAAZY/0cI64scHE1s/s400/device-2011-09-08-151603.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5650054432833197058" /&gt;&lt;br /&gt;&lt;br /&gt;Você pode implementar a comunicação com o Twitter do zero, utilizando JSON. Mas existem algumas APIs prontas que facilitam nosso trabalho. A que utilizarei aqui é a &lt;a href="http://twitter4j.org"&gt;Twitter4J&lt;/a&gt;. Baixe a última versão estável, descompacte em algum local do seu HD. Crie um novo projeto Android, e copie o arquivo twitter4j-core-android-X.X.X.jar que está na pasta lib do Twitter4J para a pasta lib do seu projeto Android (essa pasta não é criada por padrão, então crie na raiz do seu projeto). Em seguida, adicione esse JAR no Build-Path do Eclipe clicando com o botão direito sobre o arquivo, e depois selecionando Build Path &amp;gt; Add to Build path. Seu projeto deve ficar como na figura abaixo.&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 255px; height: 258px;" src="http://2.bp.blogspot.com/-MqN2XKqDpxM/TmjsKfLOlGI/AAAAAAAAAZA/dFXpy0GOuTs/s400/Screen%2Bshot%2B2011-09-08%2Bat%2B1.23.09%2BPM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5650025397447726178" /&gt;&lt;br /&gt;&lt;br /&gt;Vamos ao código :) Vou começar pelo AndroidManifest.xml&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;manifest&lt;br /&gt;xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt;package="ngvl.android.twitter"&lt;br /&gt;android:versionCode="1"&lt;br /&gt;android:versionName="1.0"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;uses-sdk android:minSdkVersion="10" /&amp;gt;&lt;br /&gt; &lt;br /&gt;&amp;lt;uses-permission android:name="android.permission.INTERNET"/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;application&lt;br /&gt; android:icon="@drawable/icon"&lt;br /&gt; android:label="@string/app_name"&amp;gt;&lt;br /&gt; &amp;lt;activity&lt;br /&gt;   android:name=".ExemploTwitterActivity"&lt;br /&gt;   android:label="@string/app_name"&lt;br /&gt;   android:noHistory="true"&amp;gt;&lt;br /&gt;   &amp;lt;intent-filter&amp;gt;&lt;br /&gt;     &amp;lt;action &lt;br /&gt;      android:name="android.intent.action.MAIN"/&amp;gt;&lt;br /&gt;     &amp;lt;category &lt;br /&gt;       android:name="android.intent.category.LAUNCHER"/&amp;gt;&lt;br /&gt;   &amp;lt;/intent-filter&amp;gt;&lt;br /&gt;   &amp;lt;intent-filter&amp;gt;&lt;br /&gt;    &amp;lt;action &lt;br /&gt;      android:name="android.intent.action.VIEW"/&amp;gt;&lt;br /&gt;     &amp;lt;category &lt;br /&gt;       android:name="android.intent.category.DEFAULT"/&amp;gt;&lt;br /&gt;     &amp;lt;category &lt;br /&gt;       android:name="android.intent.category.BROWSABLE"/&amp;gt;&lt;br /&gt;     &amp;lt;data android:scheme="nglauber-android"/&amp;gt;&lt;br /&gt;   &amp;lt;/intent-filter&amp;gt;&lt;br /&gt; &amp;lt;/activity&amp;gt;&lt;br /&gt;&amp;lt;/application&amp;gt;&lt;br /&gt;&amp;lt;/manifest&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Aqui nesse arquivo temos algumas coisas muito importantes:&lt;br /&gt;- A tag &lt;i&gt;uses-permission&lt;/i&gt; para nossa aplicação poder acessar internet;&lt;br /&gt;- Foi adicionada a propriedade &lt;i&gt;andróide:noHistory&lt;/i&gt; à tag activity, para que quando o Browser seja aberto para o usuário fazer o login, ao voltar, ele não crie outra instância dessa activity.&lt;br /&gt;- Essa activity tem dois intent-filter. O primeiro é pra execução normal da aplicação e o segundo é usado pela página do Twitter. Após a autenticação, ele redirecionará para o endereço &lt;i&gt;nglauber-android://?oauthverifier=sua_chave&lt;/i&gt;. Estamos informando que essa atividade trata esse "protocolo", dessa forma nossa activity será re-executada.&lt;br /&gt;&lt;br /&gt;Agora vamos ver o código da Activity.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package ngvl.android.twitter;&lt;br /&gt;&lt;br /&gt;import twitter4j.Twitter;&lt;br /&gt;import twitter4j.TwitterException;&lt;br /&gt;import twitter4j.TwitterFactory;&lt;br /&gt;import twitter4j.auth.AccessToken;&lt;br /&gt;import twitter4j.auth.RequestToken;&lt;br /&gt;import android.app.Activity;&lt;br /&gt;import android.content.Intent;&lt;br /&gt;import android.content.SharedPreferences;&lt;br /&gt;import android.net.Uri;&lt;br /&gt;import android.os.Bundle;&lt;br /&gt;import android.preference.PreferenceManager;&lt;br /&gt;import android.util.Log;&lt;br /&gt;import android.view.View;&lt;br /&gt;import android.widget.EditText;&lt;br /&gt;import android.widget.Toast;&lt;br /&gt;&lt;br /&gt;public class ExemploTwitterActivity extends Activity {&lt;br /&gt;&lt;br /&gt;  private final String &lt;br /&gt;    consumerKey = "SUA CONSUMER KEY";&lt;br /&gt;  private final String &lt;br /&gt;    consumerSecret = "SUA CONSUMER SECRET";&lt;br /&gt;  private final String &lt;br /&gt;    CALLBACKURL = "nglauber-android:///";&lt;br /&gt;&lt;br /&gt;  private Twitter twitter;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No código acima, as constantes cosumerKey e consumerSecret devem ser preenchidas com as informações do cadastro da sua aplicação no site do Twitter. Já a constante CALLBACKURL deve estar igual a que foi declarada no AndroidManifest.xml.&lt;br /&gt;O atributo  twitter proverá acesso ao processo de login e de atualização do status.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;@Override&lt;br /&gt;public void onCreate(Bundle savedInstanceState) {&lt;br /&gt;  super.onCreate(savedInstanceState);&lt;br /&gt;  setContentView(R.layout.main);&lt;br /&gt;  &lt;br /&gt;  twitter = new TwitterFactory().getInstance();&lt;br /&gt;  twitter.setOAuthConsumer(&lt;br /&gt;    consumerKey, consumerSecret);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No onCreate apenas inicializamos o layout da tela, obtemos a instância do Twitter através da classe TwitterFactory e setamos a consumer key e secret.&lt;br /&gt;&lt;pre name="code" class="java"&gt; public void clickLogin(View v) {&lt;br /&gt;  try {&lt;br /&gt;    AccessToken accessToken = loadAccessToken();&lt;br /&gt;    if (accessToken == null) {&lt;br /&gt;      twitter = new TwitterFactory().getInstance();&lt;br /&gt;      twitter.setOAuthConsumer(&lt;br /&gt;        consumerKey, consumerSecret);&lt;br /&gt;    &lt;br /&gt;      RequestToken requestToken = &lt;br /&gt;        twitter.getOAuthRequestToken(CALLBACKURL);&lt;br /&gt; &lt;br /&gt;      String url = requestToken.getAuthenticationURL();&lt;br /&gt;      Intent it = new Intent(&lt;br /&gt;        Intent.ACTION_VIEW, Uri.parse(url));&lt;br /&gt;      it.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);&lt;br /&gt;      startActivity(it);&lt;br /&gt;    &lt;br /&gt;      saveRequestData(requestToken.getToken(), &lt;br /&gt;        requestToken.getTokenSecret());&lt;br /&gt;   &lt;br /&gt;    } else {&lt;br /&gt;      twitter.setOAuthAccessToken(accessToken);&lt;br /&gt;    }&lt;br /&gt;  } catch (Exception e) {&lt;br /&gt;    e.printStackTrace();&lt;br /&gt;    showToast(e.getMessage());&lt;br /&gt;  }&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;O método acima, iniciará o processo de login e será chamado ao clicar no botão de login. Através do método loadAccessToken (definido mais adiante), ele tenta obter um objeto AccessToken salvo anteriormente. Caso não exista, o processo de login inicia com a obtenção da url para fazermos o login no Twitter. Notem que é passada a constante CALLBACKURL como parâmetro, isso indica qual endereço será chamado quando o login for concluído. Essa é uma URL "fake" que será chamada quando o login for efetuado. Neste momento, o browser redireciona a chave para &lt;i&gt;nglauber-android://?oauthverifier=sua_chave&lt;/i&gt;, e o "protocolo" nglauber-android está sendo tratado por nossa atividade, como definido no AndroidManifest.xml.&lt;br /&gt;A flag FLAG_ACTIVITY_NO_HISTORY evita que, ao pressionar back após o login, o browser seja exibido novamente. Após chamar o browser para o login, o token e o token secret da requisição são salvos pelo método saveRequestData (veremos esse método mais adiante).&lt;br /&gt;&lt;br /&gt;Ao clicar no botão de login, será exibida a tela de autenticação do Twitter. Aqui é solicitado autorização para que a aplicação que cadastramos no começo desse post tenha acesso a sua conta do Twitter. Digite seu login e senha e clique em "Sign In".&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 267px; height: 400px;" src="http://2.bp.blogspot.com/-7ZV0tV7PY2k/TmkBOFkKE1I/AAAAAAAAAZQ/aDNxFUZyHSI/s400/device-2011-09-08-145341.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5650048549036626770" /&gt;&lt;br /&gt;&lt;br /&gt;Após realizar o login, a página do Twitter envia a chave para nossa Activity. Tratamos o recebimento dessa chave no método onResume conforme abaixo:&lt;br /&gt;&lt;pre name="code" class="java"&gt; @Override&lt;br /&gt;protected void onResume() {&lt;br /&gt;  super.onResume();&lt;br /&gt;  &lt;br /&gt;  Uri uri = getIntent().getData();&lt;br /&gt;  if (uri != null) {&lt;br /&gt;    String oauthVerifier = &lt;br /&gt;      uri.getQueryParameter("oauth_verifier");&lt;br /&gt; &lt;br /&gt;    try {&lt;br /&gt;      RequestToken requestToken = loadRequestToken();&lt;br /&gt;      AccessToken at = twitter.getOAuthAccessToken(&lt;br /&gt;        requestToken, oauthVerifier);&lt;br /&gt;&lt;br /&gt;      saveAccessToken(&lt;br /&gt;        at.getToken(), at.getTokenSecret());&lt;br /&gt;&lt;br /&gt;    } catch (TwitterException e) {&lt;br /&gt;      e.printStackTrace();&lt;br /&gt;      showToast(e.getMessage());&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Quando a atividade é chamada pela página do twitter, uma chave de verificação da requisição de acesso é retornada. Com a requisição e a chave de verificação podemos criar um objeto AccessToken para acessar os recursos do Twitter. O token e o token secret do objeto AccessToken são salvos no método saveAccessToken (definido mais adiante) e, como vimos anteriormente podem ser recuperados quando clicamos no botão de login.&lt;br /&gt;&lt;br /&gt;Abaixo temos o método que é chamado ao clicar no botão Tweet.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public void clickTweet(View v) {&lt;br /&gt;  try {&lt;br /&gt;    if (loadAccessToken() != null){&lt;br /&gt;      EditText edt = &lt;br /&gt;        (EditText) findViewById(R.id.editText1);&lt;br /&gt;      String tweet = edt.getText().toString();&lt;br /&gt;&lt;br /&gt;      twitter.updateStatus(tweet);&lt;br /&gt;      showToast("Status atualizado com sucesso!");&lt;br /&gt;&lt;br /&gt;    } else {&lt;br /&gt;      showToast("Faça o login antes de Twittar");&lt;br /&gt;    }&lt;br /&gt;  } catch (TwitterException e) {&lt;br /&gt;      e.printStackTrace();&lt;br /&gt;      showToast(e.getMessage());&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Nada de mais aqui. Apenas pega o conteúdo da caixa de texto e manda alterar o status do objeto Twitter.&lt;br /&gt;&lt;br /&gt;Abaixo temos método auxiliares que utilizamos no nosso código. O primeiro exibe um Toast na tela.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;private void showToast(String s){&lt;br /&gt;  Toast.makeText(this, s, Toast.LENGTH_LONG).show();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Os métodos que salvam e recuperam as chaves de solicitação (RequestToken) e de acesso (AccessToken) estão definidos abaixo. Para ambos são utilizados SharedPreferences.&lt;br /&gt;&lt;pre name="code" class="java"&gt; &lt;br /&gt;private RequestToken loadRequestToken(){&lt;br /&gt;  SharedPreferences prefs = PreferenceManager.&lt;br /&gt;    getDefaultSharedPreferences(this);&lt;br /&gt;  String reqToken = &lt;br /&gt;    prefs.getString("request_token", null);&lt;br /&gt;  String reqTokenSecret = &lt;br /&gt;    prefs.getString("request_tokensecret", null);&lt;br /&gt;  &lt;br /&gt;  return new RequestToken(reqToken, reqTokenSecret);&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;private void saveRequestData(&lt;br /&gt;  String requestToken, String requestTokenSecret){&lt;br /&gt;&lt;br /&gt;  SharedPreferences prefs = PreferenceManager.&lt;br /&gt;    getDefaultSharedPreferences(this);&lt;br /&gt;  SharedPreferences.Editor editor = prefs.edit();&lt;br /&gt;&lt;br /&gt;  editor.putString(&lt;br /&gt;    "request_token", requestToken);&lt;br /&gt;  editor.putString(&lt;br /&gt;    "request_tokensecret", requestTokenSecret);&lt;br /&gt;&lt;br /&gt;  editor.commit();  &lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;private AccessToken loadAccessToken() {&lt;br /&gt;  SharedPreferences prefs = PreferenceManager.&lt;br /&gt;    getDefaultSharedPreferences(this);&lt;br /&gt;  String acToken = &lt;br /&gt;    prefs.getString("access_token", null);&lt;br /&gt;  String acTokenSecret = &lt;br /&gt;    prefs.getString("access_tokensecret", null);&lt;br /&gt;&lt;br /&gt;  if (acToken != null || acTokenSecret != null){&lt;br /&gt;    return new AccessToken(acToken, acTokenSecret);&lt;br /&gt;  }&lt;br /&gt;  return null;&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;private void saveAccessToken(&lt;br /&gt;  String accessToken, String accessTokenSecret) {&lt;br /&gt;&lt;br /&gt;  SharedPreferences prefs =&lt;br /&gt;    PreferenceManager.getDefaultSharedPreferences(this);&lt;br /&gt;&lt;br /&gt;  SharedPreferences.Editor editor = prefs.edit();&lt;br /&gt;&lt;br /&gt;  editor.putString(&lt;br /&gt;    "access_token", accessToken);&lt;br /&gt;  editor.putString(&lt;br /&gt;    "access_tokensecret", accessTokenSecret);&lt;br /&gt;&lt;br /&gt;  editor.commit();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Por fim, o método que faz o logout, limpa os valores da sharedpreference de AccessToken, o que vai forçar a realização de um novo login.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public void clickLogout(View v) {&lt;br /&gt;  saveAccessToken(null, null);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É isso pessoal, qualquer dúvida, deixem seus comentários.&lt;br /&gt;&lt;br /&gt;4br4ç05,&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-7220592565732818698?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/x-TPKqZ-GydkzE-uxzDlgH7gGgY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/x-TPKqZ-GydkzE-uxzDlgH7gGgY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/x-TPKqZ-GydkzE-uxzDlgH7gGgY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/x-TPKqZ-GydkzE-uxzDlgH7gGgY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/-Wam-lHh0CA" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=7220592565732818698" title="5 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/7220592565732818698?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/7220592565732818698?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/-Wam-lHh0CA/twitter-api-no-android.html" title="Twitter API no Android" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-w8Im2e6Xnmk/TmjmWZc-b2I/AAAAAAAAAYw/J34O501VFr4/s72-c/Screen%2Bshot%2B2011-09-08%2Bat%2B12.57.04%2BPM.png" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/09/twitter-api-no-android.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYDRXozfip7ImA9WhdXGUU.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-4954092543725279725</id><published>2011-09-02T10:05:00.000-07:00</published><updated>2011-09-02T10:06:14.486-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-02T10:06:14.486-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="espaço" /><category scheme="http://www.blogger.com/atom/ns#" term="Maps" /><category scheme="http://www.blogger.com/atom/ns#" term="TabWidget" /><category scheme="http://www.blogger.com/atom/ns#" term="ListView" /><category scheme="http://www.blogger.com/atom/ns#" term="Teclado Virtual" /><category scheme="http://www.blogger.com/atom/ns#" term="GPS" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="Google" /><category scheme="http://www.blogger.com/atom/ns#" term="Dicas" /><category scheme="http://www.blogger.com/atom/ns#" term="SDcard" /><category scheme="http://www.blogger.com/atom/ns#" term="Habilitar" /><title>Android: Dicas 4</title><content type="html">Olá povo,
&lt;br /&gt;
&lt;br /&gt;Segue mais um POST da série "dicas de Android".
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;Dica 1 - Obter o espaço disponível no aparelho&lt;/b&gt;
&lt;br /&gt;&lt;pre name="code" class="java"&gt;
&lt;br /&gt;File path = Environment.getDataDirectory();
&lt;br /&gt;StatFs stat = new StatFs(path.getPath());
&lt;br /&gt;long blockSize = stat.getBlockSize();
&lt;br /&gt;long availableBlocks = stat.getAvailableBlocks();
&lt;br /&gt;long ocupedBlocks = 
&lt;br /&gt;  stat.getBlockCount() - availableBlocks;
&lt;br /&gt;
&lt;br /&gt;String s1 = Formatter.formatFileSize(
&lt;br /&gt;  this, availableBlocks * blockSize);
&lt;br /&gt;String s2 = Formatter.formatFileSize(
&lt;br /&gt;  this, ocupedBlocks * blockSize);
&lt;br /&gt;System.out.println("---------------");
&lt;br /&gt;System.out.println("s = "+ s1);
&lt;br /&gt;System.out.println("s = "+ s2);
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;b&gt;Dica 2 - Teclado Virtual Sobre o Layout&lt;/b&gt;
&lt;br /&gt;Ao exibir o teclado virtual, o Android automaticamente redimensiona a tela do aparelho para exibir todos os elementos. Então se você tiver, por exemplo uma barra com botões na parte inferior, eles irão aparecer imediatamente em cima do teclado virtual. Para evitar isso, basta colocar a seguinte configuração na declaração da sua Activity no AndroidManifest.xml.
&lt;br /&gt;&lt;pre name="code" class="xml"&gt;
&lt;br /&gt;&amp;lt;activity
&lt;br /&gt;  android:name=".ui.MainActivity"
&lt;br /&gt;  android:windowSoftInputMode="adjustPan"
&lt;br /&gt;/&amp;gt;
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;b&gt;Dica 3 - Evitando abrir a mesma atividade 2 vezes&lt;/b&gt;
&lt;br /&gt;Os engenheiros de teste com frequência tentam "destruir" a aplicação de algum jeito :) E um bem comum é clicar rapidamente em um botão. Se esse botão chamar uma Activity serão abertas duas em sequência. Para evitar isso, basta colocar a seguinte configuração na declaração da sua Activity no AndroidManifest.xml.
&lt;br /&gt;
&lt;br /&gt;&lt;pre name="code" class="xml"&gt;
&lt;br /&gt;&amp;lt;activity
&lt;br /&gt;  android:name=".ui.MainActivity"
&lt;br /&gt;  android:launchMode="singleTop"
&lt;br /&gt;/&amp;gt;
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;Isso faz com que só seja possível apenas uma instância no topo da pilha de atividades.
&lt;br /&gt;
&lt;br /&gt;&lt;b&gt;Dica 4 - Alterando a linha abaixo da TabWidget&lt;/b&gt;
&lt;br /&gt;Essa dica é um complemento da dica sobre como mudar a imagem das abas da TabWidget. O código abaixo mostra como mudar a linha que fica na parte inferior da TabWidget. Ela tem um aspecto interessante, pois a API só disponibilizou um método "digno" pra isso a partir do Android 2.2, para as versões anteriores, essa operação tem que ser feita via Reflection.
&lt;br /&gt;
&lt;br /&gt;&lt;pre name="code" class="java"&gt;
&lt;br /&gt;// Esse código deve ser chamado dentro de 
&lt;br /&gt;// uma TabActivity
&lt;br /&gt;TabWidget tabWidget = getTabWidget();
&lt;br /&gt;
&lt;br /&gt;if (android.os.Build.VERSION.SDK_INT &amp;gt;= 
&lt;br /&gt;  android.os.Build.VERSION_CODES.FROYO){
&lt;br /&gt;  // For Android 2.2
&lt;br /&gt;  tabWidget.setLeftStripDrawable(
&lt;br /&gt;    R.drawable.barra_menu);
&lt;br /&gt;  tabWidget.setRightStripDrawable(
&lt;br /&gt;    R.drawable.barra_menu);
&lt;br /&gt;} else {
&lt;br /&gt;  // For Android 2.1 or before
&lt;br /&gt;  try {
&lt;br /&gt;    Field stripLeft = tabWidget.getClass().
&lt;br /&gt;      getDeclaredField("mBottomLeftStrip");
&lt;br /&gt;    Field stripRight = tabWidget.getClass().
&lt;br /&gt;      getDeclaredField("mBottomRightStrip");
&lt;br /&gt;
&lt;br /&gt;    if (!stripLeft.isAccessible())
&lt;br /&gt;      stripLeft.setAccessible(true);
&lt;br /&gt;    if (!stripRight.isAccessible())
&lt;br /&gt;      stripRight.setAccessible(true);
&lt;br /&gt;
&lt;br /&gt;    stripLeft.set(tabWidget, 
&lt;br /&gt;      getResources().getDrawable(
&lt;br /&gt;        R.drawable.barra_menu));
&lt;br /&gt;
&lt;br /&gt;    stripRight.set(tabWidget,
&lt;br /&gt;      getResources().getDrawable(
&lt;br /&gt;        R.drawable.barra_menu));
&lt;br /&gt;
&lt;br /&gt;  } catch (Exception e) {
&lt;br /&gt;    e.printStackTrace();
&lt;br /&gt;  }			    
&lt;br /&gt;}	
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;Nesse exemplo, estou usando a API level 8 (Android 2.2) no Eclipse para poder ter acesso aos métodos setLeftStripDrawable e setRightStripDrawable. Porém ele pode ser executado em aparelhos 2.1, que neste caso executará o código via Reflection. Para dar suporte a API 2.1, mesmo desenvolvendo com a 2.2 basta colocar a tag abaixo no AndroidManifest.xml.
&lt;br /&gt;&lt;pre name="code" class="xml"&gt;
&lt;br /&gt;&amp;lt;uses-sdk android:minSdkVersion="7" /&amp;gt;
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;b&gt;Dica 5 - Salvar estado do scroll da ListView&lt;/b&gt;
&lt;br /&gt;Na aplicação que estou desenvolvendo, sempre estava reatribuindo o Adapter à ListView no onResume da Activity. O problema era que eu clicava em um item da lista lá do final pra edita-lo era aberta a tela pra edição. Quando fechava essa tela, aí abria a tela de detalhes, mas quando voltava pra tela de listagem queria manter a posição do scroll.
&lt;br /&gt;
&lt;br /&gt;&lt;pre name="code" class="java"&gt;
&lt;br /&gt;// savedIndex e savedY é um atributo int
&lt;br /&gt;
&lt;br /&gt;// Salvar estado
&lt;br /&gt;// Esse código coloquei no onPause
&lt;br /&gt;savedIndex = getListView().getFirstVisiblePosition();
&lt;br /&gt;View v1 = getListView().getChildAt(0);
&lt;br /&gt;savedY = (v1 == null) ? 0 : v1.getTop();
&lt;br /&gt;
&lt;br /&gt;// Restaurando estado
&lt;br /&gt;// Esse código eu coloquei no onResume
&lt;br /&gt;setListAdapter(novoAdapter);
&lt;br /&gt;getListView().setSelectionFromTop(savedIndex, savedY);
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;b&gt;Dica 6 - Checar se o GPS está habilitado&lt;/b&gt;
&lt;br /&gt;Existe basicamente duas formas de obter a posição geográfica no Android: por GPS e pela Rede de Dados. Essa configuração fica no menu Configurações &gt; Local &gt; Meu Local. Se sua aplicação usa geolocalização, você deve checar se uma dessas opções está habilitada.
&lt;br /&gt;&lt;pre name="code" class="java"&gt;
&lt;br /&gt;public boolean isEnabled() {
&lt;br /&gt;  LocationManager lm = (LocationManager)
&lt;br /&gt;    context.getSystemService(
&lt;br /&gt;      Context.LOCATION_SERVICE);
&lt;br /&gt;
&lt;br /&gt;  return 
&lt;br /&gt;    locationManager.isProviderEnabled(
&lt;br /&gt;      LocationManager.GPS_PROVIDER) ||    
&lt;br /&gt;    locationManager.isProviderEnabled(
&lt;br /&gt;      LocationManager.NETWORK_PROVIDER);
&lt;br /&gt;}
&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;Dica 7 - Problema no GoogleMaps &lt;/b&gt;
&lt;br /&gt;Essa dica foi mandada pelo meu aluno da LinuxFI, Sávio (Sávio saviojp@gmail.com).
&lt;br /&gt;Durante a aula de Mapas eu passei pelo seguinte problema: Mesmo com todas as configurações da API Key e permissões definidas de modo correto, o meu emulador não carregava o mapa. Para solucionar esse problema fiz o seguinte:
&lt;br /&gt;
&lt;br /&gt;Customizei a execução da aplicação no eclipse por meio do Run Configurations/Android Application /na aba Target no campo Additional Emulator Command Line Options, setei o comando: -dns-server 8.8.8.8.
&lt;br /&gt;
&lt;br /&gt;4br4ç05,
&lt;br /&gt;nglauber&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-4954092543725279725?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HCi7gCS36esLe4sC7tpZFADOr3c/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HCi7gCS36esLe4sC7tpZFADOr3c/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HCi7gCS36esLe4sC7tpZFADOr3c/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HCi7gCS36esLe4sC7tpZFADOr3c/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/z7o5KgEGFUA" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=4954092543725279725" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/4954092543725279725?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/4954092543725279725?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/z7o5KgEGFUA/android-dicas-4.html" title="Android: Dicas 4" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/09/android-dicas-4.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkEDQHw4eSp7ImA9WhdXFk8.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-7848881738259194605</id><published>2011-08-29T06:21:00.000-07:00</published><updated>2011-08-29T07:37:51.231-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-29T07:37:51.231-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PreferenceActivity" /><category scheme="http://www.blogger.com/atom/ns#" term="SharedPreferences" /><category scheme="http://www.blogger.com/atom/ns#" term="PreferenceScreen" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="Configurações" /><title>Armazenando configurações no Android</title><content type="html">Olá povo,
&lt;br /&gt;
&lt;br /&gt;É muito comum armazenar configurações simples das nossas aplicações para que o usuário não tenha que setá-las toda vez que abrir o programa. No Android, podemos fazer isso através da interface SharedPreferences, com ela podemos salvar grupos de configurações para recuperá-las posteriormente.
&lt;br /&gt;
&lt;br /&gt;&lt;pre name="code" class="java"&gt;// Obtém a instância da SharedPreference
&lt;br /&gt;SharedPreferences prefs =
&lt;br /&gt;PreferenceManager.getDefaultSharedPreferences(this);
&lt;br /&gt;
&lt;br /&gt;// Salva dois valores nas preferências
&lt;br /&gt;SharedPreferences.Editor editor = prefs.edit();
&lt;br /&gt;editor.putString("operadora", "Claro");
&lt;br /&gt;editor.putBoolean("som", false);
&lt;br /&gt;editor.commit();
&lt;br /&gt;
&lt;br /&gt;// Recupera os valores
&lt;br /&gt;String op = prefs.getString("operadora", null);
&lt;br /&gt;boolean som = prefs.getBoolean("som", false);
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;Ao salvar esses valores eles serão armazenados na pasta /data/data/pacote.da.sua.app/shared_prefs. O valores "Claro" e false serão armazenados para as configurações "operadora" e "som" respectivamente, e estarão lá mesmo que o usuário feche a aplicação. Eles só são apagados através do menu Configurações&amp;gt; Aplicações &amp;gt; Gerencias Aplicações &amp;gt; [Sua app] &amp;gt; Limpar dados.
&lt;br /&gt;
&lt;br /&gt;Mas se eu quiser criar uma tela de configurações? O Android já tem uma API para facilitar (e padronizar) a criação de telas para esse propósito. Podemos defini-la como abaixo:
&lt;br /&gt;
&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;PreferenceScreen
&lt;br /&gt;xmlns:android="http://schemas.android.com/apk/res/android"
&lt;br /&gt;&amp;lt;CheckBoxPreference
&lt;br /&gt;  android:summaryOff="Som desabilitado"
&lt;br /&gt;  android:key="som"
&lt;br /&gt;  android:summaryOn="Som habilitado"
&lt;br /&gt;  android:title="Som" /&amp;gt;
&lt;br /&gt;&amp;lt;EditTextPreference
&lt;br /&gt;  android:key="operadora"
&lt;br /&gt;  android:dialogTitle="Operadora"
&lt;br /&gt;  android:dialogMessage="Digite o nome da operadora"
&lt;br /&gt;  android:title="Operadora" /&amp;gt;
&lt;br /&gt;&amp;lt;/PreferenceScreen&amp;gt;
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;Eu nomeei esse arquivo como tela_config.xml e salvei em res/xml. Notem que os atibutos android:key são iguais aos que foram especificados no código Java anterior. Para carregar esse arquivo, devemos ter uma classe que herda de PreferenceActivity como a seguir.
&lt;br /&gt;
&lt;br /&gt;&lt;pre name="code" class="java"&gt;public class PreferenciasActivity
&lt;br /&gt;extends PreferenceActivity {
&lt;br /&gt;
&lt;br /&gt;@Override
&lt;br /&gt;protected void onCreate(Bundle savedInstanceState) {
&lt;br /&gt;  super.onCreate(savedInstanceState);
&lt;br /&gt;  addPreferencesFromResource(R.xml.tela_config);
&lt;br /&gt;}
&lt;br /&gt;}
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;Você pode chamar essa tela como uma Activity comum, e quando os valores dessa tela forem alterados, automaticamente os valores já são salvos na SharedPreference, e consequentemente podem ser obtidos com o código mostrado mais acima. Dessa forma, não precisamos utilizar o SharedPreference.Editor para salvar as configurações ;)
&lt;br /&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 240px; height: 400px;" src="http://3.bp.blogspot.com/-VhZVVNwBBhU/TlujyFZdOkI/AAAAAAAAAYY/UxWDZsY2TZg/s400/device-2011-08-29-113525.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5646286638676785730" /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;img style="cursor:pointer; cursor:hand;width: 240px; height: 400px;" src="http://3.bp.blogspot.com/-ZxosMHSQzW8/TlujyVPsKnI/AAAAAAAAAYg/ew0eKs1JpEc/s400/device-2011-08-29-113542.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5646286642930788978" /&gt;
&lt;br /&gt;
&lt;br /&gt;Bem pessoal, esse foi um post bem rápido. Qualquer dúvida deixem seus comentários.
&lt;br /&gt;
&lt;br /&gt;4br4ç05,
&lt;br /&gt;nglauber
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-7848881738259194605?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/F5kAlxNf993fY0YLXDFvxPmyQAE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/F5kAlxNf993fY0YLXDFvxPmyQAE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/F5kAlxNf993fY0YLXDFvxPmyQAE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/F5kAlxNf993fY0YLXDFvxPmyQAE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/hekNHdSVUkk" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=7848881738259194605" title="2 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/7848881738259194605?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/7848881738259194605?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/hekNHdSVUkk/armazenando-configuracoes-no-android.html" title="Armazenando configurações no Android" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-VhZVVNwBBhU/TlujyFZdOkI/AAAAAAAAAYY/UxWDZsY2TZg/s72-c/device-2011-08-29-113525.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/08/armazenando-configuracoes-no-android.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YNRnk9eSp7ImA9WhdXFEw.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-332215249861201551</id><published>2011-08-26T19:22:00.000-07:00</published><updated>2011-08-26T20:19:57.761-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-26T20:19:57.761-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="screen" /><category scheme="http://www.blogger.com/atom/ns#" term="Activity" /><category scheme="http://www.blogger.com/atom/ns#" term="Loading" /><category scheme="http://www.blogger.com/atom/ns#" term="Splash" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><title>Fazendo uma tela de splash</title><content type="html">Olá povo,
&lt;br /&gt;
&lt;br /&gt;É muito comum vermos nas aplicações a famosa "tela de splash", ou tela de loading. É nela que a aplicação dá um feedback pro usuário informando que os recursos necessários para execução da aplicação estão sendo carregados. Após verificar uma dessas telas elaborada por uma equipe do projeto em que trabalho, resolvi dar minha sugestão de como implementá-la.
&lt;br /&gt;
&lt;br /&gt;Vamos começar pela classe que realiza esse trabalho.
&lt;br /&gt;
&lt;br /&gt;&lt;pre name="code" class="java"&gt;public class SplashActivity extends Activity
&lt;br /&gt; implements Runnable {
&lt;br /&gt;
&lt;br /&gt; private Handler handler;
&lt;br /&gt;
&lt;br /&gt; @Override
&lt;br /&gt; protected void onCreate(Bundle savedInstanceState) {
&lt;br /&gt;   super.onCreate(savedInstanceState);
&lt;br /&gt;   setContentView(R.layout.splash_layout);
&lt;br /&gt;   handler = new Handler();
&lt;br /&gt;   handler.postDelayed(this, 2000);
&lt;br /&gt; }
&lt;br /&gt;
&lt;br /&gt; @Override
&lt;br /&gt; protected void onPause() {
&lt;br /&gt;   super.onPause();
&lt;br /&gt;   handler.removeCallbacks(this);
&lt;br /&gt; }
&lt;br /&gt;	
&lt;br /&gt; @Override
&lt;br /&gt; public void run() {
&lt;br /&gt;   // Faça o carregamento necessário aqui...
&lt;br /&gt;
&lt;br /&gt;   // Depois abre a atividade principal e fecha esta
&lt;br /&gt;   Intent it = new Intent(
&lt;br /&gt;     this, PrincipalActivity.class);
&lt;br /&gt;   startActivity(it);
&lt;br /&gt;   finish();
&lt;br /&gt;   overridePendingTransition(
&lt;br /&gt;     android.R.anim.fade_in, android.R.anim.fade_out);
&lt;br /&gt; }
&lt;br /&gt;	
&lt;br /&gt;}&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;A Activity está implementando Runnable para carregaremos os recursos da aplicação em uma Thread separada, uma vez que não queremos dar a impressão de que ela está travada. Em seguida, temos um atributo do tipo Handler, ele é utilizado para atualizar os componentes da tela (informando o progresso por exemplo) através de outra Thread, uma vez que é uma restrição do Android permitir que apenas a Thread da UI (ou seja, a Thread principal) faça isso.
&lt;br /&gt;
&lt;br /&gt;Ao criar a atividade (onCreate), inicializamos o Handler e agendamos a execução da Thread de carregamento dos recursos para ser executada daqui a 2 segundos (2000 milissegundos). Como não estou carregando nada nesse exemplo, estou usando esse valor pra dar tempo de ver a splash. Na prática, esse valor deve ir para um valor mais baixo (0,5 segundo por exemplo). No método onPause, eu estou tratando o caso de o usuário clicar na tecla "Back" durante o carregamento da splash. Caso isso aconteça, o carregamento é cancelado.
&lt;br /&gt;
&lt;br /&gt;No método run, que será executado em background, devemos fazer o carregamento dos recursos da aplicação. Em seguida, criamos a Intent para a tela principal da aplicação e a chamamos com o startActivity. Por fim, finalizamos a tela de splash com o método finish.
&lt;br /&gt;
&lt;br /&gt;Um recurso interessante que coloquei nesse exemplo foi a mudança da transição padrão entre as telas. Isso é feito através do método overridePendingTransition, que recebe uma animação para a tela que será exibida e outra para a tela q está sendo fechada. Nesse exemplo, usei um efeito de transparência (Fade In e Fade Out) da classe R do próprio Android. Se quiser fazer a sua própria, eu coloquei um &lt;a href="http://nglauber.blogspot.com/2011/04/animacoes-no-android-2.html"&gt;post sobre isso&lt;/a&gt; aqui no blog.
&lt;br /&gt;
&lt;br /&gt;De código é só. O que não podemos esquecer, é de declarar a Activity no AndroidManifest.xml, e as telas de Splash e Principal têm uma configuração interessante.
&lt;br /&gt;
&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;activity
&lt;br /&gt; android:name=".SplashActivity"&amp;gt;
&lt;br /&gt; &amp;lt;intent-filter&amp;gt;
&lt;br /&gt;   &amp;lt;action 
&lt;br /&gt;      android:name="android.intent.action.MAIN" /&amp;gt;
&lt;br /&gt;   &amp;lt;category 
&lt;br /&gt;      android:name="android.intent.category.LAUNCHER" /&amp;gt;
&lt;br /&gt; &amp;lt;/intent-filter&amp;gt;
&lt;br /&gt;&amp;lt;/activity&amp;gt;
&lt;br /&gt;
&lt;br /&gt;&amp;lt;activity
&lt;br /&gt; android:name=".PrincipalActivity"&amp;gt;
&lt;br /&gt; &amp;lt;intent-filter&amp;gt;
&lt;br /&gt;   &amp;lt;action 
&lt;br /&gt;      android:name="android.intent.action.MAIN" /&amp;gt;
&lt;br /&gt;   &amp;lt;category 
&lt;br /&gt;      android:name="android.intent.category.DEFAULT" /&amp;gt;
&lt;br /&gt; &amp;lt;/intent-filter&amp;gt;
&lt;br /&gt;&amp;lt;/activity&amp;gt;
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;Notem que as duas atividades têm a ação &lt;i&gt;android.intent.action.MAIN&lt;/i&gt; que informa ao Android que elas são pontos de partida da aplicação. Entretanto, a tela de Splash tem a categoria &lt;i&gt;android.intent.category.LAUNCHER&lt;/i&gt;, enquanto que a principal tem a categoria &lt;i&gt;android.intent.category.DEFAULT&lt;/i&gt;. O que isso significa?
&lt;br /&gt;Ao clicar no ícone no menu principal de aplicações do Android (Launcher) a SplashActivity é executada (isso graças a categoria LAUNCHER), e como vimos, em seguida ela chama a PrincipalActivity e se finaliza (com o finish). 
&lt;br /&gt;Quando clicamos na tecla "Back" na tela Principal, a aplicação "morreu", e se a executarmos novamente a splash será aberta novamente. Porém, se saírmos da aplicação com a tecla "Home",  a PrincipalActivity deve ficar lá suspensa, para que se o usuário clique no ícone da aplicação novamente, a tela principal (que foi aberta anteriormente) seja exibida. Isso funciona graças a categoria DEFAULT que foi passada para a PrincipalActivity.
&lt;br /&gt;
&lt;br /&gt;Por hoje é só pessoal. Qualque dúvida, deixem seus comentários.
&lt;br /&gt;
&lt;br /&gt;4br4ç05,
&lt;br /&gt;nglauber
&lt;br /&gt;
&lt;br /&gt;P.S.: O exemplo acima pode ser feito com AsyncTask também. Fica o desafio pra quem quiser ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-332215249861201551?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/AR5ALVliBCdNq9-6Wmde0Y1IuLg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AR5ALVliBCdNq9-6Wmde0Y1IuLg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/AR5ALVliBCdNq9-6Wmde0Y1IuLg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AR5ALVliBCdNq9-6Wmde0Y1IuLg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/cZbrzRGNg8M" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=332215249861201551" title="0 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/332215249861201551?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/332215249861201551?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/cZbrzRGNg8M/fazendo-uma-tela-de-splash.html" title="Fazendo uma tela de splash" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/08/fazendo-uma-tela-de-splash.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcEQ3syfip7ImA9WhdQGUo.&quot;"><id>tag:blogger.com,1999:blog-3344721733578072661.post-3460292193641373100</id><published>2011-08-21T15:18:00.000-07:00</published><updated>2011-08-21T18:20:02.596-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-21T18:20:02.596-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Galeria" /><category scheme="http://www.blogger.com/atom/ns#" term="Foto" /><category scheme="http://www.blogger.com/atom/ns#" term="camera" /><category scheme="http://www.blogger.com/atom/ns#" term="capturando" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="Gallery" /><title>Galeria de mídia do Android</title><content type="html">Olá povo,
&lt;br /&gt;
&lt;br /&gt;Neste post vou mostrar como tirar uma foto com a aplicação de câmera, salvar a imagem em um diretório temporário e em seguida adiciona-la à galeria de mídia do aparelho. E por último, vou mostrar como carregar uma imagem da galeria.
&lt;br /&gt;
&lt;br /&gt;Vamos iniciar mostrando como chamar a aplicação de câmera.
&lt;br /&gt;
&lt;br /&gt;&lt;pre name="code" class="java"&gt;
&lt;br /&gt;public void tirarFotoClick(View v) {
&lt;br /&gt;  String nomeFoto = DateFormat.format(
&lt;br /&gt;    "yyyy-MM-dd_hhmmss", new Date()).toString();
&lt;br /&gt;
&lt;br /&gt;  caminhoFoto = new File(
&lt;br /&gt;    Environment.getExternalStorageDirectory(), 
&lt;br /&gt;    nomeFoto);
&lt;br /&gt;
&lt;br /&gt;  Intent it = new Intent(
&lt;br /&gt;    MediaStore.ACTION_IMAGE_CAPTURE);  
&lt;br /&gt;  it.putExtra(MediaStore.EXTRA_OUTPUT, 
&lt;br /&gt;    Uri.fromFile(caminhoFoto));
&lt;br /&gt;  startActivityForResult(it, 1);
&lt;br /&gt;}
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;A aplicação de câmera é chamada através da ação ACTION_IMAGE_CAPTURE passado no construtor da Intent. Um detalhe interessante aqui é o parâmetro EXTRA_OUTPUT, ele serve para indicar um caminho para a foto ser salva. Sem ele, a imagem será salva com tamanho e qualidade inferior a que a câmera realmente tirou. 
&lt;br /&gt;caminhoFoto é um atributo do tipo File.
&lt;br /&gt;
&lt;br /&gt;A chamada do método startActivityForResult indica que queremos tratar o resultado da activity que estamos chamando. Esse tratamento é feito no método onActivityResult.
&lt;br /&gt;
&lt;br /&gt;&lt;pre name="code" class="java"&gt;
&lt;br /&gt;protected void onActivityResult(
&lt;br /&gt;  int requestCode, int resultCode, Intent data) {
&lt;br /&gt;  super.onActivityResult(
&lt;br /&gt;    requestCode, resultCode, data);
&lt;br /&gt;
&lt;br /&gt;  if (resultCode == RESULT_OK &amp;&amp; requestCode == 0) {
&lt;br /&gt;    fotoTirada = BitmapFactory.decodeFile(
&lt;br /&gt;      caminhoFoto.getAbsolutePath());
&lt;br /&gt;    imageView1.setImageBitmap(fotoTirada);
&lt;br /&gt;  }
&lt;br /&gt;}
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;Quando chamamos a câmera, no startActivityForResult, passamos o valor 1 como segundo parâmetro, esse valor representa o código da requisição (requestCode). Esse valor é retornado no método onActivityResult para saber se o resultado que estamos tratando é daquela requisição. No if que fizemos, além do requestCode, checamos o resultCode. O resultCode descreve o resultado da operação, que neste caso é tirar a foto. Se o resultado for RESULT_OK, é porque uma foto foi tirada. 
&lt;br /&gt;fotoTirada é um atributo do tipo Bitmap.
&lt;br /&gt;
&lt;br /&gt;O atributo caminhoFoto que foi atribuído no método tirarFotoClick é utilizado para carregar a imagem e atribuir em um ImageView. Agora vamos ver como salvar essa imagem na galeria de mídia.
&lt;br /&gt;&lt;pre name="code" class="java"&gt;
&lt;br /&gt;public void salvarFotoClick(View v) {
&lt;br /&gt;  if (fotoTirada != null) {
&lt;br /&gt;    MediaStore.Images.Media.insertImage(
&lt;br /&gt;      getContentResolver(), fotoTirada, 
&lt;br /&gt;      caminhoFoto.getName(), "");
&lt;br /&gt;
&lt;br /&gt;    Toast.makeText(this, 
&lt;br /&gt;      "Imagem adicionada a galeria.",
&lt;br /&gt;      Toast.LENGTH_SHORT).show();
&lt;br /&gt;  }
&lt;br /&gt;}
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;A classe MediaStore.Images.Media tem um "método mágico" que permite que possamos inserir um Bitmap na galeria. Essa operação é feita graças a um ContentProvider disponibilizado pela aplicação de galeria.
&lt;br /&gt;
&lt;br /&gt;O próximo passo será como abrir a galeria de mídia para selecionarmos uma imagem.
&lt;br /&gt;
&lt;br /&gt;&lt;pre name="code" class="java"&gt;
&lt;br /&gt;public void galleryButtonClick(View v) {
&lt;br /&gt;
&lt;br /&gt;  Intent intent = new Intent(
&lt;br /&gt;    Intent.ACTION_GET_CONTENT);
&lt;br /&gt;  intent.setType("image/*");
&lt;br /&gt;  startActivityForResult(intent, 2);
&lt;br /&gt;}
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;O código acima abrirá a aplicação de galeria. Notem que agora passamos o valor 2 para o startActivityForResult. Da mesma forma que fizemos para tirar foto, usaremos o método onActivityResult para tratar a imagem selecionada.
&lt;br /&gt;
&lt;br /&gt;&lt;pre name="code" class="java"&gt;
&lt;br /&gt;// adicione esse código no onActivityResult
&lt;br /&gt;if (resultCode == RESULT_OK &amp;&amp; requestCode == 2) {
&lt;br /&gt;  Uri selectedImage = data.getData();
&lt;br /&gt;  String[] filePathColumn = { 
&lt;br /&gt;    MediaStore.Images.Media.DATA };
&lt;br /&gt;
&lt;br /&gt;  Cursor cursor = getContentResolver().query(
&lt;br /&gt;    selectedImage, filePathColumn, null, null, null);
&lt;br /&gt;  cursor.moveToFirst();
&lt;br /&gt;
&lt;br /&gt;  int columnIndex = cursor.getColumnIndex(
&lt;br /&gt;    filePathColumn[0]);
&lt;br /&gt;  String filePath = cursor.getString(columnIndex); 
&lt;br /&gt;  cursor.close();
&lt;br /&gt;
&lt;br /&gt;  Bitmap yourSelectedImage = 
&lt;br /&gt;    BitmapFactory.decodeFile(filePath);
&lt;br /&gt;
&lt;br /&gt;  imageView1.setImageBitmap(yourSelectedImage);
&lt;br /&gt;}
&lt;br /&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;A galeria retorna o endereço da imagem selecionada através de um objeto Uri que é obtido em data.getData(). Com essa informação podemos acessar o ContentProvider da galeria para obter o caminho da imagem. Com esse caminho passamos para a classe BitmapFactory que retornará um objeto Bitmap para preencher a imageView.
&lt;br /&gt;
&lt;br /&gt;A código completo da aplicação está disponível &lt;a href="https://sites.google.com/site/nglaubervasc/MediaGalleryTest.zip"&gt;aqui&lt;/a&gt;. Qualquer dúvida, deixem seus comentários.
&lt;br /&gt;
&lt;br /&gt;4br4ç05,
&lt;br /&gt;nglauber &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3344721733578072661-3460292193641373100?l=nglauber.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/K8pNdhzQvGt6y7AkCZQr0I6naZM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/K8pNdhzQvGt6y7AkCZQr0I6naZM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/K8pNdhzQvGt6y7AkCZQr0I6naZM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/K8pNdhzQvGt6y7AkCZQr0I6naZM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/DebugIsOnTheTable/~4/3QDQoss0pP4" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3344721733578072661&amp;postID=3460292193641373100" title="10 Comentários" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/3460292193641373100?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3344721733578072661/posts/default/3460292193641373100?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/DebugIsOnTheTable/~3/3QDQoss0pP4/galeria-de-midia-do-android.html" title="Galeria de mídia do Android" /><author><name>Nelson Glauber de Vasconcelos Leal</name><uri>http://www.blogger.com/profile/02476858089223420894</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="18" height="32" src="http://1.bp.blogspot.com/-DGMFmtDDwzU/TlEw907uT1I/AAAAAAAAAX4/4t6Z6T4FZOI/s220/2011-06-22_20-55-29_820.jpg" /></author><thr:total>10</thr:total><feedburner:origLink>http://nglauber.blogspot.com/2011/08/galeria-de-midia-do-android.html</feedburner:origLink></entry></feed>

