Android Alarm闹钟API使用心得

这篇具有很好参考价值的文章主要介绍了Android Alarm闹钟API使用心得。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

有什么办法可以在不打开App的时候,也能够触发一些操作呢?比如说发送通知,解决这个需求的办法有很多种选择,比如说官方推荐的WorkManager API,可以在后台执行一次性、耗时、定时的任务,但WorkManager是严格遵循电池优化策略的,也就是并不精准,虽然你可以设置为加急任务,但也还是不能满足精准时间。

所以,想要在精准时间触发通知,就只能使用Alarm了。

前置准备

理清自己需要的闹钟类型,首先选择闹钟类型:

“经过的时间”闹钟:

从设定闹钟开始计时,经过特定的时间触发的闹钟,与时区、语言无关

实时闹钟:

基于世界协调时间(UTC),一般情况下,按照现实时间触发的闹钟,但该方法会受到用户改变系统时间时受到影响。

是否唤醒CPU

选择完闹钟类型后,还需确定闹钟是否能够唤醒设备,正常情况下,关闭屏幕后一段时间,CPU就会陷入“睡眠状态”,非唤醒闹钟会等待CPU“醒来”的时候才一起触发,唤醒闹钟则会直接唤醒CPU直接触发。

实现定时不重复闹钟

我们先来测试一个定时,能够唤醒CPU仅此一次的闹钟,来发送一条通知

如果target SDK为31以上,且没有被加入电池优化策略白名单,则还需要在manifest文件中添加精确闹钟权限,该权限会在安装时授予。

如果target SDK为33以上,发送通知需要通知权限,该权限需要在发送通知前主动向系统请求,不然发不了通知


    <!--通知权限-->
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <!--闹钟权限-->
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

首先先创建一个广播接收器,这个广播接收器用来执行闹钟时间到的时候,我们需要执行的逻辑代码,例如发送一条通知(通知权限的请求本文不再书写,默认视为你已获得通知权限),本文使用的广播接收器是MyAlarmReceiver,闹钟时间到的时候,会发送一条通知,标题是My notification,内容为Hello World! 加一个随机数。

import android.Manifest;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;

import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;

import java.util.Random;


public class MyAlarmReceiver extends BroadcastReceiver {

    String CHANNEL_LOCATION_ID = "myAlarm";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e("TAG", "onReceive: NOTIFY_ALARM" );
        int count = new Random().nextInt(100);
        NotificationManager notificationManager = ContextCompat.getSystemService(context, NotificationManager.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            int importance = NotificationManager.IMPORTANCE_DEFAULT;
            NotificationChannel channel = new NotificationChannel(CHANNEL_LOCATION_ID, CHANNEL_LOCATION_ID, importance);
            channel.setDescription("test");
            notificationManager.createNotificationChannel(channel);
        }
        //通知的普通点按操作
        Intent intentN = new Intent(context, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 202, intentN, PendingIntent.FLAG_IMMUTABLE);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context,CHANNEL_LOCATION_ID)
                .setSmallIcon(R.drawable.notification_icon_blue)//发送通知必须指定一个smallIcon,背景需透明
                .setContentTitle("My notification")
                .setContentText("Hello World!"+ count)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setContentIntent(pendingIntent);
        //发送通知,检查权限
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        NotificationManagerCompat.from(context).notify(count, builder.build());
    }
}

当然,别忘了在AndroidManifest.xml中注册我们新增的receiver

<application>
    ...
        <receiver android:name=".MyAlarmReceiver"
            android:exported="false"
            >
        </receiver>
</application>

 想要设置一个闹钟,就需要给系统的闹钟服务发送一个类似“预定”一样的意图,下面这段代码我设置在17点20分0秒的闹钟,时间到的时候,系统的闹钟服务就会发送一条广播到我们的广播接收器MyAlarmReceiver,根据接收到的广播进行对应的逻辑操作。

    private AlarmManager alarmManager;
    private PendingIntent pendingIntent;
    private String packageName;
    ...
    private void initAlarm(Context context){
        Intent intent = new Intent(context,MyAlarmReceiver.class);
        pendingIntent = PendingIntent.getBroadcast(
                context,
                0,
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );
        alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    }

    private void setOneAlarm(){
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY,17);
        calendar.set(Calendar.MINUTE,20);
        calendar.set(Calendar.SECOND,0);
        Log.i("TAG", "notify time: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime()));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Log.w("TAG", "alarm: must" );
         alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),pendingIntent);
        }else{
            Log.w("TAG", "alarm: normal" );
            alarmManager.setExact(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),pendingIntent);
        }
    }

好了,前置准备我们都做完了 ,只要触发setOneAlarm()方法就设定了一个闹钟,系统的闹钟服务会在17点20分0秒发送一条广播,触发MyAlarmReceiver类中的onReceive()方法,就能发送一条通知了。

但是

你的手机如果是三星或谷歌的pixel,以上方法就已经足够了。如果你的手机是国产定制化过的系统

例如小米的MIUI,华为,VIVO,OPPO等手机的话,我们还需要获取由定制系统接管的权限,拿小米的MIUI举例,这个权限叫做 自启动权限 没有这个权限的情况下不一定能触发这个闹钟(大部分时间都无法触发)

打开App的应用设置页面我们就能看到这个权限,其他系统也基本同理,不在应用信息中就在手机管家中

Android Alarm闹钟API使用心得,Android,android

 把这个自启动开关打开,再去设定闹钟,就能触发一个定时闹钟了。

实现重复闹钟且自动取消

重复闹钟的实现很简单,只需要设定闹钟的时候使用setRepeating方法,就能指定第一次闹钟的时间,以及重复的间隔。但想要自动取消该怎么办呢?

想要取消闹钟,就需要调用闹钟服务的cancel()方法,且传递一个一样的pendingIntent

其实实现方法很简单,只需要再定一个取消的闹钟就行了。

给我们的Receiver区分一下不同的闹钟做什么事,根据intent中的"enable"值来区分是发送通知还是取消闹钟。

为1的时候,就发送通知,为0的时候就取消闹钟。

import android.Manifest;
import android.app.AlarmManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;

import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;

import java.util.Random;


public class MyAlarmReceiver extends BroadcastReceiver {

    public static final String NOTIFY_ALARM = "tdsss.myalarmnotify1.MyAlarmReceiver";
    public static final String CANCEL_ALARM = "tdsss.myalarmnotify1.cacelAlarm";

    String CHANNEL_LOCATION_ID = "myAlarm";

    @Override
    public void onReceive(Context context, Intent intent) {
        int isEnable = intent.getIntExtra("enable",-1);
        Log.e("TAG", "alarm onReceive: " );
        switch (isEnable){
            case 1:
                Log.e("TAG", "onReceive: NOTIFY_ALARM" );
                int count = new Random().nextInt(100);
                NotificationManager notificationManager = ContextCompat.getSystemService(context, NotificationManager.class);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    int importance = NotificationManager.IMPORTANCE_DEFAULT;
                    NotificationChannel channel = new NotificationChannel(CHANNEL_LOCATION_ID, CHANNEL_LOCATION_ID, importance);
                    channel.setDescription("test");
                    notificationManager.createNotificationChannel(channel);
                }
                //通知的普通点按操作
                Intent intentN = new Intent(context, MainActivity.class);
                PendingIntent pendingIntent = PendingIntent.getActivity(context, 202, intentN, PendingIntent.FLAG_IMMUTABLE);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context,CHANNEL_LOCATION_ID)
                .setSmallIcon(R.drawable.notification_icon_blue)//发送通知必须指定一个smallIcon,背景需透明
                .setContentTitle("My notification")
                .setContentText("Hello World!"+ count)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setContentIntent(pendingIntent);
                //发送通知,检查权限
                if (ActivityCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
                    return;
                }
                NotificationManagerCompat.from(context).notify(count, builder.build());
                break;
            case 0:
                Log.e("TAG", "onReceive: CANCEL_ALARM" );
                Intent cancel = new Intent(context,MyAlarmReceiver.class);
                cancel.setAction(MyAlarmReceiver.NOTIFY_ALARM);
                intent.putExtra("enable",1);
                PendingIntent cancelPendingIntent = PendingIntent.getBroadcast(
                        context,
                        0,
                        cancel,
                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
                );
                AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
                alarmManager.cancel(cancelPendingIntent);
                break;
            default:
                Log.e("TAG", "onReceive: " );
                break;
        }
    }
}

    private void setRepeatAlarmAndCancel(){
        alarmManager.cancel(pendingIntent);
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY,17);
        calendar.set(Calendar.MINUTE,30);
        calendar.set(Calendar.SECOND,0);
        Log.e("TAG", "notify time: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime()));
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),1000*60*1,pendingIntent);
        //cancel alarm
        Calendar cancelTime = Calendar.getInstance();
        cancelTime.set(Calendar.HOUR_OF_DAY,17);
        cancelTime.set(Calendar.MINUTE,35);
        cancelTime.set(Calendar.SECOND,0);
        Log.e("TAG", "cancel time: "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(cancelTime.getTime()));
        Intent cancelIntent = new Intent(getContext(),MyAlarmReceiver.class);
        cancelIntent.setAction(MyAlarmReceiver.CANCEL_ALARM);
        cancelIntent.putExtra("enable",0);
        PendingIntent cancelPendingIntent = PendingIntent.getBroadcast(getContext(),2,cancelIntent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Log.e("TAG", "alarm: must" );
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,cancelTime.getTimeInMillis(),cancelPendingIntent);
        }else{
            Log.e("TAG", "alarm: normal" );
            alarmManager.setExact(AlarmManager.RTC_WAKEUP,cancelTime.getTimeInMillis(),cancelPendingIntent);
        }
    }

设定完以后,系统就会在17点30分0秒时,发送5条通知,然后自动取消不再重复,还有更多的扩展用法就自己摸索啦!本文只是简单的使用一下~文章来源地址https://www.toymoban.com/news/detail-651801.html

到了这里,关于Android Alarm闹钟API使用心得的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android: alarm定时很短时,比如500ms,测试执行mPowerManager.forceSuspend()后,系统不会suspend

    参考文档: https://blog.csdn.net/weixin_35691921/article/details/124961404 Android: alarm定时很短时,比如500ms,然后执行mPowerManager.forceSuspend()后,系统不会suspend,原因分析:

    2024年01月22日
    浏览(46)
  • Android 操作系统日历完成提醒功能 附带开关闹钟 适配高版本安卓

    如果想要一个稳定且不用担心生命周期的提醒方式,可以试试利用系统日历去完成任务的提醒或某个活动的预约。 项目仓库地址在文末 环境 Java 11 Android sdk 30 Gredle 7.1 测试机型 mi 8(安卓 9) mi10 pro(安卓11) huawei m8(安卓7) 日历操作表 ​ 其实完成这个功能本质是对安卓原

    2024年02月03日
    浏览(43)
  • Android Studio课程心得

    Android Studio 课程是我学习 Android 开发过程中的一次非常宝贵的经历。在这门课程中,我学习了如何使用 Android Studio 进行 Android 应用程序的开发,并且通过完成项目和作业来实践和巩固所学知识。在学习的过程中我遇到了一些困难,但是通过不断地尝试和探索,最终我都找到了

    2024年02月02日
    浏览(39)
  • Android 逆向工程,反编译心得

    apk的反编译是我们在Android开发中绕不开的一个坎,对于反编译这门技术,我们应该抱着学习的态度,学的越多,也越能防备别人反编译我们,这就是所谓的知己知彼吧,哈哈 Apktool ,解包和重新打包都需要它 dex-tools ,可以直接把apk中的classes.dex文件反编译为.jar文件 jd-gui ,

    2024年02月06日
    浏览(164)
  • Android studio心得——fragment动态加载

    在Android应用程序中,Fragment是一种可以嵌入Activity中的组件。通过 Fragment,我们可以将UI 目录 前言 一、什么是Android Studio 二、简介Fragment 三、学期知识汇总 四、什么是碎片(Fragment) 五、页面实现步骤 1.程序APP主界面的常用例子 2.定义4个Fragment 3.activity_main.xml代码展示 4.四个

    2024年02月09日
    浏览(41)
  • Android Studio心得-创建登录注册项目

            首先先了解AndroidStudio是什么:Android Studio是一个由谷歌开发的Android应用程序开发环境,用于开发Android应用程序。它基于JetBrains IntelliJIDEA软件,并包含了许多定制化功能,包括易于使用的分析工具、内存分析工具和代码编辑器等,支持Java、Kotlin等多种编程语言。An

    2024年02月05日
    浏览(56)
  • Android使用postman实现模拟api接口

    需要本地模拟数据,后期需要删除模拟数据,这种操作会带来一定的工作量,并且还有误操作可能; 前端和后台的api接口基于wiki文档。在api定义好后,如果有变更,则需要修改wiki文档,而且其他端并不能及时通知到,会增加一定的沟通成本; 如果api接口有变更,前端的模拟

    2024年04月28日
    浏览(24)
  • Android中使用原生MediaRecorder APi实现录音功能

    一、MediaRecorder简介 MediaRecorder是Android中的一个API,可以用来实现录音功能。它继承自android.media.MediaRecorder类,可以实现音频和视频的录制。 二、MediaRecorder的使用 1、首先,实例化一个MediaRecorder对象,并设置音频源: 2、设置音频的输出格式: 3、设置音频的编码格式: 4、设

    2024年02月09日
    浏览(44)
  • Rockchip Android13 x3588蓝牙wifi/bt调试心得

    x3588的wifi/bt使用的是外挂双模模块,根据数据通信接口的差异分为PCIE和SDIO两种。 x3588使用的是SDIO接口双模模块:AP6398S。 参考rockchip android13: rk3588-x3588-sdk.dts 蓝牙配置: uart的rts脚:UART_CTS_N 复位脚:BT_REG_ON-BT_REG_ON_S-BT_REG_ON_H CPU唤醒蓝牙GPIO:脚:BT_WAKE 蓝牙唤醒CPU模块的GPI

    2024年02月15日
    浏览(127)
  • Flutter Navigator 2(1),一个Android程序员的面试心得

    onPressed: () { Navigator.pushNamed( context, ‘/details/1’, ); }, ), ), ); } } class DetailScreen extends StatelessWidget { String id; DetailScreen({ this.id, }); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(‘Viewing details f

    2024年04月12日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包