Пример диспетчера аварий

Я хочу реализовать функцию расписания в моем проекте. Так что я гуглил для программы Alarm Manager, но не могу найти никаких примеров.

Может кто-нибудь помочь мне с базовой программой диспетчера тревоги?

11 ответов

Это рабочий код. Процессор включается каждые 10 минут, пока телефон не выключится.

Добавить в Manifest.xml:

...
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
...
<receiver android:process=":remote" android:name=".Alarm"></receiver>
...

Код в вашем классе:

package yourPackage;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.widget.Toast;

public class Alarm extends BroadcastReceiver 
{    
    @Override
    public void onReceive(Context context, Intent intent) 
    {   
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
        wl.acquire();

        // Put here YOUR code.
        Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_LONG).show(); // For example

        wl.release();
    }

    public void setAlarm(Context context)
    {
        AlarmManager am =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent(context, Alarm.class);
        PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
        am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 10, pi); // Millisec * Second * Minute
    }

    public void cancelAlarm(Context context)
    {
        Intent intent = new Intent(context, Alarm.class);
        PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        alarmManager.cancel(sender);
    }
}

Установить сигнал тревоги от службы:

package yourPackage;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;

public class YourService extends Service
{
    Alarm alarm = new Alarm();
    public void onCreate()
    {
        super.onCreate();       
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
    {
        alarm.setAlarm(this);
        return START_STICKY;
    }

   @Override        
   public void onStart(Intent intent, int startId)
    {
        alarm.setAlarm(this);
    }

    @Override
    public IBinder onBind(Intent intent) 
    {
        return null;
    }
}

Если вы хотите установить повтор будильника во время загрузки телефона:

Добавьте разрешение и сервис в Manifest.xml:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
...
<receiver android:name=".AutoStart">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"></action>
    </intent-filter>
</receiver>
...
<service
        android:name=".YourService"
        android:enabled="true"
        android:process=":your_service" >
</service>

И создать новый класс:

package yourPackage;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class AutoStart extends BroadcastReceiver
{   
    Alarm alarm = new Alarm();
    @Override
    public void onReceive(Context context, Intent intent)
    {   
        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED))
        {
            alarm.setAlarm(context);
        }
    }
}

Я попробовал решение из ХХХ, и хотя изначально оно работало, в какой-то момент оно перестало работать. onReceive никогда не звонили снова. Я часами пытался понять, что это может быть. Я понял, что Intent по какой-то таинственной причине больше не вызывали. Чтобы обойти это, я обнаружил, что вам действительно нужно указать действие для получателя в манифесте. Пример:

<receiver android:name=".Alarm" android:exported="true">
    <intent-filter>
        <action android:name="mypackage.START_ALARM" >
        </action>
    </intent-filter>
</receiver> 

Обратите внимание, что имя ".Alarm" с периодом. В ххх setAlarm метод, создать Intent следующее:

Intent i = new Intent("mypackage.START_ALARM");

START_ALARM сообщение может быть тем, чем вы хотите. Я просто дал ему это имя в демонстрационных целях.

Я не видел получателей, определенных в манифесте, без фильтра намерений, который определяет действие. Создание их так, как определил XXX, кажется фальшивым. Указав имя действия, Android будет вынужден создать экземпляр BroadcastReceiver используя класс, который соответствует действию. Если вы полагаетесь на контекст, помните, что в Android есть несколько различных объектов, которые ВСЕ называют контекстом и могут не привести к получению вашего BroadcastReceiver создано. Заставить Android создавать экземпляр вашего класса, используя только сообщение действия, гораздо лучше, чем полагаться на какой-то сомнительный контекст, который может никогда не сработать.

Вот довольно самостоятельный пример. Через 5 секунд кнопка становится красной.

    public void SetAlarm()
    {
        final Button button = buttons[2]; // replace with a button from your own UI
        BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override public void onReceive( Context context, Intent _ )
            {
                button.setBackgroundColor( Color.RED );
                context.unregisterReceiver( this ); // this == BroadcastReceiver, not Activity
            }
        };

        this.registerReceiver( receiver, new IntentFilter("com.blah.blah.somemessage") );

        PendingIntent pintent = PendingIntent.getBroadcast( this, 0, new Intent("com.blah.blah.somemessage"), 0 );
        AlarmManager manager = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));

        // set alarm to fire 5 sec (1000*5) from now (SystemClock.elapsedRealtime())
        manager.set( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000*5, pintent );
    }

Помните, что AlarmManager срабатывает, даже если ваше приложение не запущено. Если вы вызываете эту функцию и нажимаете кнопку "Домой", подождите 5 секунд, а затем вернитесь в свое приложение, кнопка станет красной.

Я не знаю, какое поведение вы будете вести, если ваше приложение вообще не будет в памяти, поэтому будьте осторожны с тем, какое состояние вы пытаетесь сохранить.

MainActivity.java

package com.example.alarmexample;  

import android.app.Activity;  
import android.app.AlarmManager;  
import android.app.PendingIntent;  
import android.content.Intent;  
import android.os.Bundle;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  
import android.widget.EditText;  
import android.widget.Toast;  

public class MainActivity extends Activity {  
Button b1;  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main); 

        startAlert();  

}   public void startAlert() { 
        int timeInSec = 2;

        Intent intent = new Intent(this, MyBroadcastReceiver.class);  
        PendingIntent pendingIntent = PendingIntent.getBroadcast(  
                                      this.getApplicationContext(), 234, intent, 0);  
        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);  
        alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (timeInSec * 1000), pendingIntent);  
        Toast.makeText(this, "Alarm set to after " + i + " seconds",Toast.LENGTH_LONG).show();  
    }  

}

MyBroadcastReceiver.java

package com.example.alarmexample;  

import android.content.BroadcastReceiver;  
import android.content.Context;  
import android.content.Intent;  
import android.media.MediaPlayer;  
import android.widget.Toast;  

public class MyBroadcastReceiver extends BroadcastReceiver {  
    MediaPlayer mp;  
    @Override  
    public void onReceive(Context context, Intent intent) {  
        mp=MediaPlayer.create(context, R.raw.alarm);  
        mp.start();  
        Toast.makeText(context, "Alarm", Toast.LENGTH_LONG).show();  
    }  
}  

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>  
<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    package="com.example.alarmexample" >  

    <uses-permission android:name="android.permission.VIBRATE" />  


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

        <activity  
            android:name="com.example.alarmexample.MainActivity"  
            android:label="@string/app_name" >  
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />  

                <category android:name="android.intent.category.LAUNCHER" />  
            </intent-filter>  
        </activity>  

        <receiver android:name="MyBroadcastReceiver" >  
        </receiver>  
    </application>  

</manifest>  

AlarmManager в комбинации с IntentService

Я думаю, что лучший шаблон для использования AlarmManager это сотрудничество с IntentService, IntentService вызвано AlarmManager и он обрабатывает необходимые действия через намерение получения. Эта структура не влияет на производительность, как использование BroadcastReceiver, Я разработал пример кода для этой идеи в kotlin, который доступен здесь:

MyAlarmManager.kt

import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent

object MyAlarmManager {

    private var pendingIntent: PendingIntent? = null

    fun setAlarm(context: Context, alarmTime: Long, message: String) {
        val alarmManager: AlarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager

        val intent = Intent(context, MyIntentService::class.java)
        intent.action = MyIntentService.ACTION_SEND_TEST_MESSAGE
        intent.putExtra(MyIntentService.EXTRA_MESSAGE, message)

        pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
        alarmManager.set(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent)
    }

    fun cancelAlarm(context: Context) {
        pendingIntent?.let {
            val alarmManager: AlarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
            alarmManager.cancel(it)
        }
    }

}

MyIntentService.kt

import android.app.IntentService
import android.content.Intent

class MyIntentService : IntentService("MyIntentService") {

    override fun onHandleIntent(intent: Intent?) {
        intent?.apply {
            when (intent.action) {
                ACTION_SEND_TEST_MESSAGE -> {
                    val message = getStringExtra(EXTRA_MESSAGE)
                    println(message)
                }
            }
        }
    }

    companion object {
        const val ACTION_SEND_TEST_MESSAGE = "ACTION_SEND_TEST_MESSAGE"
        const val EXTRA_MESSAGE = "EXTRA_MESSAGE"
    }

}

manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.aminography.alarm">

    <application
        ... >

    <service
        android:name="path.to.MyIntentService"
        android:enabled="true"
        android:stopWithTask="false" />

    </application>

</manifest>

Использование:

val calendar = Calendar.getInstance()
calendar.add(Calendar.SECOND, 10)
MyAlarmManager.setAlarm(applicationContext, calendar.timeInMillis, "Test Message!")

Если вы хотите отменить запланированный будильник, попробуйте это:

MyAlarmManager.cancelAlarm(applicationContext)

Я сделал свою собственную реализацию, чтобы сделать это максимально простым способом.

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;

import junit.framework.Assert;

/**
 * Created by Daniel on 28/08/2016.
 */
public abstract class AbstractSystemServiceTask {

    private final Context context;
    private final AlarmManager alarmManager;
    private final BroadcastReceiver broadcastReceiver;
    private final PendingIntent pendingIntent;

    public AbstractSystemServiceTask(final Context context, final String id, final long time, final AlarmType alarmType, final BackgroundTaskListener backgroundTaskListener) {

        Assert.assertNotNull("ApplicationContext can't be null", context);
        Assert.assertNotNull("ID can't be null", id);

        this.context = context;

        this.alarmManager = (AlarmManager) this.context.getSystemService(Context.ALARM_SERVICE);

        this.context.registerReceiver(
                this.broadcastReceiver = this.getBroadcastReceiver(backgroundTaskListener),
                new IntentFilter(id));

        this.configAlarmManager(
                this.pendingIntent = PendingIntent.getBroadcast(this.context, 0, new Intent(id), 0),
                time,
                alarmType);
    }

    public void stop() {

        this.alarmManager.cancel(this.pendingIntent);
        this.context.unregisterReceiver(this.broadcastReceiver);
    }

    private BroadcastReceiver getBroadcastReceiver(final BackgroundTaskListener backgroundTaskListener) {

        Assert.assertNotNull("BackgroundTaskListener can't be null.", backgroundTaskListener);

        return new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {

                backgroundTaskListener.perform(context, intent);
            }
        };
    }

    private void configAlarmManager(final PendingIntent pendingIntent, final long time, final AlarmType alarmType) {

        long ensurePositiveTime = Math.max(time, 0L);

        switch (alarmType) {
            case REPEAT:
                this.alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), ensurePositiveTime, pendingIntent);
                break;
            case ONE_TIME:
            default:
                this.alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + ensurePositiveTime, pendingIntent);
        }
    }

    public interface BackgroundTaskListener {

        void perform(Context context, Intent intent);

    }

    public enum AlarmType {

        REPEAT, ONE_TIME;

    }

}

Единственный следующий шаг, реализовать его.

import android.content.Context;
import android.content.Intent;
import android.util.Log;

import ...AbstractSystemServiceTask;

import java.util.concurrent.TimeUnit;

/**
 * Created by Daniel on 28/08/2016.
 */
public class UpdateInfoSystemServiceTask extends AbstractSystemServiceTask {

    private final static String ID = "UPDATE_INFO_SYSTEM_SERVICE";
    private final static long REPEAT_TIME = TimeUnit.SECONDS.toMillis(10);
    private final static AlarmType ALARM_TYPE = AlarmType.REPEAT;

    public UpdateInfoSystemServiceTask(Context context) {

        super(context, ID, REPEAT_TIME, ALARM_TYPE, new BackgroundTaskListener() {

            @Override
            public void perform(Context context, Intent intent) {

                Log.i("MyAppLog", "-----> UpdateInfoSystemServiceTask");

                //DO HERE WHATEVER YOU WANT...
            }
        });

        Log.i("MyAppLog", "UpdateInfoSystemServiceTask started.");
    }

}

Мне нравится работать с этой реализацией, но другой возможный хороший способ, это не делает AbstractSystemServiceTask Абстрактный класс, и построить его через Builder.

Я надеюсь, что это поможет вам.

ОБНОВЛЕНО Улучшено, чтобы позволить несколько BackgroundTaskListener на том же BroadCastReceiver,

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;

import junit.framework.Assert;

import java.util.HashSet;
import java.util.Set;

/**
 * Created by Daniel on 28/08/2016.
 */
public abstract class AbstractSystemServiceTask {

    private final Context context;
    private final AlarmManager alarmManager;
    private final BroadcastReceiver broadcastReceiver;
    private final PendingIntent pendingIntent;

    private final Set<BackgroundTaskListener> backgroundTaskListenerSet;

    public AbstractSystemServiceTask(final Context context, final String id, final long time, final AlarmType alarmType) {

        Assert.assertNotNull("ApplicationContext can't be null", context);
        Assert.assertNotNull("ID can't be null", id);

        this.backgroundTaskListenerSet = new HashSet<>();

        this.context = context;

        this.alarmManager = (AlarmManager) this.context.getSystemService(Context.ALARM_SERVICE);

        this.context.registerReceiver(
                this.broadcastReceiver = this.getBroadcastReceiver(),
                new IntentFilter(id));

        this.configAlarmManager(
                this.pendingIntent = PendingIntent.getBroadcast(this.context, 0, new Intent(id), 0),
                time,
                alarmType);
    }

    public synchronized void registerTask(final BackgroundTaskListener backgroundTaskListener) {

        Assert.assertNotNull("BackgroundTaskListener can't be null", backgroundTaskListener);

        this.backgroundTaskListenerSet.add(backgroundTaskListener);
    }

    public synchronized void removeTask(final BackgroundTaskListener backgroundTaskListener) {

        Assert.assertNotNull("BackgroundTaskListener can't be null", backgroundTaskListener);

        this.backgroundTaskListenerSet.remove(backgroundTaskListener);
    }

    public void stop() {

        this.backgroundTaskListenerSet.clear();

        this.alarmManager.cancel(this.pendingIntent);
        this.context.unregisterReceiver(this.broadcastReceiver);
    }

    private BroadcastReceiver getBroadcastReceiver() {

        return new BroadcastReceiver() {

            @Override
            public void onReceive(final Context context, final Intent intent) {

                for (BackgroundTaskListener backgroundTaskListener : AbstractSystemServiceTask.this.backgroundTaskListenerSet) {

                    backgroundTaskListener.perform(context, intent);
                }
            }
        };
    }

    private void configAlarmManager(final PendingIntent pendingIntent, final long time, final AlarmType alarmType) {

        long ensurePositiveTime = Math.max(time, 0L);

        switch (alarmType) {
            case REPEAT:
                this.alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), ensurePositiveTime, pendingIntent);
                break;
            case ONE_TIME:
            default:
                this.alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + ensurePositiveTime, pendingIntent);
        }
    }

    public interface BackgroundTaskListener {

        void perform(Context context, Intent intent);

    }

    public enum AlarmType {

        REPEAT, ONE_TIME;

    }

}

Этот код поможет вам сделать повторяющуюся тревогу. Время повторения может быть установлено вами.

activity_main.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="vertical" 
     android:background="#000000"
     android:paddingTop="100dp">

    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center" >

    <EditText
        android:id="@+id/ethr"
    android:layout_width="50dp"
    android:layout_height="wrap_content"
    android:ems="10"
    android:hint="Hr"
    android:singleLine="true" >


        <requestFocus />
    </EditText>

    <EditText
        android:id="@+id/etmin"
    android:layout_width="55dp"
    android:layout_height="wrap_content"

    android:ems="10"
    android:hint="Min"
    android:singleLine="true" />

    <EditText
        android:id="@+id/etsec"
    android:layout_width="50dp"
    android:layout_height="wrap_content"

    android:ems="10"
    android:hint="Sec"
    android:singleLine="true" />

    </LinearLayout>

   <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content" 
    android:gravity="center"
    android:paddingTop="10dp">


    <Button
        android:id="@+id/setAlarm"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClickSetAlarm"
        android:text="Set Alarm" />

</LinearLayout>

</LinearLayout>

MainActivity.java

public class MainActivity extends Activity {
    int hr = 0;
    int min = 0;
    int sec = 0;
    int result = 1;

    AlarmManager alarmManager;
    PendingIntent pendingIntent;
    BroadcastReceiver mReceiver;

    EditText ethr;
    EditText etmin;
    EditText etsec;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ethr = (EditText) findViewById(R.id.ethr);
        etmin = (EditText) findViewById(R.id.etmin);
        etsec = (EditText) findViewById(R.id.etsec);
        RegisterAlarmBroadcast();
    } 

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    protected void onDestroy() {
        unregisterReceiver(mReceiver);
        super.onDestroy();
    }

    public void onClickSetAlarm(View v) {
        String shr = ethr.getText().toString();
        String smin = etmin.getText().toString();
        String ssec = etsec.getText().toString();

        if(shr.equals("")) 
            hr = 0;
        else {
            hr = Integer.parseInt(ethr.getText().toString());
            hr=hr*60*60*1000;
        }

        if(smin.equals(""))
            min = 0;
        else {
            min = Integer.parseInt(etmin.getText().toString());
            min = min*60*1000;
        }

        if(ssec.equals(""))
            sec = 0;
        else {
             sec = Integer.parseInt(etsec.getText().toString());
             sec = sec * 1000;
        }
        result = hr+min+sec;
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), result , pendingIntent); 
    }

    private void RegisterAlarmBroadcast() {
        mReceiver = new BroadcastReceiver() {
            // private static final String TAG = "Alarm Example Receiver";
            @Override
            public void onReceive(Context context, Intent intent) {
                Toast.makeText(context, "Alarm time has been reached", Toast.LENGTH_LONG).show();
            }
        };

        registerReceiver(mReceiver, new IntentFilter("sample"));
        pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent("sample"), 0);
        alarmManager = (AlarmManager)(this.getSystemService(Context.ALARM_SERVICE));
    }

    private void UnregisterAlarmBroadcast() {
        alarmManager.cancel(pendingIntent); 
        getBaseContext().unregisterReceiver(mReceiver);
    }
}

Если вам нужна тревога только один раз, замените

alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), result , pendingIntent);

с

 alarmManager.set( AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + result , pendingIntent );

Диспетчер тревог:

Добавить в XML-макет (* инициировать эти представления при создании в основной деятельности)

  <TimePicker
    android:id="@+id/timepicker"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="2"></TimePicker>

  <Button
    android:id="@+id/btn_start"
    android:text="start Alarm"
    android:onClick="start_alarm_event"
    android:layout_width="match_parent"
    android:layout_height="52dp" />

Добавить в манифест (внутри тега приложения и вне активности)

 <receiver android:name=".AlarmBroadcastManager"
        android:enabled="true"
        android:exported="true"/>

Создать класс AlarmBroadcastManager (унаследовать его от BroadcastReceiver)

 public class AlarmBroadcastManager extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
      MediaPlayer mediaPlayer=MediaPlayer.create(context,Settings.System.DEFAULT_RINGTONE_URI);
      mediaPlayer.start();
    }
 }

В основной деятельности (добавить эти функции):

 @RequiresApi(api = Build.VERSION_CODES.M)
 public  void start_alarm_event(View view){
    Calendar calendar=Calendar.getInstance();
    calendar.set(
    calendar.get(Calendar.YEAR),
    calendar.get(Calendar.MONTH),
    calendar.get(Calendar.DAY_OF_MONTH),
    timePicker.getHour(),
    timePicker.getMinute(),
    0
    );
    setAlarm(calendar.getTimeInMillis());
 }

 public void setAlarm(long timeInMillis){
    AlarmManager alarmManager=(AlarmManager) getSystemService(Context.ALARM_SERVICE);
    Intent intent=new Intent(this,AlarmBroadcastManager.class);
    PendingIntent pendingIntent=PendingIntent.getBroadcast(this,0,intent,0);
     alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,timeInMillis,AlarmManager.INTERVAL_DAY,pendingIntent);
    Toast.makeText(getApplicationContext(),"Alarm is Set",Toast.LENGTH_SHORT).show();


 }

У меня тоже была проблема с будильником в Android. Проблема заключалась в режиме ожидания (https://developer.android.com/training/monitoring-device-state/doze-standby). Например, будильник работал нормально, когда я установил его на один час дальше, но он не работал, если он был установлен на 4 часа ночи. Я только что обнаружил, что это очень просто, мне просто нужно использовать AlarmManager.setAlarmClock() вместо AlarmManager.set().

Поэтому я решил создать пример приложения на github.https://github.com/carlosabreu/androidalarm

Вот пример использования Alarm Manager с использованием Kotlin:

class MainActivity : AppCompatActivity() {

    val editText: EditText by bindView(R.id.edit_text)
    val timePicker: TimePicker by bindView(R.id.time_picker)
    val buttonSet: Button by bindView(R.id.button_set)
    val buttonCancel: Button by bindView(R.id.button_cancel)
    val relativeLayout: RelativeLayout by bindView(R.id.activity_main)
    var notificationId = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        timePicker.setIs24HourView(true)

        val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager

        buttonSet.setOnClickListener {
            if (editText.text.isBlank()) {
                Toast.makeText(applicationContext, "Title is Required!!", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }
            alarmManager.set(
                AlarmManager.RTC_WAKEUP,
                Calendar.getInstance().apply {
                    set(Calendar.HOUR_OF_DAY, timePicker.hour)
                    set(Calendar.MINUTE, timePicker.minute)
                    set(Calendar.SECOND, 0)
                }.timeInMillis,
                PendingIntent.getBroadcast(
                    applicationContext,
                    0,
                    Intent(applicationContext, AlarmBroadcastReceiver::class.java).apply {
                        putExtra("notificationId", ++notificationId)
                        putExtra("reminder", editText.text)
                    },
                    PendingIntent.FLAG_CANCEL_CURRENT
                )
            )
            Toast.makeText(applicationContext, "SET!! ${editText.text}", Toast.LENGTH_SHORT).show()
            reset()
        }

        buttonCancel.setOnClickListener {
            alarmManager.cancel(
                PendingIntent.getBroadcast(
                    applicationContext, 0, Intent(applicationContext, AlarmBroadcastReceiver::class.java), 0))
            Toast.makeText(applicationContext, "CANCEL!!", Toast.LENGTH_SHORT).show()
        }
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        (getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager)
            .hideSoftInputFromWindow(relativeLayout.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
        relativeLayout.requestFocus()
        return super.onTouchEvent(event)
    }

    override fun onResume() {
        super.onResume()
        reset()
    }

    private fun reset() {
        timePicker.apply {
            val now = Calendar.getInstance()
            hour = now.get(Calendar.HOUR_OF_DAY)
            minute = now.get(Calendar.MINUTE)
        }
        editText.setText("")
    }
}

Через десять лет вы можете прочитать это объяснение по обучению в официальной документации.

Другие вопросы по тегам