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

最后一部分是提醒以及每天任务刷新,两者都用到了 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);
     }
}


运行效果图:
Android版DailyInsist(五)——业务逻辑和数据操作SettingFragment & 小结_第1张图片

源码下载:百度云

小结

差不多花了一周时间写这个小程序,也没做什么详细的设计,就是想到哪做到哪。运用的知识点也都比较基础。
自己测试了下,基本功能都已经完成了,但是没有全面地测试过,所以有bug或者建议,请大家告知,在此谢过。
有些额外的功能点,比如动画方面,暂时没打算做。

你可能感兴趣的:(android,dailyinsist)