Development Tip

Android의 날짜 및 시간 변경 리스너?

yourdevel 2020. 11. 27. 21:32
반응형

Android의 날짜 및 시간 변경 리스너?


내 응용 프로그램에는 경보 서비스가 있으며 사용자가 날짜 또는 시간을 경과 시간으로 변경하면 알 수 있습니다. 예상 한 시간에 알람이 울리지 않습니다.

따라서 모든 알람을 다시 재설정해야 할 수도 있습니다. Android에 날짜 및 시간 변경 리스너가 있습니까?


인 텐트 필터 만들기 :

static {
    s_intentFilter = new IntentFilter();
    s_intentFilter.addAction(Intent.ACTION_TIME_TICK);
    s_intentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
    s_intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
}

및 방송 수신기 :

private final BroadcastReceiver m_timeChangedReceiver = new BroadcastReceiver() {                                                                                             
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();

        if (action.equals(Intent.ACTION_TIME_CHANGED) ||
                    action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
            doWorkSon();
        }
    }
};

수신자 등록 :

public void onCreate() {
    super.onCreate();
    registerReceiver(m_timeChangedReceiver, s_intentFilter);     
}

편집하다:

등록 취소 :

public void onDestroy() {
    super.onDestroy();
    unregisterReceiver(m_timeChangedReceiver);     
}

받아 들여진 답변 외에

앱이 실행되지 않는 동안 시간 변경을 듣고 싶다면 매니페스트에 등록합니다.

<receiver android:name="com.your.pacakge.TimeChangeBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.TIME_SET"/>
        <action android:name="android.intent.action.TIMEZONE_CHANGED"/>
    </intent-filter>
</receiver>

이렇게하는 경우 registerReceiver및로 코드에 수신자를 명시 적으로 등록하지 마십시오 unregisterReceiver.

다시 말하지만 이것은 허용되는 답변에 추가 된 것입니다.


날짜 변경을 감지하려면 다음 작업에 등록해야합니다.

여기에 내가 작성한 한 가지 해결책이 있으므로 클래스를 확장하고 Activity / Fragment에 등록 및 등록 취소하기 만하면됩니다.

abstract class DateChangedBroadcastReceiver : BroadcastReceiver() {
    private var curDate = LocalDate.now()

    /**called when the receiver detected the date has changed. You should still check it yourself, because you might already be synced with the new date*/
    abstract fun onDateChanged(previousDate: LocalDate, newDate: LocalDate)

    @Suppress("MemberVisibilityCanBePrivate")
    fun register(context: Context, date: LocalDate) {
        curDate = date
        val filter = IntentFilter()
        filter.addAction(Intent.ACTION_TIME_CHANGED)
        filter.addAction(Intent.ACTION_DATE_CHANGED)
        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED)
        context.registerReceiver(this, filter)
        val newDate = LocalDate.now()
        if (newDate != curDate) {
            curDate = newDate
            onDateChanged(date, newDate)
        }
    }

    /**a convenient way to auto-unregister when activity/fragment has stopped. This should be called on the onResume method of the fragment/activity*/
    fun registerOnResume(activity: AppCompatActivity, date: LocalDate, fragment: androidx.fragment.app.Fragment? = null) {
        register(activity, date)
        val lifecycle = fragment?.lifecycle ?: activity.lifecycle
        lifecycle.addObserver(object : LifecycleObserver {
            @Suppress("unused")
            @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
            fun onPause() {
//                Log.d("AppLog", "onPause, so unregistering")
                lifecycle.removeObserver(this)
                activity.unregisterReceiver(this@DateChangedBroadcastReceiver)
            }
        })
    }

    override fun onReceive(context: Context, intent: Intent) {
        val newDate = LocalDate.now()
//        Log.d("AppLog", "got intent:" + intent.action + " curDate:" + curDate + " newDate:" + newDate)
        if (newDate != curDate) {
//            Log.d("AppLog", "cur date is different, so posting event")
            val previousDate = curDate
            curDate = newDate
            onDateChanged(previousDate, newDate)
        }
    }

}

LocalDate를 사용할 수없는 경우 (현재 약 21 %의 기기에서 사용되는 비교적 새로운 API : 26을 사용하기 때문에) 대신 다음을 사용할 수 있습니다.

abstract class DateChangedBroadcastReceiver : BroadcastReceiver() {
    private var curDate = Calendar.getInstance()

    /**called when the receiver detected the date has changed. You should still check it yourself, because you might already be synced with the new date*/
    abstract fun onDateChanged(previousDate: Calendar, newDate: Calendar)

    companion object {
        fun toString(cal: Calendar): String {
            return "${cal.get(Calendar.YEAR)}-${cal.get(Calendar.MONTH)}-${cal.get(Calendar.DAY_OF_MONTH)}"
        }

        fun resetDate(date: Calendar) {
            date.set(Calendar.HOUR_OF_DAY, 0)
            date.set(Calendar.MINUTE, 0)
            date.set(Calendar.SECOND, 0)
            date.set(Calendar.MILLISECOND, 0)
        }

        fun areOfSameDate(date: Calendar, otherDate: Calendar) =
            date.get(Calendar.DAY_OF_YEAR) == otherDate.get(Calendar.DAY_OF_YEAR) &&
                    date.get(Calendar.YEAR) == otherDate.get(Calendar.YEAR)
    }

    @Suppress("MemberVisibilityCanBePrivate")
    fun register(context: Context, date: Calendar) {
        curDate = date.clone() as Calendar
        resetDate(curDate)
        val filter = IntentFilter()
        filter.addAction(Intent.ACTION_TIME_CHANGED)
        filter.addAction(Intent.ACTION_DATE_CHANGED)
        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED)
        context.registerReceiver(this, filter)
        val newDate = Calendar.getInstance()
        resetDate(newDate)
        if (!areOfSameDate(newDate, curDate)) {
            val previousDate = curDate.clone() as Calendar
            curDate = newDate
            onDateChanged(previousDate, curDate)
        }
    }

    /**a convenient way to auto-unregister when activity/fragment has stopped. This should be called on the onResume method of the fragment/activity*/
    fun registerOnResume(activity: AppCompatActivity, date: Calendar, fragment: Fragment? = null) {
        register(activity as Context, date)
        val lifecycle = fragment?.lifecycle ?: activity.lifecycle
        lifecycle.addObserver(object : LifecycleObserver {
            @Suppress("unused")
            @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
            fun onPause() {
//                Log.d("AppLog", "onPause, so unregistering")
                lifecycle.removeObserver(this)
                activity.unregisterReceiver(this@DateChangedBroadcastReceiver)
            }
        })
    }

    override fun onReceive(context: Context, intent: Intent) {
        val newDate = Calendar.getInstance()
        resetDate(newDate)
//        Log.d("AppLog", "got intent:${intent.action} curDate:${toString(curDate)} newDate:${toString(newDate)}")
        if (!areOfSameDate(newDate, curDate)) {
//            Log.d("AppLog", "cur date is different, so posting event")
            val previousDate = curDate.clone() as Calendar
            curDate = newDate
            onDateChanged(previousDate, newDate)
        }
    }

}

사용 예 :

class MainActivity : AppCompatActivity() {
    var curDate = Calendar.getInstance()

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

    override fun onResume() {
        super.onResume()
        object : DateChangedBroadcastReceiver() {
            override fun onDateChanged(previousDate: Calendar, newDate: Calendar) {
                Log.d("AppLog", "MainActivity: ${DateChangedBroadcastReceiver.toString(previousDate)} -> ${DateChangedBroadcastReceiver.toString(newDate)}")
                curDate = newDate.clone() as Calendar
                //TODO handle date change
            }
        }.registerOnResume(this, curDate)
    }
}

참고 URL : https://stackoverflow.com/questions/5481386/date-and-time-change-listener-in-android

반응형