Ví dụ về Trình quản lý báo thức


351

Tôi muốn thực hiện một chức năng lịch trình trong dự án của tôi. Vì vậy, tôi đã tìm kiếm một chương trình quản lý báo thức nhưng tôi không thể tìm thấy bất kỳ ví dụ nào.

Bất cứ ai có thể giúp tôi với một chương trình quản lý báo động cơ bản?


13
Bạn đã kiểm tra các bản trình diễn API, phải không?
EboMike

3
liên kết này liên kết hoạt động cho 4.0 được thử nghiệm
shareef

Câu trả lời:


452

Đây là mã làm việc. Nó đánh thức CPU cứ sau 10 phút cho đến khi điện thoại tắt.

Thêm vào Manifest.xml:

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

Mã trong lớp của bạn:

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);
    }
}

Đặt báo thức từ dịch vụ:

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;
    }
}

Nếu bạn muốn đặt lặp lại báo thức khi khởi động điện thoại:

Thêm quyền và dịch vụ vào 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>

Và tạo một lớp mới:

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);
        }
    }
}

38
Điều này rất hữu ích, nhưng một số điều: 1. Có thể tốt hơn để sử dụng am.setInexactRepeating(...)để điện thoại không cần phải thức dậy vì dịch vụ. Các lập trình viên khác nên lưu ý về thực tế này. 2. Thay vì tạo ra một mới Alarmtrong AutoStartkhi nhận được RECEIVE_BOOT_COMPLETEDý định, nó có thể làm cho ý nghĩa hơn để bắt đầu YourServicetừ AutoStart, như thể hiện ở đây: stackoverflow.com/a/5439320/198348
Ehtesh Choudhury

7
Tôi nghĩ rằng việc có được khóa trên phương thức onReceive là không bắt buộc vì Android sẽ làm điều đó cho bạn. Xem tại đây: developer.android.com/reference/android/app/AlarmManager.html
Ran

8
WakeLock không cần thiết trong BroadcastReceiver. Android sử dụng kết thúc chương trình BroadcastReceiver của riêng mình.
Jorge Fuentes González

13
Câu trả lời tuyệt vời, nhưng tốt hơn là mở rộng từ WakefulBroadcastReceiver thay vì BroadcastReceiver, WakefulBroadcastReceiver tự quản lý khóa đánh thức. Xem liên kết để biết thêm.
icastell

4
WakefulBroadcastReceiverbị trục xuất từAndroid O
Im Batman

57

Tôi đã thử giải pháp từ XXX và trong khi nó ban đầu hoạt động, đến một lúc nào đó nó ngừng hoạt động. Không onReceivebao giờ được gọi lại. Tôi đã dành hàng giờ cố gắng để tìm ra nó có thể là gì. Điều tôi nhận ra là Intentvì lý do bí ẩn nào đó không còn được gọi nữa. Để giải quyết vấn đề này, tôi phát hiện ra rằng bạn thực sự cần chỉ định một hành động cho người nhận trong tệp kê khai. Thí dụ:

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

Lưu ý rằng tên là ".Alarm"với thời gian. Trong setAlarmphương thức của XXX , tạo Intentnhư sau:

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

Các START_ALARMtin nhắn có thể được bất cứ điều gì bạn muốn nó được. Tôi chỉ đặt tên đó cho mục đích trình diễn.

Tôi chưa thấy các máy thu được xác định trong tệp kê khai mà không có bộ lọc ý định chỉ định hành động. Tạo chúng theo cách mà XXX đã chỉ định có vẻ như không có thật. Bằng cách chỉ định tên hành động, Android sẽ buộc phải tạo một thể hiện của việc BroadcastReceiversử dụng lớp tương ứng với hành động. Nếu bạn dựa vào ngữ cảnh, hãy lưu ý rằng Android có một số đối tượng khác nhau được gọi là TẤT CẢ và có thể không dẫn đến việc bạn BroadcastReceivertạo. Buộc Android tạo một thể hiện của lớp bạn chỉ bằng thông điệp hành động sẽ tốt hơn nhiều so với việc dựa vào một số bối cảnh iffy có thể không bao giờ hoạt động.


2
@AndroidDev Theo PendingIntent.getBroadcasttài liệu , For security reasons, the Intent you supply here should almost always be an explicit intent, that is specify an explicit component to be delivered to through Intent.setClass.
aandis

2
Bất kể tài liệu nào nói, đây sẽ là câu trả lời được chấp nhận vì nó thực sự hoạt động trái với câu trả lời được chấp nhận.
m0skit0

Khẳng định - đối với tôi báo động sẽ không bắn nếu không có ý định.
nsandersen

android:exported="true"cần thiết cho nó để làm việc?
user2259659

27

Đây là một ví dụ khá khép kín. Nó chuyển một nút màu đỏ sau 5sec.

    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 );
    }

Tuy nhiên, hãy nhớ rằng Trình quản lý báo thức kích hoạt ngay cả khi ứng dụng của bạn không chạy. Nếu bạn gọi chức năng này và nhấn nút Home, đợi 5 giây, sau đó quay lại ứng dụng của bạn, nút sẽ chuyển sang màu đỏ.

Tôi không biết bạn sẽ có loại hành vi nào nếu ứng dụng của bạn không có trong bộ nhớ, vì vậy hãy cẩn thận với loại trạng thái bạn cố gắng duy trì.


16
bạn nên đăng tất cả mã cho lớp để xem nhập khẩu và gia hạn cần thiết
shareef

Làm thế nào điều này có thể được thiết lập để lặp lại cứ sau 24 giờ?
tìm kiếmStillness

Mã này chạy phương thức onReceive chính xác một lần và sau đó không bao giờ trở lại.
Ondrej Sotolar

Điều này ( RTC_WAKEUPthay vì ELAPSED_REALTIME_WAKEUP) dường như không kích hoạt bộ thu trong một ứng dụng dường như đã được hệ thống dỡ tải để tiết kiệm năng lượng, mặc dù nó hoạt động ngay sau khi màn hình chính được đưa lên nền trước.
Ruslan

21

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>  

Mã này chạy phương thức onReceive chính xác một lần và sau đó không bao giờ trở lại.
Ondrej Sotolar

3

AlarmManagerkết hợp vớiIntentService

Tôi nghĩ rằng mô hình tốt nhất để sử dụng AlarmManagerlà sự hợp tác của nó với một IntentService. Nó IntentServiceđược kích hoạt bởi AlarmManagervà nó xử lý các hành động cần thiết thông qua ý định nhận. Cấu trúc này không có tác động hiệu suất như sử dụng BroadcastReceiver. Tôi đã phát triển một mã mẫu cho ý tưởng này trong có sẵn ở đây:

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"
    }

}

tệp kê khai

<?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>

Sử dụng:

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

Nếu bạn muốn hủy báo thức theo lịch trình, hãy thử điều này:

MyAlarmManager.cancelAlarm(applicationContext)

2

Mã này sẽ giúp bạn thực hiện một báo động lặp lại. Thời gian lặp lại có thể do bạn thiết lập.

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);
    }
}

Nếu bạn chỉ cần báo thức trong một thời gian thì thay thế

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

với

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

1

Tôi đã thực hiện riêng của mình để làm điều này theo cách đơn giản nhất có thể.

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;

    }

}

Bước tiếp theo duy nhất, thực hiện nó.

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.");
    }

}

Tôi thích làm việc với triển khai này, nhưng một cách tốt khác có thể, đó là không làm cho AbstractSystemServiceTasklớp trở nên trừu tượng và xây dựng nó thông qua Trình tạo.

Tôi hy vọng nó sẽ giúp bạn.

CẬP NHẬT Cải thiện để cho phép một số BackgroundTaskListenertrên cùng 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;

    }

}

1

Quản lý báo động:

Thêm vào Bố cục XML (* khởi tạo các chế độ xem này khi tạo trong hoạt động chính)

  <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" />

Thêm vào tệp kê khai (Thẻ ứng dụng bên trong && hoạt động bên ngoài)

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

Tạo lớp AlertBroadcastManager (kế thừa nó từ 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();
    }
 }

Trong Hoạt động chính (Thêm các chức năng này):

 @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();


 }

0

Dưới đây là một ví dụ với Trình quản lý báo thức bằng cách sử dụng 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("")
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.