Android 闹钟

闹钟工具类

package com.aijianji.module_sleep.utils

import android.app.Activity
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.provider.Settings
import com.aijianji.module_sleep.entity.Alarm
import com.aijianji.module_sleep.entity.AlarmType
import com.aijianji.module_sleep.entity.FrequencyType
import com.aijianji.module_sleep.receiver.AlarmReceiver
import com.blankj.utilcode.util.ToastUtils
import com.fenghuajueli.libbasecoreui.constants.AppConfigInfo
import com.google.gson.Gson

import java.util.*

/**
 *
 * @Description:
 * @author: GordenGao
 * @Email: gordengao124@gmail.com
 * @date: 2021年07月14日 9:16
 */
object AlarmUtil {

    const val ALARM = "alarm"

    private lateinit var pendingIntent: PendingIntent
    private lateinit var am: AlarmManager

    // 初始化Alarm
    private fun initAlarm(context: Context, alarm: Alarm, requestCode: Int) {
        val flag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            PendingIntent.FLAG_IMMUTABLE
        } else {
            PendingIntent.FLAG_UPDATE_CURRENT
        }
        pendingIntent =
            PendingIntent.getBroadcast(
                context,
                requestCode,
                getMsgIntent(context, alarm),
                flag
            )
        am = context.getSystemService(Activity.ALARM_SERVICE) as AlarmManager
    }

    private fun getMsgIntent(context: Context, alarm: Alarm): Intent {
        //AlarmReceiver 为广播在下面代码中
        val intent = Intent(context, AlarmReceiver::class.java)
        intent.action = AlarmReceiver.BC_ACTION
        intent.putExtra(ALARM, Gson().toJson(alarm))
        return intent
    }

    //设置定时执行的任务
    fun setAlarm(context: Context, alarm: Alarm): Boolean {
        initAlarm(context, alarm, alarm.hashCode())
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !am.canScheduleExactAlarms()) {
            val uri = Uri.parse("package:${AppConfigInfo.APPLICATION_ID}");
            val intent = Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM, uri);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            context.startActivity(intent)
            return false
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(context)) {
            val uri = Uri.parse("package:${AppConfigInfo.APPLICATION_ID}");
            val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, uri);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            context.startActivity(intent)
            ToastUtils.showShort("需开启浮窗权限")
            return false
        }
        val frequencyList = getFrequencyList(alarm)
        //android Api的改变不同版本中设置有所不同
        am.setExact(
            AlarmManager.RTC_WAKEUP,
            getTimeDiff(frequencyList, alarm.time!!.first.toInt(), alarm.time!!.second.toInt()),
            pendingIntent
        )
        return true
    }


    //设置定时执行的任务
    fun setLateAlarm(alarm: Alarm) {
        val frequencyList = getFrequencyList(alarm)
        var tempM = alarm.time!!.second.toInt() + 10 // 分钟延迟10
        var tempH = alarm.time!!.first.toInt()
        if (tempM >= 60) {
            tempM %= 10
            tempH++
        }
        //android Api的改变不同版本中设 置有所不同
        am.setExact(
            AlarmManager.RTC_WAKEUP,
            getTimeDiff(frequencyList, tempH, tempM),
            pendingIntent
        )
    }

    private fun getTimeDiff(frequencyList: MutableList<Int>, hour: Int, minute: Int): Long {
        val systemTime = System.currentTimeMillis()
        //这里设置的是当天的15:55分,注意精确到秒,时间可以自由设置
        val ca: Calendar = Calendar.getInstance()
        // 这里时区需要设置一下,不然可能个别手机会有8个小时的时间差
        ca.timeZone = TimeZone.getTimeZone("GMT+8")
        ca.set(Calendar.HOUR_OF_DAY, hour)
        ca.set(Calendar.MINUTE, minute)
        ca.set(Calendar.SECOND, 0)
        val selectTime = ca.timeInMillis

        val todayOfWeek = ca.get(Calendar.DAY_OF_WEEK) % 7

        // 判断当天是否需要设置闹钟a
        if (frequencyList.contains(todayOfWeek)) {
            // 若当前时间已经超时
            if (systemTime > selectTime) {
                jumpToNextDay(frequencyList, todayOfWeek, ca)
            }
        } else {
            jumpToNextDay(frequencyList, todayOfWeek, ca)
        }

        return ca.timeInMillis
    }

    private fun jumpToNextDay(
        frequencyList: MutableList<Int>,
        todayOfWeek: Int,
        ca: Calendar
    ) {
        // 计算天数差
        var deltaDay = 0

        for (day in frequencyList) {
            if (day < todayOfWeek) {
                continue
            } else {
                deltaDay = day - todayOfWeek
            }
        }

        if (frequencyList.size ==1){
            ca.add(Calendar.DAY_OF_MONTH, 1)
        }else {
            ca.add(Calendar.DAY_OF_MONTH, deltaDay)
        }
    }

    //取消定时任务的执行
    fun cancelAlarm(context: Context, alarm: Alarm, requestCode: Int) {
        am = context.getSystemService(Activity.ALARM_SERVICE) as AlarmManager
        val flag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            PendingIntent.FLAG_IMMUTABLE
        } else {
            0
        }
        am.cancel(PendingIntent.getBroadcast(context, requestCode, getMsgIntent(context, alarm), flag))
    }


    fun getFrequencyStr(alarm: Alarm): String {
        when (alarm.frequencyType) {
            FrequencyType.EVERYDAY -> return "每天"
            FrequencyType.JUSTONE -> return "仅一次"
            FrequencyType.DOUBLE -> return "双休"
            FrequencyType.ONE -> return "单休(仅本周)"
            FrequencyType.TWO -> return "双休(仅本周)"
            else -> {}
        }
        val res = StringBuilder()
        res.append("星期")
        for (day in alarm.customDay) {
            when (day) {
                2 -> res.append("一")
                3 -> res.append("二")
                4 -> res.append("三")
                5 -> res.append("四")
                6 -> res.append("五")
                7 -> res.append("六")
                1 -> res.append("七")
            }
            res.append(",")
        }
        return res.substring(0, res.length - 1).toString()
    }

    fun getFrequencyList(alarm: Alarm): MutableList<Int> {
        when (alarm.frequencyType) {
            FrequencyType.EVERYDAY -> return mutableListOf(7, 1, 2, 3, 4, 5, 6)
            FrequencyType.JUSTONE -> {
                val ca: Calendar = Calendar.getInstance()
                // 这里时区需要设置一下,不然可能个别手机会有8个小时的时间差
                ca.timeZone = TimeZone.getTimeZone("GMT+8")
                val todayOfWeek = ca.get(Calendar.DAY_OF_WEEK) % 7
                return mutableListOf(todayOfWeek)
            }
            FrequencyType.DOUBLE -> return mutableListOf(1, 2, 3, 4, 5)
            FrequencyType.ONE -> return mutableListOf(1, 2, 3, 4, 5, 6)
            FrequencyType.TWO -> return mutableListOf(1, 2, 3, 4, 5)
            FrequencyType.CUSTOM -> return alarm.customDay
        }
    }

    fun getAlarmTypeStr(alarm: Alarm): String {
        return when (alarm.alarmType) {
            AlarmType.MUSIC -> "仅响铃"
            AlarmType.SHAKE -> "仅震动"
            AlarmType.BOTH -> "响铃和震动"
        }
    }
}

闹钟实体

package com.aijianji.module_sleep.entity

import com.fenghuajueli.greendao.entity.TextTaskEntity
import java.io.Serializable

/**
 *
 * @Description:
 * @author: GordenGao
 * @Email: gordengao124@gmail.com
 * @date: 2021年07月12日 15:45
 */
data class Alarm(
        var time: Pair<String, String>? = null,
        var frequencyType: FrequencyType = FrequencyType.EVERYDAY,
        var alarmType: AlarmType = AlarmType.SHAKE,
        var musicRes: Int = 0,
        var tag: String = "生活",
        var close: Boolean = false,
        var isReRing: Boolean = false,
        var taskType: TaskType = TaskType.NONE, // 闹钟任务,
        var taskList: ArrayList<TaskItem> = arrayListOf(),
        var customDay: MutableList<Int> = mutableListOf(),
        var isOpen: Boolean = false,
    // 只定时,需关闭音乐使用
        var isOnlyTiming: Boolean = false
) : Serializable

data class TaskItem(val taskType: TaskType, var classify: String, var times: Int) : Serializable

data class WordsItem(var selected: Boolean = false, val textEntity: TextTaskEntity)

val taskTextClassify = arrayListOf(
    "励志短句",
    "高难度短句",
    "我的短句"
)

val difficultLevel = arrayListOf(
    "非常简单",
    "简单",
    "一般",
    "较难",
    "地狱模式"
)
val difficultGameRowNum = arrayListOf(
    2, 3, 5, 7, 10
)
val difficultNumberEx = arrayListOf(
    "3+4=?",
    "11x12=?",
    "81x81=?",
    "666x256=?",
    "1024x1024=?"
)

val difficultGameEx = arrayListOf(
    "2x2 瓷砖",
    "3x3 瓷砖",
    "5x5 瓷砖",
    "7x7 瓷砖",
    "10x10 瓷砖"
)

enum class TaskType {
    NONE,
    TEXT,
    NUMBER,
    GAME
}

enum class AlarmType {
    MUSIC,
    SHAKE,
    BOTH
}

enum class FrequencyType {
    EVERYDAY,
    JUSTONE,
    DOUBLE,
    ONE,
    TWO,
    CUSTOM
}

**

初始化

**

private lateinit var alarm: Alarm


if (!this::alarm.isInitialized){
                    alarm = Alarm()
                    alarm.isOpen = true
                    alarm.isOnlyTiming = true
                    alarm.frequencyType = FrequencyType.JUSTONE
                }


if (this::alarm.isInitialized){
                val musicTimingTime = getMusicTimingTime(hour,minute)
                alarm.time = Pair(
                        musicTimingTime[0],
                        musicTimingTime[1]
                )
                AlarmUtil.setAlarm(this,alarm)
            }

广播接收(响铃)

package com.aijianji.module_sleep.receiver

import android.annotation.SuppressLint
import android.app.KeyguardManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.PowerManager
import android.os.PowerManager.WakeLock
import android.util.Log
import com.aijianji.module_sleep.entity.Alarm
import com.aijianji.module_sleep.mediaPlayer.MediaPlayerUtils
import com.aijianji.module_sleep.utils.AlarmUtil
import com.fenghuajueli.libbasecoreui.constants.AppConfigInfo
import com.google.gson.Gson



/**
 *
 * @Description:
 * @author: GordenGao
 * @Email: gordengao124@gmail.com
 * @date: 2021年07月13日 17:22
 */
class AlarmReceiver : BroadcastReceiver() {

    companion object {
        val BC_ACTION = "com.aijianji.action.BC_ACTION"
    }

    private val TAG = this.javaClass.simpleName
    private val CAMERA_PACKAGE_NAME = AppConfigInfo.APPLICATION_ID

    // 唤醒屏幕
    private var mPowerManager: PowerManager? = null
    private var mWakeLock: WakeLock? = null

    override fun onReceive(context: Context, intent: Intent) {
        Log.e("clock--", "定时到,关闭音乐")
        val alarmStr = intent.getStringExtra(AlarmUtil.ALARM)
        val alarm = Gson().fromJson(intent.getStringExtra(AlarmUtil.ALARM), Alarm::class.java)

        if (alarm.isOnlyTiming && MediaPlayerUtils.getInstance().isPlaying) {
            MediaPlayerUtils.getInstance().pause()
        }
    }


    @SuppressLint("Wakelock", "InvalidWakeLockTag")
    @SuppressWarnings("deprecation")
    fun wakeUpAndUnlock(context: Context) {
        // 获取电源管理器对象
        val pm = context
            .getSystemService(Context.POWER_SERVICE) as PowerManager
        // 获取PowerManager.WakeLock对象,后面的参数|表示同时传入两个值,最后的是调试用的Tag
        val wl = pm.newWakeLock(
            PowerManager.ACQUIRE_CAUSES_WAKEUP
                    or PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bright"
        )


        // 点亮屏幕
        wl.acquire()
        // 释放
        wl.release()
        // 得到键盘锁管理器对象
        val km = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
        val kl: KeyguardManager.KeyguardLock = km.newKeyguardLock("unLock")
        // 解锁
        kl.disableKeyguard()

    }

}

manifest文件添加

<receiver
            android:name=".receiver.AlarmReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.aijianji.action.BC_ACTION" />
            </intent-filter>
   </receiver>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值