Android版DailyInsist(五)——业务逻辑和数据操作SettingFragment & 小结

2023-05-16

最后一部分是提醒以及每天任务刷新,两者都用到了 AlarmManager 这个系统管理类。

提醒

提醒功能就是一个闹钟的效果,只是这里是启动服务,在服务里发一条notification作为提醒。设置时间时, TimePicker控件会监听该事件,每次时间改变后都会重新设置系统闹钟;如果用户关闭提醒功能的话,这个系统闹钟设置的事件也会取消。修改后的 SettingFragment如下:
<span style="font-size:24px;">@EFragment (R.layout.frag_setting )
public class SettingFragment extends BaseFragment {

      @ColorRes(R.color. setting_text_dark)
      int alarmColor;

      @ColorRes(R.color. main_bg)
      int remindColor;

      @ViewById
     ToggleButton tb_alarm;

      @ViewById
     TimePicker tp_alarm;

      @Pref
     GlobalPrefBean_ globalPrefBean;

      private boolean initViewFinished;

      @AfterViews
      void AfterViews() {
            initViewFinished = true;

            tp_alarm.setIs24HourView( true);
           Util. setNumberPickerTextSizeAndColor( tp_alarm, 25, alarmColor);
           Util. resizeTimerPicker( tp_alarm, 100, LayoutParams.WRAP_CONTENT );

            tp_alarm.setOnTimeChangedListener( new TimePicker.OnTimeChangedListener() {
                 @Override
                 public void onTimeChanged(TimePicker view, int hour, int min) {
                     onTimeSet(hour, min);
                }
           });

           initView();

           initPendingIntent();
     }

      @Override
      public void show() {
            if ( initViewFinished) {
                initView();
           }
     }

      void initView() {

           String alarmTime = globalPrefBean .alarmTime().getOr("" );
            if ( "".equals(alarmTime)) {
                 tp_alarm.setEnabled( false);
                 tb_alarm.setChecked( true);
                 tp_alarm.setCurrentHour(0);
                 tp_alarm.setCurrentMinute(0);
                 tb_alarm.setTextColor( remindColor);
           } else {
                 int hour = Integer.parseInt(alarmTime.subSequence(0, 2).toString());
                 int min = Integer.parseInt(alarmTime.subSequence(2, 4).toString());
                 tp_alarm.setEnabled( true);
                 tb_alarm.setChecked( false);
                 tp_alarm.setCurrentHour(hour);
                 tp_alarm.setCurrentMinute(min);
                 tb_alarm.setTextColor( alarmColor);
                setSystemAlarm(hour, min);
           }

     }

      @Click
      void tb_alarm() {
            if ( tb_alarm.isChecked()) {
                 tp_alarm.setEnabled( false);
                 tp_alarm.setCurrentHour(0);
                 tp_alarm.setCurrentMinute(0);
                 tb_alarm.setTextColor( remindColor);
                 globalPrefBean.alarmTime().put( "");
                cancelSystemAlarm();
           } else {
                 tp_alarm.setEnabled( true);
                 tb_alarm.setTextColor( alarmColor);
                 globalPrefBean.alarmTime().put( "0000");
                setSystemAlarm(0, 0);
           }
     }

      void onTimeSet( int hour, int min) {
            /*
            * init alarm time; if it is empty originally, do nothing, else set the
            * value to empty
            */
           String alarmTime = globalPrefBean .alarmTime().getOr("" );
            if ( "".equals(alarmTime)) {
                 return;
           } else {
                alarmTime = "";
           }

            if (hour < 10) {
                alarmTime += "0";
           }
           alarmTime += "" + hour;
            if (min < 10) {
                alarmTime += "0";
           }
           alarmTime += "" + min;

            globalPrefBean.alarmTime().put(alarmTime);
           setSystemAlarm(hour, min);
     }

      @SystemService
     AlarmManager alarmManager;

     PendingIntent pi;

      @Background
      void initPendingIntent() {
           Intent intent = new Intent(getActivity().getBaseContext(),
                     AlarmService_. class);
            pi = PendingIntent. getService(getActivity(), 0, intent,
                     PendingIntent. FLAG_UPDATE_CURRENT);
     }

      @Background
      void setSystemAlarm( int hour, int min) {
           Calendar c = Calendar. getInstance();
           c.setTimeInMillis(System. currentTimeMillis());
           c.set(Calendar. HOUR_OF_DAY, hour);
           c.set(Calendar. MINUTE, min);
           c.set(Calendar. SECOND, 0);
           c.set(Calendar. MILLISECOND, 0);
            long intervalMillis = c.getTimeInMillis() > System.currentTimeMillis() ? c
                     .getTimeInMillis()
                     : (c.getTimeInMillis() + AlarmManager.INTERVAL_DAY );
            alarmManager.setRepeating(AlarmManager. RTC, intervalMillis,
                     AlarmManager. INTERVAL_DAY, pi);
     }

      @Background
      void cancelSystemAlarm() {
            alarmManager.cancel( pi);
     }
}</span>

AlarmService服务很简单,就是在每次启动时调用 onStartCommand方法,检查今天是否已经签到,没有的话发一条通知给用户作为提醒,具体代码如下:
@EService
public class AlarmService extends Service {
      private MyDatabaseHelper dbHelper = null;

      @Override
      public int onStartCommand(Intent intent, int flags, int startId) {

            if ( dbHelper == null) {
                 dbHelper = new MyDatabaseHelper(getBaseContext(), "di.db3" , 1);
           }

           TaskBean task = DailyInsistDao.getcurrentTask( dbHelper);
            if (task != null && !task.isDoneToday()) {
                sendNotification();
           }
            return super.onStartCommand(intent, flags, startId);
     }

      @SystemService
     NotificationManager nManager;

      private void sendNotification() {
           Intent intent = new Intent(AlarmService. this,
                     DailyInsistActivity_. class);
           intent.setAction(Intent. ACTION_MAIN);
           intent.addCategory(Intent. CATEGORY_LAUNCHER);
           PendingIntent pi = PendingIntent.getActivity(AlarmService. this, 0,
                     intent, PendingIntent.FLAG_UPDATE_CURRENT );

            @SuppressWarnings( "deprecation")
           Notification notify = new Notification.Builder( this)
                     . setAutoCancel( true)
                     .setTicker( "来自DI的消息" )
                     .setSmallIcon(R.drawable. ic_launcher)
                     .setContentTitle( "一条新通知" )
                     .setContentText( "今天还有任务未签到~" )
                     .setDefaults(
                                Notification. DEFAULT_SOUND
                                           | Notification.DEFAULT_LIGHTS )
                     .setWhen(System. currentTimeMillis()).setContentIntent(pi)
                     . getNotification();

            nManager.notify(0xfff, notify);
     }

      @Override
      public IBinder onBind(Intent arg0) {
            return null;
     }
}

任务刷新

任务刷新的功能,就是在每天零点重置当前任务的状态为未签到,前提条件是该任务还没有结束。更改后通知MainFragment界面做出相应的更新,这段代码加在了主Activity里,即程序启动后就设置该系统闹钟:
     @SystemService
     AlarmManager alarmManager;

      /**
      *
      * @Method : setService
      * @Description : use alarm manager to start a service that reset a task to
      *               not done everyday at 00:00:00
      * @param
      * @return void
      * @throws
      */
      @Background
      void setService() {
           Intent intent = new Intent(DailyInsistActivity. this,
                     ResetTaskService_. class);
           PendingIntent pi = PendingIntent.getService(DailyInsistActivity. this,
                     0, intent, PendingIntent.FLAG_UPDATE_CURRENT );
           Calendar c = Calendar. getInstance();
           c.setTimeInMillis(System. currentTimeMillis());
           c.set(Calendar. HOUR_OF_DAY, 0);
           c.set(Calendar. MINUTE, 0);
           c.set(Calendar. SECOND, 0);
           c.set(Calendar. MILLISECOND, 0);
            long intervalMillis = c.getTimeInMillis() + AlarmManager.INTERVAL_DAY ;
            alarmManager. setRepeating(AlarmManager. RTC_WAKEUP, intervalMillis,
                     AlarmManager. INTERVAL_DAY, pi);
     }

ResetTaskService服务也很简单,每次启动时调用 onStartCommand方法,若任务未完成,重置任务状态为未签到:
@EService
public class ResetTaskService extends Service {
      private MyDatabaseHelper dbHelper = null;

      @Override
      public int onStartCommand(Intent intent, int flags, int startId) {

            if ( dbHelper == null) {
                 dbHelper = new MyDatabaseHelper(getBaseContext(), "di.db3" , 1);
           }

           TaskBean task = DailyInsistDao.getcurrentTask( dbHelper);
            if (task != null && task.getCompleted() < task.getDuring()) {
                DailyInsistDao. updateDoneState( dbHelper, task.getTaskId(), false );
                getBaseContext().sendBroadcast(
                            new Intent(Actions.ACTION_UPDATE_MAIN_INFO ));
           }
            return super.onStartCommand(intent, flags, startId);
     }

      @Override
      public IBinder onBind(Intent intent) {
            return null;
     }

}

MainFragment中做了部分代码修改,接收广播后更新界面,具体代码请查看源代码。
最后,为了保证关机开机都会执行任务刷新,增加了一个接收系统消息开机和唤醒解锁的广播,设置系统闹钟:
@EReceiver
public class PushReceiver extends BroadcastReceiver {

      @Override
      public void onReceive(Context context, Intent intent) {
           setSystemAlarm(context);
           setService(context);
     }

      @Pref
     GlobalPrefBean_ globalPrefBean;

      @SystemService
     AlarmManager alarmManager;

      @Background
      void setSystemAlarm(Context context) {
            int hour, min;
           String alarmTime = globalPrefBean .alarmTime().getOr("" );
            if ( "".equals(alarmTime)) {
                 return;
           } else {
                hour = Integer. parseInt(alarmTime.subSequence(0, 2).toString());
                min = Integer. parseInt(alarmTime.subSequence(2, 4).toString());
           }
           Intent intent = new Intent(context, AlarmService_.class );
           PendingIntent pi = PendingIntent. getService(context, 0, intent,
                     PendingIntent. FLAG_UPDATE_CURRENT);
            Calendar c = Calendar .getInstance();
           c.setTimeInMillis(System. currentTimeMillis());
           c.set( Calendar. HOUR_OF_DAY, hour);
           c.set( Calendar. MINUTE, min);
           c.set( Calendar. SECOND, 0);
           c.set( Calendar. MILLISECOND, 0);
            long intervalMillis = c.getTimeInMillis() > System.currentTimeMillis() ? c
                     .getTimeInMillis()
                     : (c.getTimeInMillis() + AlarmManager.INTERVAL_DAY );
            alarmManager.setRepeating(AlarmManager. RTC, intervalMillis,
                     AlarmManager. INTERVAL_DAY, pi);
     }

      @Background
      void setService(Context context) {
           Intent intent = new Intent(context, ResetTaskService_.class );
           PendingIntent pi = PendingIntent. getService(context, 0, intent,
                     PendingIntent. FLAG_UPDATE_CURRENT);
            Calendar c = Calendar .getInstance();
           c.setTimeInMillis(System. currentTimeMillis());
           c.set( Calendar. HOUR_OF_DAY, 0);
           c.set( Calendar. MINUTE, 0);
           c.set( Calendar. SECOND, 0);
           c.set( Calendar. MILLISECOND, 0);
            long intervalMillis = c.getTimeInMillis() + AlarmManager.INTERVAL_DAY ;
            alarmManager.setRepeating(AlarmManager. RTC_WAKEUP, intervalMillis,
                     AlarmManager. INTERVAL_DAY, pi);
     }
}

运行效果图:
源码下载:百度云

小结

自己测试了下,基本功能都已经完成了,但是没有全面地测试过,所以有bug或者建议,请大家告知,在此谢过。
有些额外的功能点,比如动画方面,暂时没打算做。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android版DailyInsist(五)——业务逻辑和数据操作SettingFragment & 小结 的相关文章

  • onBackPressed 仅关闭 ProgressDialog

    我意识到我的异步任务有一个小问题 我意识到 当我按 Android 设备上的后退按钮来关闭进度对话框和异步任务时 只有我的进度对话框被关闭 而我的异步任务仍在执行 我真的不知道为什么会发生这种情况 所以我只是希望有人能让我回到正确的轨道并帮
  • AdMob 广告未显示

    因此 我使用 Play Services SDK 实施了 AdMob 广告 我已经 按照书本 做了所有事情 但广告不会显示 如果我将 AdView 背景设置为白色 它会显示空白 但不显示广告 我正在使用 Fragments 但我将 AdVi
  • 如何使用 zXing 在 Android 中创建 IntentIntegrator

    我想创建一个对象IntentIntegrator在安卓中 IntentIntegrator integrator new IntentIntegrator ZBarReaderActivity this Here ZBarReaderAct
  • Android Surface 与 Canvas 的关系

    Surface 和 Canvas 之间到底是什么关系 请解释 表面是一个缓冲区 画布保存绘图 视图未附加到画布 也不是表面 窗户被绑在 Surface 和 ViewRoot 询问 随后使用的画布表面 通过要绘制的视图 详细答案你可以阅读这篇
  • Robolectric 1.2:“警告:无法找到 Android SDK 的路径”

    I used Robolectric 1 1 jar 与依赖项 在我的项目中并成功使其工作 但是当我将罐子更改为 1 2 SNAPSHOT jar 与依赖项 我收到以下警告 警告 无法找到 Android SDK 的路径 两个jar包都下载
  • 如何在状态更改时更改 Android 切换按钮的文本颜色?

    我的切换按钮对于每个状态都有不同的颜色背景 红色和白色 现在我需要在激活时更改切换按钮文本 红色 白色 的颜色 使用 xml 我无法让它工作 也许有人知道我做错了什么 我的布局 xml 中的按钮
  • com.google.android:android:jar 的 dependency.dependency.version' 丢失

    我正在尝试使用 Eclipse 运行一个简单的虚拟 Android 项目 并且我正在尝试使用 Maven amd 我已按照已接受答案的教程进行操作this https stackoverflow com questions 6735562
  • 如何在Android中将文件转换为base64(如.pdf、.text)?

    如何将 SD 卡文档 pdf txt 转换为 Base 64 字符串并将字符串发送到服务器 这个方法对我有用 String encodeFileToBase64Binary encodeFileToBase64Binary yourFile
  • Android - 对话框内VideoView的MediaController出现在对话框后面

    我有一个VideoView在自定义对话框中 我正在为VideoView即时并将其分配给VideoView在代码中 但是控制器实际上并没有出现在视频上 它出现在对话框后面 知道如何让控制器位于视频上方吗 我创建了一个静态对话框帮助器类来帮助构
  • GpsStatusListener:尽管状态为 GpsStatus.GPS_EVENT_FIRST_FIX,但修复中未使用卫星

    我向我的位置管理器添加了一个 GPS 状态侦听器 以便查看何时获得第一个修复 当我收到 GPS EVENT FIRST FIX 时 我会循环遍历所有卫星 但为什么修复中没有使用它们 usedInFix 我的日志对所有卫星都显示 错误 fin
  • Android 原生 AAssetManager 的文件层次结构

    Issue 我想知道如何从本机代码创建 Android 中资产文件夹的文件层次结构 我在用着AAssetManager openDir but AAssetDir getNextFileName不返回任何目录名称 因此基本上我无法深入了解层
  • 设置 ViewGroup 的最大宽度

    如何设置 ViewGroup 的最大宽度 我正在使用一个Theme Dialog然而 当调整大小到更大的屏幕时 它看起来不太好 它也有点轻量级 我不希望它占据整个屏幕 I tried 这个建议 https stackoverflow com
  • Android appwidget 远程视图未更新

    当我从某些活动更新小部件时 列表远程视图不会更新 我的意思是刷新自身 它会出现直到应用程序小部件的更新 日志显示 但不会进入列表视图的适配器以用新数据填充它 public void onUpdate Context context AppW
  • 为什么我的字体大小在 android webview 对象中看起来比在 android 浏览器中查看时大得多?

    我正在尝试制作一个小型 Android 应用程序 它除了在 webview 对象而不是浏览中显示网站之外什么也不做 到目前为止它加载了目标网页 但文本和图像大小都比查看页面时大得多在实际设备浏览器中 在浏览器中 页面看起来正确 但在我的应用
  • 应用程序启动器图标显示在活动的操作栏上

    在我的操作栏上显示应用程序图标 我不希望它出现在操作栏上 我修改了 androidmanifest xml 并删除了android icon从活动元素中 即使图标正在显示
  • 如何强制刷新 CallLog.Calls.CACHED_NAME 列?

    我的目标是从通话记录中收集所有未知的电话号码 这可以通过以下代码来实现 private static final String CALLOG PROJECTION CallLog Calls ID CallLog Calls CACHED
  • 如何在清单文件中添加符合我意图的标志

    我们知道 我们可以使用 java 代码中的 addFlags 方法将一些标志添加到我们的意图中 有什么方法可以将这些标志添加到清单文件本身中 而不是用 java 代码编写 我需要为清单中的一项活动添加 REORDER TO FRONT 标志
  • API 24 AccessibilityService.dispatchGesture() 方法如何工作?

    通过 API 24 我们有了一种向设备发送手势的方法 但是目前还没有可靠的文档或示例 我正在尝试让它工作 但目前手势每次都会点击 onCancelled 回调 这是我调用该方法的代码 TargetApi 24 private void pr
  • Android - onLoadFinished 未调用

    我遇到了装载机的问题 我有一个活动 它显示从本地数据库检索的记录列表 当活动启动时 记录会通过 LoaderManager initLoader 方法自动加载 还可以通过 ActionBarSherlock 中的刷新按钮手动刷新列表 但是
  • 在片段视图之间切换

    在 xml 布局文件中声明片段的标准方法是

随机推荐

  • 虚拟机创建、发放与迁移

    虚拟机创建方法 xff1a 创建空虚拟机虚拟机克隆虚拟机 xff1a 虚拟机运行状态是可以克隆虚拟机的按照模板部署虚拟机 xff1a 模板存在 xff0c 可以调整参数 xff0c 批量部署模板转为虚拟机 xff1a 模板不存在 xff0c
  • Linux必学书籍!五本强烈推荐,你读过几本?

    深入理解Linux内核 推荐等级 xff1a 5颗星 为了透彻理解Linux的工作机理 xff0c 以及为何它在各种系统上能顺畅运行 xff0c 你需要深入到内核的心脏 cPu与外部世界的所有交互活动都是由内核处理的 xff0c 哪些程序会
  • 一个毕业6年的程序员工作经历和成长感悟(终)

    接上篇 xff1a 一个毕业6年的程序员工作经历和成长感悟 xff08 上 xff09 一个毕业6年的程序员工作经历和成长感悟 xff08 中 xff09 一个毕业6年的程序员工作经历和成长感悟 xff08 下 xff09 回望过去 6 年
  • 红包随机算法,给定一定的金额,一定的人数,保证每个人都能随机获得一定的金额。...

    前段时间做了一个笔试题 xff0c 觉得很有意思 xff0c 特此记录下来 题目如下 题目 请编写一个红包随机算法 需求为 xff1a 给定一定的金额 xff0c 一定的人数 xff0c 保证每个人都能随机获得一定的金额 比如100元的红包
  • linux下 ftp服务器如何设置上传文件的权限

    先用vi打开 vsftpd conf vsftpd的配置文件在Ubuntu下是vi etc vsftpd conf在centos 下是vi etc vsftpd vsftpd conf这个在不同的系统下可能不同原理一样 找到umask默认是
  • 敏捷之旅大连2013总结回顾

    12月21日 xff0c 敏捷之旅大连站如期召开 xff0c 这是今年我在大连组织的第九次程序员社区活动 xff0c 在此简单总结一下 这次活动考虑到参会人员会比平时多一些 xff0c 所以选择了中山区的比较大的会议室 xff0c 从十二点
  • 1062 Talent and Virtue

    About 900 years ago a Chinese philosopher Sima Guang wrote a history book in which he talked about people 39 s talent an
  • 演说(zhi)之法

    近年来 xff0c 参加了很多各种各样的技术会议 xff0c 在其中也听了很多高手和牛人们的演说 在总结了自己的一些经验之后 xff0c 也会在一些场合和大家分享 在以上的过程中 xff0c 越来越觉得 xff0c 想要为听众们奉献一场精彩
  • 窗体继承,然后实现按钮点击事件的重写

    做了一阵子Winform的程序之后 xff0c 越来越能够做到把窗体 控件等都看作类来对待了 以前做VB的时候 xff0c 对这些控件都是有一种敬畏的心理 xff0c 根本就不敢对其做什么 xff0c 而且当时也的确做不了什么 xff0c
  • 参加百度轻应用编程马拉松总结

    上个周末 xff0c 我到北京参加了百度举办的轻应用编程马拉松大赛 xff0c 感觉非常不错 xff0c 在此总结一下 这是我第一次参加编程马拉松的活动 xff0c 对此充满了好奇也充满了期望 xff0c 更是希望自己以后也能够组织类似的活
  • 前天奶奶来了 xff0c 把屋子里面的东西都收拾了一下 xff0c 尤其是佳佳的玩具 xff0c 有好多毛绒玩具 xff0c 都放在一个柜子的层里面了 早上佳佳醒来 xff0c 发现了新大陆 xff01 美羊羊都碰头了 xff01 维尼的碰
  • 超级简单的抽奖工具

    昨天快到中午的时候接到业务部门的一个需求 xff0c 要求对现有的抽奖软件进行改进 问题是 xff1a 现在的抽奖软件每次只能够抽出一个中奖号码 xff0c 而此次设置的各种奖项的中奖人数加起来有500人 xff0c 如果使用原有的软件 x
  • 程序员应知——把小事做好

    在从事软件开发的这些年中 xff0c 近期越来越多地听到这样的论点 xff1a 当前的程序员越来越浮躁 我的感觉也是如此 xff0c 由于在软件公司中 xff0c 人才流动特别快 xff0c 因此很多人的职位也变化的比较快 xff0c 很可
  • 程序员应知——学习、思考与分享

    有人说 xff0c 程序员是个苦差事 xff0c 一辈子总是要不停地学习 xff0c 学习新的技术 xff0c 学习新的架构 xff0c 学习新的工具 xff0c 一旦一段时间不学习 xff0c 就会发现其他人嘴里冒出来的新鲜词 xff0c
  • Evernote和有道云笔记的比较

    每个人可能都有随手记录一些事情的习惯 xff0c 可能是为了不忘记 xff0c 也可能是随时闪现在头脑中的一些想法 xff0c 因此就有了便利贴 xff0c 而在计算机或者说互联网的时代 xff0c 我们就有了更多选择 xff0c 可以随时
  • 软件开发中的哲学——世界的本原是物质(一)

    在这个系列博客的第一篇中 xff0c 首先要涉及到的哲学原理就是 世界的本原是物质 在IT领域 xff0c 有硬件和软件之分 xff0c 而二者之间的关系 xff0c 就和物质与精神类似 没有硬件的存在 xff0c 那么软件就没有能够发挥作
  • 在Prezi中输入简体中文的完美解决方案

    Prezi是一种在线制作演示文档 xff08 PPT xff09 的工具 xff0c 它与传统的Powerpoint或者Keynote的表现形式完全不同 xff0c 被称为 powerpoint的颠覆者 xff0c 在36Kr上曾经有过多篇
  • 1001 A+B Format

    Calculate a 43 b and output the sum in standard format that is the digits must be separated into groups of three by comm
  • 打印机打印列队中打印状态为错误的解决方式之一

    右键 我的电脑 xff08 win7以上为 计算机 xff09 xff0c 点击 管理 xff0c 展开 服务和应用程序 xff0c 点击 服务 找到右侧的 print spooler 项 xff0c 右键选择 停止 win 43 R打开运
  • Android版DailyInsist(五)——业务逻辑和数据操作SettingFragment & 小结

    最后一部分是提醒以及每天任务刷新 xff0c 两者都用到了 AlarmManager 这个系统管理类 提醒 提醒功能就是一个闹钟的效果 xff0c 只是这里是启动服务 xff0c 在服务里发一条notification作为提醒 设置时间时