<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Bitácora de Javier Cancela</title>
	<atom:link href="http://javiercancela.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://javiercancela.com</link>
	<description></description>
	<lastBuildDate>Sun, 14 Aug 2011 18:12:06 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='javiercancela.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Bitácora de Javier Cancela</title>
		<link>http://javiercancela.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://javiercancela.com/osd.xml" title="Bitácora de Javier Cancela" />
	<atom:link rel='hub' href='http://javiercancela.com/?pushpress=hub'/>
		<item>
		<title>Pasado, presente y futuro de la realidad aumentada</title>
		<link>http://javiercancela.com/2009/11/16/pasado-presente-y-futuro-de-la-realidad-aumentada/</link>
		<comments>http://javiercancela.com/2009/11/16/pasado-presente-y-futuro-de-la-realidad-aumentada/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 19:00:08 +0000</pubDate>
		<dc:creator>Javier Cancela</dc:creator>
				<category><![CDATA[Tecnología]]></category>
		<category><![CDATA[desarrollo móvil]]></category>
		<category><![CDATA[realidad aumentada]]></category>

		<guid isPermaLink="false">http://javiercancela.com/?p=480</guid>
		<description><![CDATA[Artículo en Loogic: Pasado, presente y futuro de la realidad aumentada Posted in Tecnología Tagged: desarrollo móvil, realidad aumentada<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=480&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Artículo en Loogic:</p>
<p><a href="http://loogic.com/pasado-presente-y-futuro-de-la-realidad-aumentada/">Pasado, presente y futuro de la realidad aumentada</a></p>
<br />Posted in Tecnología Tagged: desarrollo móvil, realidad aumentada <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/javiercancela.wordpress.com/480/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/javiercancela.wordpress.com/480/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=480&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://javiercancela.com/2009/11/16/pasado-presente-y-futuro-de-la-realidad-aumentada/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/27525d8e018e81a55b107f98b6a45ecd?s=96&#38;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">Javier Cancela</media:title>
		</media:content>
	</item>
		<item>
		<title>Nunca se sabe cu&#225;ndo vas a acabar en la isla&#8230;</title>
		<link>http://javiercancela.com/2009/08/23/nunca-se-sabe-cundo-vas-a-acabar-en-la-isla/</link>
		<comments>http://javiercancela.com/2009/08/23/nunca-se-sabe-cundo-vas-a-acabar-en-la-isla/#comments</comments>
		<pubDate>Sun, 23 Aug 2009 17:52:25 +0000</pubDate>
		<dc:creator>Javier Cancela</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Perdidos]]></category>
		<category><![CDATA[Sensor API]]></category>

		<guid isPermaLink="false">http://javiercancela.wordpress.com/2009/08/23/nunca-se-sabe-cundo-vas-a-acabar-en-la-isla/</guid>
		<description><![CDATA[… y los creadores de Android lo han tenido en cuenta. Echando un vistazo al código fuente de Android para comprobar unas cosas de la clase SensorManager me encontré con esto: public static final float GRAVITY_THE_ISLAND = 4.815162342f; &#160; La verdad es que está documentado y disponible en la clase SensorManager, pero no había reparado [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=478&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>… y los creadores de Android lo han tenido en cuenta.</p>
<p>Echando un vistazo al <a href="http://source.android.com/download">código fuente de Android</a> para comprobar unas cosas de la clase SensorManager me encontré con esto:</p>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:&#39;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">final</span> <span style="color:#0000ff;">float</span> GRAVITY_THE_ISLAND      = 4.815162342f;</pre>
<p>&#160;</p>
<p>La verdad es que está <a href="http://developer.android.com/reference/android/hardware/SensorManager.html#GRAVITY_THE_ISLAND">documentado y disponible en la clase SensorManager</a>, pero no había reparado en ello hasta ahora.</p>
<p>También han tenido en cuenta otra posible ubicación de nuestro móvil, aunque no estoy seguro de que Vodafone tenga cobertura aquí:</p>
<div id="codeSnippetWrapper">
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&#39;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">final</span> <span style="color:#0000ff;">float</span> GRAVITY_DEATH_STAR_I    = 0.000000353036145f;</pre>
<p></div>
<br />Posted in Android Tagged: Android, Perdidos, Sensor API <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/javiercancela.wordpress.com/478/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/javiercancela.wordpress.com/478/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=478&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://javiercancela.com/2009/08/23/nunca-se-sabe-cundo-vas-a-acabar-en-la-isla/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/27525d8e018e81a55b107f98b6a45ecd?s=96&#38;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">Javier Cancela</media:title>
		</media:content>
	</item>
		<item>
		<title>Realidad aumentada en Android: AR Compass &#8211; III</title>
		<link>http://javiercancela.com/2009/08/17/realidad-aumentada-en-android-ar-compass-iii/</link>
		<comments>http://javiercancela.com/2009/08/17/realidad-aumentada-en-android-ar-compass-iii/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 06:00:49 +0000</pubDate>
		<dc:creator>Javier Cancela</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[desarrollo android]]></category>
		<category><![CDATA[desarrollo móvil]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[realidad aumentada]]></category>

		<guid isPermaLink="false">http://javiercancela.wordpress.com/?p=472</guid>
		<description><![CDATA[La entrada anterior se centró la clase Compass, que describe la brújula. También presentaba la clase CompassRenderer, que es la encargada de dibujarla en su sitio. Vamos a ver esta clase con más detalle. La clase CompassRenderer 1: class CompassRenderer implements GLSurfaceView.Renderer, SensorEventListener { 2: private float mAccelerometerValues[] = new float[3]; 3: private float mMagneticValues[] [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=472&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>La entrada anterior se centró la clase Compass, que describe la brújula. También presentaba la clase CompassRenderer, que es la encargada de dibujarla en su sitio. Vamos a ver esta clase con más detalle.</p>
<p><strong>La clase CompassRenderer</strong></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;">
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum1" style="color:#606060;">   1:</span> <span style="color:#0000ff;">class</span> CompassRenderer <span style="color:#0000ff;">implements</span> GLSurfaceView.Renderer, SensorEventListener {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum2" style="color:#606060;">   2:</span>         <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">float</span>   mAccelerometerValues[] = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">float</span>[3];</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum3" style="color:#606060;">   3:</span>         <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">float</span>   mMagneticValues[] = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">float</span>[3];</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum4" style="color:#606060;">   4:</span>         <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">float</span> rotationMatrix[] = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">float</span>[16];</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum5" style="color:#606060;">   5:</span>         <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">float</span> remappedRotationMatrix[] = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">float</span>[16];</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum6" style="color:#606060;">   6:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum7" style="color:#606060;">   7:</span>         <span style="color:#0000ff;">private</span> Compass mCompass;</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum8" style="color:#606060;">   8:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum9" style="color:#606060;">   9:</span>     <span style="color:#0000ff;">public</span> CompassRenderer() {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum10" style="color:#606060;">  10:</span>         mCompass = <span style="color:#0000ff;">new</span> Compass();</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum11" style="color:#606060;">  11:</span>     }</pre>
</div>
</div>
<p>La clase CompassRenderer cumple dos funciones: capturar la información de los sensores y renderizar la brújula con esa información.</p>
<p><strong>Implementación de la interfaz SensorEventListener</strong></p>
<p>Como hemos visto en otras entradas, el método onSensorChanged es invocado cada vez que hay nueva información disponible de alguno de los sensores a los que nos hemos subscrito:</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;">
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum1" style="color:#606060;">   1:</span> @Override</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum2" style="color:#606060;">   2:</span> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> onSensorChanged(SensorEvent event) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum3" style="color:#606060;">   3:</span>        <span style="color:#0000ff;">synchronized</span> (<span style="color:#0000ff;">this</span>) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum4" style="color:#606060;">   4:</span>             <span style="color:#0000ff;">switch</span>(event.sensor.getType()) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum5" style="color:#606060;">   5:</span>             <span style="color:#0000ff;">case</span> Sensor.TYPE_ACCELEROMETER:</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum6" style="color:#606060;">   6:</span>                 mAccelerometerValues = event.values.clone();</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum7" style="color:#606060;">   7:</span>                 <span style="color:#0000ff;">break</span>;</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum8" style="color:#606060;">   8:</span>             <span style="color:#0000ff;">case</span> Sensor.TYPE_MAGNETIC_FIELD:</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum9" style="color:#606060;">   9:</span>                 mMagneticValues = event.values.clone();</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum10" style="color:#606060;">  10:</span>                 <span style="color:#0000ff;">break</span>;</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum11" style="color:#606060;">  11:</span>             <span style="color:#0000ff;">default</span>:</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum12" style="color:#606060;">  12:</span>                 <span style="color:#0000ff;">break</span>;</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum13" style="color:#606060;">  13:</span>             }</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum14" style="color:#606060;">  14:</span>        }</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum15" style="color:#606060;">  15:</span> }</pre>
</div>
</div>
<p>Para obtener la matriz de rotación (como veremos después) sólo necesitamos el acelerómetro y el sensor de campo magnético.</p>
<p>Un punto a tener en cuenta en este caso es la sincronización. Al código de la clase CompassRenderer van a acceder dos threads: el principal y thread de OpenGL. Las llamadas a los métodos de los sensores vendrán del primero, mientras que las llamadas a los métodos de renderización vendrán del segundo. Esto quiere decir que las variables miembro mAccelerometerValues y mMagneticValues serán asignadas en un thread y leídas en el otro, por lo que usamos un lock para evitar que se lean mientras se están asignando.</p>
<p><strong>Creación de la superficie OpenGL</strong></p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;">
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum1" style="color:#606060;">   1:</span> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> onSurfaceCreated(GL10 gl, EGLConfig config) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum2" style="color:#606060;">   2:</span>     <span style="color:#008000;">/*</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum3" style="color:#606060;">   3:</span> <span style="color:#008000;">     * By default, OpenGL enables features that improve quality</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum4" style="color:#606060;">   4:</span> <span style="color:#008000;">     * but reduce performance. One might want to tweak that</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum5" style="color:#606060;">   5:</span> <span style="color:#008000;">     * especially on software renderer.</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum6" style="color:#606060;">   6:</span> <span style="color:#008000;">     */</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum7" style="color:#606060;">   7:</span>     gl.glDisable(GL10.GL_DITHER);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum8" style="color:#606060;">   8:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum9" style="color:#606060;">   9:</span>     <span style="color:#008000;">/*</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum10" style="color:#606060;">  10:</span> <span style="color:#008000;">     * Some one-time OpenGL initialization can be made here</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum11" style="color:#606060;">  11:</span> <span style="color:#008000;">     * probably based on features of this particular context</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum12" style="color:#606060;">  12:</span> <span style="color:#008000;">     */</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum13" style="color:#606060;">  13:</span>      gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum14" style="color:#606060;">  14:</span>              GL10.GL_FASTEST);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum15" style="color:#606060;">  15:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum16" style="color:#606060;">  16:</span>      gl.glClearColor(0,0,0,0);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum17" style="color:#606060;">  17:</span> }</pre>
</div>
</div>
<p>Cuando el GLThread crea la superficie ejecuta el método onSurfaceCreated. Las líneas 7 y 13 son optimizaciones que le indican a OpenGL que optimice el rendimiento sobre la calidad de la imagen. La línea 16 establece los valores que se utilizarán para limpiar el buffer de color.</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;">
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum1" style="color:#606060;">   1:</span> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> onSurfaceChanged(GL10 gl, <span style="color:#0000ff;">int</span> width, <span style="color:#0000ff;">int</span> height) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum2" style="color:#606060;">   2:</span>      gl.glViewport(0, 0, width, height);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum3" style="color:#606060;">   3:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum4" style="color:#606060;">   4:</span>      <span style="color:#008000;">/*</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum5" style="color:#606060;">   5:</span> <span style="color:#008000;">      * Set our projection matrix. This doesn't have to be done</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum6" style="color:#606060;">   6:</span> <span style="color:#008000;">      * each time we draw, but usually a new projection needs to</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum7" style="color:#606060;">   7:</span> <span style="color:#008000;">      * be set when the viewport is resized.</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum8" style="color:#606060;">   8:</span> <span style="color:#008000;">      */</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum9" style="color:#606060;">   9:</span>      <span style="color:#0000ff;">float</span> ratio = (<span style="color:#0000ff;">float</span>) width / height;</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum10" style="color:#606060;">  10:</span>      gl.glMatrixMode(GL10.GL_PROJECTION);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum11" style="color:#606060;">  11:</span>      gl.glLoadIdentity();</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum12" style="color:#606060;">  12:</span>      gl.glFrustumf(-ratio, ratio, -1, 1, 1, 100);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum13" style="color:#606060;">  13:</span> }</pre>
</div>
</div>
<p>El método onSurfaceChanged después de creada la superficie, y adicionalmente cada vez que esta cambia de tamaño. En la línea 2 establecemos el <em>viewport</em>. Básicamente le decimos a sistema que utilice todo el alto y ancho de la pantalla para pintar el modelo. Las líneas 9-12 inicializan la matriz de proyección y establece la región  que se va a visualizar (ver por ejemplo <a href="http://usuarios.lycos.es/andromeda_studios/paginas/tutoriales/aptutgl01.htm#Proyeccion">este tutorial</a>).</p>
<p><strong>Dibujo de la brújula</strong></p>
<p>Cada cuadro correspondiente a la animación de la brújula se dibuja en el método onDrawFrame:</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;">
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum1" style="color:#606060;">   1:</span> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> onDrawFrame(GL10 gl) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum2" style="color:#606060;">   2:</span>     <span style="color:#008000;">// Get rotation matrix from the sensor</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum3" style="color:#606060;">   3:</span>     SensorManager.getRotationMatrix(rotationMatrix, null, mAccelerometerValues,</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;">                                          mMagneticValues);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum4" style="color:#606060;">   4:</span>     <span style="color:#008000;">// As the documentation says, we are using the device as a compass in landscape </span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#008000;">          // mode</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum5" style="color:#606060;">   5:</span>     SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_Y,</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;">                                              SensorManager.AXIS_MINUS_X,</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;">                                              remappedRotationMatrix);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum6" style="color:#606060;">   6:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum7" style="color:#606060;">   7:</span>     <span style="color:#008000;">// Clear color buffer</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum8" style="color:#606060;">   8:</span>     gl.glClear(GL10.GL_COLOR_BUFFER_BIT);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum9" style="color:#606060;">   9:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum10" style="color:#606060;">  10:</span>     <span style="color:#008000;">// Load remapped matrix</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum11" style="color:#606060;">  11:</span>     gl.glMatrixMode(GL10.GL_MODELVIEW);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum12" style="color:#606060;">  12:</span>     gl.glLoadIdentity();</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum13" style="color:#606060;">  13:</span>     gl.glLoadMatrixf(remappedRotationMatrix, 0);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum14" style="color:#606060;">  14:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum15" style="color:#606060;">  15:</span>     gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum16" style="color:#606060;">  16:</span>     gl.glEnableClientState(GL10.GL_COLOR_ARRAY);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum17" style="color:#606060;">  17:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span id="lnum18" style="color:#606060;">  18:</span>     mCompass.draw(gl);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span id="lnum19" style="color:#606060;">  19:</span> }</pre>
</div>
</div>
<p>En la línea 3 obtenemos la matriz de rotación a partir de los sensores. Como vamos a ver la imagen en formato horizontal giramos los ejes en la línea 5. Las líneas 11-13 cargan la matriz. Después habilitamos los arrays de vértices y colores en el cliente que como vimos usa la clase Compass, y finalmente llamamos al método de dibujo de la brújula (visto en la entrada anterior).</p>
<p>El código completo del proyecto está disponible aquí: <a href="http://code.google.com/p/ipoki/source/browse/#svn/trunk/ipoki/Android/ARCompass">ARCompass</a>.</p>
<br />Posted in Android Tagged: desarrollo android, desarrollo móvil, OpenGL, realidad aumentada <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/javiercancela.wordpress.com/472/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/javiercancela.wordpress.com/472/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=472&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://javiercancela.com/2009/08/17/realidad-aumentada-en-android-ar-compass-iii/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/27525d8e018e81a55b107f98b6a45ecd?s=96&#38;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">Javier Cancela</media:title>
		</media:content>
	</item>
		<item>
		<title>Realidad aumentada en Android: AR Compass &#8211; II</title>
		<link>http://javiercancela.com/2009/08/10/realidad-aumentada-en-android-ar-compass-ii/</link>
		<comments>http://javiercancela.com/2009/08/10/realidad-aumentada-en-android-ar-compass-ii/#comments</comments>
		<pubDate>Mon, 10 Aug 2009 06:00:48 +0000</pubDate>
		<dc:creator>Javier Cancela</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[desarrollo android]]></category>
		<category><![CDATA[desarrollo móvil]]></category>
		<category><![CDATA[OpenGL]]></category>
		<category><![CDATA[realidad aumentada]]></category>

		<guid isPermaLink="false">http://javiercancela.wordpress.com/?p=463</guid>
		<description><![CDATA[Una vez obtenida la imagen de la cámara pasamos a la brújula. Necesitaremos dos cosas: obtener los datos de orientación y dibujarlos en el lugar adecuado. Empezaremos inicializando los sensores y los datos iniciales de la brújula. Empezando con OpenGL Como dijimos en la entrada anterior vamos a usar OpenGL para dibujar la brújula. Una [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=463&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Una vez <a href="http://javiercancela.com/2009/08/04/realidad-aumentada-en-android-ar-compass-i/">obtenida la imagen de la cámara</a> pasamos a la brújula. Necesitaremos dos cosas: obtener los datos de orientación y dibujarlos en el lugar adecuado. Empezaremos inicializando los sensores y los datos iniciales de la brújula.</p>
<p><strong>Empezando con OpenGL</strong></p>
<p>Como dijimos en <a href="http://javiercancela.com/2009/08/04/realidad-aumentada-en-android-ar-compass-i/">la entrada anterior</a> vamos a usar OpenGL para dibujar la brújula. Una advertencia: antes de realizar esta serie de entradas no sabía nada de OpenGL, así que es probable es que el código que incluyo no sea muy ortodoxo, incluso puede que contenga errores. Aún así funciona correctamente en el HTC Magic.</p>
<p>Para aprender algo de OpenGL utilicé el libro <em>“The <a href="http://www.glprogramming.com/red/">OpenGL Programming Guide 5th Edition. The Official Guide to Learning OpenGL Version 2.1</a>”</em>, también conocido como el <em>OpenGL Red Book</em>. Por supuesto hay gran cantidad de tutoriales de OpenGL por internet. Los <a href="http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/graphics/index.html">ejemplos de Android sobre OpenGL|ES</a> permiten hacerse una idea de cómo usar OpenGL en Android. Algunas de las clases que aparecen en esta entrada están basadas en esos ejemplos.</p>
<p>Lo primero que necesitamos para trabajar con OpenGL es una superficie sobre la que pintar. La SDK incluye una diseñada para OpenGL: <a href="http://developer.android.com/reference/android/opengl/GLSurfaceView.html">GLSurfaceView</a>, un tipo especial de SurfaceView cuya principal característica es que ejecuta el código de renderizado en un thread aparte (llamado GLThread). Para ello, a la vista GLSurfaceView se le asigna un renderizador, que es una clase que hereda de <a href="http://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer.html">GLSurfaceView.Renderer</a>:</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;">
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   1:</span> <span style="color:#0000ff;">class</span> CompassRenderer <span style="color:#0000ff;">implements</span> GLSurfaceView.Renderer, SensorEventListener {</pre>
</div>
</div>
<p>En nuestro caso, dado que esta clase va a renderizar la brújula en base a los datos de los sensores, haremos que implemente también SensorEventListener (como veíamos en <a href="http://javiercancela.com/2009/07/20/desarrollo-en-android-acelermetro-magnetmetro-y-sensores-de-orientacin-y-temperatura-en-el-htc-magic/">esta entrada</a>), para tener los datos en la misma clase.</p>
<p>Pero primero tenemos que decirle a nuestra actividad que use esta vista además de la vista de la cámara:</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;">
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   1:</span> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> ARCompass <span style="color:#0000ff;">extends</span> Activity {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   2:</span>     <span style="color:#0000ff;">private</span> SensorManager mSensorManager;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   3:</span>     <span style="color:#0000ff;">private</span> CameraView mCameraView;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   4:</span>     <span style="color:#0000ff;">private</span> GLSurfaceView mGLSurfaceView;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   5:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   6:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   7:</span>     <span style="color:#008000;">/** Called when the activity is first created. */</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   8:</span>     @Override</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   9:</span>     <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> onCreate(Bundle savedInstanceState) {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  10:</span>         <span style="color:#0000ff;">super</span>.onCreate(savedInstanceState);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  11:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  12:</span>         <span style="color:#008000;">// Hide the window title.</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  13:</span>         requestWindowFeature(Window.FEATURE_NO_TITLE);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  14:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  15:</span>         mGLSurfaceView = <span style="color:#0000ff;">new</span> GLSurfaceView(<span style="color:#0000ff;">this</span>);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  16:</span>         mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  17:</span>         CompassRenderer compassRenderer = <span style="color:#0000ff;">new</span> CompassRenderer(true);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  18:</span>         mGLSurfaceView.setRenderer(compassRenderer);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  19:</span>         mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  20:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  21:</span>         setContentView(mGLSurfaceView);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  22:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  23:</span>         mCameraView = <span style="color:#0000ff;">new</span> CameraView(<span style="color:#0000ff;">this</span>);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  24:</span>         addContentView(mCameraView, <span style="color:#0000ff;">new</span> LayoutParams(LayoutParams.WRAP_CONTENT,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;">                                                         LayoutParams.WRAP_CONTENT));</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  25:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  26:</span>         mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  27:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  28:</span>         List&lt;Sensor&gt; listSensors = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  29:</span>         <span style="color:#0000ff;">if</span> (listSensors.size() &gt; 0)</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  30:</span>         {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  31:</span>             mSensorManager.registerListener(compassRenderer, listSensors.get(0),</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;">                                                   SensorManager.SENSOR_DELAY_UI);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  32:</span>         }</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  33:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  34:</span>         listSensors = mSensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  35:</span>         <span style="color:#0000ff;">if</span> (listSensors.size() &gt; 0)</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  36:</span>         {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  37:</span>             mSensorManager.registerListener(compassRenderer, listSensors.get(0),</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;">                                                                   SensorManager.SENSOR_DELAY_UI);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  38:</span>         }</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  39:</span>     }</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  40:</span>  ...</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  41:</span> }</pre>
</div>
</div>
<p>En las líneas 15-19 creamos la superficie OpenGL, establecemos los componentes de color RGB a 8 bits con profundidad de buffer a 60 bits, creamos nuestra clase CompassRenderer (que veremos después), le decimos a la superficie que vamos a renderizar en la clase CompassRenderer y finalmente establecemos en la superficie un formato de pixel que soporte varios de canal alfa. Este último paso es necesario para que la superficie sea transparente y poder ver lo que hay debajo, que será la imagen de la cámara.</p>
<p>En las líneas 21-24 asociamos la vista OpenGL a la actividad, creamos la vista de la cámara y la añadimos. La vista de la cámara queda así detrás de la vista OpenGL, visible porque esta última tiene una superficie transparente.</p>
<p>El resto del código registra los <em>Listeners </em>del acelerómetro y del sensor de campo magnético.</p>
<p><strong>La clase Compass</strong></p>
<p>La clase Compass le indica al renderizador las características del objeto a renderizar. Contiene un método draw que será llamado por el renderizador cada vez que quiera dibujar un frame:</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;">
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   1:</span> <span style="color:#0000ff;">class</span> Compass</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   2:</span> {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   3:</span>     <span style="color:#0000ff;">private</span> FloatBuffer   mVertexBuffer;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   4:</span>     <span style="color:#0000ff;">private</span> IntBuffer   mColorBuffer;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   5:</span>     <span style="color:#0000ff;">private</span> ByteBuffer  mIndexBuffer;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   6:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   7:</span>     <span style="color:#0000ff;">public</span> Compass()</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   8:</span>     {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   9:</span>          ...</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  10:</span>     }</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  11:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  12:</span>     <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> draw(GL10 gl)</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  13:</span>     {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  14:</span>         gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  15:</span>         gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  16:</span>         gl.glDrawElements(GL10.GL_LINES, 32 + 6 + 10 + 8 + 8, GL10.GL_UNSIGNED_BYTE,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;">                                mIndexBuffer);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  17:</span>     }</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  18:</span> }</pre>
</div>
</div>
<p>La clase contiene tres buffers: uno con los vértices de cada primitiva a dibujar (en nuestro caso las primitivas son líneas), otro con los colores, y el último con el orden en el que se van a aplicar cada uno de los vértices. Los buffers se asignan en el constructor, como veremos después, y contienen una descripción de la posición y el color del modelo. En nuestro caso el modelo es una serie de líneas verticales y cuatro letras que se distribuyen en una circunferencia en el plano XY alrededor del punto (0, 0, 0).</p>
<p>La línea 14 define el array de vértices a partir de nuestro buffer. Son vértices de tres coordenadas, de tipo float, sin <em>stride</em> (desplazamiento entre vértices consecutivos, usado para empaquetar información de cada vértice, ver <a href="http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/4/20_OpenGL_ES_08_-_The_Final_Primitives__Points_and_Lines_in_a_Stride.html">este artículo</a> para más información). La línea 15 define el array de colores. Y la línea 16 renderiza las primitivas: indicamos el tipo de primitivas (en este caso líneas) y el número de elementos a renderizar (en este caso vértices, 32 de la brújula, 6, 10, 8 y 8 para cada letra).</p>
<p>Veamos ahora el constructor:</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;">
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   1:</span> <span style="color:#0000ff;">public</span> Compass()</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   2:</span>  {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   3:</span>      <span style="color:#0000ff;">int</span> one = 0x10000;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   4:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   5:</span>      <span style="color:#0000ff;">int</span> colorLines[] = {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   6:</span>              0,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   7:</span>              0,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   8:</span>        };</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">   9:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  10:</span>      <span style="color:#0000ff;">int</span> colorLetters[] = {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  11:</span>              <span style="color:#008000;">//North</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  12:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  13:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  14:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  15:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  16:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  17:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  18:</span>              <span style="color:#008000;">// South</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  19:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  20:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  21:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  22:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  23:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  24:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  25:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  26:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  27:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  28:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  29:</span>              <span style="color:#008000;">// East</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  30:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  31:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  32:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  33:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  34:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  35:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  36:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  37:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  38:</span>              <span style="color:#008000;">// West</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  39:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  40:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  41:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  42:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  43:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  44:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  45:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  46:</span>              one,  one,    0,  one,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  47:</span>      };</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  48:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  49:</span>      <span style="color:#008000;">// Buffers to be passed to gl*Pointer() functions</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  50:</span>      <span style="color:#008000;">// must be direct, i.e., they must be placed on the</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  51:</span>      <span style="color:#008000;">// native heap where the garbage collector cannot</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  52:</span>      <span style="color:#008000;">// move them.</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  53:</span>      <span style="color:#008000;">//</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  54:</span>      <span style="color:#008000;">// Buffers with multi-byte datatypes (e.g., short, int, float)</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  55:</span>      <span style="color:#008000;">// must have their byte order set to native order</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  56:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  57:</span>      <span style="color:#008000;">// (( vertices_per_compass_line * coords_per_vertex * lines_number) </span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  58:</span>      <span style="color:#008000;">// + north_vertices * coords_per_vertex + south_vertices * coords_per_vertex </span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  59:</span>      <span style="color:#008000;">// + east_vertices * coords_per_vertex + west_vertices * coords_per_vertex) </span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  60:</span>      <span style="color:#008000;">// * bytes_per_float</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  61:</span>      ByteBuffer vbb = ByteBuffer.allocateDirect(((2 * 3 * 16) + (6 * 3) + (10 * 3) +</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;">                                                       (8 * 3) + (8 * 3)) * 4);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  62:</span>      vbb.order(ByteOrder.nativeOrder());</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  63:</span>      mVertexBuffer = vbb.asFloatBuffer();</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  64:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  65:</span>      <span style="color:#008000;">// ((total_compass_vertices * coords_per_color) + </span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  66:</span>      <span style="color:#008000;">// (north_vertices * coords_per_color)  + (south_vertices * coords_per_color))</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  67:</span>      <span style="color:#008000;">// * bytes_per_int</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  68:</span>      ByteBuffer cbb = ByteBuffer.allocateDirect(((32 * 4) + (6 * 4) + (10 * 4) +</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;">                                                        (8 * 4) + (8 * 4)) * 4);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  69:</span>      cbb.order(ByteOrder.nativeOrder());</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  70:</span>      mColorBuffer = cbb.asIntBuffer();</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  71:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  72:</span>      mIndexBuffer = ByteBuffer.allocateDirect(32 + 6 + 10 + 8 + 8);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  73:</span>      <span style="color:#0000ff;">float</span> x;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  74:</span>      <span style="color:#0000ff;">float</span> y;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  75:</span>      <span style="color:#0000ff;">float</span> z;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  76:</span>      <span style="color:#0000ff;">for</span> (<span style="color:#0000ff;">int</span> i = 0; i &lt; 16; i++)</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  77:</span>      {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  78:</span>          <span style="color:#0000ff;">if</span> (i % 2 == 0)</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  79:</span>              <span style="color:#0000ff;">if</span> (i % 4 == 0)</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  80:</span>                  z = 6.0f;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  81:</span>              <span style="color:#0000ff;">else</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  82:</span>                  z = 4.0f;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  83:</span>          <span style="color:#0000ff;">else</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  84:</span>              z = 2.0f;</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  85:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  86:</span>          x = (<span style="color:#0000ff;">float</span>)(Math.sin(((<span style="color:#0000ff;">double</span>)i / 16) * 2 * Math.PI) * 32);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  87:</span>          y = (<span style="color:#0000ff;">float</span>)(Math.cos(((<span style="color:#0000ff;">double</span>)i / 16) * 2 * Math.PI) * 32);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  88:</span>          mVertexBuffer.put(x);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  89:</span>          mVertexBuffer.put(y);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  90:</span>          mVertexBuffer.put(-z);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  91:</span>          mIndexBuffer.put((<span style="color:#0000ff;">byte</span>)(2 * i));</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  92:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  93:</span>          mVertexBuffer.put(x);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  94:</span>          mVertexBuffer.put(y);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  95:</span>          mVertexBuffer.put(z);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  96:</span>          mIndexBuffer.put((<span style="color:#0000ff;">byte</span>)(2 * i + 1));</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  97:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  98:</span>          mColorBuffer.put(colorLines);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;">  99:</span>      }</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 100:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 101:</span>      <span style="color:#0000ff;">float</span> north[] = {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 102:</span>          -2.0f, 32.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 103:</span>          -2.0f, 32.0f, 11.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 104:</span>          -2.0f, 32.0f, 11.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 105:</span>          2.0f, 32.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 106:</span>          2.0f, 32.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 107:</span>          2.0f, 32.0f, 11.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 108:</span>      };</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 109:</span>      mVertexBuffer.put(north);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 110:</span>      <span style="color:#0000ff;">byte</span> indices[] = {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 111:</span>              32, 33, 34, 35, 36, 37,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 112:</span>      };</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 113:</span>      mIndexBuffer.put(indices);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 114:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 115:</span>      <span style="color:#0000ff;">float</span> south[] = {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 116:</span>              2.0f, -32.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 117:</span>              -2.0f, -32.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 118:</span>              -2.0f, -32.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 119:</span>              -2.0f, -32.0f, 9.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 120:</span>              -2.0f, -32.0f, 9.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 121:</span>              2.0f, -32.0f, 9.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 122:</span>              2.0f, -32.0f, 9.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 123:</span>              2.0f, -32.0f, 11.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 124:</span>              2.0f, -32.0f, 11.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 125:</span>              -2.0f, -32.0f, 11.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 126:</span>      };</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 127:</span>      mVertexBuffer.put(south);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 128:</span>      indices = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">byte</span>[]{</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 129:</span>              38, 39, 40, 41, 42, 43, 44, 45, 46, 47,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 130:</span>      };</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 131:</span>      mIndexBuffer.put(indices);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 132:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 133:</span>      <span style="color:#0000ff;">float</span> east[] = {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 134:</span>              32.0f, -2.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 135:</span>              32.0f, 2.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 136:</span>              32.0f, -2.0f, 9.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 137:</span>              32.0f, 2.0f, 9.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 138:</span>              32.0f, -2.0f, 11.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 139:</span>              32.0f, 2.0f, 11.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 140:</span>              32.0f, 2.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 141:</span>              32.0f, 2.0f, 11.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 142:</span>      };</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 143:</span>      mVertexBuffer.put(east);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 144:</span>      indices = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">byte</span>[]{</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 145:</span>              48, 49, 50, 51, 52, 53, 54, 55,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 146:</span>      };</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 147:</span>      mIndexBuffer.put(indices);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 148:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 149:</span>      <span style="color:#0000ff;">float</span> west[] = {</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 150:</span>              -32.0f, 2.0f, 11.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 151:</span>              -32.0f, 1.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 152:</span>              -32.0f, 1.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 153:</span>              -32.0f, 0, 9.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 154:</span>              -32.0f, 0, 9.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 155:</span>              -32.0f, -1.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 156:</span>              -32.0f, -1.0f, 7.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 157:</span>              -32.0f, -2.0f, 11.0f,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 158:</span>      };</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 159:</span>      mVertexBuffer.put(west);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 160:</span>      indices = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">byte</span>[]{</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 161:</span>              56, 57, 58, 59, 60, 61, 62, 63,</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 162:</span>      };</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 163:</span>      mIndexBuffer.put(indices);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 164:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 165:</span>      mColorBuffer.put(colorLetters);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 166:</span></pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 167:</span>      mColorBuffer.position(0);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 168:</span>      mVertexBuffer.position(0);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 169:</span>      mIndexBuffer.position(0);</pre>
<pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"><span style="color:#606060;"> 170:</span>  }</pre>
</div>
</div>
<p>Esta parte contiene código aparentemente ilógico, como arrays cuyos valores se asignan a mano en vez de en bucle. La idea es que se vea con más claridad de dónde sale cada cosa y para qué se usa.</p>
<p>La variable colorLines contiene los colores de los dos vértices de una línea (en este caso verde, para una explicación del color ver <a href="http://www.glprogramming.com/red/chapter04.html#name2">esta sección del libro rojo</a>). Como vamos a crear cada línea en un bucle usaremos siempre ese array. La variable colorLetters contiene el color (amarillo) de cada vértice de cada línea de cada letra. Vamos a asignar los vértices de las letras una a una, así que esta variable contiene un color por vértice.</p>
<p>Después creamos los buffers, teniendo cuidado a la hora de dar el tamaño correcto en bytes de cada array.</p>
<p>En las líneas 76-99 vemos el bucle que crea cada línea de la brújula. Imaginamos un círculo de radio 32 en el plano XY. Las líneas (un total de 16) serán verticales a ese plano, con longitudes de 12 para las correspondientes a N, S, E y O, 8 para las que indiquen NO, NE, SE y SO, y 4 para las demás. La coordenada z se asigna al principio. Después se calculan x e y en función del seno y el coseno del ángulo (dividimos 2*PI en 16 porciones y vamos haciendo las cuentas).  En las líneas 88-96 asignan cada vértice, donde se puede ver que para cada línea de la brújula solo varía la coordenada z.</p>
<p>La variable mIndexBuffer contiene un array de bytes que le indacarán al renderizador en qué orden se deben procesar los vértices (en este array se puede indicar, por ejemplo, que se repitan vértices ya utilizados). El bucle acaba añadiendo los datos de color para cada vértice.</p>
<p>El resto del constructor es más de lo mismo, pero para las letras. Se dibujan las letras N, S, W, E con líneas, de una forma muy simple, y además utilizando como primitivas líneas sueltas, en vez de líneas continuas (se podía haber usado la primitiva GL_LINE_STRIP para no repetir los vértices que son comunes a más de una línea).</p>
<p>En la siguiente y última entrada, veremos cómo mostrar todo esto en pantalla.</p>
<br />Posted in Android Tagged: desarrollo android, desarrollo móvil, OpenGL, realidad aumentada <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/javiercancela.wordpress.com/463/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/javiercancela.wordpress.com/463/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=463&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://javiercancela.com/2009/08/10/realidad-aumentada-en-android-ar-compass-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/27525d8e018e81a55b107f98b6a45ecd?s=96&#38;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">Javier Cancela</media:title>
		</media:content>
	</item>
		<item>
		<title>Realidad aumentada en Android: AR Compass &#8211; I</title>
		<link>http://javiercancela.com/2009/08/04/realidad-aumentada-en-android-ar-compass-i/</link>
		<comments>http://javiercancela.com/2009/08/04/realidad-aumentada-en-android-ar-compass-i/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 06:00:54 +0000</pubDate>
		<dc:creator>Javier Cancela</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[desarrollo android]]></category>
		<category><![CDATA[desarrollo móvil]]></category>
		<category><![CDATA[realidad aumentada]]></category>

		<guid isPermaLink="false">http://javiercancela.wordpress.com/?p=441</guid>
		<description><![CDATA[Decíamos en el anterior artículo que la realidad aumentada combina datos generados por ordenador con imágenes del entorno obtenidas en tiempo real. La parte complicada es la superposición de los datos sobre la imagen en la posición correcta. Así que vamos a comenzar con una aplicación de realidad levemente aumentada: una brújula virtual. AR Compass [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=441&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Decíamos en el <a href="http://javiercancela.com/2009/08/03/realidad-aumentada-en-android-introduccion/">anterior artículo</a> que la realidad aumentada combina datos generados por ordenador con imágenes del entorno obtenidas en tiempo real. La parte complicada es la superposición de los datos sobre la imagen en la posición correcta. Así que vamos a comenzar con una aplicación de realidad <em>levemente</em> aumentada: una brújula virtual.</p>
<p><strong>AR Compass<img style="display:inline;margin-left:0;margin-right:0;border-width:0;" title="Mi pantalla apunta al noroeste" src="http://javiercancela.files.wordpress.com/2009/08/compass2.png?w=252&#038;h=172" border="0" alt="Mi pantalla apunta al noroeste" width="252" height="172" align="right" /></strong></p>
<p>AR Compass (brújula de realidad aumentada, en inglés queda más <em>cool</em>) es una aplicación para Android que muestra una brújula superpuesta a la imagen capturada por la cámara. La brújula consiste en una serie de líneas verticales con el norte, el sur, el este y el oeste marcados.</p>
<p>La aplicación usa OpenGL para mostrar los puntos cardinales sobre la imagen de la cámara. A partir de los datos del acelerómetro y del magnetómetro obtenemos la matriz de rotación que nos permite mostrar la dirección correcta en la pantalla.</p>
<p><strong>La imagen de la cámara</strong></p>
<p>Es código para mostrar la imagen de la cámara es bastante simple, y se puede sacar del ejemplo <a href="http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.html">CameraPreview</a>:</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;">
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   1:</span> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> CameraPreview <span style="color:#0000ff;">extends</span> Activity {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">   2:</span>     <span style="color:#0000ff;">private</span> Preview mPreview;</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   3:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">   4:</span>     @Override</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   5:</span>     <span style="color:#0000ff;">protected</span> <span style="color:#0000ff;">void</span> onCreate(Bundle savedInstanceState) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">   6:</span>         <span style="color:#0000ff;">super</span>.onCreate(savedInstanceState);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   7:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">   8:</span>         <span style="color:#008000;">// Hide the window title.</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   9:</span>         requestWindowFeature(Window.FEATURE_NO_TITLE);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  10:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  11:</span>         <span style="color:#008000;">// Create our Preview view and set it as the content of our activity.</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  12:</span>         mPreview = <span style="color:#0000ff;">new</span> Preview(<span style="color:#0000ff;">this</span>);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  13:</span>         setContentView(mPreview);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  14:</span>     }</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  15:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  16:</span> }</pre>
</div>
</div>
<p></p>
<p>En la línea 9 indicamos que no queremos que la ventana tenga titulo. Después simplemente instanciamos la vista y se la asignamos a la actividad. La vista es la clase Preview, que hereda de <a href="http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.html">SurfaceView</a>. SurfaceView es un tipo de vista que se caracteriza por contener una superficie (un objeto <a href="http://developer.android.com/reference/android/view/Surface.html">Surface</a>) sobre la que dibujar.</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;">
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   1:</span> <span style="color:#0000ff;">class</span> Preview <span style="color:#0000ff;">extends</span> SurfaceView <span style="color:#0000ff;">implements</span> SurfaceHolder.Callback {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">   2:</span>     SurfaceHolder mHolder;</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   3:</span>     Camera mCamera;</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">   4:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   5:</span>     Preview(Context context) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">   6:</span>         <span style="color:#0000ff;">super</span>(context);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   7:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">   8:</span>         <span style="color:#008000;">// Install a SurfaceHolder.Callback so we get notified when the</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   9:</span>         <span style="color:#008000;">// underlying surface is created and destroyed.</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  10:</span>         mHolder = getHolder();</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  11:</span>         mHolder.addCallback(<span style="color:#0000ff;">this</span>);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  12:</span>         mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  13:</span>     }</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  14:</span> ...</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  15:</span> }</pre>
</div>
</div>
<p></p>
<p>Además de heredar de SurfaceView, la clase Preview implementa la interfaz <a href="http://developer.android.com/reference/android/view/SurfaceHolder.Callback.html">SurfaceHolder.Callback</a>. La clase <a href="http://developer.android.com/reference/android/view/SurfaceHolder.html">SurfaceHolder</a> es el contendor que nos da acceso a la superficie, la cual no se suele usar directamente. A través de los métodos de esta interfaz nos enteraremos de cuando se crea, destruye o cambia de tamaño la superficie.</p>
<p>Las líneas 10 y 11 sirven para indicarle al SurfaceHolder que notifique los cambios de la superficie a nuestra instancia. La línea 12 especifica el tipo de superficie a usar, en este caso una que no posee sus propios buffers. No tengo muy claro qué significa esto, pero imagino que el resto de los tipos de superficie tendrán uno o dos buffers para renderizar la imagen, mientras que este tipo necesita que le propercionen los buffers con la imagen a buscar. En cualquier caso es el único tipo con el que funciona la cámara.</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;">
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   1:</span> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> surfaceCreated(SurfaceHolder holder) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">   2:</span>     <span style="color:#008000;">// The Surface has been created, acquire the camera and tell it where</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   3:</span>     <span style="color:#008000;">// to draw.</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">   4:</span>     mCamera = Camera.open();</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   5:</span>     <span style="color:#0000ff;">try</span> {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">   6:</span>        mCamera.setPreviewDisplay(holder);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   7:</span>     } <span style="color:#0000ff;">catch</span> (IOException exception) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">   8:</span>         mCamera.release();</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">   9:</span>         mCamera = null;</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  10:</span>         <span style="color:#008000;">// TODO: add more exception handling logic here</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  11:</span>     }</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  12:</span> }</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  13:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  14:</span> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> surfaceDestroyed(SurfaceHolder holder) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  15:</span>     <span style="color:#008000;">// Surface will be destroyed when we return, so stop the preview.</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  16:</span>     <span style="color:#008000;">// Because the CameraDevice object is not a shared resource, it's very</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  17:</span>     <span style="color:#008000;">// important to release it when the activity is paused.</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  18:</span>     mCamera.stopPreview();</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  19:</span>     mCamera.release();</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  20:</span>     mCamera = null;</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  21:</span> }</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  22:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  23:</span> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> surfaceChanged(SurfaceHolder holder, <span style="color:#0000ff;">int</span> format, <span style="color:#0000ff;">int</span> w, <span style="color:#0000ff;">int</span> h) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  24:</span>     <span style="color:#008000;">// Now that the size is known, set up the camera parameters and begin</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  25:</span>     <span style="color:#008000;">// the preview.</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  26:</span>     Camera.Parameters parameters = mCamera.getParameters();</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  27:</span>     parameters.setPreviewSize(w, h);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  28:</span>     mCamera.setParameters(parameters);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#606060;">  29:</span>     mCamera.startPreview();</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;"><span style="color:#606060;">  30:</span> }</pre>
</div>
</div>
<p></p>
<p>En estos tres métodos se notifican los eventos relacionados con la superficie donde mostramos la imagen de la cámara. El primero de ellos es surfaceCreated. El bucle de nuestra aplicación recibe un mensaje indicándole que la superficie ha sido creada, e invoca este método pasándole el SurfaceHolder de la misma. En la línea 4 &#8220;abrimos&#8221; la cámara  y en la 6 le decimos que muestre la imagen de previsualización usando la superficie asociada al <em>holder</em>. Si hay algún problema liberamos la cámara.</p>
<p>Cuando la superficie se destruye (por ejemplo, porque se va a iniciar otra actividad) detenemos la previsualización y liberamos la cámara. El ejemplo de la SDK no incluye la llamada a release(), lo que provoca excepciones <em>Out of memory</em> cuando la ventana se destruye y posteriormente se quiere volver a usar la cámara.</p>
<p>El método surfaceChanged se invoca si la superficie cambia de tamaño (si la pantalla gira, por ejemplo). En nuestro ejemplo no se usará, porque vamos a fijar la ventana de la actividad a formato <em>landscape</em>.</p>
<p>Para usar la cámara necesitaremos los permisos adecuados, en este caso <em>&lt;uses-permission android:name=&#8221;android.permission.CAMERA&#8221; /&gt;</em>. Precisamente <a title="Android 1.5 SDK, Release 3" href="http://developer.android.com/sdk/RELEASENOTES.html#1.5_r3">la última revisión de la SDK</a> corrige un error por el cual no se forzaba correctamente este permiso.</p>
<p>En la próxima entrada comenzaremos a usar OpenGL para añadir la brújula sobre la cámara.</p>
<br />Posted in Android Tagged: Android, desarrollo android, desarrollo móvil, realidad aumentada <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/javiercancela.wordpress.com/441/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/javiercancela.wordpress.com/441/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=441&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://javiercancela.com/2009/08/04/realidad-aumentada-en-android-ar-compass-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/27525d8e018e81a55b107f98b6a45ecd?s=96&#38;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">Javier Cancela</media:title>
		</media:content>

		<media:content url="http://javiercancela.files.wordpress.com/2009/08/compass2.png" medium="image">
			<media:title type="html">Mi pantalla apunta al noroeste</media:title>
		</media:content>
	</item>
		<item>
		<title>Realidad aumentada en Android &#8211; Introducción</title>
		<link>http://javiercancela.com/2009/08/03/realidad-aumentada-en-android-introduccion/</link>
		<comments>http://javiercancela.com/2009/08/03/realidad-aumentada-en-android-introduccion/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 07:00:05 +0000</pubDate>
		<dc:creator>Javier Cancela</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[desarrollo móvil]]></category>
		<category><![CDATA[realidad aumentada]]></category>

		<guid isPermaLink="false">http://javiercancela.com/?p=421</guid>
		<description><![CDATA[¿Qué es la realidad aumentada? Un sistema de realidad aumentada es aquel que combina datos generados por ordenador con imágenes del entorno obtenidas en tiempo real. Un sistema básico de realidad aumentada consiste en dispositivo compuesto por una cámara, una fuente de datos y una pantalla donde se muestra la imagen capturada por la cámara [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=421&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<div><strong>¿Qué es la realidad aumentada?</strong></div>
<div class="wp-caption alignright" style="width: 250px"><a href="http://www.flickr.com/photos/jamais_cascio/2756996849/"><img class=" " title="Handheld Augmented Reality" src="http://farm4.static.flickr.com/3128/2756996849_b15bb86dac_m_d.jpg" alt="Handheld Augmented Reality" width="240" height="188" /></a><p class="wp-caption-text">Buscando descuentos con el móvil</p></div>
<p>Un sistema de realidad aumentada es aquel que combina datos generados por ordenador con imágenes del entorno obtenidas en tiempo real. Un sistema básico de realidad aumentada consiste en dispositivo compuesto por una cámara, una fuente de datos y una pantalla donde se muestra la imagen capturada por la cámara con los datos superpuestos. Los datos que aparecen dependerán de la posición y orientación de la cámara, o bien de la presencia en la imagen (y por lo tanto en la escena real) de marcadores que indiquen la información a mostrar.</p>
<div>Dos ejemplos para que quede claro de qué estamos hablando:</div>
<div>
<ul>
<li><a id="dkp8" title="Wikitude AR Travel Guide" href="http://www.youtube.com/watch?v=8EA8xlicmT8">Wikitude AR Travel Guide</a></li>
<li><a id="qps_" title="Augmented Reality Tower Defense" href="http://www.youtube.com/watch?v=zyWVH6jkDHg">Augmented Reality Tower Defense</a></li>
</ul>
</div>
<div><strong>¿Cómo funciona la realidad aumentada?</strong></div>
<div>Un sistema de realidad aumentada proporciona información contextual, donde el contexto es el mundo que nos rodea. Añade datos de interés a lo que podemos apreciar a simple vista,  superponiéndolos en la pantalla. No es una ideanueva, pero ha adquirido relevancia en los últimos meses gracias a la aparición de los móviles de última generación, que poseen las características necesarias para hacer funcionar aplicaciones basadas en esta idea:</div>
<div class="wp-caption alignright" style="width: 250px"><a href="http://www.flickr.com/photos/sputz/3215919363/"><img title="Augmented Reality" src="http://farm4.static.flickr.com/3433/3215919363_85017cc879_m_d.jpg" alt="" width="240" height="160" /></a><p class="wp-caption-text">Los seis marcadores de la mesa se conviernte en figuras en la pantalla</p></div>
<div>
<ul>
<li>Una cámara. No es necesario que grabe vídeo, basta con que la pantalla del móvil sirva como visor.</li>
<li>Una interfaz de programación que permita acceder a la imagen proporcionada por la cámara.</li>
</ul>
<div>Estas dos características bastaría para desarrollar una aplicación de realidad aumentada basada en marcadores. Solo tendríamos que identificar y procesar estos marcadores para sustituirlos por la información apropiada. Sin embargo, dos sensores cada vez más habituales en los dispositivos móviles nos permiten ampliar las posibilidades:</div>
<div>
<ul>
<li>El GPS.</li>
<li>El sensor de orientación</li>
</ul>
<div>
<div class="wp-caption alignleft" style="width: 250px"><a href="http://www.flickr.com/photos/ericrice/3180390313/"><img title="iPhone Augmented Reality concept" src="http://farm4.static.flickr.com/3500/3180390313_08f8263850_m_d.jpg" alt="" width="240" height="128" /></a><p class="wp-caption-text">La Acrópolis restaurada virtualmente</p></div>
<p>Imaginemos que queremos diseñar una aplicación de realidad virtual que identifique edificios y lugares de interés turístico, mostrando sobre los mismos su nombre, fecha de construcción, horarios de visita&#8230; En este caso se plantea el problema técnico de mostrar esta información sobre la parte de la pantalla donde se esté viendo el lugar correspondiente. Para ello necesitamos que la información esté geoposicionada (disponer de las coordenadas del lugar), y necesitamos una forma de relacionar estas coordenadas con la posición y la orientación de la cámara, las cuales obtendremos de los sensores del dispositivo.</p></div>
<p>Esta última parte es la más complicada desde un punto del desarrollador. En los próximos artículos vamos a ver una serie de ejemplos básicos, con código, para hacernos una idea de cómo se podría desarrollar una aplicación de este tipo.</p></div>
</div>
<br />Posted in Android Tagged: Android, desarrollo móvil, realidad aumentada <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/javiercancela.wordpress.com/421/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/javiercancela.wordpress.com/421/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=421&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://javiercancela.com/2009/08/03/realidad-aumentada-en-android-introduccion/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/27525d8e018e81a55b107f98b6a45ecd?s=96&#38;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">Javier Cancela</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3128/2756996849_b15bb86dac_m_d.jpg" medium="image">
			<media:title type="html">Handheld Augmented Reality</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3433/3215919363_85017cc879_m_d.jpg" medium="image">
			<media:title type="html">Augmented Reality</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3500/3180390313_08f8263850_m_d.jpg" medium="image">
			<media:title type="html">iPhone Augmented Reality concept</media:title>
		</media:content>
	</item>
		<item>
		<title>Desarrollo en Android: aceler&#243;metro, magnet&#243;metro y sensores de orientaci&#243;n y temperatura en el HTC Magic</title>
		<link>http://javiercancela.com/2009/07/20/desarrollo-en-android-acelermetro-magnetmetro-y-sensores-de-orientacin-y-temperatura-en-el-htc-magic/</link>
		<comments>http://javiercancela.com/2009/07/20/desarrollo-en-android-acelermetro-magnetmetro-y-sensores-de-orientacin-y-temperatura-en-el-htc-magic/#comments</comments>
		<pubDate>Mon, 20 Jul 2009 05:00:00 +0000</pubDate>
		<dc:creator>Javier Cancela</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[acelerómetro]]></category>
		<category><![CDATA[desarrollo android]]></category>
		<category><![CDATA[desarrollo móvil]]></category>
		<category><![CDATA[magnetómetro]]></category>

		<guid isPermaLink="false">http://javiercancela.wordpress.com/?p=401</guid>
		<description><![CDATA[Android permite acceder a los sensores internos del dispositivo a través de las clases Sensor, SensorEvent y SensorManager, y de la interfaz SensorEventListener, del paquete android.hardware. La clase Sensor acepta ocho tipos de sensores, como se puede ver en la referencia. Los sensores disponibles varían en función del aparato utilizado. Listar los sensores del dispositivo [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=401&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Android permite acceder a los sensores internos del dispositivo a través de las clases <span>Sensor</span>, <span>SensorEvent</span> y <span>SensorManager</span>, y de la interfaz <span>SensorEventListener</span>, del paquete <span>android.hardware</span>.</p>
<p>La clase <span>Sensor </span>acepta ocho tipos de sensores, como se puede ver en la <a href="http://developer.android.com/reference/android/hardware/Sensor.html">referencia</a>. Los sensores disponibles varían en función del aparato utilizado.</p>
<p><strong>Listar los sensores del dispositivo</strong></p>
<p>Para ver de qué sensores dispone nuestro dispositivo usamos la clase <span>SensorManager</span>:</p>
<div class="csharpcode">
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;padding:0;">
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   1:</span> <span style="color:#008000;">// Solicitamos al sistema el servicio que gestiona los sensores</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   2:</span> SensorManager mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   3:</span> <span style="color:#008000;">// Peimos la lista con todos los sensores disponibles</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   4:</span> List&lt;Sensor&gt; listSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   5:</span> <span style="color:#008000;">// Iteramos y mostramos</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   6:</span> <span style="color:#0000ff;">for</span>(Sensor sensor:listSensors)</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   7:</span> {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   8:</span>     Log.i(<span style="color:#006080;">"SENSOR"</span>, sensor.getName());</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   9:</span> }</pre>
</div>
</div>
</div>
<p>La nueva versión de la SDK marca como obsoleto (<em>deprecated</em>) el método <span>getSensors</span> de la clase <span>SensorManager</span><span>, </span>así como la <span>interfaz SensorListener. Aunque los métodos antiguos son necesarios para versiones anteriores de la SDK, los ejemplos de este artículos se basan en la última versión. </span></p>
<p><span><strong>Los sensores del HTC Magic</strong></span></p>
<p>Esta es una lista de los valores devueltos por el código anterior ejecutándose en el HTC Magic:</p>
<ul>
<li>AK8976A 3-axis Accelerometer</li>
<li>AK8976A 3-axis Magnetic field sensor</li>
<li>AK8976A Orientation sensor</li>
<li>AK8976A Temperature sensor</li>
</ul>
<p>El <a href="http://www.asahi-kasei.co.jp/asahi/en/news/2005/e060322.html">AK8976A</a> (arriba a la izquierda en <a href="http://i.cmpnet.com/eetimes/news/online/2008/10/igoogle_2.jpg">esta figura</a>, que muestra el hardware del HTC Dream) es una combinación de acelerómetro de tres ejes y magnetómetro de tres ejes. Combinando la lectura de los campos gravitatorio y magnético terrestres proporciona también información de orientación. Incluye además un sensor interno de temperatura, útil para comprobar si el móvil se está calentado demasiado.</p>
<p><strong>Acceso a los datos del sensor</strong></p>
<p>Para tener acceso a los datos del sensor debemos indicárselo al <span>SensorManager </span>con el método <span>registerListener</span>:</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;padding:0;">
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   1:</span> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> MiActividad <span style="color:#0000ff;">extends</span> Activity {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   2:</span>     MiVista mVista; <span style="color:#008000;">// Clase que implemente SensorEventListener</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   3:</span>     <span style="color:#008000;">// ...</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   4:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   5:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   6:</span>     @Override</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   7:</span>    <span style="color:#0000ff;">protected</span> <span style="color:#0000ff;">void</span> onCreate(Bundle savedInstanceState) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   8:</span>         <span style="color:#0000ff;">super</span>.onCreate(savedInstanceState);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   9:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  10:</span>         <span style="color:#008000;">// En esta clase recibiré los eventos y usaré el resultado para lo que quiera</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  11:</span>         mVista = <span style="color:#0000ff;">new</span> MiVista(<span style="color:#0000ff;">this</span>);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  12:</span>         SensorManager mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  13:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  14:</span>         <span style="color:#008000;">// Cada sensor se registra por separado</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  15:</span>         List&lt;Sensor&gt; listSensors = mSensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  16:</span>         Sensor orientationSensor = listSensors.get(0);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  17:</span>         mSensorManager.registerListener(mTop, orientationSensor, SensorManager.SENSOR_DELAY_UI);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  18:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  19:</span>         listSensors = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  20:</span>         Sensor acelerometerSensor = listSensors.get(0);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  21:</span>         mSensorManager.registerListener(mTop, acelerometerSensor, SensorManager.SENSOR_DELAY_UI);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  22:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  23:</span>         listSensors = mSensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  24:</span>         Sensor magneticSensor = listSensors.get(0);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  25:</span>         mSensorManager.registerListener(mTop, magneticSensor, SensorManager.SENSOR_DELAY_UI);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  26:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  27:</span>         listSensors = mSensorManager.getSensorList(Sensor.TYPE_TEMPERATURE);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  28:</span>         Sensor temperatureSensor = listSensors.get(0);</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  29:</span>         mSensorManager.registerListener(mTop, temperatureSensor, SensorManager.SENSOR_DELAY_UI);</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  30:</span>         ...</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  31:</span>     }</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  32:</span>     ...</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  33:</span> }</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  34:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  35:</span> <span style="color:#0000ff;">class</span> MiVista <span style="color:#0000ff;">extends</span> View <span style="color:#0000ff;">implements</span> SensorEventListener {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  36:</span> ...</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  37:</span> }</pre>
</div>
</div>
<div></div>
<p>Es necesario registrar cada tipo de sensor por separado para poder obtener información de todos ellos. El método registerListener toma como primer parámetro la instancia de la clase que implementa el <em>SensorEventListener</em>, y que veremos a continuación. El tercer parámetro acepta cuatro posibles valores, que indican al sistema con qué frecuencia nos gustaría recibir actualizaciones del sensor. Esta indicación sirve para que el sistema estime cuánta atención necesitan los sensores, pero no garantiza una frecuencia concreta.</p>
<p><strong>Obtención de datos</strong></p>
<p>Para recibir los datos tenemos que implementar dos métodos de SensorEventListener:</p>
<div id="codeSnippetWrapper">
<div id="codeSnippet" style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;padding:0;">
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   1:</span> <span style="color:#0000ff;">class</span> MiVista <span style="color:#0000ff;">extends</span> View <span style="color:#0000ff;">implements</span> SensorEventListener {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   2:</span>     <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">float</span>   mOrientationValues[] = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">float</span>[3];</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   3:</span>     <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">float</span>   mAccelerometerValues[] = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">float</span>[3];</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   4:</span>     <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">float</span>   mMagneticValues[] = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">float</span>[3];</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   5:</span>     <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">float</span>   mTemperatureValues;</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   6:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   7:</span>     <span style="color:#008000;">/*</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   8:</span> <span style="color:#008000;">    * El resto del código de la clase para mostrar los datos</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">   9:</span> <span style="color:#008000;">    */</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  10:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  11:</span>     <span style="color:#008000;">// En este ejemplo no necesitamos enterarnos de las variaciones de </span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  12:</span>     <span style="color:#008000;">// precisión del sensor</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  13:</span>     @Override</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  14:</span>     <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> onAccuracyChanged(Sensor sensor, <span style="color:#0000ff;">int</span> accuracy) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  15:</span>         <span style="color:#008000;">// TODO Auto-generated method stub</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  16:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  17:</span>     }</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  18:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  19:</span>     @Override</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  20:</span>     <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> onSensorChanged(SensorEvent event) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  21:</span>         <span style="color:#008000;">// Cada sensor puede provocar que un thread pase por aquí, así </span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  22:</span>         <span style="color:#008000;">// que sincronizamos el acceso</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  23:</span>         <span style="color:#0000ff;">synchronized</span> (<span style="color:#0000ff;">this</span>) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  24:</span>             <span style="color:#0000ff;">switch</span>(event.sensor.getType()) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  25:</span>             <span style="color:#0000ff;">case</span> Sensor.TYPE_ORIENTATION:</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  26:</span>                 <span style="color:#0000ff;">for</span> (<span style="color:#0000ff;">int</span> i=0 ; i&lt;3 ; i++) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  27:</span>                     mOrientationValues[i] = event.values[i];</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  28:</span>                 }</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  29:</span>                 <span style="color:#0000ff;">break</span>;</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  30:</span>             <span style="color:#0000ff;">case</span> Sensor.TYPE_ACCELEROMETER:</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  31:</span>                 <span style="color:#0000ff;">for</span> (<span style="color:#0000ff;">int</span> i=0 ; i&lt;3 ; i++) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  32:</span>                     mAccelerometerValues[i] = event.values[i];</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  33:</span>                 }</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  34:</span>                 <span style="color:#0000ff;">break</span>;</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  35:</span>             <span style="color:#0000ff;">case</span> Sensor.TYPE_MAGNETIC_FIELD:</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  36:</span>                 <span style="color:#0000ff;">for</span> (<span style="color:#0000ff;">int</span> i=0 ; i&lt;3 ; i++) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  37:</span>                     mMagneticValues[i] = event.values[i];</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  38:</span>                 }</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  39:</span>                 <span style="color:#0000ff;">break</span>;</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  40:</span>             <span style="color:#0000ff;">default</span>:</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  41:</span>                 <span style="color:#0000ff;">for</span> (<span style="color:#0000ff;">int</span> i=0 ; i&lt;event.values.length ; i++) {</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  42:</span>                     mTemperatureValues = event.values[i];</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  43:</span>                 }</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  44:</span>             }</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  45:</span></pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  46:</span>             invalidate();</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  47:</span>         }</pre>
<pre style="text-align:left;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  48:</span>     }</pre>
<pre style="text-align:left;line-height:12pt;background-color:white;width:100%;font-family:'Courier New', courier, monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;border-style:none;margin:0;padding:0;"><span style="color:#606060;">  49:</span> }</pre>
</div>
</div>
<p>Cuando el evento se dispara en el método onSensorChanged comprobamos qué sensor lo ha causado y leemos los datos. Los posibles valores devueltos se indican en la <a href="http://developer.android.com/reference/android/hardware/SensorEvent.html">documentación de la clase SensorEvent</a>.</p>
<p>La clase SensorManager tiene además tres métodos (getInclination, getOrientation y getRotationMatrix), usados para calcular transformaciones de coordenadas. De ellos hablaremos en un próximo artículo.</p>
<br />Posted in Android Tagged: acelerómetro, desarrollo android, desarrollo móvil, magnetómetro <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/javiercancela.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/javiercancela.wordpress.com/401/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=401&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://javiercancela.com/2009/07/20/desarrollo-en-android-acelermetro-magnetmetro-y-sensores-de-orientacin-y-temperatura-en-el-htc-magic/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/27525d8e018e81a55b107f98b6a45ecd?s=96&#38;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">Javier Cancela</media:title>
		</media:content>
	</item>
		<item>
		<title>Errores emulando el GPS en Android</title>
		<link>http://javiercancela.com/2009/07/15/errores-emulando-el-gps-en-android/</link>
		<comments>http://javiercancela.com/2009/07/15/errores-emulando-el-gps-en-android/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 06:00:47 +0000</pubDate>
		<dc:creator>Javier Cancela</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[DDMS]]></category>
		<category><![CDATA[desarrollo android]]></category>
		<category><![CDATA[GPS]]></category>

		<guid isPermaLink="false">http://javiercancela.wordpress.com/?p=390</guid>
		<description><![CDATA[Existen dos formas de enviar datos al GPS del emulador de Android: con el DDMS (Dalvik Debug Monitor Service) y con la instrucción &#8216;geo&#8217; de la consola del emulador (como se explica en la documentación [http://developer.android.com/guide/topics/location/index.html#location]). El DDMS es especialmente útil, ya que permite cargar archivos kml o gpx a partir de los cuales enviar [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=390&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<div id="_mcePaste" style="position:absolute;width:1px;height:1px;top:0;left:-10000px;">Existen dos formas de enviar datos al GPS del emulador de Android: con el DDMS (Dalvik Debug Monitor Service) y con la instrucción &#8216;geo&#8217; de la consola del emulador (como se explica en la documentación [http://developer.android.com/guide/topics/location/index.html#location]). El DDMS es especialmente útil, ya que permite cargar archivos kml o gpx a partir de los cuales enviar actualizaciones periódicas al emulador. Sin embargo, en la versión 1.5 r2 de la SDK de Android hay dos bugs que resultan bastante molestos para desarrollar aplicaciones que usan el GPS.</div>
<div id="_mcePaste" style="position:absolute;width:1px;height:1px;top:0;left:-10000px;">El primero de ellos está relacionado con el formato de las coordenadas enviadas al emulador. Por algún motivo (probablemente relacionado con el caracter usado para separa los decimales, &#8216;,&#8217; en español y &#8216;.&#8217; en inglés) el emulador sólo recibe correctamente las actualizaciones si la configuración regional está establecida a idioma inglés. En realidad no es necesario cambiar la configuración local de todo el sistema. Usando DDMS, basta con establecer la siguiente variable de entorno: &#8216;java_debug=-Duser.language=en&#8217;, o, si usamos el plugin para Eclipse, añadir &#8216;-Duser.language=en&#8217; al eclipse.ini. Más información en la incidencia abierta en Google Code [http://code.google.com/p/android/issues/detail?id=915].</div>
<div id="_mcePaste" style="position:absolute;width:1px;height:1px;top:0;left:-10000px;">El segundo error se produce cuando intentamos enviar varias actualizaciones al GPS del emulador. Por algún motivo las localizaciones enviadas después de la primera no llegan al emulador. Esto significa que el método onLocationChanged sólo será invocado una vez. En la discusión sobre la incidencia abierta [http://code.google.com/p/android/issues/detail?id=2545] se indica una solución provisional: cancelar la subscripción al LocationListener y volverla a subscribir:</div>
<div id="_mcePaste" style="position:absolute;width:1px;height:1px;top:0;left:-10000px;">public void onLocationChanged(Location location) {</div>
<div id="_mcePaste" style="position:absolute;width:1px;height:1px;top:0;left:-10000px;"><span style="white-space:pre;"> </span>mLocationManager.removeUpdates(locationListener);</div>
<div id="_mcePaste" style="position:absolute;width:1px;height:1px;top:0;left:-10000px;"><span style="white-space:pre;"> </span>mLocationManager.requestLocationUpdates(</div>
<div id="_mcePaste" style="position:absolute;width:1px;height:1px;top:0;left:-10000px;">LocationManager.GPS_PROVIDER,</div>
<div id="_mcePaste" style="position:absolute;width:1px;height:1px;top:0;left:-10000px;">3000,</div>
<div id="_mcePaste" style="position:absolute;width:1px;height:1px;top:0;left:-10000px;">1,</div>
<div id="_mcePaste" style="position:absolute;width:1px;height:1px;top:0;left:-10000px;">locationListener);</div>
<p>Existen dos formas de enviar datos al GPS del emulador de Android: con el DDMS (Dalvik Debug Monitor Service) y con la instrucción &#8216;geo&#8217; de la consola del emulador (como se explica en la <a href="http://developer.android.com/guide/topics/location/index.html#location">documentación</a>). El DDMS es especialmente útil, ya que permite cargar archivos kml o gpx a partir de los cuales enviar actualizaciones periódicas al emulador. Sin embargo, en la versión 1.5 r2 de la SDK de Android hay dos bugs que resultan bastante incómodos.</p>
<p><strong>El GPS no recibe ninguna señal</strong></p>
<p>El primero de ellos está relacionado con el formato de las coordenadas enviadas al emulador. Por algún motivo (probablemente relacionado con el carácter usado para separa los decimales, la coma en español y punto en inglés) el emulador sólo recibe correctamente las actualizaciones si la configuración regional está establecida a idioma inglés.</p>
<p>Para solucionar este problema basta cambiar el <em>locale</em> del runtime de java. Usando DDMS, se establece la siguiente variable de entorno: &#8216;java_debug=-Duser.language=en&#8217;, o, si usamos el plugin para Eclipse, se añade &#8216;-Duser.language=en&#8217; al archivo eclipse.ini. Más información en la <a href="http://code.google.com/p/android/issues/detail?id=915">incidencia abierta en Google Code</a>.</p>
<p><strong>El GPS sólo recibe la primera localización</strong></p>
<table border="0" cellspacing="0" cellpadding="2" width="460">
<tbody>
<tr>
<td width="458" valign="top"><span style="color:#ff0000;">Actualización: La versión 1.5 release 3 de la SDK ya corrige este error</span></td>
</tr>
</tbody>
</table>
<p>El segundo error se produce cuando intentamos enviar varias actualizaciones al GPS del emulador. Por algún motivo las localizaciones enviadas después de la primera no llegan al emulador. Esto significa que el método onLocationChanged sólo será invocado una vez. En la discusión sobre la <a href="http://code.google.com/p/android/issues/detail?id=2545">incidencia abierta</a> se indica una solución provisional: cancelar la subscripción al LocationListener y volverla a subscribir:</p>
<blockquote>
<pre>public void onLocationChanged(Location location) {
<span style="white-space:pre;"> </span>mLocationManager.removeUpdates(locationListener);
<span style="white-space:pre;"> </span>mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
3000,
1,
locationListener);
...
}</pre>
</blockquote>
<p>No he podido confirmar que este error afecte a todo el mundo que usa la SDK 1.5 r2, aunque sí está bastante extendido. Es de suponer que Google lo corregirá en la próxima revisión de la SDK.</p>
<br />Posted in Android Tagged: Android, DDMS, desarrollo android, GPS <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/javiercancela.wordpress.com/390/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/javiercancela.wordpress.com/390/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=390&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://javiercancela.com/2009/07/15/errores-emulando-el-gps-en-android/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/27525d8e018e81a55b107f98b6a45ecd?s=96&#38;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">Javier Cancela</media:title>
		</media:content>
	</item>
		<item>
		<title>Notificaciones &#8216;push&#8217; en dispositivos móviles</title>
		<link>http://javiercancela.com/2009/07/13/notificaciones-push-en-dispositivos-moviles/</link>
		<comments>http://javiercancela.com/2009/07/13/notificaciones-push-en-dispositivos-moviles/#comments</comments>
		<pubDate>Mon, 13 Jul 2009 06:00:48 +0000</pubDate>
		<dc:creator>Javier Cancela</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[BlackBerry]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Notificaciones Push]]></category>

		<guid isPermaLink="false">http://javiercancela.com/?p=366</guid>
		<description><![CDATA[¿Qué es una notificación push? Es un mensaje que una aplicación servidora envía a una aplicación cliente indicándole que tiene algún tipo de información nueva disponible. Lo que distingue a las notificaciones push es que el servidor inicia la comunicación, no espera a que el cliente pregunte si hay algo nuevo. La ventaja es la [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=366&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p><strong>¿Qué es una notificación <em>push</em></strong><strong>?</strong></p>
<p><a href="http://www.flickr.com/photos/jeffhenshaw/3225601827/"><img class=" alignright" style="border:5px solid black;" title="Jeff Henshaw: Apple's Push Notification Service" src="http://farm4.static.flickr.com/3341/3225601827_3aa6473718_m.jpg" alt="Jeff Henshaw: Apples Push Notification Service" width="240" height="135" /></a></p>
<p>Es un mensaje que una aplicación servidora envía a una aplicación cliente indicándole que tiene algún tipo de información nueva disponible. Lo que distingue a las notificaciones <em>push </em>es que el servidor inicia la comunicación, no espera a que el cliente pregunte si hay algo nuevo. La ventaja es la inmediatez: la información llega al cliente (y por tanto al usuario) en cuanto está disponible en el servidor.</p>
<p>El ejemplo más clásico de este tipo de notificaciones es el correo electrónico. Un usuario tiene una aplicación de correo electrónico ejecutándose en su dispositivo. Alguien le envía un correo, que queda almacenado en el servidor. A partir de ahí pueden ocurrir dos cosas:</p>
<ul>
<li>El cliente de correo electrónico está configurado para consultar al servidor, con una frecuencia predeterminada, si hay nuevos correos. Si la frecuencia es de una vez cada 5 minutos el usuario puede tardar ese tiempo en enterarse de que ha recibido un correo nuevo.</li>
<li>El cliente (y el servidor) soportan notificaciones <em>push</em>. En este caso el servidor envía un mensaje al cliente para avisarle de que ha llegado un nuevo correo, y el cliente a su vez se lo notifica de alguna forma al usuario para que lo lea si le interesa.</li>
</ul>
<p>En el caso de las aplicaciones de mensajería instantánea la necesidad de la inmediatez es aún más manifiesta: para que la conversación sea fluida necesitamos que los mensajes nos lleguen en cuanto son enviados, e incluso queremos saber cuándo nuestro interlocutor está escribiendo algo.</p>
<p><strong>¿Cómo se implementa una notificación <em>push</em></strong><strong>?</strong></p>
<p>La manera habitual de implementar una notificación <em>push </em>es establecer una conexión TCP de larga duración. El cliente abre una conexión TCP con el servidor y la deja abierta. Sobre esta conexión TCP el servidor enviará las notificaciones al cliente, usando algún protocolo de aplicación. <a title="IMAP" href="http://en.wikipedia.org/wiki/Internet_Message_Access_Protocol" target="_self">IMAP</a> y <a title="XMPP" href="http://en.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol" target="_self">XMPP</a> son ejemplos de protocolos estándar usados para correo y mensajería respectivamente, aunque existen múltiples protocolos propietarios.</p>
<p><strong>Notificaciones <em>push </em></strong><strong>en BlackBerry</strong></p>
<p><a href="http://www.flickr.com/photos/indivisualist/3500715353/"><img class="  alignright" title="BlackBerry" src="http://farm4.static.flickr.com/3547/3500715353_8a83868705_m.jpg" alt="indivisualist - BlackBerry" width="240" height="195" /></a></p>
<p>El éxito de las BlackBerry se debe en parte a su sistema de <em>push email</em>. Cuando leer el correo desde el móvil era una experiencia dolorosa en otros sistemas, las BlackBerry ya conseguían que sus usuarios recibiesen el correo de manera instantánea. RIM subscribe un acuerdo con los operadores de telefonía, por el cual se establece una conexión permanente con unos servidores especiales operados por RIM. Estos servidores reciben el correo del usuario desde los servidores <a href="http://en.wikipedia.org/wiki/BlackBerry_Enterprise_Server">BES</a>, y lo notifican de forma inmediata a las BlackBerry.</p>
<p>La tecnología de notificaciones <em>push </em>de RIM está disponible para terceros a través de la <a href="http://na.blackberry.com/eng/developers/javaappdev/pushapi.jsp?CPID=PUSHAPI00" target="_self">BlackBerry Push API</a>.</p>
<p><strong>Notificaciones <em>push </em></strong><strong>en iPhone</strong></p>
<p>Apple incorporó desde el principio un sistema de notificaciones <em>push </em>para el correo electrónico de Yahoo. La aparición de <a href="http://www.apple.com/es/mobileme/">MobileMe</a> añadió notificaciones <em>push </em>tanto para el correo como para el calendario y los contactos.</p>
<p>Cuando Apple diseñó la SDK del iPhone tomó la decisión de no permitir a los desarrolladores crear aplicaciones que se ejecutasen en segundo plano. Como consecuencia, las aplicaciones desarrolladas por terceros sólo se ejecutan mientras están en primer plano, deteniéndose cuando el usuario quiere realizar otra actividad.</p>
<p>La nueva versión de la SDK incorpora el <a href="http://developer.apple.com/iphone/program/sdk/">Apple Push Notification service</a>, un servicio que envía notificaciones a las aplicaciones del iPhone aunque estas no se estén ejecutando. Para ello la notificación pasa primero por los servidores de Apple, con los que el móvil mantiene siempre una conexión abierta. La notificación se envía al móvil y se muestra al usuario como un mensaje de texto o como una ventana de notificación, que servirán además para lanzar la aplicación y procesar la notificación recibida.</p>
<p><strong>Notificaciones <em>push </em></strong><strong>en Android</strong></p>
<p>Android proporciona notificaciones <em>push </em>para el correo electrónico, calendario y contactos, tanto en el HTC Dream como en el HTC Magic. Como en los casos anteriores, el sistema establece un canal siempre abierto con los los servidores del proveedor (en este caso Google).</p>
<p>Aunque los desarrolladores de Android tienen la opción de programar aplicaciones que se ejecuten en segundo plano el sistema se reserva el derecho de detener cualquier aplicación cuando así lo decida, en función de los recursos disponibles en la máquina. Así que podemos desarrollar un cliente que mantenga conexiones TCP de larga duración con el servidor ejecutándose en <em>bakcground</em>, pero no podemos garantizar que la aplicación se esté ejecutando para mantener esta conexión abierta. Claro que este problema se presenta aunque queramos traernos la información usando <em>pull</em>, es decir, consultando al servidor de periódicamente.</p>
<p>En las versiones beta de la SDK se incluía un servicio llamada XMPPService o GTalkService, que permitía a los desarrolladores enviar notificaciones utilizando la infraestructura de Google Talk. Este servicio fue retirado de la versión final de la SDK por problemas de seguridad, como se explica aquí: <em><a title="Some information on APIs removed in the Android 0.9 SDK beta" href="http://android-developers.blogspot.com/2008/08/some-information-on-apis-removed-in.html">Some information on APIs removed in the Android 0.9 SDK beta</a></em>. No sería extraño que Google incluyese una versión mejorada en alguna de las próximas versiones de Android.</p>
<br />Posted in Android, BlackBerry, iPhone Tagged: Android, BlackBerry, iPhone, Notificaciones Push <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/javiercancela.wordpress.com/366/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/javiercancela.wordpress.com/366/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=366&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://javiercancela.com/2009/07/13/notificaciones-push-en-dispositivos-moviles/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/27525d8e018e81a55b107f98b6a45ecd?s=96&#38;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">Javier Cancela</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3341/3225601827_3aa6473718_m.jpg" medium="image">
			<media:title type="html">Jeff Henshaw: Apple&#039;s Push Notification Service</media:title>
		</media:content>

		<media:content url="http://farm4.static.flickr.com/3547/3500715353_8a83868705_m.jpg" medium="image">
			<media:title type="html">BlackBerry</media:title>
		</media:content>
	</item>
		<item>
		<title>Impresiones sobre el HTC Magic</title>
		<link>http://javiercancela.com/2009/07/06/impresiones-sobre-el-htc-magic/</link>
		<comments>http://javiercancela.com/2009/07/06/impresiones-sobre-el-htc-magic/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 21:55:30 +0000</pubDate>
		<dc:creator>Javier Cancela</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[HTC Magic]]></category>
		<category><![CDATA[Twidroid]]></category>
		<category><![CDATA[TwitterRide]]></category>

		<guid isPermaLink="false">http://javiercancela.wordpress.com/2009/07/06/impresiones-sobre-el-htc-magic/</guid>
		<description><![CDATA[Ha pasado un mes y medio desde que tengo el HTC Magic. Me pasé de Orange a Vodafone por este móvil, un mes antes de que Orange anunciaran en exclusiva el HTC Hero. En fin… Como Internet está lleno de análisis del Magic me limito a soltar algunas impresiones personales. No he tenido ocasión de [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=365&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<h6></h6>
<p><a href="http://www.flickr.com/photos/yufujamar/3492788468/"><img style="display:inline;margin-left:0;margin-right:0;border-width:0;" title="Foto de yufujamar" border="0" alt="Foto de yufujamar" align="right" src="http://javiercancela.files.wordpress.com/2009/07/3492788468_6d7a024eba.jpg?w=260&#038;h=180" width="260" height="180" /></a> Ha pasado un mes y medio desde que tengo el HTC Magic. Me pasé de Orange a Vodafone por este móvil, un mes antes de que Orange anunciaran en exclusiva el HTC Hero. En fin…</p>
<p>Como Internet está lleno de análisis del Magic me limito a soltar algunas impresiones personales. No he tenido ocasión de usar de forma continuada otros móviles de gama similar, así que no voy a hacer comparaciones.</p>
<ul>
<li>La pantalla es mejor de lo que esperaba. Brillante y nítida. Hubiese sido aún mejor con 3,5 pulgadas. Para evitar llevar la funda puesta le compré un protector de pantalla.&#160; </li>
<li>La interfaz de usuario resulta cómoda y agradable. Fácil de configurar. Echo en falta un sistema rápido para desinstalar aplicaciones. </li>
<li>No hay <em>multitouch</em>. Podría ser útil para ampliar imágenes o páginas web. </li>
<li>El sistema es razonablemente estable, pero de vez en cuando se ralentiza sin motivo aparente. No demasiado a menudo ni durante mucho tiempo, pero resulta molesto. Probablemente se deba a alguna de las aplicaciones instaladas. Aún no se me ha quedado colgado. </li>
<li>El <em>Market</em> contiene una buena cantidad de aplicaciones, tanto de pago como gratuitas. La interfaz es simple pero un poco limitada. Me gustaría que hubiese un sistema para actualizar varias aplicaciones de golpe. </li>
<li>El GPS es muy rápido. El magnetómetro es interesante. El acelerómetro es un pelín lento, o al menos es lenta la transición entre las dos orientaciones posibles de la interfaz. </li>
<li>Por algún motivo no se puede tener el <em>home</em> en formato <em>landscape</em>. </li>
<li>La cámara no tiene flash. Y además es muy mala. </li>
<li>El <em>trackball</em> funciona bien, pero nunca lo uso. </li>
<li>La batería no va sobrada, pero no tengo problemas para que me dure todo el día. </li>
<li>La calidad del sonido en las llamadas en buena. Tener toda la información de los contactos centralizada (y sincronizada con los contactos de GMail) resulta muy cómodo. </li>
<li>El WiFi va bastante bien. El <em>bluetooth</em> no lo he probado. </li>
<li>Me he aficionado a Twitter. Aún no me he decidido entre <a href="http://twidroid.com/">Twidroid</a> y <a href="http://twitterride.net/">TwitterRide</a>. </li>
</ul>
<br />Posted in Android Tagged: HTC Magic, Twidroid, TwitterRide <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/javiercancela.wordpress.com/365/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/javiercancela.wordpress.com/365/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=javiercancela.com&#038;blog=2480144&#038;post=365&#038;subd=javiercancela&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://javiercancela.com/2009/07/06/impresiones-sobre-el-htc-magic/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/27525d8e018e81a55b107f98b6a45ecd?s=96&#38;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fmu.gif&#38;r=G" medium="image">
			<media:title type="html">Javier Cancela</media:title>
		</media:content>

		<media:content url="http://javiercancela.files.wordpress.com/2009/07/3492788468_6d7a024eba.jpg" medium="image">
			<media:title type="html">Foto de yufujamar</media:title>
		</media:content>
	</item>
	</channel>
</rss>
