<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-674236521483788008</id><updated>2024-11-06T16:03:03.359-08:00</updated><category term="Android"/><category term="IOS"/><category term="Blogger"/><category term="XCode"/><category term="Realidad Aumentada"/><category term="Adsense"/><category term="Cocos2d"/><category term="Datos"/><category term="JavaCV"/><category term="SQLite"/><category term="Accesibilidad"/><category term="Cámara"/><category term="Diseño"/><category term="Diseño Universal"/><category term="GIT"/><category term="Google App Engine"/><category term="Guava"/><category term="JSON"/><category term="NSArray"/><category term="Network"/><category term="OpenCV"/><category term="ProGuard"/><category term="UIPageControl"/><category term="UIWebView"/><category term="Video"/><category term="sort"/><title type='text'>ITIOX | Desarrollo de aplicaciones móviles</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.itiox.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06654394446877381635</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>43</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-3358790329599466042</id><published>2013-09-16T00:52:00.003-07:00</published><updated>2013-09-16T10:11:36.072-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><title type='text'>Guardar imágenes en la galería de Android</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-ARlFgugOJxw/UdMRqU3p0EI/AAAAAAAAAMM/yBYM5oRYpc8/s1600/android-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-ARlFgugOJxw/UdMRqU3p0EI/AAAAAAAAAMM/yBYM5oRYpc8/s1600/android-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Si quieres que las fotos o vídeos de tu aplicación aparezcan en la galería de Android, copia y pega el siguiente código:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt; 
/**
 * Save image to gallery
 */
 public static void SaveToGallery(String path, Context context)
 {
    ContentValues v = new ContentValues();
    v.put(Images.Media.TITLE, &quot;MIFOTO&quot;);
    v.put(Images.Media.DISPLAY_NAME, &quot;MIFOTO.jpg&quot;);
    v.put(Images.Media.DESCRIPTION, &quot;Una foto de mi app&quot;);
    v.put(Images.Media.MIME_TYPE, &quot;image/*&quot;);
    v.put(Images.Media.ORIENTATION, 0);

    File f = new File(path);
    File parent = f.getParentFile();
    String fpath = parent.toString().toLowerCase(Locale.getDefault());
    String name = parent.getName().toLowerCase(Locale.getDefault());
    v.put(Images.ImageColumns.BUCKET_ID, fpath.hashCode());
    v.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, name);
    v.put(Images.Media.SIZE, f.length());
    f = null;

    v.put(&quot;_data&quot;, path);
    ContentResolver c = context.getContentResolver();
    c.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, v);
}

&lt;/pre&gt;
Después, sólo hay que pedirle al sistema que refresque el contenido multimedia:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;// update gallery
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
   Uri.parse(&quot;file://&quot;+ Environment.getExternalStorageDirectory())));
&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/3358790329599466042/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/09/guardar-imagenes-en-la-galeria-de.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/3358790329599466042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/3358790329599466042'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/09/guardar-imagenes-en-la-galeria-de.html' title='Guardar imágenes en la galería de Android'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-ARlFgugOJxw/UdMRqU3p0EI/AAAAAAAAAMM/yBYM5oRYpc8/s72-c/android-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-763770638700108503</id><published>2013-07-17T09:04:00.000-07:00</published><updated>2013-07-17T09:04:28.717-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="IOS"/><category scheme="http://www.blogger.com/atom/ns#" term="NSArray"/><category scheme="http://www.blogger.com/atom/ns#" term="sort"/><category scheme="http://www.blogger.com/atom/ns#" term="XCode"/><title type='text'>XCode: 4 formas de ordenar un NSArray</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s1600/apple-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s1600/apple-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Tenemos un NSArray o un NSMutableArray que queremos ordenar. Lo primero es conocer &lt;a href=&quot;http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Constants/Reference/reference.html#//apple_ref/doc/c_ref/NSComparisonResult&quot; target=&quot;_blank&quot;&gt;NSComparisonResult&lt;/a&gt;, es un &quot;enum&quot; que indica si el resultado de una comparación entre dos elementos es ascendente (a &amp;lt; b), descendente (a &amp;gt; b) o ambos son iguales (a == b). Hay varias clases de uso común que la implementan (p.ej. &lt;a href=&quot;http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;NSString&lt;/a&gt;).&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Supongamos que queremos ordenar un &quot;array&quot; de personas por su nombre:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;@interface Persona

@property NSString *nombre;

@end
&lt;/pre&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;/pre&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;// Y luego tenemos declarado&lt;/pre&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;@property NSArray *personas&lt;/pre&gt;
&lt;br /&gt;
Hay varias formas de hacerlo:&lt;br /&gt;
&lt;h3&gt;
-(NSComparisonResult)compare:&lt;/h3&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;- (NSComparisonResult)compare:(Persona *)other {
  
  return [self.nombre compare:other.nombre];
}

// Y luego en otro sitio
NSArray *sortedArray;
sortedArray = [originalArray sortedArrayUsingSelector:@selector(compare:)];

&lt;/pre&gt;
&lt;div&gt;
&lt;h2 style=&quot;background-color: white; border: 0px; font-family: &#39;Trebuchet MS&#39;, &#39;Liberation Sans&#39;, &#39;DejaVu Sans&#39;, sans-serif; font-size: 19px; line-height: 1.3; margin: 0px 0px 1em; padding: 0px; text-align: left; vertical-align: baseline; word-wrap: break-word;&quot;&gt;
NSSortDescriptor&lt;/h2&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;// Y luego en otro sitio
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@&quot;nombre&quot; ascending:YES];

NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

NSArray *sortedArray = [personas sortedArrayUsingDescriptors:sortDescriptors];
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2 style=&quot;background-color: white; border: 0px; font-family: &#39;Trebuchet MS&#39;, &#39;Liberation Sans&#39;, &#39;DejaVu Sans&#39;, sans-serif; font-size: 19px; line-height: 1.3; margin: 0px 0px 1em; padding: 0px; text-align: left; vertical-align: baseline; word-wrap: break-word;&quot;&gt;
&lt;/h2&gt;
&lt;h2 style=&quot;background-color: white; border: 0px; font-family: &#39;Trebuchet MS&#39;, &#39;Liberation Sans&#39;, &#39;DejaVu Sans&#39;, sans-serif; font-size: 19px; line-height: 1.3; margin: 0px 0px 1em; padding: 0px; text-align: left; vertical-align: baseline; word-wrap: break-word;&quot;&gt;
Blocks&lt;/h2&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;NSArray *sortedArray;
sortedArray = [personas sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSString *nombreA = [(Persona*)a nombre];
    NSString *nombreB = [(Persona*)b nombre];
    return [nombreA compare:nombreB];
}];
&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;a href=&quot;https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html&quot; target=&quot;_blank&quot;&gt;sortUsingFunction:context:&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;
Este metodo sólo es válido para NSMutableArray&#39;s, pero tiene la ventaja de que en el context le podemos enviar el parámetro que queramos (útil por ejemplo para ordenar objetos geolocalizados).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;NSComparisonResult compare(Persona *a, Persona *b, void *context) {
  return [a.nombre compare:b.nombre];
}
&lt;/pre&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;/pre&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;// Y luego en otra parte&lt;/pre&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;NSMutableArray *sortedArray = [NSMutableArray arrayWithArray:personas];&lt;/pre&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;[sortedArray sortUsingFunction:compare context:nil];&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/763770638700108503/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/07/xcode-4-formas-de-ordenar-un-nsarray.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/763770638700108503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/763770638700108503'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/07/xcode-4-formas-de-ordenar-un-nsarray.html' title='XCode: 4 formas de ordenar un NSArray'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s72-c/apple-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-1114228602552723288</id><published>2013-07-04T09:30:00.000-07:00</published><updated>2013-07-05T02:33:10.167-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Datos"/><category scheme="http://www.blogger.com/atom/ns#" term="IOS"/><category scheme="http://www.blogger.com/atom/ns#" term="SQLite"/><category scheme="http://www.blogger.com/atom/ns#" term="XCode"/><title type='text'>XCode: SQLite en 5 minutos </title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s128/apple-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s128/apple-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Esta es la continuación de &lt;a href=&quot;http://blog.itiox.com/2013/07/sqlite-en-5-minutos.html&quot;&gt;éste&lt;/a&gt; otro post de introducción a SQLite. En esta ocasión vamos a utilizar la base de datos creada en una App para iPhone.&lt;br /&gt;
&lt;br /&gt;
Aún no tengo ningún post de como crear una App en iOS desde cero, pero si os interesa dejad un comentario. Así que vamos a suponer que sabéis como crear un simple proyecto. Además vamos a utilizar ARC, que para quien no lo sepa, en pocas palabras significa que nos podemos olvidar de los &quot;alloc&quot; y los &quot;dealloc&quot; de Objective-C. Si no tocáis ningún ajuste y utilizáis una versión medianamente moderna de XCode, los proyectos utilizan ARC por defecto.&lt;br /&gt;
&lt;h3&gt;
Crear el proyecto&lt;/h3&gt;
Creamos un nuevo proyecto en XCode que podemos llamar Highscores. Vamos a crear un proyecto con una sola vista y una tabla para mostrar los datos.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/-kizHEU2Gk34/UdWH_9_et5I/AAAAAAAAAMY/0O41ksDi1hA/s730/Screen+Shot+2013-07-04+at+4.30.23+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;216&quot; src=&quot;http://3.bp.blogspot.com/-kizHEU2Gk34/UdWH_9_et5I/AAAAAAAAAMY/0O41ksDi1hA/s320/Screen+Shot+2013-07-04+at+4.30.23+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Añadimos en &quot;Frameworks&quot; la librería &quot;libsqlite3.dylib&quot;.&lt;/div&gt;
&lt;h3&gt;
Modelo&lt;/h3&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Creamos algunas entradas más en el archivo de base de datos del post anterior (&quot;ABC.sqlite&quot;) y lo añadimos al proyecto (clic derecho y &quot;Add Files to X&quot; dejando marcada la casilla de &quot;Copy items into destination group...&quot;):&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-JfJ6PBb3Ey4/UdWNPpIarBI/AAAAAAAAANQ/hGdav5G23SM/s432/Screen+Shot+2013-07-04+at+4.53.50+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;288&quot; src=&quot;http://2.bp.blogspot.com/-JfJ6PBb3Ey4/UdWNPpIarBI/AAAAAAAAANQ/hGdav5G23SM/s320/Screen+Shot+2013-07-04+at+4.53.50+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-VW-aoIrInUw/UdWNPjKnBTI/AAAAAAAAANM/sWDohPQDtmE/s631/Screen+Shot+2013-07-04+at+4.56.09+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;151&quot; src=&quot;http://2.bp.blogspot.com/-VW-aoIrInUw/UdWNPjKnBTI/AAAAAAAAANM/sWDohPQDtmE/s320/Screen+Shot+2013-07-04+at+4.56.09+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Creamos la clase &quot;Puntuacion&quot; donde guardaremos los datos. Con ARC y las últimas versiones de XCode y de iOS, no hace falta que toquemos el &quot;.m&quot;para añadir las sentencias &quot;@synthesize&quot; ya que se generan de forma automática.&amp;nbsp;Añadimos a Puntuacion.h:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#import &amp;lt;Foundation/Foundation.h&amp;gt;

@interface Puntuacion : NSObject

@property NSNumber *mode;
@property NSString *name;&lt;/pre&gt;
@property NSNumber *value;

@end

&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Creamos la clase &quot;BaseDeDatos&quot;. Esta clase será un &lt;a href=&quot;http://es.wikipedia.org/wiki/Singleton&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Singleton&lt;/a&gt; que nos permitirá comunicarnos con la base de datos desde cualquier punto de la App. El archivo &quot;BaseDeDatos.h&quot; debería de quedar tal que así:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#import &amp;lt;Foundation/Foundation.h&amp;gt;
#import &amp;lt;sqlite3.h&amp;gt;

@interface BaseDeDatos : NSObject

+(id)sharedInstance;

-(NSArray*)puntuacionesOrdenadasAscendentemente;
-(NSArray*)puntuacionesOrdenadasPorNombre;
-(NSArray*)puntuacionesOrdenadasPorModo;

@end

&lt;/pre&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Y &quot;BaseDeDatos.m&quot; tal que así:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#import &quot;BaseDeDatos.h&quot;

#import &quot;Puntuacion.h&quot;

@interface BaseDeDatos()

@property sqlite3 *database;

-(NSArray*)performQuery:(NSString*)query;

@end

@implementation BaseDeDatos

static BaseDeDatos *_sharedInstance;

+(id)sharedInstance {
  if (_sharedInstance == nil) {
    _sharedInstance = [[BaseDeDatos alloc] init];
  }
  return _sharedInstance;
}

- (id)init {
  if ((self = [super init])) {
    NSString *path = [[NSBundle mainBundle] pathForResource:@&quot;ABC&quot;
                                                         ofType:@&quot;sqlite&quot;];
    
    if (sqlite3_open([path UTF8String], &amp;amp;_database) != SQLITE_OK) {
      NSLog(@&quot;¡Error al abrir la base de datos!&quot;);
    }
  }
  
  return self;
}

-(NSArray*)performQuery:(NSString*)query {
  NSMutableArray *values = [NSMutableArray array];
  
  sqlite3_stmt *statement;
  if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &amp;amp;statement, nil)
      == SQLITE_OK) {
    while (sqlite3_step(statement) == SQLITE_ROW) {
      
      char *name = (char *) sqlite3_column_text(statement, 0);
      int value = (int) sqlite3_column_int(statement, 1);
      int mode = (int) sqlite3_column_int(statement, 2);
      
      Puntuacion *puntuacion = [[Puntuacion alloc] init];
      puntuacion.name = [NSString stringWithUTF8String:name];
      puntuacion.value = @(value);
      puntuacion.mode = @(mode);
      
      [values addObject:puntuacion];
    }
    
    sqlite3_finalize(statement);
  }
  
  return values;
}

-(NSArray*)puntuacionesOrdenadasAscendentemente {
  return [self performQuery:@&quot;select * from puntuaciones order by puntuacion asc&quot;];
}

-(NSArray*)puntuacionesOrdenadasPorNombre  {
  return [self performQuery:@&quot;select * from puntuaciones order by nombre asc&quot;];
}

-(NSArray*)puntuacionesOrdenadasPorModo {
  return [self performQuery:@&quot;select * from puntuaciones order by modo asc&quot;];
}

@end&lt;/pre&gt;
&lt;h3&gt;
Vista&lt;/h3&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Vamos al Storyboard y añadimos un UITableView y tres botones a nuestra vista. La App va a ser muy sencilla, va a mostrar los datos en la tabla y los botones van a servir para ordenarlos según un campo tal y como definimos en la base de datos.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/--5sRt204THE/UdWKGodPtZI/AAAAAAAAAMo/JW37CEOBkoA/s688/Screen+Shot+2013-07-04+at+4.42.09+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://3.bp.blogspot.com/--5sRt204THE/UdWKGodPtZI/AAAAAAAAAMo/JW37CEOBkoA/s320/Screen+Shot+2013-07-04+at+4.42.09+PM.png&quot; width=&quot;251&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Añadimos el siguiente código a ViewController.h:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#import &lt;uikit it.h=&quot;&quot;&gt;

@interface ViewController : UIViewController&amp;lt;UITableViewDataSource&amp;gt;
@property IBOutlet UITableView *tableView;

- (IBAction)orderByName:(id)sender;
- (IBAction)orderByMode:(id)sender;
- (IBAction)orderByScore:(id)sender;

@end&lt;/uikit&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
Volvemos a nuestro Storyboard y conectamos los botones con las acciones y la referencia del &quot;tableView&quot; y el datasource:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-nGLRbqPSWKI/UdWLbBT2EEI/AAAAAAAAAM4/hDPgOOdUolk/s488/Screen+Shot+2013-07-04+at+4.47.47+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;199&quot; src=&quot;http://2.bp.blogspot.com/-nGLRbqPSWKI/UdWLbBT2EEI/AAAAAAAAAM4/hDPgOOdUolk/s320/Screen+Shot+2013-07-04+at+4.47.47+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-rI-WUgYWsHM/UdWLa5BotKI/AAAAAAAAAM0/HD3Vi5gR3Kk/s383/Screen+Shot+2013-07-04+at+4.48.17+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://1.bp.blogspot.com/-rI-WUgYWsHM/UdWLa5BotKI/AAAAAAAAAM0/HD3Vi5gR3Kk/s320/Screen+Shot+2013-07-04+at+4.48.17+PM.png&quot; width=&quot;219&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h3&gt;
Controlador&lt;/h3&gt;
Y por último en el &quot;ViewController.m&quot;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#import &quot;ViewController.h&quot;

#import &quot;BaseDeDatos.h&quot;
#import &quot;Puntuacion.h&quot;

@interface ViewController ()

@property NSArray *puntuaciones;

@end

@implementation ViewController

- (void)viewDidLoad
{
  [super viewDidLoad];
  self.puntuaciones = [[BaseDeDatos sharedInstance] puntuacionesOrdenadasAscendentemente];
  [self.tableView reloadData];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  if (self.puntuaciones != nil) {
    return self.puntuaciones.count;
  }
  
  return 0;
}

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  Puntuacion *puntuacion = self.puntuaciones[indexPath.row];
  UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@&quot;puntuacion&quot;];
  
  cell.textLabel.text = puntuacion.name;
  cell.detailTextLabel.text = [NSString stringWithFormat:@&quot;%@:%@&quot;, puntuacion.mode, puntuacion.value];
  
  return cell;
}

- (IBAction)orderByName:(id)sender {
  self.puntuaciones = [[BaseDeDatos sharedInstance] puntuacionesOrdenadasPorNombre];
  [self.tableView reloadData];
}

- (IBAction)orderByMode:(id)sender {
  self.puntuaciones = [[BaseDeDatos sharedInstance] puntuacionesOrdenadasPorModo];
  [self.tableView reloadData];
}

- (IBAction)orderByScore:(id)sender {
  self.puntuaciones = [[BaseDeDatos sharedInstance] puntuacionesOrdenadasAscendentemente];
  [self.tableView reloadData];
}

@end
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Resultado&amp;nbsp;&lt;/h3&gt;
Y el resultado totalmente funcional (cambia el orden al pulsar en cada botón según el criterio):&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-eOmdm90QYQU/UdWfGHhCDwI/AAAAAAAAANk/l2HmjKmrBeU/s747/Screen+Shot+2013-07-04+at+6.12.47+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://1.bp.blogspot.com/-eOmdm90QYQU/UdWfGHhCDwI/AAAAAAAAANk/l2HmjKmrBeU/s320/Screen+Shot+2013-07-04+at+6.12.47+PM.png&quot; width=&quot;179&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Esto evidentemente no es una App, es un punto de partida con algunos de los conceptos básicos de SQLite en iOS. Y ahora, ¡a programar!&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/1114228602552723288/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/07/xcode-sqlite-en-5-minutos.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/1114228602552723288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/1114228602552723288'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/07/xcode-sqlite-en-5-minutos.html' title='XCode: SQLite en 5 minutos '/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s72-c/apple-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-7481392956715750756</id><published>2013-07-02T11:05:00.000-07:00</published><updated>2013-07-02T11:05:57.482-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Guava"/><category scheme="http://www.blogger.com/atom/ns#" term="ProGuard"/><title type='text'>Android + Guava + ProGuard</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-ARlFgugOJxw/UdMRqU3p0EI/AAAAAAAAAMI/n-Z3qnZ5Yig/s128/android-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-ARlFgugOJxw/UdMRqU3p0EI/AAAAAAAAAMI/n-Z3qnZ5Yig/s128/android-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Si habéis llegado a este post no ha sido por casualidad: ¿Cómo utilizar ProGuard en una App de Android que use Guava? Es un infierno mal documentado que vamos a solucionar en 4+1 pasos:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Descargad la librería &lt;a href=&quot;http://mvnrepository.com/artifact/javax.inject/javax.inject&quot; target=&quot;_blank&quot;&gt;javax.inject-*.jar&lt;/a&gt;&amp;nbsp;(&quot;*&quot; es la versión, bajaros la última claro está).&lt;/li&gt;
&lt;li&gt;Descargad la librería &lt;a href=&quot;http://mvnrepository.com/artifact/com.google.code.findbugs/jsr305&quot; target=&quot;_blank&quot;&gt;jsr305-*.jar&lt;/a&gt;.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Copiad las librerías en la carpeta libs de vuestro proyecto.&lt;/li&gt;
&lt;li&gt;Añadid lo siguiente a vuestro archivo &quot;proguard.cfg&quot;&lt;/li&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;-libraryjars libs/guava-14.0.1.jar
-libraryjars libs/jsr305-2.0.1.jar
-libraryjars libs/javax.inject-1.jar
-dontwarn sun.misc.Unsafe
-dontwarn com.google.common.collect.MinMaxPriorityQueue
&lt;/pre&gt;
&lt;li&gt;Dad gracias a &lt;a href=&quot;http://mvnrepository.com/&quot; target=&quot;_blank&quot;&gt;MVNRepository&lt;/a&gt; por los JARs.&lt;/li&gt;
&lt;/ol&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/7481392956715750756/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/07/android-guava-proguard.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/7481392956715750756'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/7481392956715750756'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/07/android-guava-proguard.html' title='Android + Guava + ProGuard'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-ARlFgugOJxw/UdMRqU3p0EI/AAAAAAAAAMI/n-Z3qnZ5Yig/s72-c/android-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-2578959953797827000</id><published>2013-07-02T10:03:00.004-07:00</published><updated>2013-07-05T07:40:38.065-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="SQLite"/><title type='text'>SQLite en 5 minutos</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-SLmSch7rfKA/UdLy0Rq-6JI/AAAAAAAAAL4/ZTDji9IdxpM/s128/database-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://4.bp.blogspot.com/-SLmSch7rfKA/UdLy0Rq-6JI/AAAAAAAAAL4/ZTDji9IdxpM/s128/database-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
En este post hablamos de datos y Apps.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Siempre he pensado que lo más importante en el desarrollo de Apps es el contenido. De nada vale usar las últimas novedades del sistema operativo ni efectos visuales espectaculares si tu App no tiene contenido. Y de igual forma, hay auténticos &quot;truños&quot; (p.ej. las primeras versiones de cierta red social...) cuyas descargas se cuentan por millones, ¿por qué? por que tiene fotos, contactos, mensajes... de millones de usuarios, es decir contenido.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
En Software, los contenidos son datos y los datos hay que almacenarlos y gestionarlos. Cuando necesitas almacenar una alta cantidad de datos y acceder a ellos de forma rápida y eficiente tecnologías como &lt;a href=&quot;http://developer.android.com/reference/android/content/SharedPreferences.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;SharedPreferences&lt;/a&gt; (Android) y &lt;a href=&quot;http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;NSUserDefaults&lt;/a&gt; (iOS) ya no son suficientes. Necesitamos más artillería, y esta lleva el nombre de SQLite.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Es una tecnología sencilla (los archivos de bases de datos consisten en archivos planos autocontenidos), conocida (un par de nociones de SQL y ya se puede hacer mucho), multiplataforma (la misma base de datos os servirá para Android e iOS) y con las ventajas de trabajar con una base de datos (operaciones simples como buscar, insertar, modificar filas y/o columnas se realizan de forma muy sencilla) y además ofrece una alta capacidad de almacenamiento (cadenas de texto, fechas, números... difícilmente serán un problema).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Como he comentado, una base de datos SQLite consiste en un único archivo autocontenido, es decir toda la información de la base de datos se guarda en ese mismo archivo y no hacen falta archivos adicionales.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Si trabajáis en Windows tenéis varias posibilidades (en orden): formatear e instalar alguna &lt;a href=&quot;http://www.debian.org/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;distro de Linux&lt;/a&gt;, instalar &lt;a href=&quot;http://www.cygwin.com/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;cygwin&lt;/a&gt;, bajaros el &lt;a href=&quot;http://www.sqlite.org/download.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;precompilado de SQLite&lt;/a&gt;, o utilizar alguna herramienta gráfica de terceros.&lt;/div&gt;
&lt;div&gt;
En cualquier caso vamos a considerar que tenéis correctamente instalada y configurada la versión 3 de SQLite y un Terminal (OSX), un Shell (Linux) o cualquier tipo de consola de línea de comandos. Es decir podemos ejecutar y obtenemos:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;$ sqlite3
SQLite version 3.7.17
&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
Antes que otra cosa, posibles causas de error &amp;nbsp;y pequeñas recomendaciones:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;No olvidar el ; (punto y coma) al final de las sentencias.&lt;/li&gt;
&lt;li&gt;El apóstrofe (&#39;) que sale es el que normalmente en un teclado español aparece en la tecla &quot;?&quot; (a la derecha del &quot;0&quot;).&lt;/li&gt;
&lt;li&gt;El prompt ($) puede variar dependiendo de vuestro Shell y sesión. Cuando estáis dentro de la sesión de SQLite el prompt cambia a &quot;sqlite&amp;gt;&quot; (ah, y el prompt es lo que aparece en la línea donde introducís las órdenes).&lt;/li&gt;
&lt;li&gt;Los datos que devuelve el Shell, están en cursiva para que los distingáis fácilmente.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
Vamos a crear una simple base de datos para guardar las puntuaciones de un juego llamado ABC:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Crear base de datos (la extensión no es necesaria pero ayuda a reconocer el tipo de archivo):&lt;/li&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;$ sqlite3 ABC.sqlite3
&lt;i&gt;SQLite version 3.7.17
Enter &quot;.help&quot; for instructions
Enter SQL statements terminated with a &quot;;&quot; &lt;/i&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;li&gt;Creamos la tabla de puntuaciones (cada entrada tendrá un campo para guardar el nombre y otro campo para guardar la puntuación)&lt;/li&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;sqlite&amp;gt; create table puntuaciones(nombre varchar(10), puntuacion smallint);
&lt;/pre&gt;
&lt;br /&gt;
&lt;li&gt;Insertamos algunas puntuaciones:&lt;/li&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;sqlite&amp;gt; insert into puntuaciones values(&#39;Pepe&#39;,10);
sqlite&amp;gt; insert into puntuaciones values(&#39;Juan&#39;, 20);
&lt;/pre&gt;
&lt;br /&gt;
&lt;li&gt;Leemos las puntuaciones:&lt;/li&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;sqlite&amp;gt; select * from puntuaciones;
&lt;i&gt;Pepe|10
Juan|20&lt;/i&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;li&gt;Añadimos un nuevo jugador y leemos las puntuaciones de forma ordenada (&quot;asc&quot; de menor a mayor y &quot;desc&quot; de mayor a menor):&lt;/li&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;sqlite&amp;gt; insert into puntuaciones values(&#39;Eva&#39;, 15);
sqlite&amp;gt; select * from puntuaciones order by puntuacion asc;
&lt;i&gt;Pepe|10
Eva|15
Juan|20&lt;/i&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;li&gt;Obtenemos la puntuación de un jugador:&lt;/li&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;sqlite&amp;gt; select puntuacion from puntuaciones where nombre=&#39;Eva&#39;;
15
&lt;/pre&gt;
&lt;br /&gt;
&lt;li&gt;Imaginemos que el juego tiene varios modos de dificultad (0,1,2...), creamos una columna para el modo y actualizamos las entradas al modo en el que consiguieron la puntuación:&lt;/li&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;sqlite&amp;gt; alter table puntuaciones add column modo smallint;
sqlite&amp;gt; update puntuaciones set modo=0 where nombre=&#39;Pepe&#39;;
sqlite&amp;gt; update puntuaciones set modo=2 where nombre=&#39;Eva&#39;;
sqlite&amp;gt; update puntuaciones set modo=0 where nombre=&#39;Juan&#39;;
sqlite&amp;gt; select * from puntuaciones;
&lt;i&gt;Pepe|10|0
Juan|20|0
Eva|15|2&lt;/i&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;li&gt;Y finalmente para salir de la sesión:&lt;/li&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;sqlite&amp;gt; .exit
&lt;/pre&gt;
&lt;br /&gt;
&lt;/ol&gt;
Ya tenéis creada vuestra base de datos con las puntuaciones del juego en el archivo &quot;ABC.sqlite3&quot; (o como lo hayáis nombrado). Evidentemente son ejemplos sencillos fácilmente adaptables a vuestras necesidades.&lt;br /&gt;
&lt;h4&gt;
Más cosas&lt;/h4&gt;
Tabla con los típicos campos id &quot;autoincrement&quot; y timestamp con la fecha por defecto de inserción:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;CREATE TABLE nombre_de_tabla (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  t TIMESTAMP
  DEFAULT CURRENT_TIMESTAMP
);
&lt;/pre&gt;
&lt;br /&gt;
Ver las tablas que hay en una base de datos:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;sqlite&amp;gt; .tables
&lt;/pre&gt;
&lt;br /&gt;
Obtener información de una tabla (varios métodos):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;sqlite&amp;gt; .schema nombre_de_tabla
sqlite&amp;gt; pragma table_info(nombre_de_tabla);  
&lt;/pre&gt;
&lt;br /&gt;
Borrar una tabla:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;sqlite&amp;gt; drop table hombre_de_tabla;      
&lt;/pre&gt;
&lt;br /&gt;
Supongamos que tenemos la tabla &quot;clientes&quot; (con campos &quot;id&quot; y &quot;nombre&quot;) y la tabla &quot;compras&quot; (con campos &quot;cliente_id&quot; y &quot;precio&quot;). Y queremos obtener todos los nombres de clientes que hayan realizado una compra de más de 50$:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;sqlite&amp;gt; select X.* from clientes X inner join compras Y on X.id = Y.cliente_id where Y.precio&amp;gt;=50;
&lt;/pre&gt;
&lt;br /&gt;
SQLite admite múltiples tipos de datos en su sintaxis, pero todos los convierte a alguno de estos tipos básicos según unas &lt;a href=&quot;http://www.sqlite.org/datatype3.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;reglas definidas&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;ul&gt;
&lt;li&gt;&lt;b&gt;NULL&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;INTEGER&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;REAL&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TEXT&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;BLOB&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/2578959953797827000/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/07/sqlite-en-5-minutos.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/2578959953797827000'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/2578959953797827000'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/07/sqlite-en-5-minutos.html' title='SQLite en 5 minutos'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-SLmSch7rfKA/UdLy0Rq-6JI/AAAAAAAAAL4/ZTDji9IdxpM/s72-c/database-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-7776754811834580175</id><published>2013-07-01T11:44:00.003-07:00</published><updated>2013-07-01T11:45:24.388-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Accesibilidad"/><category scheme="http://www.blogger.com/atom/ns#" term="Diseño"/><category scheme="http://www.blogger.com/atom/ns#" term="Diseño Universal"/><title type='text'>Principios de Diseño Universal</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-1GCeK_FKdOU/UdHODz-R50I/AAAAAAAAALo/_7RS1eueaXQ/s128/accesibility-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://4.bp.blogspot.com/-1GCeK_FKdOU/UdHODz-R50I/AAAAAAAAALo/_7RS1eueaXQ/s128/accesibility-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
En este post voy a tratar un tema con el que me ha tocado trabajar últimamente. Es el tema de la accesibilidad para los usuarios con algún tipo de discapacidad o handicap en el uso de aplicaciones.&lt;br /&gt;
&lt;br /&gt;
Me parece un tema muy importante, pero que a priori no genera mucho interés entre nuestra comunidad de desarrolladores (me temo que este post no será de los que tengan más visitas :( ). De hecho y sin ir más lejos, el propio autor de este post al principio tenía poco o casi ningún interés. Sin embargo hay cosas técnicamente muy interesantes que se han desarrollado al respecto y a poco que te introduces en este tema, si que te vas interesando.&lt;br /&gt;
&lt;br /&gt;
En otros posts hablaré sobre la accesibilidad en iOS y Android, pero en este os voy a hablar de un documento, poco conocido en español, pero que hemos tenido que utilizar en uno de nuestros últimos proyectos para obtener una certificación de la App que se desarrollaba.&lt;br /&gt;
&lt;h3&gt;
Principios de Diseño Universal&lt;/h3&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;h4&gt;
&lt;li&gt;
Uso equitativo
&lt;/li&gt;
&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Proveer los mismos medios a todos los usuarios: de forma idéntica cuando sea posible; de forma equivalente cuando no.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Evitar segregar o estigmatizar a cualquier usuario.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Lo dispuesto para la privacidad, la seguridad debe garantizar el acceso a todos los usuarios.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Hacer el diseño atractivo para todos los usuarios.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
&lt;li&gt;Flexibilidad en el Uso&lt;/li&gt;
&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Proporcionar elección en los métodos de uso.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Acomodar el acceso y el uso diestro y zurdo.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Facilitar la exactitud y la precisión del usuario.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Proporcionar capacidad de adaptación al ritmo del usuario.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
&lt;li&gt;Uso Simple e Intuitivo&lt;/li&gt;
&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Eliminar la complejidad innecesaria.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Ser consistente con la intuición y las expectativas del usuario.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Adaptar a una amplia gama de conocimientos y habilidades lingüísticas.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Organizar la información de acuerdo con su importancia.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Ofrecer indicaciones e información relevante durante y después de la finalización de las tareas.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
&lt;li&gt;Información Perceptible&lt;/li&gt;
&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Usar diferentes modos (gráficos, verbales, táctiles) para la presentación redundante de información esencial.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Ofrecer un adecuado contraste entre la información esencial y sus alrededores.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Maximizar la &quot;legibilidad&quot; de información esencial.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Diferenciar los elementos de formas que puedan ser descritas (p.ej. facilitar dar instrucciones o direcciones).&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Proporcionar compatibilidad con una variedad de técnicas o dispositivos usados por personas con discapacidades sensoriales.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
&lt;li&gt;Tolerancia al Error&lt;/li&gt;
&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Organizar los elementos para minimizar los riesgos y errores: los elementos más usados, más accesibles; los elementos peligrosos eliminados, aislados o asegurados.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Proporcionar advertencias de riesgos y errores.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Proporcionar características de seguridad ante fallos.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Desalentar las acciones inconscientes en tareas que requieran vigilancia.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
&lt;li&gt;Esfuerzo Físico Bajo&lt;/li&gt;
&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Permitir que el usuario mantenga una posición corporal neutra.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Uso razonable de las fuerzas operativas.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Minimizar las acciones repetitivas.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Minimizar el esfuerzo físico sostenido.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
&lt;li&gt;Tamaño y Espacio para el Acceso y el Uso&lt;/li&gt;
&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Proporcionar una línea de visión clara hacia los elementos importantes, para cualquier usuario que se encuentre sentado o de pie.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Facilitar el acceso a todos los componentes para cualquier usuario que se encuentre sentado o de pie.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Adaptarse a las variaciones en la mano y el tamaño de la empuñadura.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Proporcionar un espacio adecuado para el uso de dispositivos de ayuda o asistencia personal.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;Documento original:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: HelveticaNeue; font-size: 10pt; font-weight: normal;&quot;&gt;&lt;a href=&quot;http://www.ncsu.edu/ncsu/design/cud/about_ud/udprinciples.htm&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;“The Center forUniversal Design (1997). The Principles of Universal Design, Version 2.0. Raleigh,NC: North Carolina State University.”&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: HelveticaNeue; font-size: 10pt; font-weight: normal;&quot;&gt;“Copyright © 1997 NC
State University, The Center for Universal Design.”&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/7776754811834580175/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/07/principios-de-diseno-universal.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/7776754811834580175'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/7776754811834580175'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/07/principios-de-diseno-universal.html' title='Principios de Diseño Universal'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-1GCeK_FKdOU/UdHODz-R50I/AAAAAAAAALo/_7RS1eueaXQ/s72-c/accesibility-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-5556220628151070259</id><published>2013-06-30T02:27:00.001-07:00</published><updated>2014-09-07T03:50:38.045-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Blogger"/><title type='text'>Gadget de entradas con navegador para Blogger</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-ND-CXHcIIuQ/Ub2TZeLxxDI/AAAAAAAAAIY/VX55kYFwD-M/s1600/blogger-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-ND-CXHcIIuQ/Ub2TZeLxxDI/AAAAAAAAAIY/VX55kYFwD-M/s1600/blogger-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Este gadget es muy práctico. Te permite navegar por todo el blog viendo las entradas con un resumen y una foto sin cambiar de página. El resultado es algo así:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/-vtuYS5RUNwM/VAw4cxpL9rI/AAAAAAAAAOU/NOr8sMc0198/s1600/Captura%2Bde%2Bpantalla%2B2014-09-07%2Ba%2Bla(s)%2B12.49.33.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://3.bp.blogspot.com/-vtuYS5RUNwM/VAw4cxpL9rI/AAAAAAAAAOU/NOr8sMc0198/s1600/Captura%2Bde%2Bpantalla%2B2014-09-07%2Ba%2Bla(s)%2B12.49.33.png&quot; height=&quot;320&quot; width=&quot;216&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Si lo quieres en tu blog, añade un nuevo gadget &amp;nbsp;HTML/Javascript desde Diseño.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Copia el siguiente código:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;div class=&quot;widget-content&quot;&amp;gt;
&amp;lt;style type=&quot;text/css&quot;&amp;gt;
#mas-terbaru{border:1px solid #585858;width:100%;margin:0 auto}
#terbaru{margin:0px}
.mas-elemen{border:1px solid #ccc;margin:5px 0;padding:5px;height:79px}
.mas-elemen img{background:#999;padding:4px;float:left;height:70px;margin-right:8px;width:70px}
.mas-elemen h6,.mas-elemen h6 a{font-size:12px!important;font-weight:700!important;margin:0;color:#111}
.mas-elemen:hover{background-color:#c3c3c3}
.mas-elemen p{font:14px PT Sans Narrow;text-align:justify;color:#555;line-height:14px;margin:5px 0}
#mas-loading{color:#888;font-family:Tahoma;font-size:100px;letter-spacing:-10px;text-align:center;text-shadow:-5px 0 1px #444;background:#141414 url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGINo_YC8IZCBtH5wFfIMbQvHnuvsW8Q_TXvHBB9qebYTLl0uz5iZZ7wCQCuiIpFug4YeOl-IDUiU1tEUyIbh5mcvXV67oMZ_TVeAN_cIz3QO6cRoW76mjs7tN4n583p9-maQexkXboxQ/s1600/loading.gif) no-repeat 50% 50%;height:470px;border:1px solid #c3c3c3}
#mas-navigasifeed{border:1px solid #c3c3c3;color:#bbb;font-family:Verdana;font-size:12px;text-align:center;margin:0px}
#mas-navigasifeed:hover{background-color:#c3c3c3}
#mas-navigasifeed a{color:#141414!important;font-family:Tahoma!important;font-size:12px!important;font-weight:400!important;display:block;padding:5px 10px}
#mas-navigasifeed span{padding:5px 10px}
#mas-navigasifeed .next{float:right}
#mas-navigasifeed .previous{float:left}
#mas-navigasifeed .home{text-align:center}
#mas-navigasifeed a:hover,#mas-navigasifeed span.noactived{color:transparant!important}
&amp;lt;/style&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
//&amp;lt;![CDATA[
var numfeed = 4;
var startfeed = 0;
var urlblog = &quot;http://MIBLOG.blogspot.com/&quot;;
var charac = 60;
var urlprevious, urlnext;

function maskolisfeed(johny,banget){
var showfeed = johny.split(&quot;&amp;lt;&quot;);
for(var i=0;i&amp;lt;showfeed.length;i++){
if(showfeed[i].indexOf(&quot;&amp;gt;&quot;)!=-1){
showfeed[i] = showfeed[i].substring(showfeed[i].indexOf(&quot;&amp;gt;&quot;)+1,showfeed[i].length);
}
}
showfeed =  showfeed.join(&quot;&quot;);
showfeed = showfeed.substring(0,banget-1);
return showfeed;
}
function showterbaru(json) {
var entry, posttitle, posturl, postimg, postcontent;
var showblogfeed = &quot;&quot;;
urlprevious = &quot;&quot;;
urlnext = &quot;&quot;;
for (var k = 0; k &amp;lt; json.feed.link.length; k++) {
if (json.feed.link[k].rel == &#39;previous&#39;) {
urlprevious = json.feed.link[k].href;
}
if (json.feed.link[k].rel == &#39;next&#39;) {
urlnext = json.feed.link[k].href;
}
}
for (var i = 0; i &amp;lt; numfeed; i++) {
if (i == json.feed.entry.length) { break; }
entry = json.feed.entry[i];
posttitle = entry.title.$t;
for (var k = 0; k &amp;lt; entry.link.length; k++) {
if (entry.link[k].rel == &#39;alternate&#39;) {
posturl = entry.link[k].href;
break;
}
}
if (&quot;content&quot; in entry) {
postcontent = entry.content.$t;
} else if (&quot;summary&quot; in entry) {
postcontent = entry.summary.$t;
} else {
postcontent = &quot;&quot;;
}
if (&quot;media$thumbnail&quot; in entry) {
postimg = entry.media$thumbnail.url;
} else {
postimg = &quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhV6aLR5ybD96BEPqPjMcOWNKXrPAUs6hIoUA93NdJG0uV8ClpIv_yvWcVCCNJwq1K5jlpN59wjt-SdW2HaUWe7dBS99cYag0GZ_fus5EWXa4X00uRmxbRvFCfgUV3OlSr-y6pjojHoUcM/s1600/no+image.jpg&quot;;
}
showblogfeed += &quot;&amp;lt;div class=&#39;mas-elemen&#39;&amp;gt;&quot;;
showblogfeed += &quot;&amp;lt;a href=&#39;&quot; + posturl + &quot;&#39; target=&#39;_blank&#39;&amp;gt;&amp;lt;img src=&#39;&quot; + postimg + &quot;&#39; /&amp;gt;&amp;lt;/a&amp;gt;&quot;;
showblogfeed += &quot;&amp;lt;h6&amp;gt;
&amp;lt;a href=&#39;&quot; + posturl + &quot;&#39;&amp;gt;&quot; + posttitle + &quot;&amp;lt;/a&amp;gt;&amp;lt;/h6&amp;gt;
&quot;;
showblogfeed += &quot;&amp;lt;p&amp;gt;
&quot; + maskolisfeed(postcontent,charac) + &quot;...&amp;lt;/p&amp;gt;
&quot;;
showblogfeed += &quot;&amp;lt;/div&amp;gt;
&quot;;
}
document.getElementById(&quot;terbaru&quot;).innerHTML = showblogfeed;
showblogfeed = &quot;&quot;;
if(urlprevious) {
showblogfeed += &quot;&amp;lt;a href=&#39;javascript:navigasifeed(-1);&#39; class=&#39;previous&#39;&amp;gt;&amp;amp;#9668; Previous&amp;lt;/a&amp;gt;&quot;;
} else {
showblogfeed += &quot;&amp;lt;span class=&#39;noactived previous&#39;&amp;gt;&amp;amp;#9668; Previous&amp;lt;/span&amp;gt;&quot;;
}
if(urlnext) {
showblogfeed += &quot;&amp;lt;a href=&#39;javascript:navigasifeed(1);&#39; class=&#39;next&#39;&amp;gt;Next &amp;amp;#9658;&amp;lt;/a&amp;gt;&quot;;
} else {
showblogfeed += &quot;&amp;lt;span class=&#39;noactived next&#39;&amp;gt;Next &amp;amp;#9658;&amp;lt;/span&amp;gt;&quot;;
}
showblogfeed += &quot;&amp;lt;a href=&#39;javascript:navigasifeed(0);&#39; class=&#39;home&#39;&amp;gt;Home&amp;lt;/a&amp;gt;&quot;;
document.getElementById(&quot;mas-navigasifeed&quot;).innerHTML = showblogfeed;
}

function navigasifeed(url){
var p, parameter;
if(url==-1) {
p = urlprevious.indexOf(&quot;?&quot;);
parameter = urlprevious.substring(p);
} else if (url==1) {
p = urlnext.indexOf(&quot;?&quot;);
parameter = urlnext.substring(p);
} else {
parameter = &quot;?start-index=1&amp;amp;max-results=&quot; + numfeed + &quot;&amp;amp;orderby=published&amp;amp;alt=json-in-script&quot;
}
parameter += &quot;&amp;amp;callback=showterbaru&quot;;
incluirscript(parameter);
}
function incluirscript(parameter) {
if(startfeed==1) {removerscript();}
document.getElementById(&quot;terbaru&quot;).innerHTML = &quot;&amp;lt;div id=&#39;mas-loading&#39;&amp;gt;
&amp;lt;/div&amp;gt;
&quot;;
document.getElementById(&quot;mas-navigasifeed&quot;).innerHTML = &quot;&quot;;
var archievefeed = urlblog + &quot;/feeds/posts/default&quot;+ parameter;
var terbaru = document.createElement(&#39;script&#39;);
terbaru.setAttribute(&#39;type&#39;, &#39;text/javascript&#39;);
terbaru.setAttribute(&#39;src&#39;, archievefeed);
terbaru.setAttribute(&#39;id&#39;, &#39;MASLABEL&#39;);
document.getElementsByTagName(&#39;head&#39;)[0].appendChild(terbaru);
startfeed = 1;
}
function removerscript() {
var elemen = document.getElementById(&quot;MASLABEL&quot;);
var parent = elemen.parentNode;
parent.removeChild(elemen);
}
onload=function() { navigasifeed(0); }
//]]&amp;gt;
&amp;lt;/script&amp;gt;
&amp;lt;br /&amp;gt;
&amp;lt;div id=&quot;terbaru&quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&quot;mas-navigasifeed&quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
Cambia MIBLOG por el nombre de tu blog.&lt;br /&gt;
Puedes cambiar el número de entradas que quieres que aparezca y la longitud del resumen. Vamos, te puedes entretener en personalizar el gadget.&lt;br /&gt;
&lt;br /&gt;
Sólo una advertencia, y es que consume mucho tiempo de carga :( , por eso no lo ves es este blog.</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/5556220628151070259/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/gadget-de-entradas-con-navegador-para.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/5556220628151070259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/5556220628151070259'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/gadget-de-entradas-con-navegador-para.html' title='Gadget de entradas con navegador para Blogger'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06654394446877381635</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-ND-CXHcIIuQ/Ub2TZeLxxDI/AAAAAAAAAIY/VX55kYFwD-M/s72-c/blogger-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-7047161602906250130</id><published>2013-06-25T09:18:00.002-07:00</published><updated>2013-06-25T09:20:10.675-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="IOS"/><category scheme="http://www.blogger.com/atom/ns#" term="UIPageControl"/><category scheme="http://www.blogger.com/atom/ns#" term="XCode"/><title type='text'>XCode: UIPageControl</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s1600/apple-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s1600/apple-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
¿Conocéis el típico interfaz de iOS con varios puntitos y que os permite hacer scroll sobre varias vistas? He aquí un tutorial rápido de como conseguirlo:&lt;br /&gt;
&lt;br /&gt;
1. Añadís un UIViewController en vuestro Storyboard y cambiáis el nombre de la clase por PageViewController:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-O31M6NLh5aI/Ucm_0wH23MI/AAAAAAAAAKU/lORG4_iJjIw/s1600/Screen+Shot+2013-06-25+at+5.56.25+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;279&quot; src=&quot;http://2.bp.blogspot.com/-O31M6NLh5aI/Ucm_0wH23MI/AAAAAAAAAKU/lORG4_iJjIw/s320/Screen+Shot+2013-06-25+at+5.56.25+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;span style=&quot;text-align: -webkit-auto;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
Añadís un UIScrollView, desactiváis las barras de scroll y habilitáis el paging:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-H7XF9iIfo9s/Ucm_2Jonb4I/AAAAAAAAAK0/XsEAP3Hehrw/s1600/Screen+Shot+2013-06-25+at+5.59.09+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;305&quot; src=&quot;http://4.bp.blogspot.com/-H7XF9iIfo9s/Ucm_2Jonb4I/AAAAAAAAAK0/XsEAP3Hehrw/s320/Screen+Shot+2013-06-25+at+5.59.09+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
Añadís un UIPageControl (y ajustáis el color de los puntos...). Hay que tener cuidado de no añadirlo dentro del UIScrollView, tienen que estar ambos al mismo nivel dentro del UIView:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-fQ2ERtsqpG4/Ucm_1egv47I/AAAAAAAAAKw/amdcu7Xot-I/s1600/Screen+Shot+2013-06-25+at+5.57.47+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://1.bp.blogspot.com/-fQ2ERtsqpG4/Ucm_1egv47I/AAAAAAAAAKw/amdcu7Xot-I/s1600/Screen+Shot+2013-06-25+at+5.57.47+PM.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-yWEjZ2uxIEA/Ucm_1v8EEvI/AAAAAAAAAK4/gLwD6FVIPxk/s1600/Screen+Shot+2013-06-25+at+5.58.30+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;304&quot; src=&quot;http://4.bp.blogspot.com/-yWEjZ2uxIEA/Ucm_1v8EEvI/AAAAAAAAAK4/gLwD6FVIPxk/s320/Screen+Shot+2013-06-25+at+5.58.30+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Creáis un nuevo UIViewController al que llamáis PageViewController:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/-SFYkDAPlqrM/Ucm_1BBnQaI/AAAAAAAAAKs/37YVoxZ78TI/s1600/Screen+Shot+2013-06-25+at+5.47.07+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;215&quot; src=&quot;http://3.bp.blogspot.com/-SFYkDAPlqrM/Ucm_1BBnQaI/AAAAAAAAAKs/37YVoxZ78TI/s320/Screen+Shot+2013-06-25+at+5.47.07+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Añadís el siguiente código a PageViewController.h:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#import &lt;uikit it.h=&quot;&quot;&gt;

@interface PageViewController : UIViewController &lt;uiscrollviewdelegate&gt;

@property (strong, nonatomic) IBOutlet UIScrollView* scrollView;
@property (strong, nonatomic) IBOutlet UIPageControl* pageControl;

-(IBAction)pageControlValueChanged:(id)sender;

@end
&lt;/uiscrollviewdelegate&gt;&lt;/uikit&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Añadís el siguiente código a PageViewController.m:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;#import &quot;PageViewController.h&quot;

@interface PageViewController ()

@end

@implementation PageViewController

- (void)viewDidLoad
{
  [super viewDidLoad];
}

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  
  int count = 0;
  float width = self.scrollView.frame.size.width;
  float height = self.scrollView.frame.size.height;
  
  NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@&quot;PageViews&quot; owner:self options:nil];
  for (UIView *view in nibViews) {
    [view setFrame:CGRectMake(width*count++, 0, width, height)];
    [self.scrollView addSubview:view];
  }
  
  self.scrollView.contentSize = CGSizeMake(width*count, height);
  self.pageControl.currentPage = 0;
  self.pageControl.numberOfPages = count;
}

- (void)didReceiveMemoryWarning
{
  [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(IBAction)pageControlValueChanged:(id)sender {
  
    // First, determine which page is currently visible
  CGFloat pageWidth = self.scrollView.frame.size.width;
  
  self.scrollView.contentOffset = CGPointMake(self.pageControl.currentPage*pageWidth, 0);
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
  
    // First, determine which page is currently visible
  CGFloat pageWidth = self.scrollView.frame.size.width;
  NSInteger page = (NSInteger)floor((self.scrollView.contentOffset.x * 2.0f + pageWidth) / (pageWidth * 2.0f));
  
    // Update the page control
  self.pageControl.currentPage = page;
}

@end
&lt;/pre&gt;
&lt;br /&gt;
Conectáis los IBOutlets, delegate del UIScrollView y el IBAction del UIPageControl en Interface Builder:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-Kmb2WU6AQ8g/Ucm_4IVOMoI/AAAAAAAAALc/VmYwi_AHY1A/s1600/Screen+Shot+2013-06-25+at+6.04.48+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://1.bp.blogspot.com/-Kmb2WU6AQ8g/Ucm_4IVOMoI/AAAAAAAAALc/VmYwi_AHY1A/s320/Screen+Shot+2013-06-25+at+6.04.48+PM.png&quot; width=&quot;246&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Y ahora vamos a añadir las vistas, pero de un modo bastante práctico. Vamos a crear un NIB con todas ellas y se van a cargar automáticamente. Creamos un NIB que llamaremos PageViews:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-vwoJwd-a4lk/Ucm_2vOSG6I/AAAAAAAAALQ/uZzuKTFwrac/s1600/Screen+Shot+2013-06-25+at+5.59.38+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;216&quot; src=&quot;http://4.bp.blogspot.com/-vwoJwd-a4lk/Ucm_2vOSG6I/AAAAAAAAALQ/uZzuKTFwrac/s320/Screen+Shot+2013-06-25+at+5.59.38+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Y le añadimos todas las vistas que queramos de modo secuencial:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-COw5bsHmI0w/Ucm_2mQFuXI/AAAAAAAAALM/z2jV08w8IIc/s1600/Screen+Shot+2013-06-25+at+6.01.59+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;159&quot; src=&quot;http://2.bp.blogspot.com/-COw5bsHmI0w/Ucm_2mQFuXI/AAAAAAAAALM/z2jV08w8IIc/s320/Screen+Shot+2013-06-25+at+6.01.59+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Aconsejo renombrar las vistas (tontería, siempre lo aconsejo, mientras más descriptivo el software mejor) porque en el orden en que aparezcan en la columna de la izquierda (en Objects) es como luego aparecerán.&lt;br /&gt;
&lt;br /&gt;
Y el resultado:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/-ProrcNHV6UM/Ucm_2244nUI/AAAAAAAAALU/xKTJPqFYoj8/s1600/Screen+Shot+2013-06-25+at+6.03.54+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://3.bp.blogspot.com/-ProrcNHV6UM/Ucm_2244nUI/AAAAAAAAALU/xKTJPqFYoj8/s320/Screen+Shot+2013-06-25+at+6.03.54+PM.png&quot; width=&quot;176&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Podéis moveros entre las diferentes vistas con sólo deslizar el dedo y los puntitos se actualizarán solos. Además los puntitos también responden y podéis ir de una a otra pantalla al tocarlos.</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/7047161602906250130/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/xcode-uipagecontrol.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/7047161602906250130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/7047161602906250130'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/xcode-uipagecontrol.html' title='XCode: UIPageControl'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s72-c/apple-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-8739350198013996726</id><published>2013-06-25T08:41:00.002-07:00</published><updated>2013-06-25T11:19:19.272-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="IOS"/><category scheme="http://www.blogger.com/atom/ns#" term="UIWebView"/><category scheme="http://www.blogger.com/atom/ns#" term="XCode"/><title type='text'>XCode: UIWebView</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s1600/apple-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s1600/apple-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Si quieres cargar contenidos web de forma fácil en iOS la respuesta es &lt;a href=&quot;http://developer.apple.com/library/ios/#documentation/uikit/reference/UIWebView_Class/Reference/Reference.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;UIWebView&lt;/a&gt;. Pero no sólo eso, también vale para cargar texto formateado de forma fácil y rápida. Y además con la ventaja de que no os tenéis que preocupar por si el texto no cabe ya que permite hacer scroll.&lt;br /&gt;
&lt;br /&gt;
Lo puedes añadir desde Interface Builder o crear una instancia en código:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/-WSuUjkov3Zg/UcmzDZtRAzI/AAAAAAAAAJ8/dq9V1GU-z_M/s1600/Screen+Shot+2013-06-25+at+5.08.37+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;114&quot; src=&quot;http://3.bp.blogspot.com/-WSuUjkov3Zg/UcmzDZtRAzI/AAAAAAAAAJ8/dq9V1GU-z_M/s320/Screen+Shot+2013-06-25+at+5.08.37+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;UIWebView *webView = [[UIWebView alloc] init];
&lt;/pre&gt;
&lt;br /&gt;
Desde Interface Builder puedes seleccionar que detecte varios tipos de datos (Links, números de teléfono, direcciones...) de forma que si aparece uno al seleccionarlo se producirá la acción correspondiente (p.ej. si es un número de teléfono se realizará una llamada a ese número). También da la opción de escalar la página al View, lo cual suele ser interesante para código HTML que no se adapte automáticamente.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-6uRcgNt_KhY/UcmzDNkFW7I/AAAAAAAAAKA/8xGEFQLhXgc/s1600/Screen+Shot+2013-06-25+at+5.08.59+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://1.bp.blogspot.com/-6uRcgNt_KhY/UcmzDNkFW7I/AAAAAAAAAKA/8xGEFQLhXgc/s1600/Screen+Shot+2013-06-25+at+5.08.59+PM.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Para cargar una página web externa:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;  NSURL *url = [NSURL URLWithString:&quot;www.direcciondemiweb.com&quot;];
  NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
  [webView loadRequest:requestObj];
&lt;/pre&gt;
&lt;br /&gt;
Para cargar código HTML directamente desde un NSString:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;NSString* htmlString = @&quot;&amp;lt;h2&amp;gt;Título&amp;lt;/h2&amp;gt;&amp;lt;p&amp;gt;Algo de texto&amp;lt;/p&amp;gt;&quot;;
[webView loadHTMLString:htmlString baseURL:nil];
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Para cargar una página desde un archivo local:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:@&quot;mi_pagina&quot; ofType:@&quot;html&quot;];
NSString* htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[webView loadHTMLString:htmlString baseURL:baseURL];
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Y si queréis cargar alguna imagen local lo podéis hacer así:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;img src=&quot;mi_imagen.png&quot;&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
Además tiene un delegate (&lt;a href=&quot;http://developer.apple.com/library/ios/#documentation/uikit/reference/UIWebViewDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intf/UIWebViewDelegate&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;UIWebViewDelegate&lt;/a&gt;) que podéis implementar y os informa del estado de la operación de cargar una web (p.ej. si ha habido error, si se ha cargado correctamente...).&lt;br /&gt;
&lt;br /&gt;
Y juntando una cosa con la otra surge un hack muy útil (definiendo hack como dar un uso alternativo a una funcionalidad para conseguir una solución práctica a un problema):&lt;br /&gt;
&lt;br /&gt;
Supongamos que nos conectamos a un servidor y este nos devuelve datos de texto pero formateados en html y/o unicode (p.ej. con etiquetas o códigos de caracteres: &amp;lt;b&amp;gt;, \u00d1...). Y los queremos mostrar en un UILabel, pero si lo hacemos tal cual, aparecerán esas etiquetas y códigos. Sin embargo sólo nos interesa el texto y si lo puede parsear otro (Homer: &quot;¡que lo haga otro!&quot;, en este caso que lo haga el UIWebView) mejor que mejor.&lt;br /&gt;
&lt;br /&gt;
Podemos crear un UIWebView (invisible, no hace falta añadirlo a la vista), cargarle el HTML e implementar el delegate. Y cuando termine de cargar:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSString *textoPlano = [webView stringByEvaluatingJavaScriptFromString:@&quot;document.body.innerHTML&quot;];
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/8739350198013996726/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/xcode-uiwebview.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/8739350198013996726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/8739350198013996726'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/xcode-uiwebview.html' title='XCode: UIWebView'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s72-c/apple-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-6844540178922976148</id><published>2013-06-23T10:22:00.000-07:00</published><updated>2013-06-23T10:40:42.198-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaCV"/><title type='text'>Android y JavaCV: Cargar imágenes</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-ZjWZZMZ7wXM/UcTflCbcmdI/AAAAAAAAAJQ/QP0REJOl12M/s1600/android-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://4.bp.blogspot.com/-ZjWZZMZ7wXM/UcTflCbcmdI/AAAAAAAAAJQ/QP0REJOl12M/s1600/android-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Tanto JavaCV como OpenCV son muy fáciles de utilizar en un ordenador. Pero a la hora de trabajar en Android en seguida surge un pequeño problema: ¿Cómo cargo las imágenes?. La clase BufferedImage no existe en Android, y la mitad de los métodos no funcionan por una u otra razón.&lt;br /&gt;
&lt;br /&gt;
Nota: Recordad que en OpenCV (y por lo tanto JavaCV), el formato por defecto es BGR para las imágenes en color (CV_LOAD_IMAGE_COLOR).&lt;br /&gt;
&lt;h4&gt;
&lt;br /&gt;&lt;/h4&gt;
&lt;h4&gt;
Soluciones para cargar imagenes&lt;/h4&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;Desde recursos (p.ej: res/drawable/imagen.png)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Aquí el problema consiste en que los recursos se accede a través de un identificador tipo int, así que el truco consiste en cargar un bitmap y copiar directamente los píxeles desde el bitmap a una IplImage:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;// Se carga el recurso en un bitmap
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.imagen);

// Se crea la imagen
IplImage image = IplImage.create(bitmapMask.getWidth(), bitmapMask.getHeight(), IPL_DEPTH_8U, 4); // ARGB

// Se copian los píxeles del bitmap a la imagen
bitmap.copyPixelsToBuffer(image);&lt;/pre&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;
Desde Assets (p.ej: assets/imagen.jpg)&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;
El problema consiste en que los archivos guardados en assets están comprimidos, por lo que acceder a través del path (file:///android_asset/imagen.jpg) no funciona. El truco consiste en copiarlo a la caché y cargar la imagen desde ahí:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;// type: CV_LOAD_IMAGE_COLOR
public static IplImage loadImageFromAsset(Context context, String filename, int type) {

  IplImage image = null;

  File file = new File(context.getCacheDir() + &quot;/&quot; + filename);
  if (!file.exists())
   try {

    InputStream is = context.getAssets().open(filename);
    int size = is.available();
    byte[] buffer = new byte[size];
    is.read(buffer);
    is.close();

    FileOutputStream fos = new FileOutputStream(file);

    fos.write(buffer);
    fos.close();
   } catch (Exception e) {
    throw new RuntimeException(e);
   }

  if (file.exists()) {
   image = cvLoadImage(file.getAbsolutePath(), type);
  }

  return image;
 }&lt;/pre&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;
Y por último desde la SD o path (y aunque resulte obvio desde el ejemplo anterior):&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;IplImage image = cvLoadImage(path, CV_LOAD_IMAGE_COLOR);
&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/6844540178922976148/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/android-y-javacv-cargar-imagenes.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/6844540178922976148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/6844540178922976148'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/android-y-javacv-cargar-imagenes.html' title='Android y JavaCV: Cargar imágenes'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-ZjWZZMZ7wXM/UcTflCbcmdI/AAAAAAAAAJQ/QP0REJOl12M/s72-c/android-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-2518541379635175297</id><published>2013-06-21T16:21:00.000-07:00</published><updated>2013-06-21T16:21:40.541-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Cámara"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaCV"/><category scheme="http://www.blogger.com/atom/ns#" term="OpenCV"/><category scheme="http://www.blogger.com/atom/ns#" term="Video"/><title type='text'>Android y JavaCV: Grabar videos con la cámara</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/-ZjWZZMZ7wXM/UcTflCbcmdI/AAAAAAAAAJM/T44IM9rku6I/s1600/android-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://3.bp.blogspot.com/-ZjWZZMZ7wXM/UcTflCbcmdI/AAAAAAAAAJM/T44IM9rku6I/s1600/android-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Si hay una diferencia entre Android e iOS realmente objetiva es el tema de las cámaras de videos. En iOS existen multitud de cámaras con diversos efectos especiales y únicos, mientras que en Android nos resignamos a los pocos que vienen de fábrica dependiendo de la versión de Android que tengas. Y el efecto sepia no mola.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
Y con la amplia gama de dispositivos Android, de los cuales más de uno cuentan con mejores procesadores y cámaras que la gama iPhone, ¿cómo se pueden hacer &amp;nbsp;aplicaciones de cámaras con efectos especiales al igual que existen en iPhone?:&lt;/div&gt;
&lt;div&gt;
Pues oficialmente no se puede, el firmware en Android funciona de otra forma que impide este tipo de aplicaciones. Si cuentas con acceso&amp;nbsp;&lt;i&gt;root&lt;/i&gt;, podrías intentar hacer algo con el&amp;nbsp;&lt;i&gt;Framebuffer&lt;/i&gt;... pero eso sería pasar al lado oscuro... (y no tengo nada en contra excepto que si te saltas las &quot;reglas&quot; es cuando comienzan los errores inesperados porque cada Android es diferente).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&amp;nbsp;Hay dos formas de grabar vídeos en Android &quot;oficialmente&quot;:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Lanzando un Intent: lo cual es como pedirle al usuario que si quiere grabar un video abra la aplicación de la cámara y que por favor lo grabe.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Con las clases &lt;a href=&quot;http://developer.android.com/reference/android/hardware/Camera.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Camera&lt;/a&gt; y &lt;a href=&quot;http://developer.android.com/reference/android/media/MediaRecorder.VideoSource.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;MediaRecorder&lt;/a&gt;: Te permiten grabar un video, controlando algunos parámetros como la resolución, el zoom... y puedes aplicar unos pocos efectos predefinidos (según versión, pero casualmente siempre podrás aplicar el efecto sepia :( ).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Oficialmente no puedes &quot;meter código&quot; entre la cámara y el codificador de video, por lo que no se puede alterar las imágenes antes de que se graben en el archivo de video y por lo tanto la tarea de hacer efectos de video se complica.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
¿Pero hay solución no?: ¡Claro! (bueno, hay soluciones...):&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Lo primero que hay que hacer es obtener los frames de la cámara. O bien las obtenéis directamente a través de la clase Camera (en este &lt;a href=&quot;http://blog.itiox.com/2013/03/previsualizacion-de-la-camara-de.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;post&lt;/a&gt; hablo de ello) o bien usáis una librería de terceros (&lt;a href=&quot;http://opencv.willowgarage.com/wiki/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;OpenCV&lt;/a&gt; es una opción).&lt;/li&gt;
&lt;li&gt;En segundo lugar procesáis los frames, aplicáis efectos especiales, máscaras, filtros, ... (OpenCV e &lt;a href=&quot;http://www.imagemagick.org/script/index.php&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;ImageMagick&lt;/a&gt; son dos buenas opciones según lo que busquéis).&lt;/li&gt;
&lt;li&gt;Y luego grabar el video (y aquí &lt;a href=&quot;http://ffmpeg.org/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;ffmpeg&lt;/a&gt; es &quot;la solución&quot;).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Pues existe la librería &lt;a href=&quot;http://code.google.com/p/javacv/http://code.google.com/p/javacv/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;JavaCV&lt;/a&gt;&amp;nbsp;que integra OpenCV, ffmpeg y un montón de cosas más y además ¡os permite programar en Java!.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
¿Cómo se integra?&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;De este &lt;a href=&quot;http://code.google.com/p/javacv/downloads/list&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;enlace&lt;/a&gt;, os descargáis javacv-*-bin.zip (* es la versión) y javacv-cppjars.zip y los descomprimimos.&lt;/li&gt;
&lt;li&gt;Creáis un proyecto (también vale uno que ya esté creado) y en la carpeta libs copiáis javacv.jar y javacpp.jar (ambos de javacv-*-bin.zip).&lt;/li&gt;
&lt;li&gt;Los archivos jar, no son más que contenedores a los que les podéis cambiar la extensión por .zip y descomprimir para ver lo que hay dentro. Pues eso tenéis que hacer con los archivos javacv-android-arm.jar, ffmpeg-*-android-arm.jar y opencv-*-android-arm.jar. Dentro encontraréis varias subcarpetas anidadas y al fondo del todo unos cuantos archivos .so (librerías nativas).&lt;/li&gt;
&lt;li&gt;Debéis crear una subcarpeta dentro de la carpeta libs en vuestro proyecto que se llame armeabi y copiáis dentro todos los .so del punto anterior (luego habrá tiempo para quitar los que no utilicéis).&lt;/li&gt;
&lt;li&gt;&amp;nbsp;En Eclipse seleccionáis el proyecto, clic derecho --&amp;gt; Properties --&amp;gt; Java Build Path --&amp;gt; Libraries --&amp;gt; Add JARs y añadís las librerías del punto 2.&lt;/li&gt;
&lt;li&gt;Dentro de la carpeta javacv-bin (del punto 1) hay una subcarpeta samples. De ella copiáis el archivo RecordActivity.java en el source de vuestro proyecto. Lo más fácil en Eclipse es copiar el archivo y pegarlo directamente en la carpeta en Eclipse, le cambiáis el nombre del paquete por el correspondiente y punto.&lt;/li&gt;
&lt;li&gt;En la cabecera del archivo anterior explica como usarlo, básicamente copiáis la parte del Manifest que indica en el vuestro (más que nada los permisos y la declaración de la clase) y luego creáis un layout para la actividad en los recursos con el código que indica a continuación.&lt;/li&gt;
&lt;li&gt;Conectáis vuestro Android (con cámara) y ejecutáis la aplicación.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
Si no cambiáis nada el resultado se almacena en un archivo de extensión FLV en /mnt/sdcard/stream.flv&quot; y el resultado es:&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-t1zkhIa5faY/UcTfSObisNI/AAAAAAAAAJE/15KqLt9tw4k/s1600/Screenshot_2013-06-22-01-15-27.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;192&quot; src=&quot;http://4.bp.blogspot.com/-t1zkhIa5faY/UcTfSObisNI/AAAAAAAAAJE/15KqLt9tw4k/s320/Screenshot_2013-06-22-01-15-27.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/2518541379635175297/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/android-y-javacv-grabar-videos-con-la.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/2518541379635175297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/2518541379635175297'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/android-y-javacv-grabar-videos-con-la.html' title='Android y JavaCV: Grabar videos con la cámara'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-ZjWZZMZ7wXM/UcTflCbcmdI/AAAAAAAAAJM/T44IM9rku6I/s72-c/android-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-8595586307119204658</id><published>2013-06-21T04:58:00.001-07:00</published><updated>2014-09-07T03:52:33.729-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Blogger"/><title type='text'>Mostrar código fuente en Blogger</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-ND-CXHcIIuQ/Ub2TZeLxxDI/AAAAAAAAAIY/VX55kYFwD-M/s1600/blogger-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-ND-CXHcIIuQ/Ub2TZeLxxDI/AAAAAAAAAIY/VX55kYFwD-M/s1600/blogger-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
Hace algunos posts, explicábamos cómo formatear el código fuente de una entrada usando&lt;br /&gt;
SyntaxHighlighter. Puedes leerla&amp;nbsp;&lt;a href=&quot;http://blog.itiox.com/2013/01/publicar-codigo-fuente-en-blogger-con.html&quot;&gt;aquí&lt;/a&gt;. El resultado es muy bonito, pero el rendimiento es bastante pobre.&lt;br /&gt;
&lt;br /&gt;
Otra forma para conseguir código con formato para tu blog, es usar&amp;nbsp;&lt;a href=&quot;http://code.google.com/p/google-code-prettify/&quot;&gt;google-code-prettify&lt;/a&gt;. Se instala muy fácilmente siguiendo esto pasos:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Entra en tu blog&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Ve a Diseño-&amp;gt;Edición HTML&lt;/li&gt;
&lt;li&gt;Busca el cierre del head, &amp;lt;/head&amp;gt; y justo arriba pegas el siguiente código&lt;/li&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;script src=&quot;
https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js&quot;&amp;gt;
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;También puedes descargarte el módulo completo desde&amp;nbsp;&lt;a href=&quot;http://code.google.com/p/google-code-prettify/downloads/list&quot;&gt;aquí&lt;/a&gt;&amp;nbsp;y usar esto:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;link href=&quot;prettify.css&quot; type=&quot;text/css&quot; rel=&quot;stylesheet&quot; /&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;prettify.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Guarda los cambios&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Así, cuando escribas una entrada nueva, en la edición HTML, debes encerrar tu código con estos tags:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;span class=&quot;s1&quot;&gt;&amp;lt;pre&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s3&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;s4&quot;&gt;=&lt;/span&gt;&quot;prettyprint&quot;&lt;span class=&quot;s1&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;p2&quot;&gt;
&amp;nbsp; mi código aquí&lt;/div&gt;
&lt;div class=&quot;p3&quot;&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div class=&quot;p1&quot;&gt;
Puedes ir comprobando el resultado con la Vista previa del blog. El resultado es:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;mi código aquí
&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/8595586307119204658/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/mostrar-codigo-fuente-en-blogger.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/8595586307119204658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/8595586307119204658'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/mostrar-codigo-fuente-en-blogger.html' title='Mostrar código fuente en Blogger'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-ND-CXHcIIuQ/Ub2TZeLxxDI/AAAAAAAAAIY/VX55kYFwD-M/s72-c/blogger-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-9095031636677130040</id><published>2013-06-20T11:10:00.002-07:00</published><updated>2013-06-20T11:10:41.762-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Datos"/><category scheme="http://www.blogger.com/atom/ns#" term="JSON"/><category scheme="http://www.blogger.com/atom/ns#" term="Network"/><title type='text'>Redes, Apps y JSON: JSend</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-1Jzk6ZI8KpY/UcM6YvqhztI/AAAAAAAAAI0/yEhErC3pcLs/s1600/network-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://1.bp.blogspot.com/-1Jzk6ZI8KpY/UcM6YvqhztI/AAAAAAAAAI0/yEhErC3pcLs/s1600/network-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a href=&quot;http://www.json.org/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;JSON&lt;/a&gt; es un formato de intercambio de datos cliente-servidor muy liviano y fácil de utilizar. Junto con XML son los formatos (basados en texto) probablemente más extendidos en la red.

&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;{
    &quot;firstName&quot;: &quot;John&quot;,
    &quot;lastName&quot;: &quot;Smith&quot;,
    &quot;age&quot;: 25,
    &quot;address&quot;: {
        &quot;streetAddress&quot;: &quot;21 2nd Street&quot;,
        &quot;city&quot;: &quot;New York&quot;,
        &quot;state&quot;: &quot;NY&quot;,
        &quot;postalCode&quot;: 10021
    },
    &quot;phoneNumbers&quot;: [
        {
            &quot;type&quot;: &quot;home&quot;,
            &quot;number&quot;: &quot;212 555-1234&quot;
        },
        {
            &quot;type&quot;: &quot;fax&quot;,
            &quot;number&quot;: &quot;646 555-4567&quot;
        }
    ]
}

&lt;/pre&gt;
Fácil, ¿no?&lt;br /&gt;
&lt;br /&gt;
En el mundo de las aplicaciones móviles JSON es muy importante porque la gran mayoría necesitan conectarse a un servidor para funcionar. AdMob, Yahoo Weather, Google Play Game Services... casi todos los &quot;grandes&quot; usan JSON (y XML), para codificar los datos que intercambian con las aplicaciones.&lt;br /&gt;
&lt;br /&gt;
Y si eres de los &quot;pequeños&quot; ( o de los nuestros ;)), y tienes un servidor que quieres utilizar para desarrollar una App, quizás una base de datos MySql y unos cuantos PHP, un sincero consejo: &lt;b&gt;usa JSON&lt;/b&gt;. Las dos grandes plataformas móviles (iOS y Android o Android e iOS), se integran muy bien y también se lleva bien con PHP+MySql. La segunda opción sería XML, pero en mi opinión los móviles hacen mejores migas con JSON.&lt;br /&gt;
&lt;br /&gt;
Y entonces llega la segunda gran pregunta cuando diseñas uno de estos sistemas de intercambio de datos y te das cuenta de que tienes 10 o 20 tipos de mensajes diferentes cliente-servidor y el mismo número de archivos de código para interpretarlos (y por lo tanto un montón de bugs y errores): &quot;Debe existir &amp;nbsp;algún sistema estándar para estructurar estos mensajes, ¿no?. Así podría reutilizar algo de código y eliminar bugs...&quot;.&lt;br /&gt;
&lt;br /&gt;
Pues a falta de una gran respuesta oficial, mi sugerencia es &lt;a href=&quot;http://labs.omniti.com/labs/jsend&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;JSend&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;{
    status : &quot;success&quot;,
    data : {
        &quot;post&quot; : { &quot;id&quot; : 1, &quot;title&quot; : &quot;Título&quot;, &quot;body&quot; : &quot;Mensaje&quot; }
     }
}
&lt;/pre&gt;
&lt;br /&gt;
Los campos principales son:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;status&lt;/b&gt;: que indica si la operación ha sido correcta (&quot;success&quot;), ha fallado (&quot;fail&quot;) o ha habido un error (&quot;error&quot;). La diferencia entre fallo y error es que el primero se utiliza cuando hay un problema con los datos que se han enviado en la petición o cuando hay un problema en la llamada a la API (p.ej. una petición que requiere estar logueado sin estarlo).&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;data&lt;/b&gt;: contiene los datos que se envían en el mensaje en caso de haber sido la operación correcta, o los motivos de fallo. &lt;u&gt;Obligatorio&lt;/u&gt; en caso de petición correcta o con fallo.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;message&lt;/b&gt;: En caso de haber ocurrido un error (p.ej. en el servidor) indica los motivos del error. &lt;u&gt;Obligatorio&lt;/u&gt; en caso de error.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;code&lt;/b&gt;: Código descriptivo del error, podéis utilizar los mismos que de HTTP si queréis. &lt;u&gt;Opcional&lt;/u&gt; en caso de error.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Ejemplos:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Petición de datos de un usuario correcta:
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;{
    &quot;status&quot; : &quot;success&quot;,
    &quot;data&quot; : { &quot;post&quot; : { &quot;id&quot; : 1, &quot;username&quot; : &quot;pepe&quot;, &quot;name&quot; : &quot;José&quot;, &quot;lastname&quot; : &quot;Navarro&quot; }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Fallo de autenticación:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;{
    &quot;status&quot; : &quot;fail&quot;,
    &quot;data&quot; : { &quot;title&quot; : &quot;La contraseña no es correcta&quot; }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Error en el servidor por tiempo de espera superado:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;{
    &quot;status&quot; : &quot;error&quot;,
    &quot;message&quot; : &quot;Tiempo de espera superado&quot;
    &quot;code&quot; : &quot;508&quot;
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/9095031636677130040/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/redes-apps-y-json-jsend.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/9095031636677130040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/9095031636677130040'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/redes-apps-y-json-jsend.html' title='Redes, Apps y JSON: JSend'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-1Jzk6ZI8KpY/UcM6YvqhztI/AAAAAAAAAI0/yEhErC3pcLs/s72-c/network-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-3281212627401310163</id><published>2013-06-19T15:03:00.002-07:00</published><updated>2013-06-19T15:18:00.866-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Cocos2d"/><title type='text'>Cocos2d-X: Menús y botones</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-XSxA0FIq2ng/Ub2OU_ksg8I/AAAAAAAAAIE/YvMc6RpppGc/s1600/cocos2dx-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://1.bp.blogspot.com/-XSxA0FIq2ng/Ub2OU_ksg8I/AAAAAAAAAIE/YvMc6RpppGc/s1600/cocos2dx-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;En Cocos la manera más sencilla de crear botones es a través de las clases CCMenu y CCMenuItem. Es decir se crea un menú (CCMenu) y se le añaden los botones (CCMenuItem).&lt;/span&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
Lo primero y más importante es como recibir el evento de botón pulsado:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;// Dentro del método init() de vuestro CCLayer
// CCMenuItem *button;
button-&amp;gt;setTarget(this, menu_selector(TuClase::buttonCallback));
&lt;/pre&gt;
&lt;br /&gt;
Donde el callback lo podéis definir como:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;// pSender es la instancia del botón
void buttonCallback(cocos::CCObject* pSender);
&lt;/pre&gt;
&lt;br /&gt;
Para crear un botón a partir de imagen&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;// CCSprite *normalSprite; --&amp;gt; Botón sin pulsar
// CCSprite *selectedSprite; --&amp;gt; Botón pulsado
CCMenuItemSprite::create(normalSprite, selectedSprite);&lt;/pre&gt;
&lt;br /&gt;
Y para crear un botón a partir de texto (los dos últimos parámetros son para el evento de botón pulsado):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;CCMenuItemFont* pCreditsButton = CCMenuItemFont::create(&quot;Jugar&quot;, this, menu_selector(TuClase::botonJugarCallback) );&lt;/pre&gt;
&lt;h4&gt;
Menús&lt;/h4&gt;
Normalmente en la pantalla de inicio de juego, suele haber un menú con botones para jugar, ver la ayuda, los créditos, la tienda... Para crear un menú, se crean los ítems que va a albergar (heredan todos de CCMenuItem), se crea el menú, se le añaden los items y se añade el menú a la capa (CCLayer).&lt;br /&gt;
&lt;br /&gt;
La manera más sencilla es crear un array con todos los botones y añadírselos al menú al crear este último:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;// Dentro del método init() de vuestro CCLayer
// CCArray* arrayOfCCMenuItems
CCMenu *menu = CCMenu::createWithArray(arrayOfCCMenuItems);

// O también
CCMenu::create(pButton0, pButton1, pButton2, NULL);

this-&amp;gt;addChild(menu);
&lt;/pre&gt;
&lt;br /&gt;
Si es un menú como el descrito, querréis alinear automáticamente los botones:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;// Alineación vertical
menu-&amp;gt;alignItemsVertically();

// Alineación horizontal
menu-&amp;gt;alignItemsHorizontally()

&lt;/pre&gt;
Ejemplo de pantalla de menú completo (a partir de un proyecto recien creado, en el archivo HelloWorld.cpp):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
  if ( !CCLayer::init() )
  {
    return false;
  }
  
    // ask director the window size
  CCSize size = CCDirector::sharedDirector()-&amp;gt;getWinSize();

  CCMenuItemFont* pPlayButton = CCMenuItemFont::create(&quot;Jugar&quot;, this, menu_selector(HelloWorld::playCallback) );
  CCMenuItemFont* pHelpButton = CCMenuItemFont::create(&quot;Ayuda&quot;, this, menu_selector(HelloWorld::helpCallback) );
  CCMenuItemFont* pCreditsButton = CCMenuItemFont::create(&quot;Créditos&quot;, this, menu_selector(HelloWorld::creditsCallback) );

  // create menu, it&#39;s an autorelease object
  CCMenu* pMenu = CCMenu::create(pPlayButton, pHelpButton, pCreditsButton, NULL);
  pMenu-&amp;gt;setPosition( ccp(size.width / 2, size.height / 2) );
  pMenu-&amp;gt;alignItemsVertically();
  this-&amp;gt;addChild(pMenu);
  return true;
}

void HelloWorld::playCallback(CCObject *) {
  // TODO
}
...
&lt;/pre&gt;
&lt;br /&gt;
Y el resultado:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-Fz8yvgj5szE/UcIqhSNIUzI/AAAAAAAAAIk/CVYqjJar2S8/s1600/Screen+Shot+2013-06-20+at+12.01.13+AM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://1.bp.blogspot.com/-Fz8yvgj5szE/UcIqhSNIUzI/AAAAAAAAAIk/CVYqjJar2S8/s320/Screen+Shot+2013-06-20+at+12.01.13+AM.png&quot; width=&quot;173&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;/h4&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/3281212627401310163/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/cocos2d-x-menus-y-botones.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/3281212627401310163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/3281212627401310163'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/cocos2d-x-menus-y-botones.html' title='Cocos2d-X: Menús y botones'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-XSxA0FIq2ng/Ub2OU_ksg8I/AAAAAAAAAIE/YvMc6RpppGc/s72-c/cocos2dx-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-1694090095475112695</id><published>2013-06-19T03:53:00.002-07:00</published><updated>2014-09-07T03:54:42.952-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Blogger"/><title type='text'>Gadget Seguir a de Twitter para Blogger</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-ND-CXHcIIuQ/Ub2TZeLxxDI/AAAAAAAAAIY/VX55kYFwD-M/s1600/blogger-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-ND-CXHcIIuQ/Ub2TZeLxxDI/AAAAAAAAAIY/VX55kYFwD-M/s1600/blogger-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Si quieres incluir en tu blog el gadget &quot;Seguir a&quot; de Twitter, sigue estos pasos.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-Le8W50WgIp4/VAw5W5kRw4I/AAAAAAAAAOc/WXint9lyuVc/s1600/Captura%2Bde%2Bpantalla%2B2014-09-07%2Ba%2Bla(s)%2B12.54.01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-Le8W50WgIp4/VAw5W5kRw4I/AAAAAAAAAOc/WXint9lyuVc/s1600/Captura%2Bde%2Bpantalla%2B2014-09-07%2Ba%2Bla(s)%2B12.54.01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Entra en tu blog a la sección de Diseño&lt;/li&gt;
&lt;li&gt;Añade un nuevo gadget del tipo HTML/Javascript&lt;/li&gt;
&lt;li&gt;Copia y pega el siguiente código&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;a href=&quot;https://twitter.com/USUARIO&quot; class=&quot;twitter-follow-button&quot; 
data-show-count=&quot;true&quot; data-lang=&quot;es&quot;&amp;gt;Seguir a USUARIO&amp;lt;/a&amp;gt;&amp;lt;br/&amp;gt;
&amp;lt;script&amp;gt;!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];
if(!d.getElementById(id)){js=d.createElement(s);js.id=id;
js.src=&quot;//platform.twitter.com/widgets.js&quot;;fjs.parentNode.insertBefore(js,fjs);}}
(document,&quot;script&quot;,&quot;twitter-wjs&quot;);&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Cambia USUARIO por tu usuario de twitter&lt;/li&gt;
&lt;li&gt;La opción&amp;nbsp;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;data-show-count=&quot;true&quot;&lt;/span&gt; mostrará el número de seguidores en un recuadro&lt;/li&gt;
&lt;li&gt;Dale a guardar y ¡voilá!&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;h4&gt;
Relacionado&lt;/h4&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;a href=&quot;http://blog.itiox.com/2013/05/anadir-botones-sociales-en-vertical-tu.html&quot;&gt;Botones sociales en vertical para Blogger&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;a href=&quot;http://blog.itiox.com/2013/05/gadget-twitter-para-blogger.html&quot;&gt; Gadget Twitter para Blogger&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/1694090095475112695/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/gadget-seguir-de-twitter-para-blogger_19.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/1694090095475112695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/1694090095475112695'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/gadget-seguir-de-twitter-para-blogger_19.html' title='Gadget Seguir a de Twitter para Blogger'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-ND-CXHcIIuQ/Ub2TZeLxxDI/AAAAAAAAAIY/VX55kYFwD-M/s72-c/blogger-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-2998463540303815588</id><published>2013-06-15T09:48:00.000-07:00</published><updated>2013-06-20T02:53:29.135-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Cocos2d"/><category scheme="http://www.blogger.com/atom/ns#" term="IOS"/><title type='text'>Cocos2d-X Backgrounds: Color, Gradiente, Imagen de fondo, Tiled...</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-XSxA0FIq2ng/Ub2OU_ksg8I/AAAAAAAAAH8/YtMYxOJ-iVk/s1600/cocos2dx-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://1.bp.blogspot.com/-XSxA0FIq2ng/Ub2OU_ksg8I/AAAAAAAAAH8/YtMYxOJ-iVk/s1600/cocos2dx-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
Cocos2d es genial, y la versión &lt;a href=&quot;http://www.cocos2d-x.org/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Cocos2d-X&lt;/a&gt; es de mis favoritas. Pero a veces lo simple se complica.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Por ejemplo el fondo de una escena. ¿Cómo se pone de un color?:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;  CCLayerColor *backgroundLayer = CCLayerColor::create(ccc4(255, 0, 0, 255));
  backgroundLayer-&amp;gt;setZOrder(0);
  this-&amp;gt;addChild(backgroundLayer);
&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/-zMkycxnJYmA/UbyUXEJmZsI/AAAAAAAAAFo/e1BZAtDv2tY/s1600/Screen+Shot+2013-06-15+at+6.20.03+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;170&quot; src=&quot;http://3.bp.blogspot.com/-zMkycxnJYmA/UbyUXEJmZsI/AAAAAAAAAFo/e1BZAtDv2tY/s320/Screen+Shot+2013-06-15+at+6.20.03+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
¿Y un gradiente?:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;  CCLayerGradient *backgroundLayer = CCLayerGradient::create(ccc4(255, 0, 0, 255), ccc4(0, 0, 255, 255));
  backgroundLayer-&amp;gt;setZOrder(0);
  this-&amp;gt;addChild(backgroundLayer);
&lt;/pre&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-EHfVNwZJUy4/UbyVVgr0l1I/AAAAAAAAAF0/kAuNcGFSfas/s1600/Screen+Shot+2013-06-15+at+6.23.54+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;167&quot; src=&quot;http://2.bp.blogspot.com/-EHfVNwZJUy4/UbyVVgr0l1I/AAAAAAAAAF0/kAuNcGFSfas/s320/Screen+Shot+2013-06-15+at+6.23.54+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
¿Y un gradiente pero con otra dirección, por ejemplo diagonal?&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;  CCSize size = CCDirector::sharedDirector()-&amp;gt;getWinSize();

  CCLayerGradient *backgroundLayer = CCLayerGradient::create(ccc4(255, 0, 0, 255), ccc4(0, 0, 255, 255), ccp(size.width/2, size.height/2));
  backgroundLayer-&amp;gt;setZOrder(0);
  this-&amp;gt;addChild(backgroundLayer);
&lt;/pre&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-8tRehGGE0EM/UbyVy5Ovb4I/AAAAAAAAAF8/n71jLkBGs2c/s1600/Screen+Shot+2013-06-15+at+6.26.06+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;164&quot; src=&quot;http://1.bp.blogspot.com/-8tRehGGE0EM/UbyVy5Ovb4I/AAAAAAAAAF8/n71jLkBGs2c/s320/Screen+Shot+2013-06-15+at+6.26.06+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
¿Y una imagen de fondo?&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;  CCSprite *backgroundSprite = CCSprite::create(&quot;HelloWorld.png&quot;);
  backgroundSprite-&amp;gt;setPosition(ccp(size.width/2, size.height/2));
  backgroundSprite-&amp;gt;setZOrder(0);
  this-&amp;gt;addChild(backgroundSprite);
&lt;/pre&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-AkmpiFHuLRQ/UbyXILkZdsI/AAAAAAAAAGI/k2hWLVsMF7M/s1600/Screen+Shot+2013-06-15+at+6.31.31+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;163&quot; src=&quot;http://4.bp.blogspot.com/-AkmpiFHuLRQ/UbyXILkZdsI/AAAAAAAAAGI/k2hWLVsMF7M/s320/Screen+Shot+2013-06-15+at+6.31.31+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Y para sacar nota: ¿Qué pasa si tengo una imagen que quiero que se repita en el eje X y el eje Y de forma automática ocupando toda la pantalla (y claro, que funcione no sólo en el tamaño de la pantalla del iPhone)?&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;    // ask director the window size
  CCSize size = CCDirector::sharedDirector()-&amp;gt;getWinSize();

  CCRect rect(0, 0, size.width, size.height);
  CCSprite *backgroundSprite = CCSprite::create(&quot;WhereIsThatFly.png&quot;, rect);
  backgroundSprite-&amp;gt;setPosition(ccp(size.width/2, size.height/2));
  backgroundSprite-&amp;gt;setZOrder(0);
  ccTexParams params = {GL_LINEAR,GL_LINEAR,GL_REPEAT,GL_REPEAT};
  backgroundSprite-&amp;gt;getTexture()-&amp;gt;setTexParameters(&amp;amp;params);
  this-&amp;gt;addChild(backgroundSprite);
&lt;/pre&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-jCC8gYFb7Vs/UbyZZ4MZJWI/AAAAAAAAAGY/9WsJaQ9hYcE/s1600/Screen+Shot+2013-06-15+at+6.41.08+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;166&quot; src=&quot;http://4.bp.blogspot.com/-jCC8gYFb7Vs/UbyZZ4MZJWI/AAAAAAAAAGY/9WsJaQ9hYcE/s320/Screen+Shot+2013-06-15+at+6.41.08+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
En este caso hay que tener cuidado el tamaño de la imagen, funcionará sin problemas si las longitudes (ancho y alto) en píxeles son potencia de dos (es decir 16, 32, 64, 128, 256...).&lt;br /&gt;
&lt;br /&gt;
La imagen utilizada es el icono de nuestro último (¡y primer!) juego hasta la fecha (espero que cuando leáis esto haya alguno más) disponible en Google Play: &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.itiox.wtf&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;¿Dónde está la mosca?&lt;/a&gt;&amp;nbsp;Actualmente estoy haciendo el &lt;i&gt;port&lt;/i&gt; a Cocos2D-X.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-wWO0C3AdC-U/UbyadvjEePI/AAAAAAAAAGk/xva53KIiln8/s1600/WhereIsThatFly.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-wWO0C3AdC-U/UbyadvjEePI/AAAAAAAAAGk/xva53KIiln8/s1600/WhereIsThatFly.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/2998463540303815588/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/cocos2d-x-backgrounds-color-gradiente.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/2998463540303815588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/2998463540303815588'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/cocos2d-x-backgrounds-color-gradiente.html' title='Cocos2d-X Backgrounds: Color, Gradiente, Imagen de fondo, Tiled...'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-XSxA0FIq2ng/Ub2OU_ksg8I/AAAAAAAAAH8/YtMYxOJ-iVk/s72-c/cocos2dx-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-1185144859076845316</id><published>2013-06-14T11:48:00.001-07:00</published><updated>2013-06-26T10:09:09.810-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="IOS"/><category scheme="http://www.blogger.com/atom/ns#" term="XCode"/><title type='text'>Xcode: Archivos de recursos, pantalla retina, iPhone 5 y iPad&#39;s</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s1600/apple-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s1600/apple-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Hay iPhone 3GS, otros con pantalla retina, luego está el iPhone 5 que es más largo y a parte están los iPad (con y sin retina).&lt;/div&gt;
&lt;br /&gt;
Una imagen que carguéis para uno de estos dispositivos puede que no se vea bien (o todo lo bien que se podría ver), según el dispositivo. Por eso a veces conviene hacer diferentes versiones que se adapten a cada uno de los diferentes tipos de dispositivos.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
En Xcode es posible y de manera muy fácil, usar diferentes recursos que se carguen de forma automática según si la pantalla es retina o no, si es iPhone 5 o si es un iPad. Todo se basa en un sistema de sufijos que se añaden entre el nombre del archivo y su extensión (p.ej. &quot;.png&quot;). Son los siguientes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Pantallas retina: añadir&amp;nbsp;&lt;b&gt;@2x&lt;/b&gt;&amp;nbsp;(p.ej. &lt;i&gt;imagen@2x.png&lt;/i&gt;).&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;iPads: añadir &lt;b&gt;~ipad &lt;/b&gt;(p.ej. &lt;i&gt;imagen~ipad.png&lt;/i&gt; y si fuera también retina&lt;i&gt; imagen@2x~ipad.png&lt;/i&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;iPhone 5: añadir &lt;b&gt;-568h@2x (&lt;/b&gt;p.ej.&lt;i&gt; imagen-568h@2x.png&lt;/i&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Sólo para iPhones y iPods Touch: añadir &lt;b&gt;~iphone&lt;/b&gt;&amp;nbsp;(p.ej. &lt;i&gt;imagen~iphone.png&lt;/i&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Y para cargar una imagen en un UIImage por ejemplo, debéis usar el nombre del archivo normal sin ningún tipo de sufijo, ya que la elección se realiza de forma automática. Por ejemplo:&lt;i&gt; [UIImage imageNamed:@&quot;image.png&quot;];&lt;/i&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/1185144859076845316/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/xcode-archivos-de-recursos-pantalla.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/1185144859076845316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/1185144859076845316'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/xcode-archivos-de-recursos-pantalla.html' title='Xcode: Archivos de recursos, pantalla retina, iPhone 5 y iPad&#39;s'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s72-c/apple-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-1833490938965695295</id><published>2013-06-14T11:20:00.000-07:00</published><updated>2013-06-26T10:08:41.900-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="IOS"/><category scheme="http://www.blogger.com/atom/ns#" term="XCode"/><title type='text'>Xcode: Localizar o Internacionalizar tu App</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s1600/apple-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s1600/apple-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
Una vez has desarrollado tu aplicación toca internacionalizarla. Excepto algunas aplicaciones que tocan temas muy locales, si desarrollas tu aplicación sólo en español estás perdiendo un montón de usuarios potenciales de habla inglesa (o que más o menos se defienden con el inglés). De igual forma si tu aplicación está sólo en inglés hay un gran público de habla hispano que estás marginando (y si estás leyendo este blog es porque hablas español).&lt;br /&gt;
&lt;br /&gt;
El mecanismo en Xcode ha ido cambiando con cada versión y aquí voy a explicar como se hace en la versión 4.6. Para otras versiones supongo que casi o todo de lo siguiente se puede aplicar:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Haciendo clic en el proyecto, buscas la sección &quot;Localizations&quot; en el formulario que aparece. Tienes que añadir los idiomas que vaya a soportar tu aplicación (por ejemplo inglés y español).&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/-fSTwj9deUZA/UbtWSh3l25I/AAAAAAAAAEs/-aHgpBGKR1s/s1600/Screen+Shot+2013-06-14+at+7.41.44+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;75&quot; src=&quot;http://3.bp.blogspot.com/-fSTwj9deUZA/UbtWSh3l25I/AAAAAAAAAEs/-aHgpBGKR1s/s320/Screen+Shot+2013-06-14+at+7.41.44+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;

&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Añades al proyecto un nuevo archivo de recursos de tipo Strings y lo llamas &lt;i&gt;Localizable.strings&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-rKHQ0t4Kkw0/UbtWymf2MoI/AAAAAAAAAE0/ZlXv_9zXGOU/s1600/Screen+Shot+2013-06-14+at+7.44.41+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;215&quot; src=&quot;http://1.bp.blogspot.com/-rKHQ0t4Kkw0/UbtWymf2MoI/AAAAAAAAAE0/ZlXv_9zXGOU/s320/Screen+Shot+2013-06-14+at+7.44.41+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;Seleccionas el nuevo archivo y normalmente en el lado derecho, bajo la descripción del archivo, aparece la opción Localizar. Lo localizamos y añadimos los idiomas de inglés y español (o los que hayamos añadido en el paso 1).&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-fafEz8y0gsE/UbtXhew-zLI/AAAAAAAAAFA/MQzmqiZ3XWI/s1600/Screen+Shot+2013-06-14+at+7.46.35+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://1.bp.blogspot.com/-fafEz8y0gsE/UbtXhew-zLI/AAAAAAAAAFA/MQzmqiZ3XWI/s1600/Screen+Shot+2013-06-14+at+7.46.35+PM.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-70qkxkXrD8c/UbtXhm7b9XI/AAAAAAAAAFE/ovOwNq1i6-o/s1600/Screen+Shot+2013-06-14+at+7.46.51+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-70qkxkXrD8c/UbtXhm7b9XI/AAAAAAAAAFE/ovOwNq1i6-o/s1600/Screen+Shot+2013-06-14+at+7.46.51+PM.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Lo que Xcode realmente hace es crear dos carpetas (en.lproj y es.lproj para inglés y español respectivamente) donde crea dos versiones diferentes del archivo Localizable.strings. Luego en tiempo de ejecución detecta el idioma en el que el usuario tiene configurado su dispositivo y carga la correcta.&lt;/li&gt;
&lt;li&gt;Abrimos uno de los dos archivos y el formato que hay que seguir para añadir traducciones es: &lt;i&gt;&quot;Key&quot; = &quot;Value&quot;;&lt;/i&gt; es decir una clave entre comillas dobles, símbolo igual, y el valor (normalmente la traducción) también entre comillas, ah ¡y no olvidar el punto y coma al final!&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-T1Kh0AzOF18/UbtZXO9vZ_I/AAAAAAAAAFY/IGECZu9OAeE/s1600/Screen+Shot+2013-06-14+at+7.54.51+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;80&quot; src=&quot;http://1.bp.blogspot.com/-T1Kh0AzOF18/UbtZXO9vZ_I/AAAAAAAAAFY/IGECZu9OAeE/s320/Screen+Shot+2013-06-14+at+7.54.51+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Hay bastante discusión sobre las buenas prácticas a la hora de añadir traducciones, yo suelo ver tres formas:&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;&lt;i&gt;&quot;Valor por defecto en inglés&quot; = &quot;Valor por defecto en el idioma local&quot;;&lt;/i&gt; (p.ej. &lt;i&gt;&quot;Hello&quot; = &quot;Hola&quot;;&lt;/i&gt;).&lt;/li&gt;
&lt;li&gt;&lt;i&gt;&quot;Clave descriptiva&quot; = &quot;Valor por defecto en el idioma local&quot;;&lt;/i&gt; (p.ej. en la pantalla ficticia llamada &quot;ayuda&quot;, tenemos un botón de contacto: &lt;i&gt;&quot;ayuda_boton_contacto&quot; = &quot;Contactar&quot;;&lt;/i&gt;).&lt;/li&gt;
&lt;li&gt;Una mezcla de las dos anteriores. Por ejemplo lo que yo suelo hacer es usar el primer método para palabras y expresiones muy comunes en mi aplicación (nombre de la aplicación, diálogos de error o botones como aceptar o cancelar...).&lt;/li&gt;
&lt;/ol&gt;
&lt;li&gt;Por último y para utilizar todo esto, nada más fácil que usar el método&amp;nbsp;&lt;span style=&quot;background-color: white; color: #666666; font-family: Courier, Consolas, monospace; font-size: 13px;&quot;&gt;&lt;a href=&quot;http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;NSLocalizedString(NSString *key, NSString *comment)&lt;/a&gt;&amp;nbsp;&lt;/span&gt;que devuelve un NSString. &lt;i&gt;key&lt;/i&gt; es la clave y &lt;i&gt;comment&lt;/i&gt; es un comentario para uso de desarrollo que a veces tiene sentido usarlo y otras simplemente lo podéis poner a &lt;i&gt;nil&lt;/i&gt;. Por ejemplo &lt;i&gt;NSLocalizedString(@&quot;Hello&quot;, nil)&lt;/i&gt; devolvería &lt;i&gt;@&quot;Hola&quot;&lt;/i&gt;&amp;nbsp;según el ejemplo del punto anterior si el usuario tuviera ajustado su móvil a español.&lt;/li&gt;
&lt;/ol&gt;
Hasta aquí lo básico que es localizar texto. Sin embargo podéis localizar cualquier otro recurso, por ejemplo gráficos, audio... siguiendo el mismo procedimiento. De esta forma podéis mostrar imágenes o reproducir sonidos diferentes según el idioma del usuario.&lt;br /&gt;
&lt;ol&gt;
&lt;/ol&gt;
No sólo los recursos, sino también los &lt;i&gt;Storyboards&lt;/i&gt; y los &lt;i&gt;XIBs&lt;/i&gt;. Por lo que el ejemplo anterior (&quot;ayuda_boton_contacto&quot;) puede que no tenga demasiado sentido ya que podéis poner diferentes textos al botón según la versión del &lt;i&gt;Storyboard&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Y luego hay ciertos &quot;&lt;i&gt;hacks&lt;/i&gt;&quot; que pueden resultar muy útiles en el caso del archivo Localizable.strings. Consisten en utilizarlos no para traducciones de texto, si no para cambiar el funcionamiento de la aplicación según el idioma:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Por ejemplo, en el caso de que si la aplicación se ejecuta en español os queréis conectar al servidor A y en el caso de inglés al servidor B podríais añadir una clave &quot;server&quot; donde en el archivo localizado en español tenga como valor A y en el otro valor B.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/1833490938965695295/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/xcode-localizar-o-internacionalizar-tu.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/1833490938965695295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/1833490938965695295'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/xcode-localizar-o-internacionalizar-tu.html' title='Xcode: Localizar o Internacionalizar tu App'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s72-c/apple-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-7500162343383146457</id><published>2013-06-14T04:00:00.002-07:00</published><updated>2013-06-20T02:59:31.853-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="IOS"/><category scheme="http://www.blogger.com/atom/ns#" term="Realidad Aumentada"/><title type='text'>iOS y Augmented Reality: Mostrar la cámara en un UIView</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-XDetJaboGZ8/Ub2OUinWUuI/AAAAAAAAAII/2RfB4OdYi60/s1600/apple-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-XDetJaboGZ8/Ub2OUinWUuI/AAAAAAAAAII/2RfB4OdYi60/s1600/apple-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
En la mayoría de las aplicaciones de realidad aumentada se usa la cámara.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
La forma directa de mostrar la cámara es a través de la clase &lt;a href=&quot;https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIImagePickerController_Class/UIImagePickerController/UIImagePickerController.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;UIImagePickerController&lt;/a&gt;. Básicamente te permite abrir la cámara en todos los modos disponibles, hacer fotos, vídeos, ... Y usar un overlay que podéis colocar encima.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Sin embargo puede que por el diseño o los requisitos de vuestra aplicación el mencionado overlay no sea la opción más adecuada. ¿Cuál es la otra opción? : El framework&amp;nbsp;&lt;a href=&quot;http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVFoundationFramework/_index.html#//apple_ref/doc/uid/TP40008072&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;AV Foundation&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Este método os va a permitir diseñar vuestra aplicación con vuestro Storyboard, XIB, ... y mostrar la previsualización de la cámara en el UIView que queráis. El cual no tiene porque ser de pantalla completa ni situarse en el centro.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Instrucciones:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;Añadir el framework de AV Foundation a vuestro proyecto.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-LkRnozH4reU/Ubr1oqt1_2I/AAAAAAAAAEc/1ggqvHOgTjI/s1600/Screen+Shot+2013-06-14+at+12.50.39+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://1.bp.blogspot.com/-LkRnozH4reU/Ubr1oqt1_2I/AAAAAAAAAEc/1ggqvHOgTjI/s320/Screen+Shot+2013-06-14+at+12.50.39+PM.png&quot; width=&quot;278&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Necesitáis una referencia al UIView sobre el que queráis mostrar la cámara. Supongamos que la llamamos &lt;i&gt;cameraView&lt;/i&gt;.&lt;/li&gt;
&lt;li&gt;Añadir el código:&lt;br /&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;
- (void)startCameraPreview {
  NSLog(@&quot;startCameraPreview&quot;);
  captureSession = [[AVCaptureSession alloc] init];
  
  
  AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
  NSError *error = nil;
  AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&amp;error];
  if (input) {
    [captureSession addInput:input];
    AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
    
      // Custom Fix to fill the view
    CGRect bounds=self.cameraView.layer.bounds;
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    previewLayer.bounds=bounds;
    previewLayer.position=CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
    
    [self.cameraView.layer addSublayer:previewLayer];
    [captureSession startRunning];
  }
  else {
      // Handle the failure.
  }
  
}&lt;/pre&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;No olvidéis llamar a &lt;i&gt;stopRunning&lt;/i&gt; al acabar!&lt;/li&gt;
&lt;/ol&gt;
Con pequeñas modificaciones lo podéis adaptar para capturar audio o audio y video a la vez.&lt;br /&gt;
&lt;ol&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/7500162343383146457/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/ios-y-augmented-reality-mostrar-la.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/7500162343383146457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/7500162343383146457'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/ios-y-augmented-reality-mostrar-la.html' title='iOS y Augmented Reality: Mostrar la cámara en un UIView'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-XDetJaboGZ8/Ub2OUinWUuI/AAAAAAAAAII/2RfB4OdYi60/s72-c/apple-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-6065909398351135023</id><published>2013-06-14T03:27:00.002-07:00</published><updated>2013-06-26T10:08:14.579-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="GIT"/><category scheme="http://www.blogger.com/atom/ns#" term="IOS"/><category scheme="http://www.blogger.com/atom/ns#" term="XCode"/><title type='text'>Xcode y GIT: Conectar tu proyecto a un repositorio remoto GIT</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s1600/apple-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s1600/apple-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Hay dos cosas imprescindibles en la programación que no son programar: comentar adecuadamente el código y usar un sistema de control de versiones.&lt;br /&gt;
&lt;br /&gt;
Si no sabes que es un sistema de control de versiones, en pocas y toscas palabras: es como lo que hacías cuando empezaste a programar y para no perder los cambios ibas copiando los archivos de código en diferentes carpetas con nombres como &quot;prueba1_del_martes&quot;, &quot;prueba10_funciona_en_X&quot; y otros nombres &lt;i&gt;Sui generis&lt;/i&gt;. Pues todo eso (y mucho más) pero bien pensado, diseñado y estandarizado.&lt;br /&gt;
&lt;br /&gt;
A todos (o casi todos, Subversion tiene muchos fans y aún queda algún dinosaurio que usa CVS) nos gusta GIT, el cual es un sistema de control de versiones diseñado por nada más y nada menos que Linus Torvalds (¡nada más que añadir!). &lt;br /&gt;
&lt;br /&gt;
Cuando creas un nuevo proyecto en Xcode te da la oportunidad de crear un repositorio GIT local el cual es una buena idea porque así puedes mantener un sistema de versiones de forma local (es decir, en tu propio ordenador). Puedes volver a versiones anteriores, crear branches para testeo o release, etc. Marcas la casilla y creas el proyecto normalmente.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/-GlxiF7Te3nY/UbrnwKyMdAI/AAAAAAAAAEI/iJ_7L2bfj8M/s1600/Screen+Shot+2013-06-14+at+11.50.24+AM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;63&quot; src=&quot;http://3.bp.blogspot.com/-GlxiF7Te3nY/UbrnwKyMdAI/AAAAAAAAAEI/iJ_7L2bfj8M/s320/Screen+Shot+2013-06-14+at+11.50.24+AM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
Pero una de las cosas más interesantes del control de versiones, es poder trabajar en remoto. Es decir tener un repositorio en un servidor externo (que puede ser casero o alojado en algún proveedor). Si se te rompe tu ordenador no pierdes el proyecto porque puedes recuperarlo (con un simple &lt;i&gt;git&lt;/i&gt;&amp;nbsp;&lt;i&gt;clone&lt;/i&gt;) del servidor y además si sois varios podéis tener un punto común (el servidor) donde mandar vuestros cambios (&lt;i&gt;git push&lt;/i&gt;) y obtener los cambios de los demás (&lt;i&gt;git pull&lt;/i&gt;).&lt;br /&gt;
&lt;br /&gt;
No voy a explicar como crear el repositorio en el servidor porque hay un montón de sitios que hablan de ello y muchas formas de hacerlo. Lo que voy a explicar es como conectar tu repositorio local (en tu ordenador) al repositorio remoto (en el servidor):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Desde Xcode, File --&amp;gt; Source Control --&amp;gt; repositories y se abrirá una nueva pantalla.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;Buscáis vuestro proyecto y seleccionáis la carpeta Remotes. Y entonces hacéis clic en &quot;Add Remote&quot;.&lt;/li&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/-M7Z0rxRIwF0/UbrnvCkWLYI/AAAAAAAAAD4/lPS2i2RDPb4/s1600/Screen+Shot+2013-06-14+at+11.48.17+AM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://3.bp.blogspot.com/-M7Z0rxRIwF0/UbrnvCkWLYI/AAAAAAAAAD4/lPS2i2RDPb4/s1600/Screen+Shot+2013-06-14+at+11.48.17+AM.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;li&gt;En el diálogo que aparece, rellenáis el nombre remoto con &quot;origin&quot; y en el otro apartado ponéis la ubicación y el método de acceso. En mi caso suelo configurarlo con un acceso SSH pero la persona que os haya creado el repositorio remoto (si no sois vosotros mismos) sabrá que poner en este campo.&lt;/li&gt;
&lt;/div&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-WU0m0dGSKq4/UbrnvlI_6CI/AAAAAAAAAEA/iJMdfpmSuNA/s1600/Screen+Shot+2013-06-14+at+11.47.47+AM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;216&quot; src=&quot;http://2.bp.blogspot.com/-WU0m0dGSKq4/UbrnvlI_6CI/AAAAAAAAAEA/iJMdfpmSuNA/s320/Screen+Shot+2013-06-14+at+11.47.47+AM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
Y ya está configurado, a partir de aquí es usarlo.&lt;br /&gt;
&lt;br /&gt;
Uso rápido (todo dentro de File --&amp;gt; Source Control):&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-OZ9ddbygN7Q/UbrnuXpIKfI/AAAAAAAAADo/BMnJ4QJJNY4/s1600/Screen+Shot+2013-06-14+at+11.46.08+AM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;68&quot; src=&quot;http://1.bp.blogspot.com/-OZ9ddbygN7Q/UbrnuXpIKfI/AAAAAAAAADo/BMnJ4QJJNY4/s320/Screen+Shot+2013-06-14+at+11.46.08+AM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Cuando tengáis cambios hacéis un &lt;i&gt;Commit&lt;/i&gt; donde escribís una breve explicación de los cambios realizados y luego hacéis un &lt;i&gt;Push&lt;/i&gt; para subirlo al servidor (seleccionando &lt;i&gt;origin/master&lt;/i&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-4b7c_skCvU0/UbrnusIHiuI/AAAAAAAAADw/7PzjqE6LWjI/s1600/Screen+Shot+2013-06-14+at+11.46.34+AM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://1.bp.blogspot.com/-4b7c_skCvU0/UbrnusIHiuI/AAAAAAAAADw/7PzjqE6LWjI/s1600/Screen+Shot+2013-06-14+at+11.46.34+AM.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Cuando otra persona haya hecho cambios hacéis un &lt;i&gt;Pull&lt;/i&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Luego existen un montón de cosas que se pueden hacer como Merge, crear Branches... pero ya debéis consultar una guía de GIT.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/6065909398351135023/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/xcode-y-git-conectar-tu-proyecto-un.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/6065909398351135023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/6065909398351135023'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/xcode-y-git-conectar-tu-proyecto-un.html' title='Xcode y GIT: Conectar tu proyecto a un repositorio remoto GIT'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-wecdie4qmIQ/Uclypf6gKnI/AAAAAAAAAJs/q23-5r26O0Q/s72-c/apple-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-6319464576242433166</id><published>2013-06-13T09:45:00.000-07:00</published><updated>2013-06-20T03:06:09.485-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Realidad Aumentada"/><title type='text'>Android Code Snippet: Augmented Reality y Sistemas de coordenadas</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-JB-rGLSamHY/Ub2OUpBCPnI/AAAAAAAAAIA/Eag_ALWh_iI/s1600/android-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-JB-rGLSamHY/Ub2OUpBCPnI/AAAAAAAAAIA/Eag_ALWh_iI/s1600/android-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
La realidad aumentada es un concepto que incluye a muchos tipos diferentes de aplicaciones.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Algunas descodifican códigos QR dibujando &quot;Pokemons&quot; (o coches, dinosaurios, personajes animados...) 3D sobre ellas, otras detectan caras y rasgos faciales, reconocen objetos...&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Y luego hay otro gran grupo que utiliza los sensores del teléfono para &quot;localizar&quot; objetos o información a nuestro alrededor.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Para este último grupo necesitamos usar los sensores del dispositivo para localizarnos con respecto al entorno que nos rodea. Hay varios tipos de sensores (aceleración, geomagnéticos, gravedad...) que junto a la información de geoposicionamiento podemos utilizar para nuestra aplicación.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Lo primero que hay que saber, es que la información que se obtiene de estos sensores se refiere al sistema de coordenadas del&amp;nbsp;dispositivo&amp;nbsp;y éste no cambia con la orientación (&quot;portrait&quot;/&quot;landscape&quot;), ni con el movimiento del dispositivo.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-xwj03ogi6G8/UbnnTYc5i0I/AAAAAAAAADE/MHlUCZa7Ark/s1600/axis_device.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://1.bp.blogspot.com/-xwj03ogi6G8/UbnnTYc5i0I/AAAAAAAAADE/MHlUCZa7Ark/s1600/axis_device.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
En segundo lugar, debéis decidir cual es el sistema de referencia que vuestra aplicación necesita. En mi opinión a varios tipos que dependen del diseño de vuestra aplicación y sobre todo de como se sujete el móvil:&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;Aplicación en el que el móvil se sujeta verticalmente: la más común, por ejemplo la típica aplicación en la que se utiliza la cámara y que situáis información de objetos/edificios/monumentos sobre la pantalla.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Aplicación en el que el móvil se sujeta horizontalmente (paralelo al suelo): por ejemplo una brújula, compás, mapas...&lt;/li&gt;
&lt;li&gt;Otras: por ejemplo las de posición de estrellas/fases lunares... en el firmamento o juegos como &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.itiox.wtf&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;¿Dónde está la mosca?&lt;/a&gt;&amp;nbsp;aquí que cada uno aguante su vela y elija su propio sistema (aunque lo más probable es que el más conveniente sea el del primer tipo).&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
Siendo el tipo 1 el más común es el que vamos a explicar ya que adaptarlo para los otros tipos no es muy difícil. En este caso se define el eje Y hacia dentro (hacia adonde apunta la cámara). Lo explican &lt;a href=&quot;http://developer.android.com/reference/android/hardware/SensorManager.html#remapCoordinateSystem(float%5B%5D,%20int,%20int,%20float%5B%5D)&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;aquí&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;Implementáis el interfaz &lt;a href=&quot;http://developer.android.com/reference/android/hardware/SensorEventListener.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;SensorEventListener&lt;/a&gt;&amp;nbsp;en vuestra clase.&lt;/li&gt;
&lt;li&gt;Obtenéis una instancia de SensorManager (p.ej. desde una Activity &lt;i&gt;(SensorManager)getSystemService(Context.SENSOR_SERVICE);&amp;nbsp;&lt;/i&gt;).&lt;/li&gt;
&lt;li&gt;Registráis los sensores:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;private void registerSensors() {
 Sensor accelerometer = mSensorManager
   .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
 boolean success = mSensorManager.registerListener(this, accelerometer,
   SensorManager.SENSOR_DELAY_GAME);
 Sensor magneticField = mSensorManager
   .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
 success &amp;amp;= mSensorManager.registerListener(this, magneticField,
   SensorManager.SENSOR_DELAY_GAME);
 
 if(!success) {
  Log.e(TAG, &quot;SensorManager not supported&quot;);
  new java.lang.Exception(&quot;SensorManager not supported&quot;);
 }
}&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;En el método del interfaz implementado:&amp;nbsp;&lt;/li&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;@Override
public void onSensorChanged(SensorEvent event) {

    float[] gravity = new float[3];
    float[] linearAcceleration = new float[3];
    float[] magnetic = new float[3];
    float[] matrixInR = new float[16];
    float[] matrixOutR = new float[16];
    float[] matrixI = new float[16];
    float[] orientation = new float[3];
  
    switch (event.sensor.getType()) {
    case Sensor.TYPE_ACCELEROMETER:
    gravity = event.values.clone();
    break;
    case Sensor.TYPE_MAGNETIC_FIELD:
    magnetic = event.values.clone();
    break;
    default:
    break;
    }

  // If gravity and geomag have values then find rotation matrix
  if (gravity != null &amp;amp;&amp;amp; magnetic != null) {
   
  // checks that the rotation matrix is found
  boolean success = SensorManager.getRotationMatrix(matrixInR,
     matrixI, gravity, magnetic);
  if (success) {
    // Re-map coordinates so y-axis comes out of camera
    SensorManager.remapCoordinateSystem(matrixInR,
    SensorManager.AXIS_X, SensorManager.AXIS_Z,
    matrixOutR);

    // Finds the Azimuth and Pitch angles of the y-axis with
    // magnetic north and the horizon respectively
    SensorManager.getOrientation(matrixOutR, orientation);
    float azimuth = (float) Math.toDegrees(orientation[0]);
    float pitch = (float) Math.toDegrees(orientation[1]);
    float roll = (float) Math.toDegrees(orientation[2]);
   }
 }
}
&lt;/pre&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
¡Y ya está! :P Bueno aún queda un poco. Como podéis comprobar el resultado son 3 parámetros (&lt;i&gt;azimuth&lt;/i&gt;, &lt;i&gt;pitch&lt;/i&gt; y &lt;i&gt;roll&lt;/i&gt;) que si tenéis algo de conocimientos de aeronáutica o astronomía os sonarán mucho. Son los ángulos de rotación de vuestro dispositivo con respecto al sistema de referencia por el norte magnético, el eje de gravedad y el eje resultante del producto vectorial de ambos:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-ps9lH2oJfXg/UbnxZrczuRI/AAAAAAAAADU/snww5oD-mZQ/s1600/axis_globe_inverted.png.gif&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://4.bp.blogspot.com/-ps9lH2oJfXg/UbnxZrczuRI/AAAAAAAAADU/snww5oD-mZQ/s1600/axis_globe_inverted.png.gif&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Donde los ángulos se definen como (&lt;a href=&quot;http://developer.android.com/reference/android/hardware/SensorManager.html#getOrientation(float%5B%5D,%20float%5B%5D)&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;documentación&lt;/a&gt;):&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;azimuth: rotación sobre el eje Z&lt;/li&gt;
&lt;li&gt;pitch: rotación sobre el eje X&lt;/li&gt;
&lt;li&gt;roll: rotación sobre el eje Y&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
Dependiendo de la aplicación y el tipo de cálculos matemáticos que requiera, podéis utilizar los ángulos de rotación, la propia matriz de rotación (la que he definido en el ejemplo como &lt;i&gt;matrixOutR, &lt;/i&gt;es la típica matriz 4x4 de rotación tal y como se define en &lt;a href=&quot;http://es.wikipedia.org/wiki/Matriz_de_rotaci%C3%B3n&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Wikipedia&lt;/a&gt;) &amp;nbsp;e incluso existen métodos para trabajar con &lt;a href=&quot;http://es.wikipedia.org/wiki/Cuaterni%C3%B3n&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Cuaternios&lt;/a&gt;. A partir de aquí ya cada uno tendrá que seguir su camino.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Y por último hay que tener en cuenta el ruido en los datos proporcionados por los sensores. Puede que sea necesario, por ejemplo, aplicar un filtro paso baja a los valores obtenidos antes de hacer los cálculos. Aunque en mi experiencia es casi más importante si no ya imprescindible filtrar los valores obtenidos para pintar una vez ya calculados (es decir las posiciones x,y donde pintas en el display), porque puede resultar muy molesto al usuario.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/6319464576242433166/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/android-code-snippet-augmented-reality_13.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/6319464576242433166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/6319464576242433166'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/android-code-snippet-augmented-reality_13.html' title='Android Code Snippet: Augmented Reality y Sistemas de coordenadas'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-JB-rGLSamHY/Ub2OUpBCPnI/AAAAAAAAAIA/Eag_ALWh_iI/s72-c/android-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-1451439290084204835</id><published>2013-06-12T09:54:00.004-07:00</published><updated>2013-06-16T03:09:31.643-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Realidad Aumentada"/><title type='text'>Android Code Snippet: Augmented Reality y la Apertura de la cámara</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-JB-rGLSamHY/Ub2OUpBCPnI/AAAAAAAAAIA/Eag_ALWh_iI/s1600/android-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-JB-rGLSamHY/Ub2OUpBCPnI/AAAAAAAAAIA/Eag_ALWh_iI/s1600/android-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Estáis desarrollando una app de realidad aumentada, probablemente tengáis un SurfaceView para la cámara y otro sobre el anterior para los objetos y la información propia de vuestra realidad aumentada.&lt;br /&gt;
&lt;br /&gt;
Probablemente situéis los objetos utilizando el GPS y los sensores de orientación con respecto al dispositivo móvil, pero claro: ¿dónde pintáis las cosas?&lt;br /&gt;
&lt;br /&gt;
Con pápel, lápiz y un poco de trigonometría, rápidamente os dais cuenta que os falta un parámetro: el ángulo de visión de la cámara (&lt;a href=&quot;http://es.wikipedia.org/wiki/%C3%81ngulo_de_visi%C3%B3n&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Wikipedia&lt;/a&gt;), el cual es un parámetro bastante complejo de calcular y que además depende de &quot;otros&quot; factores que tampoco conocéis.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/7/72/Angle_of_view.svg/500px-Angle_of_view.svg.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;264&quot; src=&quot;http://upload.wikimedia.org/wikipedia/commons/thumb/7/72/Angle_of_view.svg/500px-Angle_of_view.svg.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
¡No desesperemos y seamos prácticos!&lt;br /&gt;
&lt;br /&gt;
En primer lugar el ángulo de visión depende del zoom, eso es evidente así como lo es que si no necesitáis hacer uso del mismo mejor.&lt;br /&gt;
&lt;br /&gt;
En segundo lugar estamos hablando de una lente estándar, por lo cual su ángulo de apertura estará aproximadamente definido entre 25º y 50º, siendo lo más común en los dispositivos unos 45º (//TODO: poner fuentes de estos datos).&lt;br /&gt;
&lt;br /&gt;
Para complicarlo un poco más el ángulo de visión horizontal puede ser diferente (y de hecho suele serlo) al vertical.&lt;br /&gt;
&lt;br /&gt;
¿Y cuáles son las opciones?&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;La clase &lt;a href=&quot;http://developer.android.com/reference/android/hardware/Camera.Parameters.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Camera.Parameters&lt;/a&gt;&amp;nbsp;(accesible a través del método de instancia getParameters() ), contiene dos métodos para obtener estos dos ángulos (&lt;a href=&quot;http://developer.android.com/reference/android/hardware/Camera.Parameters.html#getHorizontalViewAngle()&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;getHorizontalViewAngle()&lt;/a&gt; y &lt;a href=&quot;http://developer.android.com/reference/android/hardware/Camera.Parameters.html#getVerticalViewAngle()&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;getVerticalViewAngle()&lt;/a&gt; ). Google obliga a los fabricantes de móvil a proporcionar un valor que es el que devuelven estos métodos, pero paradójicamente, este valor no tiene por qué ser cierto, y de hecho suele ser una constante.&lt;/li&gt;
&lt;li&gt;En ciertas aplicaciones (por ejemplo para medir objetos reales), se puede idear algún tipo de procedimiento para calcular el ángulo de visión del dispositivo móvil en concreto (por ejemplo a partir de una fotografía y varios puntos conocidos).&lt;/li&gt;
&lt;li&gt;La opción rápida es comprobar el valor que devuelve el método 1 y si estos valores no tienen sentido hacer una aproximación. La que utilizo en el juego&amp;nbsp;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.itiox.wtf&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;¿Dónde está la mosca?&lt;/a&gt; es 40º para el ángulo horizontal y 50º para el vertical.&lt;/li&gt;
&lt;/ol&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/1451439290084204835/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/android-code-snippet-augmented-reality.html#comment-form' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/1451439290084204835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/1451439290084204835'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/android-code-snippet-augmented-reality.html' title='Android Code Snippet: Augmented Reality y la Apertura de la cámara'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-JB-rGLSamHY/Ub2OUpBCPnI/AAAAAAAAAIA/Eag_ALWh_iI/s72-c/android-icon.png" height="72" width="72"/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-2577963517438760295</id><published>2013-06-11T11:53:00.001-07:00</published><updated>2013-06-20T03:19:26.678-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><title type='text'>Google Play Game Services (Android)</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-JB-rGLSamHY/Ub2OUpBCPnI/AAAAAAAAAIA/Eag_ALWh_iI/s1600/android-icon.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://2.bp.blogspot.com/-JB-rGLSamHY/Ub2OUpBCPnI/AAAAAAAAAIA/Eag_ALWh_iI/s1600/android-icon.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Marcadores y puntuaciones en tiempo real, logros y premios, botón +1, mensajería en tiempo real entre jugadores y mucho más. Eso es lo que ofrece el nuevo servicio de Google a los desarrolladores.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Requisitos previos&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Necesitas un dispositivo con la versión 2.2 de Android o superior (API 8) y con Google Play para probar (así que alguna ROM puede que no vaya). Si no también se puede probar con el simulador, creando una instancia del AVD del 4.2.2 o superior. &lt;/li&gt;
&lt;li&gt;Si usáis eclipse (como el 99% de todos), abrís &lt;i&gt;Android SDK Manager&lt;/i&gt; y en la carpeta &lt;i&gt;Extras&lt;/i&gt;, marcáis &quot;&lt;i&gt;Google Play Services&lt;/i&gt;&quot;. Actualizar además a la última API (mínimo la 17) y las herramientas es recomendable. Instaláis los paquetes.&lt;/li&gt;
&lt;li&gt;Una vez instalados y desde eclipse, en el mismo workspace que vuestro juego, importáis el proyecto que está en la carpeta&amp;nbsp;&lt;span style=&quot;background-color: #f9f9f9; color: #006600; font-family: monospace; font-size: 13px; line-height: 14px;&quot;&gt;&amp;lt;android-sdk&amp;gt;/extras/google/google_play_services/libproject/google-play-services_lib/&amp;nbsp;&lt;/span&gt;(&amp;lt;android-sdk&amp;gt; es donde hayáis instalado el SDK).&amp;nbsp;&lt;/li&gt;
&lt;li&gt;En las propiedades del proyecto de vuestro juego (clic-derecho en la carpeta desde Eclipse), os vais a Android y añadís el proyecto de google-play-services-lib como referencia.&lt;/li&gt;
&lt;li&gt;Además seleccionáis el Target de vuestro proyecto con la última versión que tengáis de las Google APIs (mínimo la 17).&amp;nbsp;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://1.bp.blogspot.com/-2V35FGAgEhU/UbdiHog-kuI/AAAAAAAAACw/RIBWUQPAlRs/s1600/GOOGLE-PLAY-SERVICES.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;276&quot; src=&quot;http://1.bp.blogspot.com/-2V35FGAgEhU/UbdiHog-kuI/AAAAAAAAACw/RIBWUQPAlRs/s320/GOOGLE-PLAY-SERVICES.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;

&lt;span id=&quot;goog_1310853306&quot;&gt;&lt;/span&gt;&lt;span id=&quot;goog_1310853307&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
Dentro de Eclipse&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;En el archivo de Proguard, (proguard-project.txt se puede abrir desde Eclipse), añadís &amp;nbsp;&lt;/li&gt;
&lt;pre class=&quot;prettyprint&quot; style=&quot;font-size: 12px;&quot;&gt;-keep class * extends java.util.ListResourceBundle { protected Object[][] getContents();}
&lt;/pre&gt;
&lt;li&gt;Os descargáis de GitHub&amp;nbsp;&lt;a href=&quot;https://github.com/playgameservices/android-samples/tree/master/BaseGameUtils&quot;&gt;https://github.com/playgameservices/android-samples/tree/master/BaseGameUtils&lt;/a&gt;&amp;nbsp;y añadís el contenido de la carpeta src a vuestro proyecto. Es licencia Apache y funciona muy bien para empezar. Hay sólo un par de clases y es muy fácil de usar, de hecho la única que usaréis será BaseGameActivity&lt;/li&gt;
&lt;li&gt;Evidentemente vuestra actividad principal, o desde la que queráis hacer todo el tema social (marcadores, logros, etc), debe heredar de BaseGameActivity.&lt;/li&gt;
&lt;li&gt;En el Manifest, dentro de la etiqueta &lt;i&gt;application&lt;/i&gt;&amp;nbsp;añadís el siguiente código:&lt;/li&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;meta-data android:name=&quot;com.google.android.gms.games.APP_ID&quot; android:value=&quot;@string/app_id&quot; /&amp;gt;&lt;/pre&gt;
&lt;li&gt;¡Error de compilación! No os preocupéis , necesitamos el app_id, y para ello nos vamos a la &lt;a href=&quot;https://play.google.com/apps/publish&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;consola de desarrollador&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;h4&gt;
Consola de desarrollador&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Lo primero que necesitáis es subir una versión del juego, si ya está publicado ya la tenéis y si no firmad una versión y la subís a alpha.&lt;/li&gt;
&lt;li&gt;En la sección &quot;Servicios de juegos&quot; añadís el juego, esto es un poco engañoso, puesto que no se refiere al APK, si no a una &quot;entidad&quot; en la que podréis crear marcadores, logros, gestionar mensajería y enlazar las aplicaciones, de forma que podéis tener varias versiones del APK (de pago, gratis con publicidad) o en diferentes plataformas (en iOS o Web) y todas compartiendo los mismos marcadores y logros. Podéis crear algún marcador y añadir algún logro para probar después.&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://3.bp.blogspot.com/-9C44w5e5c4M/UbdqEWXy6yI/AAAAAAAAABs/OB84UJXcQus/s1600/Screen+Shot+2013-06-11+at+8.02.19+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;125&quot; src=&quot;http://3.bp.blogspot.com/-9C44w5e5c4M/UbdqEWXy6yI/AAAAAAAAABs/OB84UJXcQus/s320/Screen+Shot+2013-06-11+at+8.02.19+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Enlazáis el APK que habéis subido previamente.&lt;/li&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://4.bp.blogspot.com/-LXeZHmwW0yU/UbdqIJHUx_I/AAAAAAAAAB0/qql-utKOjHE/s1600/Screen+Shot+2013-06-11+at+8.18.13+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;89&quot; src=&quot;http://4.bp.blogspot.com/-LXeZHmwW0yU/UbdqIJHUx_I/AAAAAAAAAB0/qql-utKOjHE/s320/Screen+Shot+2013-06-11+at+8.18.13+PM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;li&gt;El identificador que necesitamos (app_id) es un código numérico que aparece justo al lado del nombre del juego, en el título. Lo copiamos y creamos un archivo XML en la carpeta de res/values donde lo añadimos: &lt;span style=&quot;color: #009192; font-family: Monaco; font-size: 11px;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #399191; font-family: Monaco; font-size: 11px;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;font-family: Monaco; font-size: 11px;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #9b2a8d; font-family: Monaco; font-size: 11px;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;font-family: Monaco; font-size: 11px;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #0049f7; font-family: Monaco; font-size: 11px;&quot;&gt;&quot;app_id&quot;&lt;/span&gt;&lt;span style=&quot;color: #009192; font-family: Monaco; font-size: 11px;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;font-family: Monaco; font-size: 11px;&quot;&gt;XXXXXXXX&lt;/span&gt;&lt;span style=&quot;color: #009192; font-family: Monaco; font-size: 11px;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #399191; font-family: Monaco; font-size: 11px;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #009192; font-family: Monaco; font-size: 11px;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;En la sección de Testing, debéis añadir al menos una cuenta de prueba, para poder probar los servicios antes de publicar la app. Deben ser cuentas con perfiles Google+ (p.ej. de GMail).&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
Consola API de Google&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;En la &quot;otra&quot; consola (&lt;a href=&quot;https://code.google.com/apis/console&quot;&gt;https://code.google.com/apis/console&lt;/a&gt;) entráis en la sección &lt;i&gt;API Access&lt;/i&gt; y dentro en hacéis clic en &quot;Create another client ID&quot;.&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://2.bp.blogspot.com/-O-mXNDvO_KI/Ubds--Fj4gI/AAAAAAAAACE/jCAgQYpD7BQ/s1600/Screen+Shot+2013-06-11+at+8.29.43+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;http://2.bp.blogspot.com/-O-mXNDvO_KI/Ubds--Fj4gI/AAAAAAAAACE/jCAgQYpD7BQ/s320/Screen+Shot+2013-06-11+at+8.29.43+PM.png&quot; width=&quot;252&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Seleccionáis&lt;i&gt; Installed application&lt;/i&gt;, Android, introducís el nombre del paquete, y deshabilitáis la opción Deep Linking. Todavía no le dáis a crear.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;El certificado SHA1 lo podéis obtener con la herramienta keytools. En un Mac/Ubuntu estará en el Path por lo que no habrá problema y en un Windows la encontraréis dentro del JDK. En un terminal introducís:&amp;nbsp;&lt;span class=&quot;pln&quot; style=&quot;border: 0px; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; text-align: left; vertical-align: baseline;&quot;&gt;keytool &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;border: 0px; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; text-align: left; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;border: 0px; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; text-align: left; vertical-align: baseline;&quot;&gt;list &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;border: 0px; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; text-align: left; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;border: 0px; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; text-align: left; vertical-align: baseline;&quot;&gt;v &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;border: 0px; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; text-align: left; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;border: 0px; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 14px; line-height: 18px; margin: 0px; padding: 0px; text-align: left; vertical-align: baseline;&quot;&gt;keystore vuestro_archivo_de_firmas.key&amp;nbsp;&lt;/span&gt;Donde vuestro_archivo_de_firmas.key es evidentemente el que utilizáis para firmar los APK. Introducís en el formulario el código obtenido y ya podéis crear. Si había otro identificador de cliente lo podéis borrar.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
De nuevo en Eclipse&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Google Play Services sólo funciona en aplicaciones firmadas, por lo que debéis firmar los APK antes de testearlos.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Es fácil comprobar si Google Play Services está disponible, podéis usar el método estático: &lt;a href=&quot;http://developer.android.com/reference/com/google/android/gms/common/GooglePlayServicesUtil.html#isGooglePlayServicesAvailable(android.content.Context)&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;GooglePlayServicesUtil.isGooglePlayServicesAvailable(Context context)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Y ya sólo consiste en curiosear dentro de las clases del proyecto de GitHub que hemos importado previamente. Según que queráis hacer podéis habilitar un cliente u otro (p.ej. CLIENT_GAMES para marcadores y logros, CLIENT_PLUS para el botón&amp;nbsp;+1) y con los métodos getGamesClient y getPlusClient podéis acceder a las instancias desde las que podréis realizar todas las operaciones.&lt;/li&gt;
&lt;/ol&gt;
Podéis probar el resultado con nuestro último juego: &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.itiox.wtf&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;¿Dónde está la mosca? / Where&#39;s That Fly?&lt;/a&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/2577963517438760295/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/google-play-services-android.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/2577963517438760295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/2577963517438760295'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/google-play-services-android.html' title='Google Play Game Services (Android)'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-JB-rGLSamHY/Ub2OUpBCPnI/AAAAAAAAAIA/Eag_ALWh_iI/s72-c/android-icon.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-1432225180835289119</id><published>2013-06-11T08:14:00.002-07:00</published><updated>2013-06-16T03:10:04.439-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Realidad Aumentada"/><title type='text'>¿Dónde está la mosca?</title><content type='html'>&lt;h4&gt;
Introducción&lt;/h4&gt;
Dos desarrolladores y un perro, un cuarto lleno de trastos, una buena dosis de ilusión y otra de incertidumbre y casi dos meses de desarrollo, publicamos nuestro primer juego (por ahora para Android): &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.itiox.wtf&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;¿Dónde está la mosca?&lt;/a&gt;.&amp;nbsp;Un juego sencillo y sin grandes pretensiones, de tipo &quot;casual&quot; y apto para todos los públicos.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.itiox.wtf&quot; target=&quot;_blank&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://1.bp.blogspot.com/8iTtpMNc-WqUCGCGT1HD4N66fTDkvjVUWWVnkXC5CcLPGX2xAaH4CQQnpvUmzpY3d7o=w124&quot; title=&quot;Where is That Fly?&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h4&gt;
Antecedentes&lt;/h4&gt;
Trata un tema que no distingue entre clases: la típica mosca y/o mosquito que te quita el sueño durante la noche rondándote la oreja hasta que decides encender las luces y acabar con el asunto. Y sin embargo nada más encenderlas y aún con los ojos entreabiertos la mosca deja de hacer ruido y desaparece misteriosamente.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h4&gt;
Juego&lt;/h4&gt;
Abres la aplicación, pulsas el botón de &quot;Jugar&quot; y comienza el juego. Debes mover el móvil a tu alrededor buscando donde el sonido del insecto se hace más intenso hasta que aparezca en la pantalla. En ese momento, y con un golpe seco hacia delante, agitas tu dispositivo como si fuera un matamoscas real y si lo haces bien aplastarás al bicho.&lt;br /&gt;
&lt;br /&gt;
Tienes 50 segundos para aplastar a todos los bichos que puedas, estos pueden estar abajo, detrás, encima de ti... en cualquier lugar y no hay trampas, siguen trayectorias bien definidas.&lt;br /&gt;
&lt;br /&gt;
Hay diferentes tipos de bichos, desde moscas comunes a moscas tsetse, y cada una tiene un valor en puntos y una dificultad diferente para acabar con ella. Con los puntos puedes comprar diferentes armas que te harán menos ardua la tarea, comprar tiempo adicional o incluso quitar el baner de publicidad (sin tener que pagar dinero de verdad).&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.itiox.wtf&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;http://1.bp.blogspot.com/-sQNCfBo5tnk/UbdXQLB07SI/AAAAAAAAABM/5DPaqfaDUqg/s200/menu.png&quot; width=&quot;120&quot; /&gt;&lt;/a&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.itiox.wtf&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;http://3.bp.blogspot.com/-JZ3sjaCIAec/UbdXT71F51I/AAAAAAAAABU/turZQD-4Ap4/s200/device-2013-06-04-125953.png&quot; width=&quot;120&quot; /&gt;&lt;/a&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span id=&quot;goog_368586272&quot;&gt;&lt;/span&gt;&lt;span id=&quot;goog_368586273&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.itiox.wtf&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;http://2.bp.blogspot.com/-pIMVulQBGpE/UbdXldX7VyI/AAAAAAAAABc/D3bf2byjBiE/s200/shop.png&quot; width=&quot;120&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h4&gt;
Fundamentos físicos y Realidad aumentada&lt;/h4&gt;
&amp;nbsp;La Realidad aumentada es una tecnología que se basa en &quot;aumentar&quot; la información que proporciona la realidad, con otros estímulos sensoriales como sonidos, imágenes... En este caso aprovechamos los acelerómetros y sensores magnéticos de los dispositivos para crear un sistema de referencia donde &quot;volará&quot; la mosca.&lt;br /&gt;
&lt;br /&gt;
De esta forma podemos situar la mosca con unas coordenadas con unos ejes ortonormales apuntando al norte magnético y al centro de gravedad de la tierra (al norte y hacia abajo) y con centro en el dispositivo móvil. Estas coordenadas las transformamos a otro sistema de referencia con origen en el dispositivo móvil pero ya con los ejes coincidentes con la pantalla. Y a partir de estas coordenadas 3D, de la apertura focal de la cámara y del tamaño del insecto lo podemos transformar en un Sprite que por fin podemos pintar en pantalla.&lt;br /&gt;
&lt;br /&gt;
Los insectos siguen trayectorias espirales (el propio logo de ITIOX sigue la formula de una espiral) con un factor de probabilidad para cambiar de dirección y velocidad según la fase del juego (cada vez vuelan más rápido).&lt;br /&gt;
&lt;br /&gt;
Y al igual que en la realidad, los bichos sienten cierta atracción por la luz, así que la luminancia que capta la cámara también se tiene en cuenta, ¡pero esto es un truco del juego, por lo que no se puede decir más!&lt;br /&gt;
&lt;h4&gt;
Desarrollo&lt;/h4&gt;
Gráficos, sonidos, música y ¡a parte el código! Ha sido intenso y muy divertido al mismo tiempo.&lt;br /&gt;
&lt;br /&gt;
Es un juego (o aplicación), que pese a no utilizar demasiados recursos (no consume ni el 10% que otros juegos hechos con motores gráficos y además apenas ocupa 5MB), sí que utiliza casi todos los sensores y cosas que tiene un dispositivo móvil moderno: acelerómetros, sensores magnéticos, cámara, GPS e internet (para los marcadores de google), OpenGL, audio...&lt;br /&gt;
&lt;br /&gt;
También utiliza, después del fallecido Openfeint :&#39;( , lo último de Google, que te permite tener marcadores en tiempo real, logros, etc y todo conectado a través de Google+ (ya no saben que hacer para que usemos Google+ :P) que está muy bien, aunque muy mal documentado, por lo que escribiré algún post sobre esta API en breve.&lt;br /&gt;
&lt;h4&gt;
Conclusión&lt;/h4&gt;
Un juego, aunque aparentemente simple, lleva su tiempo en completarse (optimizar gráficos, testear, depurar errores, testear, ajustar la dificultad, testear...).&lt;br /&gt;
&lt;br /&gt;
Desarrollar una aplicación simple de entretenimiento con los mismos fundamentos no es muy difícil y en apenas un par de semanas habría estado lista. La diferencia está en convertirla en un juego. Y un juego según mi definición tiene la muchas de las siguientes características: &quot;fácil de comenzar, difícil de dominar&quot;, marcadores (&quot;hiscores/high scores&quot;), logros, puntos, variantes de armas y/o monstruos, fases, tiempo, cierta estética y cuidado gráfico/audio...&lt;br /&gt;
&lt;br /&gt;
Por nuestra parte y con el conocimiento de que es un juego muy modesto, nos lo hemos pasado muy bien al desarrollar nuestro primer videojuego.&amp;nbsp;Y sin más dejamos a los usuarios tener la última palabra.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/1432225180835289119/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/donde-esta-la-mosca.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/1432225180835289119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/1432225180835289119'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/donde-esta-la-mosca.html' title='¿Dónde está la mosca?'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/8iTtpMNc-WqUCGCGT1HD4N66fTDkvjVUWWVnkXC5CcLPGX2xAaH4CQQnpvUmzpY3d7o=s72-w124-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-674236521483788008.post-5998483713701631145</id><published>2013-06-11T05:29:00.002-07:00</published><updated>2013-06-20T03:20:24.576-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="IOS"/><title type='text'>Cómo promocionar tu aplicación</title><content type='html'>Eres o sois un pequeño grupo de desarrolladores trabajando casi o sin ingresos. Mucha ilusión, pocos recursos, una buena dosis de talento y muchísimas más ganas que nadie de hacer las cosas bien.&lt;br /&gt;
&lt;br /&gt;
Acabáis de desarrollar una app y la habéis publicado en el market (iTunes, Google Play, Amazon, sin distinciones).&lt;br /&gt;
&lt;br /&gt;
Y entonces el peor castigo: la indiferencia. Ni para bien ni para mal, veis pasar los días como vuestra app va desapareciendo entre otros millones sin más pena que gloria y apenas descargas.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;h4&gt;
Opciones Kowalski:&amp;nbsp;&lt;/h4&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Hundirse en la miseria, abandonar la programación y echar curriculum en un McDonalds de algún país extranjero en el que aún haya empleo. Problema: no mola volver a tener granos pasada la adolescencia.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Entrar en una cabina telefónica, arrancarse la camisa dejando a la luz un uniforme, discutiblemente masculino, compuesto por unas mallas azules y dar varias vueltas a la tierra a una velocidad mayor que la luz para así volver atrás en el tiempo e invertir en Apple o en Google asegurándose que se compran acciones y no preferentes. Problema: encontrar una cabina telefónica.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Seguir estos sencillos consejos, que os llevarán mucho tiempo de dedicación (&quot;Si se siembra la semilla con fe y se cuida con perseverancia, sólo será cuestión de tiempo recoger sus frutos.&quot;, Thomas Carlyle).&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
Advertencia: el autor está actualmente poniéndolos en práctica a la vez que escribe este post. Para más info: &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.itiox.wtf&quot;&gt;https://play.google.com/store/apps/details?id=com.itiox.wtf&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;Instrucciones:&lt;/span&gt;&lt;/h4&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
Hay que hacer marketing, lamentablemente no todo se soluciona con unas líneas de código. Y para esta labor existen (entre otros) los foros, agregadores, bloggers y cómo no, twitter.&lt;br /&gt;
&lt;br /&gt;
Antes de soltar una lista de sitios, foros, blogs, grupos, etc. una serie de consejos muy básicos pero muy importantes:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Designad a una persona para estos menesteres, si vas en rollo &quot;solo&quot; ánimo, te ha tocado.&lt;/li&gt;
&lt;li&gt;Cread una cuenta de mail específica para asuntos &quot;sociales&quot;, porque os va a llegar mucho Spam sobre todo de gente que quiere que le paguéis a cambio de publicidad. Utilizad LastPass (o similar) para los cientos de claves o una clave &quot;soft&quot; (por eso también es importante que sea otra cuenta).&lt;/li&gt;
&lt;li&gt;Registraos cuanto antes (con la cuenta anterior) en todo tipo de foros, sitios, comunidades, grupos y redes sociales que tengan algo que ver con aplicaciones, software y móviles.&lt;/li&gt;
&lt;li&gt;No vale registrarse y a continuación publicar un thread del tipo: &quot;nueva aplicación superdivertida, probadla ya!&quot;. Os pondrán en la lista de Spammers, os bannearan, borrarán el thread y no os harán ni caso. Esperad al menos un mes desde que os hayáis registrado.&lt;/li&gt;
&lt;li&gt;Publicad, contestad, preguntad o responded a los usuarios de esa comunidad al menos una vez por semana para crear actividad en vuestra cuenta. No hace falta que sea sobre lo vuestro, podéis hablar de cualquier otra cosa, dejad que os conozcan.&lt;/li&gt;
&lt;li&gt;Todos los puntos anteriores son válidos para redes sociales y vuestros propios blogs y webs, creadlos cuanto antes mejor y que haya actividad regular en ellos.&lt;/li&gt;
&lt;li&gt;Imprescindible screenshots, capturas imágenes promocionales preparadas y listas para usar/compartir. Quasi imprescindible video (Youtube) también preparado y listo.&lt;/li&gt;
&lt;li&gt;Y todo hay que empezar a hacerlo antes de publicar la app, no hay excusas, de nada valdrá tanto trabajo si nadie se la baja.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
Listados&lt;/h4&gt;
&lt;div&gt;
Casi todos tratan indiferentemente de Android, iOS, Windows... pero como regla general si contiene la palabra Android van a ser de Android e iOS para iPhone/iPad.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
Lista de foros (¡muy importante presentarse antes de postear!):&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://forum.xda-developers.com/forumdisplay.php?f=530&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;XDA&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://forums.androidcentral.com/android-applications/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Android Central&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://androidforums.com/application-announcements/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Android Forums&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://plus.google.com/+AndroidCommunity/posts&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;AndroidCommunity&lt;/a&gt;&amp;nbsp;(Google&amp;nbsp;+)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.androidpit.com/en/android/forum/category/1005050/Let-me-show-you-my-app&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;AndroidPIT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.android.net/forum/android-apps/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Android NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.android.net/forum/android-games/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Android NET (Juegos)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.reddit.com/r/androidapps/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Reddit (androidapps)&lt;/a&gt;&amp;nbsp;y&amp;nbsp;&lt;a href=&quot;http://www.reddit.com/r/Android&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Reddit (Android)&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
Sitios de reviews, consejos:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Probad muy bien y corregir todos los errores posibles antes de mandar la app a algún review.&lt;/li&gt;
&lt;li&gt;Os mandarán Spam, os dirán que tienen mucho trabajo y que tienen un servicio especial que acaban de sacar que pagando una pequeña cantidad... Centraos en que si tenéis una buena aplicación es importante pasar por el aro pero no hace falta pagar (¡y si podéis pagar iros a otro blog!).&lt;/li&gt;
&lt;li&gt;Sea un correo, formulario, twitter... rellenar todos los campos de cada uno de los sitios (¡y no en plan robot copiando y pegando lo mismo en todas partes!).&lt;/li&gt;
&lt;li&gt;Por último echad un vistazo a cada sitio y con algo de humildad, pensad si vuestra app tiene cabida y sentido en el sitio.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.xda-developers.com/suggest-content/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;XDA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.androidcentral.com/app-submit&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;AndroidCentral&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.androidauthority.com/contact-us/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Android Authority&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://android.appstorm.net/about/get-your-app-reviewed/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;AppStorm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.gamezebo.com/contact&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Gamezebo (Juegos)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.idgcsmb.com/contact/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;IDG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.appszoom.com/developers&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;AppsZoom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.androidtapp.com/get-reviewed/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;AndroidTapp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.androidguys.com/contact/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Android Guys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://droidgamers.com/index.php/component/flexicontactplus/?view=contact&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;DroidGamers (Juegos)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.tapscape.com/submit-app-review/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;tapscape&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://androinica.com/contact-us/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;androinica&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://apps400.com/submit-your-application-for-review&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;apps400&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.appeggs.com/service.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;AppEggs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://101bestandroidapps.com/auth/login&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;101 Best Android Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://crazymikesapps.com/developers/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Crazy Mike&#39;s Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mobileappsgallery.com/submit-android-app/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Mobile Apps Gallery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.playandroid.com/blog/review-inquiries/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Play Android (Juegos)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://appstouse.com/submit-app-for-review&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Apps To Use&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.androidrundown.com/about/submit-app-hardware-review/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Android Rundown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.lifeofandroid.com/submit-an-app/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Life of Android&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.appreviewcentral.net/app-submission/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;App Review Central&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://appsplit.com/blog/submit-an-app/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Appsplit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.askyourandroid.com/request-for-review/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Ask your Android&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.androidpolice.com/contact/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Android Police&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.pocketgamer.co.uk/r/Multiformat/feature.asp?c=11845&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Pocket Gamer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://getandroidstuff.com/send-tipsnews/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Get Android Stuff&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.androidshock.com/developers/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Android Shock&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://eurodroid.com/contact/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Eurodroid&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Twitter:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.innovatty.com/twitter/IDRTG/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;IDRTG&lt;/a&gt;&amp;nbsp;Sólo para muy indies. Funciona así&amp;nbsp;&lt;b style=&quot;color: #515d5d; font-family: &#39;Lucida Grande&#39;, &#39;Lucida Sans Unicode&#39;, Arial, Verdana, sans-serif; font-size: 12px; text-align: left;&quot;&gt;PLZ RT - &quot;Your Tweet&quot; #IDRTG &lt;/b&gt;donde en &quot;Your Tweet&quot; pones un link a tu app. Las reglas son sencillas, tener más de 50 seguidores y ayudar también retuiteando las apps de los otros miembros.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Nota adicional:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Los piratas ya no son ingleses o argelinos como cuando navegaban en barco, ahora tienen los ojos rasgados, llevan gafas y pasan muchas horas delante de los ordenadores. Su &lt;i&gt;modus operandi&lt;/i&gt;&amp;nbsp;consiste en coger vuestra app (un apk de Android es lo más fácil), decompilarla, cambiar un par de códigos y volverla a subir usando sobre todo los mercados secundarios chinos (aunque a veces ni eso y lo publican directamente en los oficiales asumiendo la autoría). Un post interesante hablando del asunto se encuentra en&amp;nbsp;&lt;a href=&quot;http://www.andengine.org/forums/project-development-blogs/china-t8765.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Andengine&lt;/a&gt;.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
Referencias:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://blog.muhammada.li/where-to-promote-android-apps&quot;&gt;http://blog.muhammada.li/where-to-promote-android-apps&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://blog.tapgage.com/2012/10/81-different-ways-to-promote-your-mobile-app-game/&quot;&gt;http://blog.tapgage.com/2012/10/81-different-ways-to-promote-your-mobile-app-game/&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.ideatoappster.com/20-ways-to-promote-your-app-for-free/&quot;&gt;http://www.ideatoappster.com/20-ways-to-promote-your-app-for-free/&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.itiox.com/feeds/5998483713701631145/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://blog.itiox.com/2013/06/como-promocionar-tu-aplicacion.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/5998483713701631145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/674236521483788008/posts/default/5998483713701631145'/><link rel='alternate' type='text/html' href='http://blog.itiox.com/2013/06/como-promocionar-tu-aplicacion.html' title='Cómo promocionar tu aplicación'/><author><name>Anonymous</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/blank.gif'/></author><thr:total>0</thr:total></entry></feed>