zoukankan      html  css  js  c++  java
  • Android学习笔记之AlarmManager有关的定时器和闹钟的实现

      毕业设计中有个功能模块叫就医提醒,大抵的功能就是用户设定一个未来时间的闹钟,并设置闹钟的标签,标签上写着去哪里就医之类的信息,主要设计参考魅族系统自带的闹钟功能。我在网上看了不少博客,也在github上下载了不少源码,发现也没有写的特别好的,总有这种或者那种的问题,比如说闹钟不是写成后台服务的模式,APP关闭之后闹钟不会提醒,或者手机关机之后之前设置的闹钟信息丢失,所以我准备自己写一个功能比较齐全的。

      所以这个闹钟的功能需要用到Android的数据库Sqlite、Service、BroadcastReceiver三大比较重要的模块,之前在看《第一行代码》时,由于看的比较匆忙,所以书本后面的部分知识点学习的并不扎实,书中的代码并没有亲自在IDE中敲一敲,所以借着五一假期三天又重头好好看了一遍《第一行代码》中关于数据库Sqlite、Service、BroadcastReceiver的部分。

      Sqlite是一个轻量级的Android内置数据库,通常只占几百KB的内存,所以在移动设备上也非常的适用。创建数据库的表如下,并写了一个Helper类对数据库操作进行了封装,简化了底层操作数据的操作。

     1 public class AlarmDBHelper extends SQLiteOpenHelper{
     2     public static final String DATABASE_NAME = "userinfo.db";
     3     public static final int DATABASE_VERSION = 2;
     4     public static final String TABLE = "alarm";
     5 
     6 
     7     private static final String CREATE_ALARM_TABLE = "CREATE TABLE " + TABLE + " ("
     8             + AlarmColumn._ID + " integer primary key AUTOINCREMENT,"
     9             + AlarmColumn.ALARM_ID + " text UNIQUE ON CONFLICT REPLACE,"
    10             + AlarmColumn.ALARM_CALENDAR + " text,"
    11             + AlarmColumn.ALARM_CANCELABLE + " text,"
    12             + AlarmColumn.ALARM_TAG + " text,"
    13             + AlarmColumn.ALARM_AVAILABLE + " text,"
    14             + AlarmColumn.ALARM_RINGTONE + " text)";
    15 
    16     public AlarmDBHelper(Context context) {
    17         super(context, DATABASE_NAME, null, DATABASE_VERSION);
    18     }
    19 
    20     @Override
    21     public void onCreate(SQLiteDatabase db) {
    22         db.execSQL(CREATE_ALARM_TABLE);
    23     }
    24 
    25     @Override
    26     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    27         String sql=" DROP TABLE IF EXISTS "+TABLE;
    28         db.execSQL(sql);
    29         onCreate(db);
    30     }
    31 }

    若要修改原先的数据库,只需要在 dbHelper = new AlarmDBHelper(this, "userinfo.db", null, 3); 中增加version的版本号即可。数据库的操作无非就是CRUD,C代表添加(Create),R代表查询(Retrieve),U代表更新(Update),D代表删除(Delete)。操作基本与SQL相同,同时官方支持使用SQL语句建立数据库和CRUD。其中查询数据库设计到一个新的数据类型——Cursor,本意为光标,可以理解为数据库中每行的内容。cursor.moveToFirst()移动到表中的第一行,cursor.moveToNext() 即指移动到下一行。上述代码即创建一个闹钟的 table ,将创建闹钟所需的一些信息保存在数据库中。

     1 public class BootReceiver extends BroadcastReceiver{
     2     @Override
     3     public void onReceive(Context context, Intent intent) {
     4         ArrayList<Alarm> alarms = getAllAlarms(context);
     5         for (Alarm alarm : alarms) {
     6             // Test
     7             // 当重启后,所有的都应该恢复,而如果这是定时任务,那么只要恢复月度和年度的就可以了.
     8             // 如果每天00:00重建闹钟的话,那么00:00时响的闹钟会不会响呢
     9             // 所以最后错开一点,因为闹钟没有秒数,所以设置为00:00:30秒何如。
    10             // 不论是什么闹钟,都会保证如果第二天有闹钟的话就会设置上的,所以不用担心00:00的闹钟不会设置上
    11             alarm.activate();
    12         }
    13     }
    14 
    15     /**
    16      * 从本地数据库恢复所有的闹钟
    17      *
    18      * @return
    19      */
    20     private ArrayList<Alarm> getAllAlarms(Context context) {
    21         AlarmHelper helper = new AlarmHelper(context);
    22         return helper.getAlarms();
    23     }
    24 }

    并注册一个广播监听开机的action,每当开机时将所有的alarm从数据库中都出来,并激活所有的闹钟,即AlarmReceive监听所有闹钟。

     1  private void setOneTimeAlarm() {
     2         if (AudreyCalendar.getTimeInMillis() - System.currentTimeMillis() > 0) {
     3             // 最后一个参数必须是PendingIntent.FLAG_UPDATE_CURRENT,否则BroadcastReceiver将收不到参数。
     4             PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext,
     5                     0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
     6             AlarmManager manager = (AlarmManager) mContext
     7                     .getSystemService(Context.ALARM_SERVICE);
     8             manager.set(AlarmManager.RTC_WAKEUP,
     9                     AudreyCalendar.getTimeInMillis(), pendingIntent);
    10         } else {
    11             Toast.makeText(mContext, "小伙子,设置太早闹钟是不会执行滴!",
    12                     Toast.LENGTH_SHORT).show();
    13         }
    14     }

    通过这样数据库中的闹钟会在 setOneTimeAlarm() 设置响铃的时间。AlarmReceive 中的代码如下,

     1 public class AlarmReceiver extends BroadcastReceiver{
     2 
     3     @Override
     4     public void onReceive(Context context, Intent intent) {
     5 
     6         Alarm alarm=new Alarm(context, intent.getExtras());
     7         Intent intent2=new Intent();
     8         intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     9         intent2.setClass(context, RingActivity.class);
    10         intent2.putExtras(Alarm.alarm2Bundle(alarm));
    11         context.startActivity(intent2);
    12 
    13 
    14 
    15     }
    16 }

    通过Receive中的方法启动RingActivity,触发响铃的操作,整个闹钟的逻辑就完成了。

    按理说,闹钟的实现应该通过service实现,这样就可以使得即使app关闭时,后台的闹钟也是在运行的,不过如何在service中启动一个闹钟我不知道如何实现。整个的逻辑应该是当设置好闹钟的属性,点击增加闹钟时,闹钟的信息被保存在数据库中,同时触发一个service启动,在service服务中接受alarm中的信息,设置后一个

     PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext,
     5                     0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
     6             AlarmManager manager = (AlarmManager) mContext
     7                     .getSystemService(Context.ALARM_SERVICE);
     8             manager.set(AlarmManager.RTC_WAKEUP,
     9                     AudreyCalendar.getTimeInMillis(), pendingIntent);   将getBroadcast改成getActivity,跳转到RingActivity即可实现整个的逻辑。


    因我的代码借鉴了他人的代码,导致我在代码的阅读中陷入了极大的混乱,同时整个的逻辑也非常的不清晰,造成了代码工作非常缓慢的事实,此后我必须在阅读他人的代码的基础上理解整个逻辑实现,理清思路,完成自己的设计。
  • 相关阅读:
    WGS84经纬度坐标与web墨卡托之间的转换【转】
    ArcGIS API for Javascript配置
    百度地图BMap API实例
    VS2010 Web项目需要缺少的Web组件才能加载
    单态模式
    对服务的操作
    根据子级ID获取其所有父级
    在DropDownList里显示多级分类
    jQuery给CheckBox添加事件
    FolderBrowserDialog使用
  • 原文地址:https://www.cnblogs.com/fengmanlou/p/4477997.html
Copyright © 2011-2022 走看看