Como cambiar el idioma a español en el SonarQube


Sonar nació para ser utilizada en desarrollos Java, pero actualmente soporta más de 20 lenguajes incluyendo Java, C#, JavaScript, TypeScript, C/C++, COBOL  y mas   integrándose  con  Maven, Ant y herramientas de integración continua como Atlassian Bamboo y Jenkins.

SonarQube es pues  una potente herramienta open software  que permite analizar el código fuente  informándonos ,entre otras cosas, sobre código duplicado, estándares de codificación, pruebas unitarias, cobertura de código, complejidad ciclomática y mucho mas.

 

Instalación  automática plugins

SonarQube puede extender su funcionalidad por medio de la instalación de los famosos  plugins, los cuales atienden  a funcionalidades ampliadas  como pueden ser lenguajes soportados ( los mas normales son c#, java y js), otras herramientas de desarrollo,integración y gobierno así como otros  Idiomas soportados para el interfaz de Sonar

De  forma general  siempre que queramos instalar un plugin debemos asegurarnos que dicho plugin está disponible para la versión de SonarQube que estamos usando   comprobándolo antes en la  matriz de versiones para cerciorarnos de que dicho plugin es compatible con nuestra versión

Para instalar un plugin  de  forma automática por medio del Update Center  solamente hay que ir  Administration –> System  –>Update Center

En el caso de querer instalar el  idioma español el plugin se llama Spanish Pack 

Pulsaremos Install  sobre la opción Spanish  Pack el lado derecho    y luego realizada la descarga     no  olvidemos pulsar  el boton   Restart  en la parte superior y

 

Instalación manual de Plugins

Para instalar un plugin de forma manual  basta con ubicar el archivo JAR en la carpeta
\sonarqube-XXXX\extensions\plugins y en el siguiente inicio de Sonar ya se contará con el plugin.

En caso de no tener el archivo JAR tendremos que ejecutar un mvn package, mover el jar al directorio de plugins  y reiniciar el Sonar, procedimiento que podemos seguir por ejemplo  para cambiar el idioma del Sonar a esapañol .

Para  instalar el  plugin para tener Sonar en Castellano  podemos seguir los siguientes pasos:

1-Comprobamos también  antes en la  matriz de versiones para cerciorarnos de que dicho plugin es compatible con nuestra versión  pudiéndose instalar éstos  tanto de forma automática por medio del Update Center como de forma manual.

En el caso de idioma español el plugin como hemos dicho , se llama Spanish Pack  y es compatible con todas las versiones del Sonar:

spanishpack.PNG

2- En la matriz de plugin  citada pulsamos en el link de Spanish Pack lo que nos lleva al repositorio de GitHub del siguiente pantallazo.
Obtenemos asi la URL en la parte inferior derecha para, mediante git, clonar el repositorio. La  url del Git  seria:https://github.com/SonarQubeCommunity/sonar-l10n-es 

github.PNG

3-  Descargaremos el  archivo   ZIP   ,   descomprimiendo después el fichero en un directorio del ordenador

4-Ahora , desde una ventana de comandos nos iremos al directorio donde los descargamos y  ejecutamos:  mvn  package

consola

Al finalizar el proceso , que como vemos tarda unos 13 minutos , en la carpeta target dentro de la  carpeta que descomprimimos, ya    tendremos el archivo JAR

español.PNG

Ahora  solo nos toca  copiar   dicho ficjero jar al directorio de Plugins  del sonnar  , y ya nos  servirá como plugin para modificar el idioma en cuanto se reinicie.

sonarplugins

Si esta el sonar ejecutándose sobre Windows habría que matar los procesos  java relacionados con el Sonar  o si no nos importa reiniciamos el equipo , y  volvemos a lanzar el Sonar

 

Tanto si lo hace de forma automática como si hace la instalación del  plugin de forma manual al reiniciar ya debería tener el idioma español:

 

Mas información  en  SonarQube,org

Anuncios

Subir una app a Google Play creada con Visual Studio con Ionics


En las siguientes lineas veremos paso  a paso como preparar una aplicación creada  con Ionics desde Visual Studio para publicarla en Google Play en  sencillos pasos:

Paso 1: Modifique la configuración de su aplicación

 La configuración general de la aplicación aparece en la página Común del diseñador de configuración  que se activa justamente abriendo el  fichero  config.xml.

comun

  • El nombre para mostrar es el nombre que aparece en la tienda de aplicaciones.
  • El nombre del paquete es una cadena que identifica de forma exclusiva su aplicación.Elija un esquema de nomenclatura que reduzca la probabilidad de un conflicto de nombres.
  •  Acceso al dominio muestra los dominios a los que debe acceder su aplicación. Por ejemplo, WeatherApp que aparece en la imagen anterior, obtiene datos meteorológicos de un punto final de servicio que tiene el dominio https://query.yahooapis.com .

 El propósito de la mayoría de los demás ajustes se borran del título, pero puede encontrar más información en el fichero config.xml .

Las configuraciones específicas de Android aparecen en la pestaña Android del diseñador de configuración.

android.PNG

 Puede leer acerca de cada opción en la sección de preferencias del tema de referencia config.xml.

 Paso 2 :Generar una clave privada

Para firmar su aplicación, se  necesita crear un almacén de claves ( keystore ) 

Un almacén de claves es un archivo binario que contiene un conjunto de claves privadas. En las siguiente líneas aprenderemos  a  crear uno:

  • Abra un símbolo del sistema en modo administrador.
  • En el símbolo del sistema, cambie al   directorios   al  que apunte la carpeta %JAVA_HOME%\bin . (Por ejemplo: C:\Program Files (x86)\Java\jdk1.7.0_55\bin ).
  • En el símbolo del sistema, para java 1.7.0_55 ejecute el siguiente comando keytool  :
 keytool -genkey -v -keystore c:\my-release-key.keystore -alias johnS -keyalg RSA -keysize 2048 -validity 10000

(  Reemplace my-release-key.keystore y johnS con nombres que tengan sentido para usted.)

  • Se le pedirá que proporcione una contraseña y los campos Nombre distinguido de su clave.
  • Esta serie de respuestas le da una idea de los tipos de información que proporcionará para cada solicitud. Al igual que en el comando anterior, responda a cada solicitud con información que tenga sentido para su aplicación.
  •  Después de proporcionar esta información, aparece en el símbolo del sistema.
  • El SDK de Android genera el almacén de claves como un archivo denominado my-release-key.keystore y coloca ese archivo en la unidad C: \. EL keystore  o almacén de claves contiene una sola clave, válida para 10000 días.

 Si desea obtener más detalles sobre este proceso, consulte la documentación para desarrolladores de Android aquí:Signing your applications .

Paso 3: Consulte la clave privada en un archivo de configuración

 En primer lugar, identifique la versión del CLI de Cordova que utiliza su proyecto. Esto determina qué archivo de configuración utiliza para referirse a su clave.

Encuentre la versión CLI de su proyecto

 El número de versión de CLI aparece en la página Plataformas del diseñador de configuración.

Versión CLI

También puede encontrarlo en el archivo taco.json en la raíz de su proyecto

 Si la versión CLI de Cordova es mayor que 5.0, utilice estos pasos

En el Explorador de soluciones , expanda la carpeta de proyecto y, a continuación, el archivo build.json . Si ese archivo falta en su proyecto, su proyecto se creó con una versión anterior de Cordova y debe crear ese archivo manualmente (y rellenarlo con contenido en el paso 2).Android: crear activos El archivo build.json aparece en el editor de código.

En el archivo build.json , agregue la información que describe su clave.

 { {
 "android": { "android": {
     "release": { "lanzamiento": {
         "keystore":"c:\\my-release-key.keystore", "keystore": "c: \\ mi-release-key.keystore",
         "storePassword":"pwd123", "storePassword": "pwd123",
         "alias":"johnS", "alias": "johnS",
         "password":"pwd123", "contraseña": "pwd123",
         "keystoreType":"" "keystoreType": ""
       } }
   } }
} }

Paso 4: Crear el paquete

 En la barra de herramientas Estándar, elija la plataforma Android .Selector de plataforma

 Elija la configuración de generación de Release .                              Liberar configuración de compilación

 Elija uno de los emuladores de Android.Selector de destino. .

. Importante : No elija ninguno de los simuladores Ripple.  Elija solo un emulador de Android o el dispositivo.

. En el menú Generar , elija Generar solución . Esto crea un archivo con una extensión de archivo .apk.  Ese es el archivo que subirá a la tienda. Puede encontrar ese archivo en la carpeta bin/Android/Release/ de su proyecto.

 Es el archivo que no contiene la palabra unaligned en el nombre del archivo.

ubicación del archivo apk

 Envíe su aplicación a la tienda

 Ahora ya puede publicar tu aplicación en Google Play con su cuenta de desarrollador de Google Play.

 Para prepararse para el gran día, revise Essentials para obtener una aplicación exitosa .(en ingles)

A continuación, vea Cargar una aplicación para que su aplicación sea accesible para el mundo.

Instalación de ionic en Windows y posibles fallos por tener conectividad bajo un Proxy


El proceso de instalación de Ionic es relativamente sencillo:

Instalar node.js

Primero, instale Node.js.Una vez instalado Node, abra el Terminal y ejecute  node -v.  Este comando le dice a Node que informe de nuevo la versión actualmente instalada:

>node-v
>v8.2.1

También debe asegurarse de que npm  ( el nodo gestor de paquetes para módulos de node)  está actualizado . Cuando instala Node.js esto se hace automáticamente para usted, pero si desea comprobar qué versión de npm se ha instalado  ejecute ;

>npm -v
>5.4.1

Si necesita actualizar su instalación de npm, el comando es:    $ npm install npm -g

Instalación de Git

Con Node y npm instalados correctamente, ahora deberiamos instalaremos Git, pues aunque que usted es libre de elegir cualquier solución de control de versiones (Perforce, SourceSafe o Git), el Ionic CLI aprovecha Git para la gestión de plantillas.
Vaya a https://git-scm.com/download/win  para descargar el paquete de windows . Siga adelante y abra el archivo de paquete y siga la instalación predeterminada.
Una vez que la instalación se haya completado, desde el interfaz de comandos :

>git –version
>git versión 2.14.1.vindows-1-1

Instalación de la CLI de Apache Cordova..

Aunque podemos instalar tanto Cordova como Ionic al mismo tiempo, se recomienda instalar cada uno individualmente , de modo  qeu en caso de que haya un problema durante el proceso de instalación podamos resolverlo mas facilmente.
La instalación de Cordova CLI utiliza el administrador de paquetes del nodo (npm) para realizar la instalación. Para instalarlo, abra la ventana Terminal o Git Bash e introduzca el siguiente comando:

>npm install -g cordova

Dependiendo de su conexión a Internet, esto puede tomar un tiempo. Una vez finalizado para comprobar como ha quedado  puede ejecutar

>cordova -v
>7.0.1

Siga las guías de plataforma para Android e iOS para instalar las herramientas necesarias para el desarrollo

Instalar Ionic

Al igual que la instalación del CLI de Cordova, el Ionic CLI también se instala a través de npm. En la ventana Terminal, ingrese el siguiente comando:

>npm install -g cordova ionic

Esta instalación tardará un tiempo en completarse. Una vez que la CLI Ionic haya completado su instalación, volveremos a comprobarlo emitiendo el comando ionic en nuestro cmd:

>ionic -v (hay que situarse en el camino d; \ user\ Appdata \ Roaming \ nmp \)
>3.10.3

Ahora tenemos nuestra instalación base en el lugar para el desarrollo iónico. Sin embargo, eventualmente queremos probar nuestras aplicaciones en un emulador de dispositivo o en un dispositivo real. Vamos a echar un vistazo a la instalación de estas herramientas en breve. Pero primero, vamos a configurar una aplicación de ejemplo y ver cómo visualizarla en nuestro navegador.

Desarrolladores de Windows: se recomienda Visual Studio Community , que viene con todo lo que necesita, incluyendo plantillas de inicio

Iniciar una aplicación

La CLI Ionic proporciona un comando sencillo que le permite configurar un proyecto  generando  una aplicación Ionic básica en el directorio activo. El marco iónic puede scaffold este proyecto vía una colección de plantillas del arrancador. Estos pueden provenir de una plantilla con nombre, un repo GitHub, un código o incluso un directorio local. Las plantillas nombradas están en blanco, sidemenu y pestañas.

Por ahora, ejecute el comando siguiente para crear un proyecto de Ionic:

ionic start myApp tabs

Para proyectos v1, utilice el --type ionic1 .

$ ionic start myApp blank

$ ionic start myApp tabs

$ ionic start myApp sidemenu

Ejecutar su aplicación

myApp ionic serve cd myApp ionic serve

Gran parte de su aplicación se puede construir directamente en el navegador con ionic serve .Se recomienda comenzar con este flujo de trabajo.

Su panel de control siempre está disponible en dashboard.ionicjs.com

Lista de url ‘s asociados:

Componente URL
Node.js nodejs.org
Git git-scm.com
Ionic ionicframework.com
Apache Cordova cordova.apache.org

Problemas

Puede que a pesar  de haber instalado  todas las herramientas necesarias ,al intentar crear un proyecto nuevo nos de error:

D:\user\AppData\Roaming\npm>ionic -v
3.10.1
D:\user\AppData\Roaming\npm>ionic start testApp
? What starter would you like to use: tabs
[INFO] Fetching app base
       (https://github.com/ionic-team/ionic2-app-base/archive/master.tar.gz)
× Downloading – failed!
Error: connect ETIMEDOUT 192.30.253.113:443
    at Object.exports._errnoException (util.js:1024:11)
    at exports._exceptionWithHostPort (util.js:1047:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1150:14)

 

inicio iónico [appName] comando de trabajo detrás de un proxy. Me encontré con el problema al pasar por los pasos de la página Introducción a Ionic .Por alguna razón, el cmd ionic no utiliza la configuración del proxy npm o del proxy git.

Hice esto en una máquina de Windows 7 pero el mismo debe trabajar en otro OS apenas las localizaciones del archivo serán diferentes.

1. Agregue la url proxy a request.js ubicada en ‘C: \ Usuarios \ [nombre de usuario] \ AppData \ Roaming \ npm \ node_modules \ ionic \ node_modules \ request \ request.js’.

D:[nombre de usuario]\AppData\Roaming\npm\node_modules\npm\node_modules\request\request.js

Aquí está la actualización incluyendo las líneas justo antes y después para que pueda encontrar dónde ponerlo.

if (self.strictSSL === false) {
self.rejectUnauthorized = false
}

// hack to add proxy
self.proxy = ‘http://10.68.0.5:8080’;

if (self.proxy) {
if (typeof self.proxy == ‘string’) self.proxy = url.parse(self.proxy)

// do the HTTP CONNECT dance using koichik/node-tunnel
if (http.globalAgent && self.uri.protocol === “https:”) {
var tunnelFn = self.proxy.protocol === “http:”
? tunnel.httpsOverHttp : tunnel.httpsOverHttps

var tunnelOptions = { proxy: { host: self.proxy.hostname
, port: +self.proxy.port
, proxyAuth: self.proxy.auth
, headers: { Host: self.uri.hostname + ‘:’ +
(self.uri.port || self.uri.protocol === ‘https:’ ? 443 : 80) }}
, rejectUnauthorized: self.rejectUnauthorized
, ca: this.ca }

self.agent = tunnelFn(tunnelOptions)
self.tunnel = true
}
}

2. Agregue la URL del proxy a registry.js ubicada en ‘C: \ Users \ [nombre de usuario] \ AppData \ Roaming \ npm \ node_modules \ cordova \ node_modules \ plugman \ src \ registry \ registry.js o   D:[nombre de usuario]\AppData\Roaming\npm\node_modules\cordova\node_modules\cordova-lib\src\plugman\registry

las líneas alrededor del hack para que pueda encontrar dónde ponerlo.

headers.accept = “application/json”

headers[“user-agent”] = settings[‘user-agent’] ||
‘node/’ + process.version

// hack to add proxy
var p = settings.proxy || ‘http://10.68.0.5:8080’
var sp = settings[‘https-proxy’] || p
opts.proxy = remote.protocol === “https:” ? sp : p

// figure out wth ‘what’ is
if (what) {
if (Buffer.isBuffer(what) || typeof what === “string”) {
opts.body = what
headers[“content-type”] = “application/json”
headers[“content-length”] = Buffer.byteLength(what)
} else {
opts.json = what
}
}

 

Comunicacion con un smartphone usando el magnetometro


Una forma barata y sencilla de comunicación entre un microcontrolador (por ejemplo, Arduinoo Netduino +) y un dispositivo Android es sorprendentemente difícil de lograr siendo el medio más práctico para lograrlo es utilizar un módulo Bluetooth o WiFi que aumente significativamente el costo de un proyecto (del orden de $ 30 – $ 60).

En este post veremos  un pequeño hack que permite comunicaciones de ancho de banda muy bajo en una dirección y prácticamente  sin costo alguno. No es práctico para la mayoría de las aplicaciones, pero  la idea era suficientemente interesante para explorarla 

Se puede utiliza el magnetómetro  de cualquier dispositivo para realizar una comunicación inalámbrica. El truco reside en crear una pequeña bobina a modo de antena y variar el campo magnético de la brújula del teléfono: de esta forma mediante esas pequeñas variaciones, podemos enviar datos al teléfono de una forma muy sencilla (la conexión de datos no es rápida ya que tan sólo permite un refresco de unos 40Hz pero es interesante ver cómo funciona).

Paraa probar el montaje necesitará lo siguiente:

  • Un teléfono o dispositivo Android que cuente con un magnetómetro (brújula electrónica). A dia de hoy no se conoce e ningún dispositivo sin uno.
  • Un Arduino
  • Aproximadamente 1 metro de alambre de cobre esmaltado (alambre del imán), aunque cualquier alambre aislado fino hará.
  • La aplicacion android ‘ Tricorder ‘ (disponible gratuitamente en la tienda de aplicaciones de Android)
  • Resistencia de 120 ohmios
  • Un diodo (opcional)

Haga una bobina envolviendo el 1 metro de hilo magnético alrededor de algo cilíndrico (por ejemplo, una pila  AAA) con un diámetro de aproximadamente 1 cm. Usted debe obtener alrededor de 30 vueltas de 1 metro. El diámetro o el número de vueltas no es importante mientras estén en bien erolladas para lo cual puede envolver  un hilo ligero alrededor de la bobina para ayudar a mantener su forma.

 

Conecte ahora a bobina como se ilustra en el esquema anterior. La resistencia de 120 ohmios limita el consumo de corriente a aproximadamente 40mA, que es el máximo permitido

El propósito del diodo es proteger el Arduino de un golpe de disparo de EMF cuando el pasador 13 está bajo. Esto se conoce como un diodo de retorno . Con sólo 30 vueltas y un núcleo de aire, es probable que salga sin usarlo,pero es una buena práctica incluirlo.

Ahora toca localizar el magnetómetro delterminal pues su ubicación variará de un dispositivo a otro. Aquí es donde el tricorder sera muy útil pues  la aplicación Tricorder  mostrara el campo magnético.

Para el HTC Desire la señal es más fuerte en la parte inferior . A la izquierda de la pantalla LCD es donde se encuentra el magnetómetro  pero esto es probable que varíe de un dispositivo a otro.

Ahora  cargue este skretch en su placa  Arduino antes de conectar la bobina.

  Unesdoc.unesco.org unesdoc.unesco.org
  * Generar una onda cuadrada de 1 Hz en el pin 13
  * /
 Void setup () {
   PinMode (13, OUTPUT);
 }

 Void loop () {
     DigitalWrite (13,1);
     Retardo (500);
     DigitalWrite (13,0);
     Retardo (500);
 }

Cuando la bobina está desconectada, debería ver el LED del Arduino parpadeando.

Ahora conecte la bobina. El LED debe dejar de parpadear en este punto porque la bobina pone en cortocircuito el LED ,lo cual  es lo  esperado.

Inicie la aplicación Tricorder y cambie al modo MAG e inicie la exploración.

Escanee metódicamente la bobina a través de la superficie del teléfono Android hasta que empiece a ver una fuerte onda cuadrada:donde vea la amplitud de este pico de señales es donde se encuentra el magnetómetro.

Debería ver una onda cuadrada similar si coloca la bobina en la misma ubicación en la superficie inferior del dispositivo. Utilice un poco de cinta para mantenerlo colocado allí.

Ahora tenemos una forma de detectar  en Android ,por lo que la tentación  es conectar la bobina al Arduino UART y comenzar a enviar  datos a 9600bps , pero desafortunadamente esto no va a suceder porque estamos limitados por la tasa de muestreo del magnetómetro disponible para nosotros por el sistema operativo Android.

Aquí está un histograma de time-between-samples de un HTC Desire ejecutando Froyo (Anrdoi 2.2) a una velocidad de muestreo máxima:

Podemos ver aquí que casi todas las muestras vienen en entre 18ms y 25ms. Hay algunos  picos qeu van todo el camino hasta 45ms pero  son tan pocos que podemos ignorarlos. Esto significa que estamos limitados a un máximo de una tasa de muestreo de 40 Hz. Si manejamos la bobina con una línea de E / S digital que inmediatamente tapa nuestro ancho de banda máximo a 40bps.

Este otro sketch para  Arduino energiza la bobina con una onda cuadrada de inicio a 500Hz y disminuye a aproximadamente 1Hz durante unos segundos.

  Int i;
 Int d = 1;
 Void setup () {
   PinMode (13, OUTPUT);
 }

 Void loop () {
   Para (i = 1; i <500; i + = d) {
    
     // Aumenta el incremento a medida que disminuye la frecuencia
     D = (i ^ {6}) + 1;
   
     DigitalWrite (13,1);
     Retraso (i);
     DigitalWrite (13,0);
     Retraso (i);
   }
 }


Aquí están los datos del magnetómetro:


Como se esperaba, no se detectan altas frecuencias (a la izquierda). Parece que sólo obtener buena recogida cuando la frecuencia baja a alrededor de 6Hz!

Para la codificación utilizamos NRZ (no retorno a cero) similar a la utilizada en RS232 con un período de bit de 140ms (aproximadamente 7 bps). El límite inferior UART de Arduino es de 300bps, así que no podemos usarlo para generar la señal.

Del mismo modo, en el terminal Android vamosa tener que decodificar en el software también.

#define BIT_DELAY 140

int i;
char *text = "Hello World! ";

void setup() {
  pinMode(13,OUTPUT);
}

void loop() {
 
  char *s;
  s = text;
  while (*s != 0) {
    transmitByte(*s++);
  }
  
  delay (BIT_DELAY*10); 
}
/**
 * Bit bang a byte
 */
void transmitByte (byte c) {
  
  // Start bit
  digitalWrite (13,1);
  delay(BIT_DELAY);
  
  // Data bits
  for (i = 0; i < 8; i++) {
      digitalWrite (13, ( (c&0x80)!=0 ? 1 : 0) );
      delay(BIT_DELAY);
      c <<= 1;
  }
  
  // Stop bit
  digitalWrite (13, 0);
  delay(BIT_DELAY);
}

 

Aquí vemos el ejemplo  en acción:

Nota :la aplicación Tricorder no esa disponible temporalmente en Google Play ,pero en su lugar hay algunas apps similares como  Magentic Filed measure

Via    jdesbonnet

Como recompilar una aplicación en Android en otra version


Si esta  desarrollando un aplicación con Android Studio  , en el momento que se crea un proyecto nuevo habrá especificado el  API LEVEL de la  aplicación Android

Seguro que con bastante esfuerzo habrá desarrollado partir de la estructura inicial  su aplicación basándose en esa especificación ,pero una vez  finalizado el desarrollo  ( y las pruebas de la app) si  intenta subirla a Google Play,  quizás  en un segundo intento vez, habrá visto que da error en la subida del APK debido a que ya tiene un archivo con ese código de versión.

Este problema  también le puede ocurrir cuando desee probar su aplicación con otro terminal   que   cuente con una versión de Android inferior

En este post precisamente  vamos  a ver cómo cambiar el código de versión de una aplicación Android o el nivel del  API  para  solucionar  precisamente los problemas comentados  .Como vamos a ver es un procedimiento realmente sencillo, y no debería llevarnos ninguna complicación.

En primer lugar,  veamos  en la siguiente tabla las diferentes versiones del nivel de API de Android  en relación a la versión  que todos conocemos : la versión de la Plataforma

Versión de la plataforma Nivel de API VERSION_CODE
Android 7.0 24 N
Android 6.0 23 M
Android 5.1 22 LOLLIPOP_MR1
Android 5.0 21 LOLLIPOP
Android 4.4W 20 KITKAT_WATCH
Android 4.4 19 KITKAT
Android 4.3 18 JELLY_BEAN_MR2
Android 4.2 y 4.2.2 17 JELLY_BEAN_MR1
Android 4.1 y 4.1.1 16 JELLY_BEAN
Android 4.0.3 y 4.0.4 15 ICE_CREAM_SANDWICH_MR1
Android 4.0, 4.0.1 y 4.0.2 14 ICE_CREAM_SANDWICH
Android 3.2 13 HONEYCOMB_MR2
Android 3.1.x 12 HONEYCOMB_MR1
Android 3.0.x 11 HONEYCOMB
Android 2.3.4 10 GINGERBREAD_MR1
Android 2.3.3
Android 2.3.2 9 GINGERBREAD
Android 2.3.1
Android 2.3
Android 2.2.x 8 FROYO
Android 2.1.x 7 ECLAIR_MR1
Android 2.0.1 6 ECLAIR_0_1
Android 2.0 5 ECLAIR
Android 1.6 4 DONUT
Android 1.5 3 CUPCAKE
Android 1.1 2 BASE_1_1
Android 1.0 1 BASE
Si por la razón que sea  quiere cambiar el API Level, por ejemplo de API  16 ( correspondiente a : Android 4.1 Jelly Bean)  a API 22 ( correspondiente a : Android 5.1.0 (Lollipop)  sólo hay que seguir los siguientes pasos:
  •  Buscar la carpeta app del menú desplegable “Project” ( o la carpeta que contenga el nombre de nuestra app )
  •  Pulsación en el  Botón derecho => OPEN MODULE SETTINGS:
openmodules.png
  •  Nos aparecerá  otro menú  con cinco pestañas  posicionándose por defecto en Properties  donde especificamos la versión del complilador , la cual recomendamos dejar en la máxima versión( 7.1.1):
properties.PNG
  • Haremos clic sobre la tercera pestaña FLAVORS:
ejmplo
  •  Aparecen en esta pantalla   el nivel dela API minimo y  otras parametros . Pincharemos en el desplegable de MIN SDK VERSION, donde podemos escoger el nuevo API LEVEL ( clic sobre la flecha )  que deseemos:
androidversionmion
Una vez situados aquí, también  podemos  cambiar el código de la versión del APK, que es efectivamente el que tenemos seleccionado. El primer APK por defecto lleva versionCode 1, pero la siguiente versión debe llevar el 2 y así sucesivamente, de ahí a quGoogle Play de error si subimos un APK con la misma versionCode o código de versión.Lo que haremos será tan sencillo como cambiar la Version Code cada vez que generamos una nueva versión de la aplicación, es decir, un nuevo APK a publicar. Una vez hecho esto, tan solo tendremos que guardar el proyecto y volver a generar el APK.
  • GRADLE reconstruirá  automáticamente todo el proyecto ( SYNC )  al  darle al botón Aceptar
  • Este proceso podemos repetirlo cuantas veces deseemos con diferentes versiones para adaptar nuestro proyecto a las diferentes versiones de Android
 Con esta actuación ( y todas las que deseemos )   habremos configurado el fichero  build.gradle (Module:app) de forma segura   y  completamente funcional.

Envío de e-mail sin intervención del usuario en Android Studio


El SDK de Android facilita muchísimo el envío de correos electrónicos desde una aplicación, pues sólo necesitamos incluir   el permiso correspondiente en el fichero AndroidManifiest.xml  y luego ya podemos usarlo en un nuestra   clase principal

Por ejemplo  esta  es una forma de incluir lo  permisos necesarios  en el fichero AndroidManifiest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.usuario.ejemplo" >
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Con los permisos  otorgados,    en el  fichero  MainActivity .java  necesitaremos  incluir una referencia a dicho modulo:

import android.net.Uri;

Y  ya desde el propio  fichero  MainActivity .java   crearemos la clase de envio de  correos  ,la cual  podremos invocar desde cualquier parte  para enviar el correo

    protected void sendEmail() {
        Log.e("Test email:", "enviando email");
        String[] TO = {""};
        String[] CC = {""};
        Intent emailIntent = new Intent(Intent.ACTION_SEND);

        emailIntent.setData(Uri.parse("mailto:"));
        emailIntent.setType("text/plain");
        emailIntent.putExtra(Intent.EXTRA_EMAIL, TO);
        emailIntent.putExtra(Intent.EXTRA_CC, CC);
        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Your subject");
        emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message goes here");

        try {
            startActivity(Intent.createChooser(emailIntent, "Send mail..."));
            finish();
            Log.e("Test email:", "Fin envio email");

        } catch (android.content.ActivityNotFoundException ex) {
            Toast.makeText(MainActivity.this, "There is no email client installed.", Toast.LENGTH_SHORT).show();
        }
    }
};

Por desgracia, esta vía es sólo válida si se desea enviarlos a través de la  propia aplicación de correo incorporada.

Para la mayoría de las situaciones este  método  funciona muy bien, y como hemos visto con muy poco código  , pero   silo que quiere es enviar algo y no quiere  ver  ninguna entrada  o  intervención del usuario ya  no es tan fácil.
En las siguientes lineas vamos a ver  cómo enviar un correo electrónico en background, es decir in que el usuario  sea consciente de ello ya que  la aplicación hará todo por detrás
Antes de comenzar, necesitará descargar tres librerías  a través del siguiente enlace:

https://code.google.com/archive/p/javamail-android/downloads

Esta es una versión especial de la API de JavaMail, que ha sido escrita específicamente para Android por Jon Simon.

googlecode

Esta librerias debemos  añádirlas como bibliotecas externas para que sean accesibles por la clase Mail.

Una forma sencilla de hacerlo es copiar directamente  estos ficheros  donde se encuentre el fichero activitymain,java ( por ejemplo   en c:\Users\miususairo\AndroidStudioProjects\ejemplo\app\src\main\java\com\example\misusuario\ejemplo\ )

De este modo, será visible el contenido desde la carpeta java de nuestro  proyecto;

libreias

Ahora ya sólo nos queda  pinchar sobre cada librería de las tras copiadas , con el boton derecho  y seleccionaremos “Add  as Library”

addas.png

.

Al pulsar esta opción  nos pide donde añadira la librerria , qeu simplemnte  aceptaremos

create.PNG

Ahora vamos  a ver  el codigo completo de la clase que nos permitira usar esta tres librerias que hemos imporatado para poder enviar correos mediante nuestra cuenta de gmail sin intervencion de Android

import java.util.Date; 
import java.util.Properties; 
import javax.activation.CommandMap; 
import javax.activation.DataHandler; 
import javax.activation.DataSource; 
import javax.activation.FileDataSource; 
import javax.activation.MailcapCommandMap; 
import javax.mail.BodyPart; 
import javax.mail.Multipart; 
import javax.mail.PasswordAuthentication; 
import javax.mail.Session; 
import javax.mail.Transport; 
import javax.mail.internet.InternetAddress; 
import javax.mail.internet.MimeBodyPart; 
import javax.mail.internet.MimeMessage; 
import javax.mail.internet.MimeMultipart; 
 
 
public class Mail extends javax.mail.Authenticator { 
  private String _user; 
  private String _pass; 
 
  private String[] _to; 
  private String _from; 
 
  private String _port; 
  private String _sport; 
 
  private String _host; 
 
  private String _subject; 
  private String _body; 
 
  private boolean _auth; 
   
  private boolean _debuggable; 
 
  private Multipart _multipart; 
 
 
  public Mail() { 
    _host = "smtp.gmail.com"// default smtp server 
    _port = "465"// default smtp port 
    _sport = "465"// default socketfactory port 
 
    _user = ""// username 
    _pass = ""// password 
    _from = ""// email sent from 
    _subject = ""// email subject 
    _body = ""// email body 
 
    _debuggable = false// debug mode on or off - default off 
    _auth = true// smtp authentication - default on 
 
    _multipart = new MimeMultipart(); 
 
    // There is something wrong with MailCap, javamail can not find a handler for the multipart/mixed part, so this bit needs to be added. 
    MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap(); 
    mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html"); 
    mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml"); 
    mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain"); 
    mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed"); 
    mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822"); 
    CommandMap.setDefaultCommandMap(mc); 
  } 
 
  public Mail(String user, String pass) { 
    this(); 
 
    _user = user; 
    _pass = pass; 
  } 
 
  public boolean send() throws Exception { 
    Properties props = _setProperties(); 
 
    if(!_user.equals("") && !_pass.equals("") && _to.length > 0 && !_from.equals("") && !_subject.equals("") && !_body.equals("")) { 
      Session session = Session.getInstance(props, this); 
 
      MimeMessage msg = new MimeMessage(session); 
 
      msg.setFrom(new InternetAddress(_from)); 
       
      InternetAddress[] addressTo = new InternetAddress[_to.length]; 
      for (int i = 0; i < _to.length; i++) { 
        addressTo[i] = new InternetAddress(_to[i]); 
      } 
        msg.setRecipients(MimeMessage.RecipientType.TO, addressTo); 
 
      msg.setSubject(_subject); 
      msg.setSentDate(new Date()); 
 
      // setup message body 
      BodyPart messageBodyPart = new MimeBodyPart(); 
      messageBodyPart.setText(_body); 
      _multipart.addBodyPart(messageBodyPart); 
 
      // Put parts in message 
      msg.setContent(_multipart); 
 
      // send email 
      Transport.send(msg); 
 
      return true; 
    } else { 
      return false; 
    } 
  } 
 
  public void addAttachment(String filename) throws Exception { 
    BodyPart messageBodyPart = new MimeBodyPart(); 
    DataSource source = new FileDataSource(filename); 
    messageBodyPart.setDataHandler(new DataHandler(source)); 
    messageBodyPart.setFileName(filename); 
 
    _multipart.addBodyPart(messageBodyPart); 
  } 
 
  @Override 
  public PasswordAuthentication getPasswordAuthentication() { 
    return new PasswordAuthentication(_user, _pass); 
  } 
 
  private Properties _setProperties() { 
    Properties props = new Properties(); 
 
    props.put("mail.smtp.host", _host); 
 
    if(_debuggable) { 
      props.put("mail.debug""true"); 
    } 
 
    if(_auth) { 
      props.put("mail.smtp.auth""true"); 
    } 
 
    props.put("mail.smtp.port", _port); 
    props.put("mail.smtp.socketFactory.port", _sport); 
    props.put("mail.smtp.socketFactory.class""javax.net.ssl.SSLSocketFactory"); 
    props.put("mail.smtp.socketFactory.fallback""false"); 
 
    return props; 
  } 
 
  // the getters and setters 
  public String getBody() { 
    return _body; 
  } 
 
  public void setBody(String _body) { 
    this._body = _body; 
  } 
 
  // more of the getters and setters ….. 
} 



En este  código inicializamos las propiedades, y configuramos los valores por defecto.

Además, estamos configurando los tipos mime para javamail.

También hay o un comentario que describe por qué necesitamos esto: Hay algo mal con MailCap, javamail no puede encontrar un controlador para la parte multipart / mixed, por lo que este bit tiene que ser añadido

Y probablemente ha notado que hay 2 constructores – uno sobrepasa al otro, solo en caso de que quiera pasar el nombre de usuario y la contraseña al instanciar la clase

 

El método más importante es  send()  pues  estamos poniendo todos los datos de las propiedades y el envío del correo. Puede llamar a este método en cualquier momento si desea agregar un archivo adjunto, pero asegúrese de llamar  a  _setProperties   antes del método de envío.

Dicha clase  configura las propiedades para la recuperación de correo: predeterminado para la autenticación SMTP pues debe  tenerse en cuenta que todo esto es predeterminado para conectarse al servidor SMTP de Gmail (Google).

A continuación se muestra un ejemplo de cómo utilizar el contenedor de correo en una actividad de Android.

 

@Override 
public void onCreate(Bundle icicle) { 
  super.onCreate(icicle); 
  setContentView(R.layout.main); 
 
  Button addImage = (Button) findViewById(R.id.send_email); 
  addImage.setOnClickListener(new View.OnClickListener() { 
    public void onClick(View view) { 
      Mail m = new Mail("[email protected]""password"); 
 
      String[] toArr = {"[email protected]""[email protected]"}; 
      m.setTo(toArr); 
      m.setFrom("[email protected]"); 
      m.setSubject("This is an email sent using my Mail JavaMail wrapper from an Android device."); 
      m.setBody("Email body."); 
 
      try { 
        m.addAttachment("/sdcard/filelocation"); 
 
        if(m.send()) { 
          Toast.makeText(MailApp.this"Email was sent successfully.", Toast.LENGTH_LONG).show(); 
        } else { 
          Toast.makeText(MailApp.this"Email was not sent.", Toast.LENGTH_LONG).show(); 
        } 
      } catch(Exception e) { 
        //Toast.makeText(MailApp.this, "There was a problem sending the email.", Toast.LENGTH_LONG).show(); 
        Log.e("MailApp""Could not send email", e); 
      } 
    } 
  }); 
} 

Programar en Android no es tan complicado (parte 2)


En un post  anterior veíamos que  el panorama del entorno necesario para programar un aplicación   que se ejecute sobre cualquier dispositivo Android  ha cambiado sustancialmente  reduciéndose  simplemente a una potente herramienta   gratuita  , que ademas proporciona Google: Android Studio.

En este  post seguiremos  profundizando en el desarrollo de aplicaciones con Android Studio deteniéndonos en uno de los aspectos mas llamativos de cualquier aplicación : la  interfaz gráfica de usuario

Android proporciona un vocabulario de XML que corresponde a las subclases de View y ViewGroup, de modo que puede definir su IU en XML usando una jerarquía de elementos de IU y  los diseños son subclases de ViewGroup

Generalmente, los objetos View son widgets de IU como botones o campos de texto y los objetos ViewGroup son contenedores de vistas invisibles que definen la disposición de las vistas secundarias, como en una cuadrícula o en una lista vertical.

 

 

 

 

Diseño interfaz

Aunque existen infinitas  posibilidades de diseño del interfaz ,para empezar,  usaremos un diseño sencillo lineal que coloca todos los elementos gráficos uno a continuación del otro:

  • En la ventana Project de Android Studio, abra el fichero activity_main.xml( app > res > layout > activity_main.xml).Este archivo XML define el diseño de tu actividad y contiene la vista de texto predeterminada “Hello World”.
  • Cuando abra un archivo de diseño, lo primero que ve es el editor de diseño, pero muchos programadores prefieren trabajar directamente con el XML; por lo tanto, haga clic en la pestaña Text en la parte de abajo de la ventana para pasar al editor de texto.
  • Borre todo el contenido del fichero  e introduzca  el siguiente XML:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        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"
        android:orientation="horizontal">
    </LinearLayout>

LinearLayout es un grupo de vistas (una subclase de ViewGroup) que dispone las vistas secundarias en sentido vertical u horizontal, según lo especificado por el atributo android:orientation. Cada elemento secundario de un LinearLayout aparece en la pantalla en el orden en que aparece en XML.

Se necesitan otros dos atributos, android:layout_width y android:layout_height, para especificar el tamaño de todas las vistas.

Debido a que LinearLayout es la vista de raíz en el diseño, debería ocupar el área de la pantalla completa que está disponible para la app al establecer el ancho y el alto en "match_parent". Este valor declara que la vista debería expandir su ancho o alto para coincidir con el ancho o alto de la vista primaria.

Agregar un campo de texto

En el archivo activity_main.xml, dentro del elemento <LinearLayout>, agregue el siguiente elemento <EditText>:

<LinearLayout
    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"
    android:orientation="horizontal">


   <EditText android:id="@+id/edit_message" 
    android:layout_weight="1"
    android:layout_width="0dp" 
    android:layout_height="wrap_content"
    android:hint="@string/edit_message" />


</LinearLayout>

A continuación, se ofrece una descripción de los atributos del <EditText> que ha agregado:

  • android:id:Esto proporciona un identificador único para la vista, que puede usar para hacer referencia al objeto desde elcódigo de la app, como leer y manipular el objeto .El signo de arroba (@) se requiere cuando se hace referencia a cualquier objeto de recursos de XML y va seguido por el tipo de recursos (id en este caso), una barra diagonal y el nombre del recurso ().El signo más (+) antes del tipo de recurso se necesita solo cuando se está definiendo un ID de recurso por primera vez. Cuando compila la app, las herramientas del SDK usan el nombre del ID para crear un nuevo ID de recurso en el archivo R.java de tu proyecto que hace referencia al elemento EditText. Con el ID de recurso declarado una vez de esta forma, otras referencias al identificador no necesitan el signo más. Es necesario el uso del signo más solo cuando se especifica un nuevo ID de recurso y no se necesita para los recursos concretos, como strings o diseños. Consulta el cuadro lateral para más información sobre los objetos del recurso.
  • android:layout_width y android:layout_height:En lugar de usar tamaños específicos para el ancho y el alto, el valor "wrap_content" especifica que la vista solo debe ser lo suficientemente grande para ajustarse al contenido de la vista. Si en cambio usa "match_parent", el elemento EditText ocupará la pantalla porque coincidirá con el tamaño del elemento primario LinearLayout. Para más información, consulta la guía de Diseños.Fijar el ancho en cero (0 dp) hace que la casilla de entrada ocupe el ancho de pantalla y mejora el rendimiento del diseño, ya que el uso de "wrap_content" como ancho exige que el sistema calcule un ancho, lo cual a la larga es irrelevante porque el valor de peso requiere otro cálculo de ancho para completar el espacio restante.
  • android:hint :Esta es una string predeterminada para mostrar cuando el campo de texto esté vacío. En lugar de usar una string codificada como valor, el valor "@string/edit_message" hace referencia a un recurso de string definido en un archivo separado. Debido a que esto hace referencia a un recurso concreto (no simplemente un identificador), no necesita el signo más. Sin embargo, debido a que aún no se ha  identificado el recurso de string, aparecera  un error del compilador. Este recurso de string tiene el mismo nombre que el ID del elemento: edit_message. Sin embargo, las referencias a los recursos siempre tienen ámbitos por tipo de recurso (como id o string); por lo tanto, usar el mismo nombre no genera conflictos.

 

Agregar recursos

De manera predeterminada, en un proyecto de Android se incluye un archivo de recursos en string en  un  fichero  llamado    strings.xml ( res > values > strings.xml) .

Parar, agregar  strings nuevas al fichero strings.xml siga los siguientes pasos.

  1. Desde la ventana Project, abra res > values > strings.xml.
  2. Agregue dos strings de modo que el archivo se vea de esta forma:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="app_name">My First App</string>
        <string name="edit_message">Introduzca un mensaje</string>
        <string name="button_send">Enviar</string>
    </resources>

Para el texto en la interfaz de usuario, siempre especifique cada string como un recurso. Los recursos de strings de texto  permiten administrar todos los textos de IU en una sola ubicación, lo que hace que sea mucho  más fácil encontrar y actualizar el texto.

Externalizar las strings también  permite localizar su aplicacion ara diferentes idiomas al proporcionar definiciones alternativas para cada recurso de string.

 

Agregar un botón

Vuelva al archivo activity_main.xml y agregue un botón después del widget <EditText>.

El archivo debería tener el siguiente aspecto:

      
  <Button
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/button_send" />

Como vemos este botón no necesita el atributo android:id porque no se hará referencia a él desde el código de la actividad.

Actualmente, la configuración del diseño hace que los widgets EditText y Button tengan el tamaño necesario para ajustarse a su contenido, como se muestra a continuación

Esto funciona bien para el botón, pero no tan bien para el campo de texto porque el usuario podría escribir algo más largo. Sería bueno rellenar el ancho de la pantalla excedente con el campo de texto. Puedes hacerlo dentro de un LinearLayout con la propiedad de peso, que puedes especificar usando el atributo android:layout_weight.

El valor weight es un número que especifica la cantidad del espacio restante que cada vista debería consumir, relativo a la cantidad consumida por vistas del mismo nivel. Esto funciona como la cantidad de ingredientes en una receta de una bebida: “2 partes de refresco, 1 parte de sirope” significa que dos tercios de la bebida son de refresco. Por ejemplo, si le das a una vista un valor de weight de 2 y a otra un valor de weight de 1, la suma es 3, de manera que la primera vista completa 2/3 del espacio restante y la segunda vista completa el resto. Si agregas una tercera vista y le das un valor de weight de 1, la primera vista (con un peso de 2) ahora obtiene 1/2 del espacio restante, mientras que las dos restantes obtienen 1/4.

El valor de weight predeterminado para todas las vistas es 0, de manera que si especificas cualquier valor de weight superior a 0 para solo una vista, dicha vista completa el espacio restante después de que se asigne el espacio requerido a todas las vistas.

El resultado de modificar el  fichero   activity_main.xml, deberia ofrecer el siguiente aspecto:

 

Lo siguiente es qué apariencia debería tener el archivo de diseño activity_main.xml completo:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:orientation="horizontal"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
    <EditText android:id="@+id/edit_message"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="@string/edit_message" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_send" />
</LinearLayout>


Dar funcionalidad al  botón

Una vez hemos definido el botón  tenemos asignarle una funcionalidad, para lo cual podemos seguir los siguientes pasos:

  1. En el archivo res > layout > activity_main.xml, agrega el atributo android:onClick al elemento <Button>, como se muestra a continuación:
    <Button
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/button_send"
          android:onClick="sendMessage" />
        

    Este atributo indica al sistema que llame al método sendMessage() de tu actividad cuando un usuario haga clic en el botón.

  2. En el archivo java > com.example.myfirstapp > MainActivity.java, agregar el código auxiliar del método sendMessage() como se muestra a continuación:
    public class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        /** Called when the user clicks the Send button */
        public void sendMessage(View view) {
            // Do something in response to button
        }
    }

    Para que el sistema haga coincidir este método con el nombre del método proporcionado a android:onClick, la firma debe ser exactamente como se muestra. Específicamente, el método debe:

    • Ser público
    • Tener un valor de retorno vacío
    • Tener un objeto View como el único parámetro (esto será el View al que se le hizo clic)

Luego, completarás este método para leer el contenido del campo de texto y entregar dicho texto a otra actividad.

Crear una intent

Un Intent es un objeto que proporciona enlace de tiempo de ejecución entre componentes separados (como dos actividades) representando la “intención de hacer algo” de una app.

En el fichero MainActivity.java, agregue el código que aparece a continuación para sendMessage():

public class MainActivity extends AppCompatActivity {
    public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /** Called when the user clicks the Send button */
    public void sendMessage(View view) {
        Intent intent = new Intent(this, DisplayMessageActivity.class);
        EditText editText = (EditText) findViewById(R.id.edit_message);
        String message = editText.getText().toString();
        intent.putExtra(EXTRA_MESSAGE, message);
        startActivity(intent);
    }
}

Android Studio mostrará errores Cannot resolve symbol porque este código hace referencia a clases que no están importadas. Puede resolver algunos de estos errores con la funcionalidad de “importación de clase” de Android Studio presionando Alt + Intro (u Opción + Regresar en Mac).

Sus importados deben terminar de la siguiente forma:

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;

En sendMessage() tienen lugar muchísimos procesos. Por ello, explicaremos lo que sucede.

El constructor de Intent toma dos parámetros:

  • Un Context como su primer parámetro (se usa this porque la clase Activity es una subclase de Context)
  • La Class del componente de la app a la cual el sistema debe entregar la Intent (en este caso, la actividad que debería iniciarse).

    Nota: La referencia a DisplayMessageActivity emitirá un error en Android Studio porque la clase aún no existe. Ignora el error por ahora; pronto crearás la clase.

El método putExtra() agrega el valor de EditText a la intent. Una Intent puede llevar tipos de datos como pares clave-valor denominados extra. La clave es una EXTRA_MESSAGE constante pública porque la actividad siguiente usa la clave para devolver el valor de texto. Es bueno definir claves para los campos extra de intents usando el nombre del paquete de tu app como prefijo. Esto garantiza que las claves sean únicas, en caso de que tu app interactúe con otras apps.

El método startActivity() inicia una instancia del DisplayMessageActivity especificado por la Intent. Ahora debes crear la clase.

Crear la segunda actividad

  1. En la ventana Project, haz clic con el botón secundario en la carpeta app y selecciona New > Activity > Empty Activity.
  2. En la ventana Configure Activity, ingresa “DisplayMessageActivity” en Activity Name y haz clic en Finish

Android Studio automáticamente realiza tres acciones:

  • Crea el DisplayMessageActivity.java de la clase con una implementación del método onCreate() obligatorio.
  • Crea el archivo de diseño activity_display_message.xml correspondiente.
  • Agrega el elemento <activity> obligatorio en AndroidManifest.xml.

Si ejecutas la app y haces clic en el botón Send en la primera actividad, la segunda actividad se iniciará, pero estará vacía. Esto sucede porque la segunda actividad usa el diseño predeterminado vacío proporcionado por la plantilla.

Mostrar el mensaje

A continuación puede, modificar la segunda actividad para que muestre el mensaje que pasó la primera.

  1. En DisplayMessageActivity.java, agregue el siguiente código al método onCreate():
    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_display_message);
    
       Intent intent = getIntent();
       String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
       TextView textView = new TextView(this);
       textView.setTextSize(40);
       textView.setText(message);
    
       ViewGroup layout = (ViewGroup) findViewById(R.id.activity_display_message);
       layout.addView(textView);
    }
  2. Presione Alt + Intro (u Opción + Regresar en Mac) para importar las clases faltantes. Los importados deben tener la siguiente terminación:
    import android.content.Intent;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.ViewGroup;
    import android.widget.TextView;

Tienen lugar muchísimos procesos. Veamos la explicación:

  1. La llamada getIntent() captura la intent que inició la actividad. Toda Activity se invoca a través de una Intent, independientemente de cómo el usuario navegue hasta el punto en cuestión. La llamada getStringExtra() muestra los datos de la primera actividad.
  2. De manera programática, se crea un elemento TextView y se establece el tamaño y mensaje de este.
  3. Se agrega el elemento TextView al diseño identificado por R.id.activity_display_message. Se transmite el diseño a ViewGroup porque es la superclase de todos los diseños y contiene el método addView().

Nota: Es posible que el diseño XML generado por versiones anteriores de Android Studio no incluya el atributo android:id. La llamada findViewById() fallará si el diseño no tiene el atributo android:id. En este caso, abra el fichero  activity_display_message.xml y agregue el atributoandroid:id="@+id/activity_display_message" al elemento de diseño.

Ejecucion de  la app

Para ver el aspecto que ahora tendrá su  app en tu dispositivo, haga clic en Run en la barra de herramientas .

Cuando se abra, escriba un mensaje en el campo de texto y haga clic en Send. La segunda actividad reemplaza a la primera en la pantalla, con lo cual se mostrara el mensaje que ingresoe en la primera actividad.

Eso es todo. ¡Ha creado una  nueva app de Android!

 

Mas información en  developer.android.com