Páginas

Grabar vídeo de la pantalla en Android
Recording the screen on Android

Hasta ahora, si queríamos grabar un vídeo de la pantalla de nuestro móvil, teníamos que recurrir a aplicaciones del market. He cacharreado con algunas, y no es un proceso sencillo, ya que la mayoría requieren tener el móvil rooteado o instalar programas auxiliares en el ordenador.
Por suerte, a partir de la versión 4.4 de Android (API level 19), se incluye la utilidad screenrecord al adb. Con ella, grabar la pantalla es tan sencillo como conectar el móvil e invocar el siguiente comando:

$ adb shell screenrecord /sdcard/record.mp4

De esa forma comienza la grabación. Para pararla pulsamos ctrl + C. El resultado estará en la ruta de nuestro teléfono que hayamos indicado.

El comando permite muchas opciones, como fijar el tiempo de grabación, el bit rate, etc. Aquí puedes encontrar más información.

En algunas ocasiones el comando me ha mostrado el error:

unable to create video/avc codec instance

No he conseguido averiguar a qué se debe, pero aplicando la solución universal del informático, se resuelve: reinicia tu móvil.
Until now, if you wanted to record a video of the screen of our mobile, we had to use market applications. I have tried some of them, and it´s not a simple process, as most require you to have the phone rooted or auxiliary programs installed on your computer.
Fortunately, since version 4.4 of Android (API level 19), it includes the adb utility screenrecord. With it, recording the display is as simple as plugging the phone and calling the following command:

$ adb shell screenrecord /sdcard/record.mp4

In this way the recording begins. To stop it press ctrl + C. The result is in the path of our phone that we have stated.

The command allows many options, such as setting the recording time, bit rate, etc. Here you can find more information.

Sometimes the command has shown me the error:

unable to create video/avc codec instance

I have not managed to find out why that is, but applying the universal solution to the computer, it solves: reboot your phone.

Asignar id a una vista en ejecución
Assign id to a view programmatically

Cuando se declara una vista en un fichero layout de Android, lo habitual es asignarle automáticamente un id.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/boardLayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

Sin embargo, puede haber casos en que no podamos hacerlo. Por ejemplo, si queremos reutilizar una vista por medio de la etiqueta include, y necesitamos que cada instancia de la vista tenga un identificador distinto.

En estos casos tenemos la posibilidad de definir identificadores en un fichero de recursos.

<resources>
    <item name="id_1" type="id"/>
</resoruces>

Estos identificadores serán creados en la clase R, por lo que podremos recuperarlos y asignarlos a una vista con el siguiente código.

String name = "id" + i;   
view.setId(getResources().getIdentifier(name, "id", getPackageName()));

A partir de ese momento podremos recuperar la vista buscando por el id.
Views are usually declared in Android layout files with and id.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/boardLayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

However, sometimes we can´t assign the id. For example, if we want to reuse a view with include tag, and we need each instance to have a different id.

In this situation, we have the option to define ids in a resource file.

<resources>
    <item name="id_1" type="id"/>
</resoruces>

This identifiers are created in R class, so you can access and assign them to a view in code.

String name = "id" + i;   
view.setId(getResources().getIdentifier(name, "id", getPackageName()));

From this point, we can find the view searching by id.

Evitar el giro de pantalla en Android
Avoid screen rotation in Android

Por defecto, las actividades Android se adaptan automáticamente a la orientación del dispositivo. Si queremos evitar este comportamiento no tenemos más que definir en el fichero AndroidManifest.xml de nuestra aplicación cuál es la orientación que debe tener cada actividad (portrait para vertical, y landscape para horizontal).

<activity android:name="package.YourActivity"
          android:screenOrientation="portrait" >

By default, Android activities adapt to device orientation. If we want to avoid this behaviour, we just have to define and orientation for any activity on AndroidManifest.xml file (portrait or landscape).

<activity android:name="package.YourActivity"
          android:screenOrientation="portrait" >

Evitar que se apague la pantalla
Keep the screen on

Cuando se está programando un juego, podemos requerir que la pantalla del dispositivo permanezca encendida incluso si el usuario pasa un tiempo sin interactuar. Es habitual encontrar soluciones que proponen el uso de wake locks, pero estos tienen dos grandes inconvenientes: requieren permisos especiales, y hacen que el programador tenga que ocuparse de liberarlos en el momento oportuno.

Existe una solución mucho más simple, que de hecho es recomendada en la página de desarrolladores de Android: usar el flag keep_screen_on. Este flag puede activarse para actividades individuales, tanto desde el manifest de la aplicación, como desde código. Esta segunda opción tiene la ventaja de que el flag puede igualmente desactivarse por código si en algún momento ya no es necesario.

En el manifest, declararíamos una actividad así:

<activity android:name="jvel.android.games.saveme.MainActivity" 
          android:keepScreenOn="true" />

En código, añadiríamos las siguientes líneas:

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}

Si optamos por la opción de código, y más adelante queremos eliminar el flag:

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

When we are programming a game, we may want the screen of the device to keep on. There´s a solution based on wake locks, but it has two big advantages: it requieres special permission, and the developer needs to worry about releasing unused locks.

There is a much simpler solution, that is recommended in Android developers page: using flag_keep_screen_on. This flag can be activated only in an activity, from manifest or from code. This scond option has the adventage that the flag can be cleared if you don´t need it, allowing the screen to turn off again.

In manifest, we can declare an activity with:

<activity android:name="jvel.android.games.saveme.MainActivity" 
          android:keepScreenOn="true" />

In code, we have to add this line:

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}

If we choose code option, and we want to clear the flag:

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

Añadir scroll a una actividad
Making an activity scrollable

Una duda habitual cuando se empieza a trabajar con Android es cómo añadir scroll a una actividad, o a algún componente de la interfaz. Y la verdad es que la solución es muy simple. Basta con añadir un ScrollView por encima del elemento al que queramos añadir el scroll.

Es importante tener en cuenta que la etiqueta ScrollView admite un único hijo. Lo habitual es que ese hijo sea un layout que a su vez contenga los elementos sobre los que se quiere hacer scroll.

Por tanto, si queremos que se pueda hacer scroll sobre la pantalla completa de una actividad, tendríamos algo así:

<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
        <!-- your components -->
    </RelativeLayout>
</ScrollView>

Si queremos aplicar el scroll a un grupo concreto de componentes de nuestra actividad, también podemos hacerlo. Por ejemplo, esta es la estructura de la actividad de configuración del juego en Batalla de Memoria, que deja la publicidad fija en la parte superior, y el botón en la inferior, haciendo que la barra de desplazamiento sólo afecte a las opciones en sí.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/adLayout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:orientation="horizontal" >
    </LinearLayout>

    <ScrollView
        android:id="@+id/options_layout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/adLayout"
        android:layout_above="@+id/playButton" >
        
        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" >
            <!-- your components -->
        </RelativeLayout>
    </ScrollView>

    <Button
        android:id="@+id/playButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
         />

</RelativeLayout>
A typical question when someone is beginning with Android is how to add scroll to an activity, or a component of the interface. It has a really simple solution. You just have to add a ScrollView tag above the element you want to scroll.

It´s important to note that ScrollView tag supports just one child. It uses to be a layout that contains the rest of the components.

Therefore, if we want to make scroll over the entire interface of an activity, we have to write something like this:

<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
        <!-- your components -->
    </RelativeLayout>
</ScrollView>

If we want to apply scroll to a concrete group of components, we also can do it. This is the structure of configuration activity in Match Pairs Battle, which lets ad at the top, a button at the bottom, and allows scroll over the options.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/adLayout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:orientation="horizontal" >
    </LinearLayout>

    <ScrollView
        android:id="@+id/options_layout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/adLayout"
        android:layout_above="@+id/playButton" >
        
        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" >
            <!-- your components -->
        </RelativeLayout>
    </ScrollView>

    <Button
        android:id="@+id/playButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
         />

</RelativeLayout>

Entradas multilenguaje en blogger
Multilingual posts in blogger

Una de las grandes carencias de Blogger es el multilenguaje, ya que hasta la fecha no aporta una solución para poder publicar las entradas en diferentes idiomas.

Tras bastante tiempo probando soluciones encontradas por la web, he conseguido llegar a una opción bastante sencilla y satisfactoria, basada en jQuery. Su principal ventaja respecto a la mayoría de las que he visto, es que permite que la entrada y su título puedan verse en distintos idiomas, de forma que las visitas, comentarios, etc., son únicos. También intenta mostrar al visitante el idioma más adecuado, de acuerdo a la configuración del navegador.

La solución se basa en crear un panel con el contenido del texto en cada uno de los idiomas deseados, y añadir botones que muestran un idioma determinado, y ocultan el resto.

La solución, paso a paso, sería:

1. Añadir la librería jQuery a la plantilla de nuestro blog. Para ello, vamos a Plantilla - Editar HTML, y en el código búscamos la etiqueta </head>. Justo detrás copiamos la siguiente línea:

<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js' type='text/javascript'/>

2. Añadir el script que selecciona el idioma por defecto, y controla las pulsaciones de los botones. Lo pegamos detrás de la línea anterior:

<script type='text/javascript'>
   $(document).ready(function() {
   <!-- Select the initial language -->
   var userLang = navigator.language || navigator.userLanguage; 
   if (userLang.indexOf(&quot;es&quot;) &gt;= 0) {
  $(&quot;div.english&quot;).hide();
   }
   else {
  $(&quot;div.spanish&quot;).hide();
   }
  <!-- If spanish button is clicked, hide english text, and show spanish text -->
  $(&quot;#spanish_button&quot;).click(function () {
    $(&quot;div.english&quot;).hide();
    $(&quot;div.spanish&quot;).fadeIn(300);
  });
  
  <!-- If english button is clicked, hide spanish text, and show english text -->
  $(&quot;#english_button&quot;).click(function () {
    $(&quot;div.english&quot;).fadeIn(300);
    $(&quot;div.spanish&quot;).hide();
  });
   });
 </script>

3. Añadir los botones para cambiar de idioma. Podemos ponerlos en cada una de las entradas, pegando siempre el código al comienzo de las mismas, en la vista HTML, o en algún lugar fijo del blog. En mi caso los he colocado en la cabecera. Como fuente de las imágenes debéis poner la ruta a aquellas que queráis utilizar.

<img align='right' height='50' id='english_button' src=%your_image% width='50'/>
<img align='right' height='50' id='spanish_button' src=%your_image% width='50'/>

4. Para cada entrada, escribir el texto en cada uno de los idiomas, dentro de una etiqueta div, indicando el idioma en el atributo class:

<div class="english">
English Text.
</div>
<div class="espanish">
Spanish Text.
</div>

Y ya está. Podéis ver el resultado en este mismo blog. Puedes añadir tantos idiomas como quieras.
One of the major shortcomings of Blogger is multilingual and, to date, it does not provide a solution to publish entries in different languages.

After some time testing solutions found in the web, I got a fairly simple and satisfactory option, based on jQuery. Its main advantage over most I've seen, is that it allows one entry with different languages, so that the views, comments, etc., are unique. It also attempts to show visitors the most appropriate language, according to the browser settings.

The solution is to create a panel with the contents of the entry in each of the desired languages, and add buttons for each language, showing the corresponding panel when it´s pressed, and hidding the others.

The solution, step by step:

1. Add the jQuery library to our blog template. To do this, go to Template - Edit HTML, and in code we search for </head>. Just behind, copy the following line:

<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js' type='text/javascript'/>

2. Add the script to select default language, and control clicks on the buttons. Paste it below the import line.

<script type='text/javascript'>
   $(document).ready(function() {
   <!-- Select the initial language -->
   var userLang = navigator.language || navigator.userLanguage; 
   if (userLang.indexOf(&quot;es&quot;) &gt;= 0) {
  $(&quot;div.english&quot;).hide();
   }
   else {
  $(&quot;div.spanish&quot;).hide();
   }
  <!-- If spanish button is clicked, hide english text, and show spanish text -->
  $(&quot;#spanish_button&quot;).click(function () {
    $(&quot;div.english&quot;).hide();
    $(&quot;div.spanish&quot;).fadeIn(300);
  });
  
  <!-- If english button is clicked, hide spanish text, and show english text -->
  $(&quot;#english_button&quot;).click(function () {
    $(&quot;div.english&quot;).fadeIn(300);
    $(&quot;div.spanish&quot;).hide();
  });
   });
 </script>

3. Add buttons to change language. We can place them in each post; to do that, we have to paste the code in the beginning of each one. The other option is to place the buttons in a fixed location. (Change %your_image% by the url of the image you want to use for the button).

<img align='right' height='50' id='english_button' src=%your_image% width='50'/>
<img align='right' height='50' id='spanish_button' src=%your_image% width='50'/>

4. For each post, write the text for each language in a div tag, indicating the language in class attribute. Do the same for the title.

<div class="english">
English Text.
</div>
<div class="espanish">
Spanish Text.
</div>

And that's it. You can see the result in the entries of this blog. You can add as many languages ​​as you want.

Now, I just have to improve my english...

Texto alternativo para listas vacías
Alternative text for empty lists

La clase ListView de Android ofrece el método setEmptyView, que permite mostrar un mensaje al usuario si una lista está vacía. Para utilizarlo, es necesario definir en el layout de la página un elemento con visibilidad gone, que será el que se le pase a dicho método.

Como ejemplo podemos ver cómo se ha implementado la lista de jugadores de Memory Battle. Este es el fragmento del fichero de layout.

    <ListView
        android:id="@+id/players_list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" /> 

    <TextView
        android:id="@+id/no_players_text"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/playersList"
        android:text="@string/no_players"
        android:visibility="gone" />

Y este el código que indica a la lista que debe usar el TextView como vista a mostrar cuando no tiene elementos.

playersList = (ListView) findViewById(R.id.playersList);
playersList.setEmptyView(findViewById(R.id.no_players_text));

Dado que lo que espera setEmptyView es un objeto View, se podría cambiar el texto por cualquier otro componente, como una imagen.
ListView class in Android provides setEmptyView method, which allows us to show a message to the user if the list is empty. To use it, we have to define in the layout file an element with gone visibility. That will be the parameter for setEmptyView.

This example shows how I´ve implemented the players list on Memory Battle. This is the fragment in the layout file:

    <ListView
        android:id="@+id/players_list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" /> 

    <TextView
        android:id="@+id/no_players_text"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/playersList"
        android:text="@string/no_players"
        android:visibility="gone" />

And this is the code to tell the list that it has to show the TextView when it has no elements.

playersList = (ListView) findViewById(R.id.playersList);
playersList.setEmptyView(findViewById(R.id.no_players_text));

You can use any View object as parameter for setEmptyView, so you could change the text for an image, for example.