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 MainActivity. Simplemente añada TextViews y botones y restrínjalos usando el ConstraintLayout como sigue:

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 ActividadPrincipal como se indica a continuación:

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 un Toast.

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ó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 destino.
  • También añadimos las dependencias de las librerías AppCompat y de apoyo al 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 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

  1. Descargue el proyecto anterior.
  2. Obtendrás un archivo comprimido, extráelo.
  3. Abre el Android Studio.
  4. Ahora cierra, el proyecto ya abierto.
  5. Desde la barra de menú haz clic en Archivo >Nuevo> Importar proyecto.
  6. Ahora elija una Carpeta de Destino, desde donde quiere importar el proyecto.
  7. Elija un Proyecto Android.
  8. Ahora haga clic en "Aceptar".
  9. 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 un Toast.

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étodo setContentView().
  • Las vistas que utilizamos son EditTexts y buttons.
  • 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 incluimos content_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 nuestra barra 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 de android.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.

Descargar

Categorizado en:

Etiquetado en: