AlarmManager
es una clase que nos permite crear alarmas. Las alarmas permiten a nuestras apps programar códigos específicos para que se ejecuten en determinados momentos en el futuro.
public class AlarmManager extends Object{}
Es mejor y más eficiente usar la clase AlarmManager
para crear alarmas para programar que usar algo como un temporizador.
AlarmManager
nos proporciona el acceso a los servicios de alarma del sistema, así que no es que vayamos a inventar nuestros algoritmos de programación.
AlarmManager
se utiliza principalmente junto con BroadcastReceivers
. Así es como funciona:
*La primera alarma se dispara o suena.
- El sistema emite una "intención". Este es el
intent
que ha sido registrado para ello. - Esto inicia automáticamente la aplicación de destino en caso de que no se esté ejecutando.
- Si el dispositivo duerme, las alarmas que ya están registradas se conservan.
- Si la alarma se dispara mientras el dispositivo está durmiendo, entonces el dispositivo se despierta. Esto es opcional.
- Si el usuario apaga el dispositivo o lo reinicia, las alarmas se borran.
Se garantiza que el teléfono no dormirá hasta que haya terminado de manejar su emisión. Las transmisiones son manejadas por el método onReceive()
del android.content.BroadcastReceiver
. Este es un método que se anula después de derivar esta clase.
Mientras el método onReceive()
se esté ejecutando, el AlarmManager
mantendrá un bloqueo de la CPU. Así que el dispositivo no dormirá.
Entonces el AlarmManager
libera el bloqueo de vigilia cuando el método onReceive()
termina de ejecutarse y regresa.
Pero a veces, justo cuando el método onReceive()
termina, es posible que el teléfono se duerma inmediatamente. Debido a que el dispositivo ha dormido rápidamente, si has solicitado un servicio usando el Context.startService()
no se iniciará. Esto es porque el dispositivo ha dormido antes de ser llamado. Sin embargo, el bloqueo inicial de la vigilia ya no existe. Ha sido liberado en el momento en que la función onReceive()
ha regresado. Entonces, ¿cuál es la solución? Bueno, implementa un bloqueo de activación separado en tu BroadcastReceiver
y Service
. Este bloqueo de activación asegurará que el dispositivo se ejecute hasta que el servicio esté disponible.
Así que, ¿cuándo debes usar AlarmManager
y cuándo no? Utiliza AlarmManager
para programar operaciones. No lo utilices para operaciones de temporización y tic-tac. Y no uses temporizadores para operaciones de programación. El código programado que utiliza el AlarmManager
no requiere que la aplicación se ejecute todo el tiempo. Si utilizas un temporizador entonces tendría que ejecutarse todo el tiempo. Esto desperdicia memoria y tiempo de procesamiento.
El sistema operativo Android desplaza las alarmas para que minimicemos los despertares y el uso de la batería. Esto es a partir de Android API 19(KitKat). Esto las alarmas pueden no ser estrictamente exactas. Si necesitas que sean estrictamente exactas, entonces puedes usar el método setExact()
.
El AlarmManager
no se instala directamente. En su lugar se utiliza el método estático getSystemService()
de la clase Context
. Se pasa la bandera Context.ALARM_SERVICE
.
Context.getSystemService(Context.ALARM_SERVICE
Ejemplo 1: Kotlin Android Build an Alarm Clock
Este es un ejemplo para enseñar el uso de Alarmas y Broadcastreceiver. En el proceso se construye un simple reloj de alarma. Este ejemplo te permite aprender estas tecnologías de forma práctica.
Paso 1: Crear un proyecto Kotlin
Comienza creando un proyecto Kotlin vacío en Android Studio.
Paso 2: Dependencias
No se necesitan dependencias especiales. Sin embargo, debido a que se utilizan Coroutines, asegúrese de utilizar Kotlin.
Paso 3: Permisos
No se necesitan permisos para este proyecto. Sin embargo en tu en AndroidManifest.xml
, asegúrate de registrar el receptor
ya que se utiliza BroadcastReceiver
en este despertador.
<receiver
android:name=".AlarmReceiver"
android:exported="false" />
Paso 4: Diseñar el layout
Sólo necesitas un diseño, el diseño
como sigue:MainActivity
. Simplemente añada TextViews y botones y restrínjalos usando el
ConstraintLayout
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background_black"
tools:context=".MainActivity">
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginHorizontal="50dp"
android:background="@drawable/background_white_ring"
app:layout_constraintBottom_toTopOf="@id/onOffButton"
app:layout_constraintDimensionRatio="H,1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/timeTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="09:30"
android:textColor="@color/white"
android:textSize="50sp"
app:layout_constraintBottom_toTopOf="@id/ampmTextView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="@+id/ampmTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="AM"
android:textColor="@color/white"
android:textSize="25sp"
app:layout_constraintBottom_toTopOf="@id/onOffButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/timeTextView" />
<Button
android:id="@+id/onOffButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/on_alarm"
app:layout_constraintBottom_toTopOf="@id/changeAlarmTimeButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/changeAlarmTimeButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/change_time"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Paso 5: Crear la clase modelo
Crear una clase modelo, clase de datos Kotlin que recibe los dos enteros y un booleano a través del constructor
. Los enteros son la hora y el minuto mientras que el booleano es un swicth de encendido y apagado. Estos se utilizarán para construir una vista del temporizador que se mostrará en el reloj de alarma:
AlarmDisplayModel.kt
package com.example.alarmclock
data class AlarmDisplayModel(
val hour: Int,
val minute: Int,
var onOff: Boolean
) {
val timeText: String
get() {
val h = "%02d".format(if (hour < 12) hour else hour - 12)
val m = "%02d".format(minute)
return "$h:$m"
}
val ampmText: String
get() {
return if (hour < 12) "AM" else "PM"
}
val onOffText: String
get() {
return if (onOff) "알람 끄기" else "알람 켜기"
}
fun makeDataForDB(): String {
return "$hour:$minute"
}
}
Paso 5: Crear un Receptor de alarma
.
Esto se hace extendiendo el broadcast receiver
y sobrescribiendo el método onReceive()
. Dentro de onReceive()
crearás un canal de notificación así como construirás una notificación.
Aquí está el código completo:
AlarmReceiver.kt
package com.example.alarmclock
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
class AlarmReceiver: BroadcastReceiver() {
companion object {
const val NOTIFICATION_ID = 100
const val NOTIFICATION_CHANNEL_ID = "1000"
}
override fun onReceive(context: Context, intent: Intent) {
createNotificationChannel(context)
notifyNotification(context)
}
private fun createNotificationChannel(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"기상 알람",
NotificationManager.IMPORTANCE_HIGH
)
NotificationManagerCompat.from(context).createNotificationChannel(notificationChannel)
}
}
private fun notifyNotification(context: Context) {
with(NotificationManagerCompat.from(context)) {
val build = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setContentTitle("알람")
.setContentText("일어날 시간입니다.")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setPriority(NotificationCompat.PRIORITY_HIGH)
notify(NOTIFICATION_ID, build.build())
}
}
}
Paso 6: Creación de la Actividad principal
.
Finalmente crea tu
como se indica a continuación:ActividadPrincipal
MainActivity.kt
package com.example.alarmclock
import android.app.AlarmManager
import android.app.PendingIntent
import android.app.TimePickerDialog
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import java.util.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initOnOffButton()
initChangeAlarmTimeButton()
val model = fetchDataFromSharedPreferences()
renderView(model)
}
private fun initOnOffButton() {
val onOffButton = findViewById<Button>(R.id.onOffButton)
onOffButton.setOnClickListener {
val model = it.tag as? AlarmDisplayModel ?: return@setOnClickListener
val newModel = saveAlarmModel(model.hour, model.minute, model.onOff.not())
renderView(newModel)
if (newModel.onOff) {
// 켜진 경우 -> 알람을 등록
val calendar = Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, newModel.hour)
set(Calendar.MINUTE, newModel.minute)
if (before(Calendar.getInstance())) {
add(Calendar.DATE, 1)
}
}
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(this, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this, ALARM_REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT)
alarmManager.setInexactRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
} else {
cancelAlarm()
}
}
}
private fun initChangeAlarmTimeButton() {
val changeAlarmButton = findViewById<Button>(R.id.changeAlarmTimeButton)
changeAlarmButton.setOnClickListener {
val calendar = Calendar.getInstance()
TimePickerDialog(this, { picker, hour, minute ->
val model = saveAlarmModel(hour, minute, false)
renderView(model)
cancelAlarm()
}, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), false).show()
}
}
private fun saveAlarmModel(
hour: Int,
minute: Int,
onOff: Boolean
): AlarmDisplayModel {
val model = AlarmDisplayModel(
hour = hour,
minute = minute,
onOff = onOff
)
val sharedPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
with(sharedPreferences.edit()) {
putString(ALARM_KEY, model.makeDataForDB())
putBoolean(ONOFF_KEY, model.onOff)
commit()
}
return model
}
private fun fetchDataFromSharedPreferences():AlarmDisplayModel {
val sharedPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
val timeDBValue = sharedPreferences.getString(ALARM_KEY, "9:30") ?: "9:30"
val onOffDBValue = sharedPreferences.getBoolean(ONOFF_KEY, false)
val alarmData = timeDBValue.split(":")
val alarmModel = AlarmDisplayModel(
hour = alarmData[0].toInt(),
minute = alarmData[1].toInt(),
onOff = onOffDBValue
)
// 보정 보정 예외처리
val pendingIntent = PendingIntent.getBroadcast(this, ALARM_REQUEST_CODE, Intent(this, AlarmReceiver::class.java), PendingIntent.FLAG_NO_CREATE)
if ((pendingIntent == null) and alarmModel.onOff) {
// 알람은 꺼져있는데, 데이터는 켜저있는 경우
alarmModel.onOff = false
} else if ((pendingIntent != null) and alarmModel.onOff.not()){
// 알람은 켜져있는데, 데이터는 꺼져있는 경우
// 알람을 취소함
pendingIntent.cancel()
}
return alarmModel
}
private fun renderView(model: AlarmDisplayModel) {
findViewById<TextView>(R.id.ampmTextView).apply {
text = model.ampmText
}
findViewById<TextView>(R.id.timeTextView).apply {
text = model.timeText
}
findViewById<Button>(R.id.onOffButton).apply {
text = model.onOffText
tag = model
}
}
private fun cancelAlarm() {
val pendingIntent = PendingIntent.getBroadcast(this, ALARM_REQUEST_CODE, Intent(this, AlarmReceiver::class.java), PendingIntent.FLAG_NO_CREATE)
pendingIntent?.cancel()
}
companion object {
private const val SHARED_PREFERENCES_NAME = "time"
private const val ALARM_KEY = "alarm"
private const val ONOFF_KEY = "onOff"
private const val ALARM_REQUEST_CODE = 1000
}
}
Paso 7: Ejecutar
Finalmente ejecute el proyecto.
Referencia
Aquí están los enlaces de referencia del código:
Número | Enlace |
---|---|
1. | Descargar código |
2. | Seguir al autor del código |
Ejemplo 2: Cómo iniciar una alarma
Una de esas aplicaciones de software similares a las de los móviles es la Alarma. O cualquier aplicación que pueda programar algo para que ocurra en el futuro. Esto es aún más importante en los dispositivos móviles que en las aplicaciones de escritorio.
Porque nunca dejamos o apagamos nuestros dispositivos móviles. Son nuestros asistentes personales. Así que los usamos de forma más personal de lo que haríamos con las aplicaciones de escritorio.
Así que Android nos proporciona una clase rica llamada AlarmManager
. Una clase que nos permite acceder a los servicios del sistema. La clase es obviamente pública y deriva de java.lang.Object
.
Esta es su definición:
public class AlarmManager extends Object{}
¿Qué construimos?
Bien, veamos un simple ejemplo de android AlarmManager
. Vemos como iniciar y cancelar una alarma en android. Tenemos un texto de edición básico. El usuario introduce el tiempo en milisegundos para que suene la alarma. La alarma suena mostrando un simple mensaje Toast
.
Estructura del proyecto
Esta es la estructura del proyecto:
Paso 1 - Crear el proyecto Android
- En tu android studio ve a Archivo -- Nuevo -- Nuevo Proyecto.
- Escriba el nombre del proyecto.
- Elija el sdk mínimo.
- De las plantillas elija actividad vacía o bla.
Paso 2. - Vamos a modificar nuestro build.gradle
.
Este es nuestro segundo paso. Los proyectos Android creados en android studio tienen dos archivos buil.gradle
. Estamos interesados en el nivel de aplicación build.gradle
.
Añade el siguiente código en la sección de dependencias:
implementation 'com.android.support:appcompat-v7:24.2.1'
implementation 'com.android.support:design:24.2.1'
Hemos añadido dos dependencias de la biblioteca de soporte: AppCompat
y design
.
Paso 3. Preparemos nuestros recursos.
El único recurso que necesitamos preparar en este caso son los diseños. He elegido la actividad básica como plantilla. Así que tengo dos diseños:
- activity_main.xm : diseño de la plantilla
- content_main.xml : esto es lo que modificamos.
Todo lo que necesito es añadir un texto de edición y un botón. El edittext donde el usuario introducirá el tiempo en segundos y el botón de inicio para iniciar la alarma.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_paddingBottom="@dimen/activity_vertical_margin"
android_paddingLeft="@dimen/activity_horizontal_margin"
android_paddingRight="@dimen/activity_horizontal_margin"
android_paddingTop="@dimen/activity_vertical_margin"
app_layout_behavior="@string/appbar_scrolling_view_behavior"
tools_context="com.tutorials.hp.alarmmanagerstarter.MainActivity"
tools_showIn="@layout/activity_main">
<EditText
android_id="@+id/timeTxt"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignParentLeft="true"
android_layout_alignParentTop="true"
android_layout_marginTop="28dp"
android_ems="10"
android_hint="Number of seconds"
android_inputType="numberDecimal" />
<Button
android_id="@+id/startBtn"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignRight="@+id/timeTxt"
android_layout_below="@+id/timeTxt"
android_layout_marginRight="60dp"
android_layout_marginTop="120dp"
android_text="Start" />
</RelativeLayout>
Paso 4. Vamos a crear nuestra clase BroadcastReceiver
.
Un BroadcastReceiver
es uno de los componentes de android. Otros incluyen Activity
, Service
y ContentProvider
.
Un BroadcastReceiver
escucha los eventos del sistema.
En realidad es una clase abstracta que es obviamente pública. Deriva de java.lang.Object
:
public abstract class BroadcastReceiver extends Object{}
Los intentos enviados por el sendBroadcast()
serán recibidos por esta clase base.
Es una clase abstracta por lo que anularemos el método onReceive()
.
Primero crea una clase java :
public class MyReceiver{}
Añade los siguientes imports:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
Haz que derive de android.content.BroadcastReceiver
:
public class MyReceiver extends BroadcastReceiver {}
Esto nos obligará a omitir el método onReceive()
:
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm Ringing...", Toast.LENGTH_SHORT).show();
}
Paso 5. Vamos a nuestra clase MainActivity
.
Las actividades son componentes androides que representan una interfaz de usuario. Creamos actividades derivando de una actividad. Para soportar más dispositivos usamos AppCompatActivity
.
Así que vamos a crear una actividad:
public class MainActivity extends AppCompatActivity {}
Añade los siguientes imports encima de la actividad:
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
Nuestra actividad tendrá tres métodos y dos campos:
Primero definimos nuestros dos campos: básicamente un botón un edittext. Añádelos dentro de la clase MainActivity
:
Button startBtn;
EditText timeTxt;
Luego creamos un método go()
. Este método se encargará de inicializar nuestro AlarmManager
y de iniciar la alarma:
private void go()
{
//GET TIME IN SECONDS AND INITIALIZE INTENT
int time=Integer.parseInt(timeTxt.getText().toString());
Intent i=new Intent(this,MyReceiver.class);
//PASS CONTEXT,YOUR PRIVATE REQUEST CODE,INTENT OBJECT AND FLAG
PendingIntent pi=PendingIntent.getBroadcast(this,0,i,0);
//INITIALIZE ALARM MANAGER
AlarmManager alarmManager= (AlarmManager) getSystemService(ALARM_SERVICE);
//SET THE ALARM
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+(time*1000),pi);
Toast.makeText(MainActivity.this, "Alarm set in "+time+" seconds", Toast.LENGTH_SHORT).show();
}
Luego venimos a crear otro método para inicializar nuestro botón y edittext y manejar el onclick listener del botón:
private void initializeViews()
{
timeTxt= (EditText) findViewById(R.id.timeTxt);
startBtn= (Button) findViewById(R.id.startBtn);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
go();
}
});
}
Paso 6. Comprobemos el AndroidManifest
.
Revisa el androidmanifest.xml
. Queremos asegurarnos de que nuestra clase BroadcastReceiver
está registrada dentro de nuestro manifiesto.
Puedes ver que nuestra clase broadcastreceiver
está registrada:
<receiver android_name="MyReceiver" >
</receiver>
Esto es lo que tengo:
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="com.tutorials.hp.alarmmanagerstarter">
<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"
android_label="@string/app_name"
android_theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android_name="android.intent.action.MAIN" />
<category android_name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android_name="MyReceiver" >
</receiver>
</application>
</manifest>
Ejemplo: Android AlarmManager
- Programar la visualización de Toast
Los ingenieros de Android añadieron la clase AlarmManager
en el nivel 1 de la API, por lo que ha existido desde el principio de android. Esta clase permite programar operaciones que se harán en algún momento en el futuro. Con AlarmManager
, puedes establecer un código que se ejecutará en el futuro.
Esto es genial, ya que no es necesario que tu aplicación se esté ejecutando para que ese código se ejecute. Por supuesto, tu aplicación se iniciará, pero sólo en el momento registrado. Alarm Maanager pertenece al paquete android.app y hereda de java.lang.Object.
Incluso mientras el dispositivo está dormido, las alarmas se conservan mientras estén registradas. Puedes encontrar más detalles sobre AlarmManager
aquí.
Captura de pantalla
- Aquí está la captura de pantalla del proyecto.
Preguntas comunes que explora este ejemplo
- Cómo usar el
AlarmManager
de android. - ¿Qué es
AlarmManager
? - ¿Cómo programar el trabajo a realizar en el futuro en android?
- Ejemplo fácil de
AlarmManager
con unToast
.
Herramientas utilizadas
Este ejemplo fue escrito con las siguientes herramientas:
- Windows 8
- AndroidStudio IDE
- Emulador Genymotion
Código fuente
Vamos a saltar directamente al código fuente.
Build.Gradle
- Normalmente en los proyectos android, hay dos archivos
build.gradle
. Uno es el nivel de aplicaciónbuild.gradle
, el otro es el nivel de proyectobuild.gradle
. El nivel de aplicación pertenece dentro de la carpeta de la aplicación y es donde normalmente añadimos nuestras dependencias y especificamos los sdks de compilación y destino. - También añadimos las dependencias de las librerías
AppCompat
y de apoyo al diseño. - Nuestra
MainActivity
derivará deAppCompatActivity
mientras que también utilizaremosFloatingActionButton
de las bibliotecas de soporte de diseño.
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "25.0.1"
defaultConfig {
applicationId "com.tutorials.hp.alarmmanagerstarter"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
implementation 'com.android.support:appcompat-v7:24.2.1'
implementation 'com.android.support:design:24.2.1'
}
MyReceiver.java"
- Nuestra clase
Broadcast Receiver
. - Hacerla extender android.app.content.BroadCastReceiver.
- Luego anulamos el método
OnReceive()
. Aquí es donde escribimos el código que se ejecutará cuando suene la alarma. - En este caso simplemente mostramos un mensaje
Toast
.
package com.tutorials.hp.alarmmanagerstarter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
/*
RING ALARM WHEN IN WHEN WE RECEIVE OUR BROADCAST
*/
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm Ringing...", Toast.LENGTH_SHORT).show();
}
}
MainActivity
.java
- Actividad de lanzamiento.
ActivityMain.xml
inflado como el contentview para esta actividad.- Inicializamos las vistas y los widgets dentro de esta actividad.
- También inicializamos e iniciamos nuestra alarma dentro de aquí usando el objeto
AlarmManager
.
package com.tutorials.hp.alarmmanagerstarter;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
Button startBtn;
EditText timeTxt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initializeViews();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
/*
INITIALIZE VIEWS
*/
private void initializeViews()
{
timeTxt= (EditText) findViewById(R.id.timeTxt);
startBtn= (Button) findViewById(R.id.startBtn);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
go();
}
});
}
/*
INITIALIZE AND START OUR ALARM
*/
private void go()
{
//GET TIME IN SECONDS AND INITIALIZE INTENT
int time=Integer.parseInt(timeTxt.getText().toString());
Intent i=new Intent(this,MyReceiver.class);
//PASS CONTEXT,YOUR PRIVATE REQUEST CODE,INTENT OBJECT AND FLAG
PendingIntent pi=PendingIntent.getBroadcast(this,0,i,0);
//INITIALIZE ALARM MANAGER
AlarmManager alarmManager= (AlarmManager) getSystemService(ALARM_SERVICE);
//SET THE ALARM
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+(time*1000),pi);
Toast.makeText(MainActivity.this, "Alarm set in "+time+" seconds", Toast.LENGTH_SHORT).show();
}
}
ActivityMain.xml
- Diseño de la plantilla.
- Contiene nuestro ContentMain.xml.
- También define el appbarlayout, la barra de herramientas así como el buttton de floatingaction.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_fitsSystemWindows="true"
tools_context="com.tutorials.hp.alarmmanagerstarter.MainActivity">
<android.support.design.widget.AppBarLayout
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android_id="@+id/toolbar"
android_layout_width="match_parent"
android_layout_height="?attr/actionBarSize"
android_background="?attr/colorPrimary"
app_popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
android_id="@+id/fab"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_gravity="bottom|end"
android_layout_margin="@dimen/fab_margin"
android_src="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
ContentMain.xml
- Diseño del contenido.
- Define las vistas y widgets que se mostrarán dentro de la
MainActivity
.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_paddingBottom="@dimen/activity_vertical_margin"
android_paddingLeft="@dimen/activity_horizontal_margin"
android_paddingRight="@dimen/activity_horizontal_margin"
android_paddingTop="@dimen/activity_vertical_margin"
app_layout_behavior="@string/appbar_scrolling_view_behavior"
tools_context="com.tutorials.hp.alarmmanagerstarter.MainActivity"
tools_showIn="@layout/activity_main">
<EditText
android_id="@+id/timeTxt"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignParentLeft="true"
android_layout_alignParentTop="true"
android_layout_marginTop="28dp"
android_ems="10"
android_hint="Number of seconds"
android_inputType="numberDecimal" />
<Button
android_id="@+id/startBtn"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignRight="@+id/timeTxt"
android_layout_below="@+id/timeTxt"
android_layout_marginRight="60dp"
android_layout_marginTop="120dp"
android_text="Start" />
</RelativeLayout>
Cómo ejecutar
- Descargue el proyecto anterior.
- Obtendrás un archivo comprimido, extráelo.
- Abre el Android Studio.
- Ahora cierra, el proyecto ya abierto.
- Desde la barra de menú haz clic en Archivo >Nuevo> Importar proyecto.
- Ahora elija una Carpeta de Destino, desde donde quiere importar el proyecto.
- Elija un Proyecto Android.
- Ahora haga clic en "Aceptar".
- Listo, ya has terminado de importar el proyecto, ahora edítalo.
Conclusión.
Hemos visto un simple ejemplo de android AlarmManager
.
Ejemplo: Programar Alarmas Repetitivas/Recurrentes en Android
El AlarmManager
ha existido desde el principio de Android. Nos permite programar tareas que se harán en algún momento en el futuro.
Con AlarmManager
, puedes establecer un código que se ejecutará en el futuro.
AlarmManager pertenece al paquete android.app
y hereda de java.lang.Object
. Incluso cuando el dispositivo está dormido, las alarmas se conservan siempre que se hayan registrado. En este ejemplo veremos cómo trabajar con alarmas recurrentes/repetitivas.
Programaremos la visualización de mensajes Toast
después de un número determinado de segundos. Por ejemplo, si el usuario introduce 5 en el edittexts
y pulsa el botón de inicio, cada 5 segundos se mostrará el mensaje Toast
hasta que el usuario pulse el botón de cancelación para anular las alarmas. Así que vemos cómo empezar a repetir las alarmas y cancelarlas. Puedes encontrar más detalles sobre el AlarmManager
aquí.
Preguntas comunes que este ejemplo explora
- Cómo usar el
AlarmManager
de android. - Cómo establecer alarmas repetitivas/recurrentes en android y cancelarlas.
- Cómo iniciar y cancelar alarmas en android.
- ¿Cómo programar el trabajo a realizar en el futuro en android?
- Ejemplo fácil de
AlarmManager
recurrente con unToast
.
Herramientas utilizadas
Este ejemplo fue escrito con las siguientes herramientas:
- Windows 8
- AndroidStudio IDE
- Emulador Genymotion
- Lenguaje : Java
- Tema : Alarmas Recurrentes Android,
AlarmManager
, Iniciar Cancelar Repetición de alarmas
Librerías utilizadas
- No utilizamos ninguna librería de tercera parte.
Código fuente
Vamos a saltar directamente al código fuente.
Build.Gradle
Normalmente en los proyectos android, hay dos archivos build.gradle
. Uno es el nivel de aplicación build.gradle
, el otro es el nivel de proyecto build.gradle
. El nivel de aplicación pertenece dentro de la carpeta de la aplicación y es donde normalmente añadimos nuestras dependencias y especificamos los sdks de compilación y de destino.
También se añaden las dependencias para AppCompat
y las librerías de soporte de diseño.
Nuestra MainActivity
derivará de AppCompatActivity
mientras que también utilizaremos FloatingActionButton
de las bibliotecas de soporte de diseño.
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "com.tutorials.hp.repeatingalarm"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidtestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'com.android.support:appcompat-v7:26.+'
implementation 'com.android.support.constraint:constraint-layout:1.0.0-alpha7'
implementation 'com.android.support:design:26.+'
testImplementation 'junit:junit:4.12'
}
MyReceiver.java
- Nuestra clase
MyReceiver
. - Deriva de
android.content.BroadcastReceiver
. - Sobrescribimos el método
onReceive()
y realizamos aquí la tarea a realizar cuando suene la alarma.
package com.tutorials.hp.repeatingalarm;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
/*
RING ALARM WHEN IN WHEN WE RECEIVE OUR BROADCAST
*/
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm Ringing...", Toast.LENGTH_SHORT).show();
}
}
MainActivity
.java
- Nuestra clase
MainActivity
. - Deriva de
AppCompatActivity
que es una clase base para las actividades que utilizan las características de la barra de acción de la biblioteca de soporte. - Métodos:
onCreate()
,initializeViews()
,initializeAlarmManager()
,go()
. - Inflado desde
activity_main.xml
usando el métodosetContentView()
. - Las vistas que utilizamos son
EditTexts
ybuttons
. - Haz referencia a ellas desde nuestra especificación de diseño usando
findViewById()
. - Inicializar el
AlarmManager
. - Iniciar la alarma usando
setInExactRepeating()
.
package com.tutorials.hp.repeatingalarm;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
Button startBtn,cancelBtn;
EditText timeTxt;
AlarmManager alarmManager;
PendingIntent pi;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initializeViews();
initializeAlarmManager();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
go();
}
});
}
/*
INITIALIZE VIEWS
*/
private void initializeViews()
{
timeTxt= (EditText) findViewById(R.id.timeTxt);
startBtn= (Button) findViewById(R.id.startBtn);
cancelBtn= (Button) findViewById(R.id.cancelBtn);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
go();
}
});
cancelBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(alarmManager != null)
{
alarmManager.cancel(pi);
}
}
});
}
/*
INITIALIZE AND START OUR ALARM
*/
private void initializeAlarmManager()
{
// INITIALIZE INTENT
Intent intent=new Intent(this,MyReceiver.class);
//PASS CONTEXT,YOUR PRIVATE REQUEST CODE,INTENT OBJECT AND FLAG
pi= PendingIntent.getBroadcast(this,0,intent,0);
//INITIALIZE ALARM MANAGER
alarmManager= (AlarmManager) this.getSystemService(ALARM_SERVICE);
}
/*
START OUR ALARM
*/
private void go()
{
//GET TIME IN SECONDS
int time=Integer.parseInt(timeTxt.getText().toString());
//SET THE ALARM
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+(time*1000),time*1000,pi);
Toast.makeText(MainActivity.this, "Alarm set in "+time+" seconds", Toast.LENGTH_SHORT).show();
}else
{
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME,System.currentTimeMillis()+(time*1000),time*1000,pi);
Toast.makeText(MainActivity.this, "Yes Alarm set in "+time+" seconds", Toast.LENGTH_SHORT).show();
}
}
}
ActivityMain.xml
Esta es una plantilla de diseño para nuestra MainActivity
. Nuestra etiqueta de diseño raíz es CoordinatorLayout
. El CoordinatorLayout
es un viewgroup que es un superpowered en framelayout.
CoordinatorLayout
está pensado para dos casos de uso principales: Como una decoración de la aplicación de nivel superior o diseño de cromo Como un contenedor para una interacción específica con una o más vistas de los niños- Dentro de nuestro
CoordinatorLayout
añadimos:AppBarLayout
, FloatingActionButton e incluimoscontent_main.xml
. - El
AppBarLayout
es un LinearLayout vertical que implementa las características de desplazamiento del concepto material design. - Debe ser un hijo directo de
CoordinatorLayout
, de lo contrario muchas características no funcionarán. - Dentro del
AppBarLayout
añadimos nuestrabarra de herramientas
, a la que damos un color azul. - Añadiremos nuestros widgets en nuestro
content_main.xml
, no aquí ya que este es un diseño de plantilla. - Finalmente tenemos un
FloatingActionButton
, una clase que deriva deandroid.support.design.widget.VisibilityAwareImageButton
. Es el botón redondo que ves en nuestra interfaz de usuario.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
tools_context="com.tutorials.hp.repeatingalarm.MainActivity">
<android.support.design.widget.AppBarLayout
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android_id="@+id/toolbar"
android_layout_width="match_parent"
android_layout_height="?attr/actionBarSize"
android_background="?attr/colorPrimary"
app_popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
android_id="@+id/fab"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_gravity="bottom|end"
android_layout_margin="@dimen/fab_margin"
app_srcCompat="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
ContentMain.xml
- Nuestro archivo
ContentMain.xml
. - Se inflará a
MainActivity
. - La etiqueta raíz es
ConstraintLayout
. - Contiene
EditTexts
y dos botones. - El usuario introducirá el número de segundos después de que la alarma suene en el texto de edición.
- Luego haga clic en el botón de inicio para iniciar la alarma.
- Y el botón Cancelar para cancelar la alarma.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
app_layout_behavior="@string/appbar_scrolling_view_behavior"
tools_context="com.tutorials.hp.repeatingalarm.MainActivity"
tools_showIn="@layout/activity_main">
<LinearLayout
android_layout_width="368dp"
android_layout_height="327dp"
android_orientation="vertical"
app_layout_constraintTop_toTopOf="parent"
android_layout_marginTop="8dp">
<EditText
android_id="@+id/timeTxt"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignParentLeft="true"
android_layout_alignParentTop="true"
android_ems="10"
android_hint="Number of seconds"
android_inputType="numberDecimal"
/>
<Button
android_id="@+id/startBtn"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_alignRight="@+id/timeTxt"
android_layout_below="@+id/timeTxt"
android_text="Start"
/>
<Button
android_id="@+id/cancelBtn"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_alignRight="@+id/timeTxt"
android_layout_below="@+id/timeTxt"
android_text="Cancel"
/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
Video/Preview
- Tenemos un canal de YouTube con casi mil tutoriales, siendo este de abajo uno de ellos.
https://www.youtube.com/watch?v=23Gw-11JFqc
Descarga
- Puedes descargar el proyecto completo a continuación. El código fuente está bien comentado.