[java] 알람 관리자 예

프로젝트에서 일정 기능을 구현하고 싶습니다. 그래서 알람 관리자 프로그램을 검색했지만 예제를 찾을 수 없습니다.

누구나 기본 알람 관리자 프로그램으로 나를 도울 수 있습니까?



답변

이것은 작동 코드입니다. 전화가 꺼질 때까지 10 분마다 CPU를 깨 웁니다.

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


답변

XXX에서 솔루션을 시도했지만 처음에는 작동했지만 어느 시점에서 작동이 중지되었습니다. 그만큼onReceive다시 호출되지있어 않습니다. 나는 그것이 무엇인지 알아 내려고 몇 시간을 보냈습니다. 내가 깨닫게 된 Intent것은 신비한 이유가 더 이상 불려지지 않았다는 것입니다. 이 문제를 해결하려면 매니페스트에서 수신자에 대한 작업을 지정해야한다는 것을 알게되었습니다. 예:

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

이름은 ".Alarm"마침표로되어 있습니다. XXX에서setAlarm 메소드에서 Intent다음을 작성하십시오 .

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

START_ALARM메시지는 당신이 원하는 무엇이든 할 수있다. 나는 단지 그것을 시연 목적으로 그 이름을 주었다.

동작을 지정하는 의도 필터가 없으면 매니페스트에 정의 된 수신자를 보지 못했습니다. XXX에서 지정한 방식으로 만들면 가짜처럼 보입니다. 액션 이름을 지정하면 Android는 BroadcastReceiver액션에 해당하는 클래스를 사용하여 인스턴스를 생성해야합니다 . 컨텍스트에 의존하는 경우 Android에는 모두 컨텍스트라고하며 여러 가지 객체가 BroadcastReceiver생성되어 생성 되지 않을 수 있습니다 . Android가 액션 메시지 만 사용하여 클래스의 인스턴스를 작성하도록하는 것은 결코 작동하지 않을 수있는 일부 iffy 컨텍스트에 의존하는 것보다 훨씬 낫습니다.


답변

여기에 상당히 독립적 인 예가 있습니다. 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 . 이 아이디어에 대한 샘플 코드를 개발했습니다. 여기에서 사용할 수 있습니다 :

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)


답변

이 코드는 반복 알람을 만드는 데 도움이됩니다. 반복 시간을 설정할 수 있습니다.

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


답변

가능한 한 가장 간단한 방법 으로이 작업을 수행하기 위해 직접 구현했습니다.

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클래스를 추상화 하지 않고 빌더를 통해 빌드하는 것입니다.

도움이 되길 바랍니다.

UPDATED
여러 개 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;

    }

}