Información de batería (Android – XE5)
En esta entrada vamos a tratar de cómo obtener infoemación del estado de la batería de un dispositivo Android.
En algunos casos se trata como un sensor más del sistema, aunque en Delphi XE5, no se tiene en cuenta en las clases específicas para acceder a los sensores.
Sea como sea, no es más que una forma de obtener información de un aspecto más, de nuestros dispositivos.
Para acceder a la información de la batería del dispositivo vamos a hacerlo utilizando “Intents”. En Delphi podemos acceder a ellos a través de la clase JIntent, definida en la unit Androidapi.JNI.GraphicsContentViewText.
Un ejemplo de utilización de la clase JIntent, para abrir una página en el navegador o para abrir un fichero, podéis verla en esta pregunta de stackoverflow y la respuesta por parte de Rodrigo Ruz.
Un “Intent” es una forma de solicitar/pedir a nuestro dispositivo Android que necesitamos invocar a un “componente”. Un componente puede ser parte de la interfaz gráfica, un servicio, un código que se ejecuta, un “broadcast receiver” o un proveedor de contenido, por citar algunos.
Simplificando, diremos que un “intent” es una forma de interactuar con otra aplicación, ya sea para añadir datos o para pedir información. Y podemos podemos dividirlos en 2 tipos:
-
Llamada a otra aplicación.
-
Llamada a otra aplicación y esperar respuestas desde ella.
En es link, podemos acceder a la información de la clase Intent en Android. En la parte inferior están definidas las ACTIONS que podemos utilizar según categorías.
Una vez creado un “intent” lo primero que debemos hacer es definirle una o más acciones que queremos asociarle.
// Creamos y Configuramos el Intent filter := TJIntentFilter.Create; // Asociamos la ACTION que queremos capturar filter.addAction(TJIntent.JavaClass.ACTION_BATTERY_CHANGED); // lo registramos intentBatt := aContext.RegisterReceiver(nil, filter); |
Por último, en este trozo de código aparece una llamada a RegisterReceiver.
Necesitamos utilizar este método, ya que la acción ACTION_BATTERY_CHANGED, que utilizaremos, necesita registrarse para recibir notificaciones (tal como explica en la documentación).
“Broadcast Action: This is a sticky broadcast containing the charging state, level, and other information about the battery. See BatteryManager
for documentation on the contents of the Intent.”
Una vez registrado, ya podemos empezar a interrogarlo.
Si accedemos a la documentación de BatteryManager, podemos ver todos los valores por los que podemos preguntar y las constantes necesarias para hacerlo. Para ello utilizaremos un código como el que se ve a continuación:
// health i := intentBatt.getIntExtra(StringToJString('health'), -1); Memo1.Lines.Add('Salut: ' + BateryHealthStr[i]); // Icon // i := battery.getIntExtra(StringToJString('icon-smal'), -1); // Memo1.Lines.Add('icon-smal: ' + IntToStr(i)); // Nivel de batería iLevel := intentBatt.getIntExtra(StringToJString('level'), -1); Memo1.Lines.Add('Level: ' + IntToStr(iLevel)); // Plugged i := intentBatt.getIntExtra(StringToJString('plugged'), -1); Memo1.Lines.Add('Enchufado: ' + BateryPluggedStr[i]); // battery present b := intentBatt.getBooleanExtra(StringToJString('present'), False); Memo1.Lines.Add('Presente: ' + BoolToStr(b, True)); // Escala para medir el nivel iScale := intentBatt.getIntExtra(StringToJString('scale'), -1); Memo1.Lines.Add('Escala: ' + IntToStr(iScale)); // status de la batería i := intentBatt.getIntExtra(StringToJString('status'), -1); Memo1.Lines.Add('Estado: ' + BateryStatusStr[i]); // tecnología de la batería Str := intentBatt.getStringExtra(StringToJString('technology')); Memo1.Lines.Add('Tecnología: ' + JStringToString(Str)); // Temperatura (en décimas de grado) i := intentBatt.getIntExtra(StringToJString('temperature'), -1); Memo1.Lines.Add('Temperatura: ' + FloatToStr(i / 10) + '°'); // Voltage (en MILIVOLTIOS) i := intentBatt.getIntExtra(StringToJString('voltage'), -1); Memo1.Lines.Add('Voltaje: ' + FloatToStr(i/1000) + ' v.'); |
Antes de acabar, hacer referencia a la línea que obtiene el contexto de la aplicación, que utiliza la función SharedActivityContext, y que está definida en la unit FMX.Helpers.Android.
// Contexto myContext := SharedActivityContext; |
He generado un formulario para poder visualizar los valores que se obtienen de cada una de las constantes.
En la documentación además podemos encontrar que para obtener el nivel de batería (Level) tenemos que tener en cuenta el valor de Scale.
El valor de la temperatura se expresa en grados celsius y viene en décimas de grado.
Y por último, el voltaje de la batería viene expresado en milivoltios.
Os dejo el código fuente del proyecto y el instalable para Android (apk).
Un pequeño vídeo de la aplicación corriendo en mi teléfono.
Finalmente, aunque no tenga que ver expresamente con este tema, al generar la aplicación para un dispositivo, he tenido que completar algunos pasos finales.
Desde las opciones del proyecto, podemos seleccionar, de forma similar a como se hace en las aplicaciones de escritorio, el icono (en las diferentes resoluciones) que va a tener nuestra aplicación.
También desde la configuración, las diferentes orientaciones que va a admitir nuestra aplicación cuando se ejecute en los dispositivos.
Un saludo y hasta la próxima.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
Hola,
He llegado a esta entrada buscando otra cosa pero mira tú por dónde no hay mala búsqueda que por bien no venga. :)
¡Gracias Germán!
Hola David.
Ya he visto que has añadido a los componentes la clase para el acceso a la información de la batería.
Fantástico. ;-)
________________
Germán
Hola Germán.
Sé que tiene tiempo este post, pero ando revisando y no encuentro nada parecido.
¿Sería posible controlar cuando se dispara la cámara integrada del teléfono (ya sea delantera o trasera) y obtener la fotografía que acaba de realizar? No se si con Delphi XE5, XE6 o XE7 podría realizar algo así.
Sé que podría hacerlo con la aplicación que estoy desarrollando pero lo que quiero es lo contrario que el usuario saque las fotos normalmente entrando directamente en la cámara y no en mi aplicación.
Gracias por tu blog y por todo de ante mano.
Saludos,
Enrique.
@Enrique
Tal vez revisando el directorio donde se almacenan. No se si puedes capturarlas directamente cuando se hacen.
@Germán Estévez
Estuve mirando y revisando y creo que he encontrado algo que me puede servir: ACTION_NEW_PICTURE lo probaré y te diré pero gracias de todos modos!
Hi
Thanks for this post, if i use this function in a android service what i should use for aContext?