【冠亚体育手机网站】定时提醒,简单实现Android闹钟功能

闹钟的简单实现,只有显示时间和设置闹钟。

前言
近期研究了下APP中实现定时提醒功能。几经周折算是产出了一个方案。这绝对不是最优的方案,但起码是可用的、相对简单稳定的,希望对大家的实际开发工作有所帮助。喜欢探讨Android开发技术的同学可以加学习小组QQ群:
193765960

AlarmView

版权归作者所有,如有转发,请注明文章出处:http://www.jianshu.com/u/d43d948bef39

package com.example.lenovo.clock2; 

import android.app.AlarmManager; 
import android.app.PendingIntent; 
import android.app.TimePickerDialog; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.icu.util.Calendar; 
import android.os.Build; 
import android.support.annotation.Nullable; 
import android.support.annotation.RequiresApi; 
import android.support.v7.app.AlertDialog; 
import android.util.AttributeSet; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.LinearLayout; 
import android.widget.ListView; 
import android.widget.TimePicker; 

import java.util.Date; 

/** 
 * Created by lenovo on 2017/11/20. 
 */ 
//闹钟 
public class AlarmView extends LinearLayout { 
// public AlarmView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 
//  super(context, attrs, defStyleAttr); 
// } 

 public AlarmView(Context context, @Nullable AttributeSet attrs) { 
  super(context, attrs); 
  init(); 
 } 
 public AlarmView(Context context) { 
  super(context); 
  init(); 
 } 

 private void init(){ 
  alarmManager= (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); 
 } 

 @RequiresApi(api = Build.VERSION_CODES.N) 
 @Override 
 protected void onFinishInflate() { 
  super.onFinishInflate(); 

  btnAddAlarm=findViewById(R.id.btnAddAlarm); 
  lvAlarmList=findViewById(R.id.lvAlarmList); 

  adapter=new ArrayAdapter<AlarmView.AlarmData>(getContext(),R.layout.support_simple_spinner_dropdown_item); 
  lvAlarmList.setAdapter(adapter); 
  readSavedAlarmList(); 

  //adapter.add(new AlarmData(System.currentTimeMillis())); 

  btnAddAlarm.setOnClickListener(new OnClickListener() { 
   @RequiresApi(api = Build.VERSION_CODES.N) 
   @Override 
   public void onClick(View view) { 
    addAlarm(); 
   } 
  }); 

  lvAlarmList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener(){ 
   @Override 
   public boolean onItemLongClick(AdapterView<?> adapterView, View view, final int position, long id) { 
    new AlertDialog.Builder(getContext()).setTitle("操作选项").setItems(new CharSequence[]{"删除"}, new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialogInterface, int which) { 
      switch (which){ 
       case 0: 
        deleteAlarm(position); 
        break; 
       default: 
        break; 
      } 
     } 
    }).setNegativeButton("取消",null).show(); 
    return true; 
   } 
  }); 

 } 

 private void deleteAlarm(int position){ 

  AlarmData ad=adapter.getItem(position); 
  adapter.remove(ad); 
  saveAlarmList();//重新保存 
  alarmManager.cancel(PendingIntent.getBroadcast(getContext(),ad.getId(),new Intent(getContext(),AlarmReceiver.class),0)); 
 } 
 @RequiresApi(api = Build.VERSION_CODES.N) 
 private void addAlarm(){ 
  //获取当前时间 
  Calendar c=Calendar.getInstance(); 
  //时间选择框 
  new TimePickerDialog(getContext(), new TimePickerDialog.OnTimeSetListener() { 
   @Override 
   public void onTimeSet(TimePicker view, int hourOfDay, int minute) { 
    Calendar calendar =Calendar.getInstance(); 
    calendar.set(Calendar.HOUR_OF_DAY,hourOfDay); 
    calendar.set(Calendar.MINUTE,minute); 
    calendar.set(Calendar.SECOND,0); 
    calendar.set(Calendar.MILLISECOND,0); 


    //写出当前时间 
    Calendar currentTime=Calendar.getInstance(); 

    //设置时间小于当前时间,往后推一天 
    if(calendar.getTimeInMillis()<=currentTime.getTimeInMillis()){ 
     calendar.setTimeInMillis(calendar.getTimeInMillis()+24*60*60*1000); 
    } 

    AlarmData ad=new AlarmData(calendar.getTimeInMillis()); 
    adapter.add(ad); 


/* 
第一个参数 RTC操作系统时间为启动时间点,WAKEUP系统休眠时同样执行 
第二个参数 什么时候启动 
第三个参数 启动之后什么时间再次启动 
第四个参数 Pendingintent挂起的Intent,不立即执行 
*/ 
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 
      ad.getTime(),//当前时间当做请求码 
      5*60*1000, 
      //执行广播 
      PendingIntent.getBroadcast(getContext(), 
        ad.getId(), 
        new Intent(getContext(), 
          AlarmReceiver.class), 
        0)); 

//每一个闹钟对应一个请求码,根据请求码移除特定的闹钟,那么把时间当做请求码 
    saveAlarmList(); 
   } 
  },c.get(Calendar.HOUR_OF_DAY),c.get(Calendar.MINUTE),true).show(); 

 } 
 //保存闹钟数据 
 private void saveAlarmList(){ 
  SharedPreferences.Editor editor=getContext().getSharedPreferences(AlarmView.class.getName(),Context.MODE_PRIVATE).edit(); 

  StringBuffer sb=new StringBuffer(); 
  for(int i=0;i<adapter.getCount();i++){ 
   sb.append(adapter.getItem(i).getTime()).append(","); 

  } 

  if(sb.length()>1){ 
   String content=sb.toString().substring(0,sb.length()-1);//去掉最后一个逗号 
   editor.putString(KEY_ALARM_LIST,content); 
  }else{ 
   editor.putString(KEY_ALARM_LIST,null); 
  } 
  editor.commit(); 
 } 
 //读取已存数据 

 @RequiresApi(api = Build.VERSION_CODES.N) 
 private void readSavedAlarmList(){ 

  SharedPreferences sp=getContext().getSharedPreferences((AlarmView.class.getName()), Context.MODE_PRIVATE); 
  String content=sp.getString(KEY_ALARM_LIST,null); 


  if(content!=null){ 
   String[] timeStrings=content.split(","); 
   for(String string:timeStrings){ 
    adapter.add(new AlarmData(Long.parseLong(string))); 


   } 
  } 

 } 


 private static final String KEY_ALARM_LIST="alarmList"; 
 private Button btnAddAlarm; 
 private ListView lvAlarmList; 
 private ArrayAdapter<AlarmData> adapter; 
 private AlarmManager alarmManager;//系统的闹钟服务 
 private static class AlarmData{ 

  //闹钟所要响起的时间 
  @RequiresApi(api = Build.VERSION_CODES.N) 
  public AlarmData(long time){ 
   this.time=time; 

   date= Calendar.getInstance(); 
   date.setTimeInMillis(time); 

   timeLable=String.format("%d月%d日 %d:%d", 
     date.get(Calendar.MONTH)+1,//getMonth的返回值是从0开始的 
     date.get(Calendar.DAY_OF_MONTH), 
     date.get(Calendar.HOUR_OF_DAY), 
     date.get(Calendar.MINUTE)); 
  } 
  public long getTime(){ 
   return time; 
  } 
  public String getTimeLable(){ 
   return timeLable; 
  } 

  @Override 
  public String toString() { 
   return getTimeLable(); 
  } 
  public int getId(){ 
   return (int)(getTime()/1000/60);//精确到分钟,getTime为毫秒 
  } 


  //获取时间的标签 
  private String timeLable=""; 
  private long time=0; 
  private Calendar date; 


 } 
} 

在实现定时提醒的过程中,前前后后考虑过定时推送、系统闹钟、本地定时系统日历的方案。具体的情况将分别简单说一下。

TimeView

最终技术选型:系统日历

package com.example.lenovo.clock2; 

import android.content.Context; 
import android.icu.util.Calendar; 
import android.os.Build; 
import android.os.Handler; 
import android.os.Message; 
import android.support.annotation.IntDef; 
import android.support.annotation.NonNull; 
import android.support.annotation.Nullable; 
import android.support.annotation.RequiresApi; 
import android.util.AttributeSet; 
import android.view.View; 
import android.widget.LinearLayout; 
import android.widget.TextView; 

/** 
 * Created by lenovo on 2017/11/20. 
 */ 
//时钟 显示目前的时间 
public class TimeView extends LinearLayout { 
 public TimeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 
  super(context, attrs, defStyleAttr); 
 } 
 public TimeView(Context context, @Nullable AttributeSet attrs) { 
  super(context, attrs); 
 } 

 public TimeView(Context context) { 
  super(context); 
 } 

 @Override 

 protected void onFinishInflate() { 
  super.onFinishInflate(); 

  tvTime=findViewById(R.id.tvTime); 
  tvTime.setText("这里显示时间"); 

  timerHander.sendEmptyMessage(0); 

 } 
 //判断可见属性是否发生改变 
 @Override 
 protected void onVisibilityChanged(View changedView, int visibility) { 
  super.onVisibilityChanged(changedView, visibility); 
  if(getVisibility()== View.VISIBLE){ 
   timerHander.sendEmptyMessage(0);//可见,则呈现 
  }else{ 
   timerHander.removeMessages(0);//否则移除所有消息 
  } 
 } 

 //刷新时间 
 @RequiresApi(api = Build.VERSION_CODES.N) 
 private void refreshTime(){ 
  Calendar c=Calendar.getInstance(); 
  tvTime.setText(String.format("%d:%d:%d",c.get(Calendar.HOUR_OF_DAY),c.get(Calendar.MINUTE),c.get(Calendar.SECOND))); 

 } 
 //Hander每隔一秒执行一次 
 private Handler timerHander=new Handler(){ 

  @RequiresApi(api = Build.VERSION_CODES.N) 
  @Override 
  public void handleMessage(Message msg) { 

   refreshTime(); 
   //若为当前页面,则刷新;否则,没有必要刷新 
   if (getVisibility()== View.VISIBLE) { 
    timerHander.sendEmptyMessageDelayed(0, 1000);//1000毫秒后再执行handleMessage方法 
   } 
  }; 
 }; 
 private TextView tvTime; 
} 

1. 服务器推送

比如京东的Android端APP,经过观察,其走的是后台推送的方案。
这个方案有个前提是:你的APP必须高保活,京东作为超级APP,无论从技术上还是和手机厂商合作上,其保活方案肯定没得说,推送服务的可到达率也毋庸置疑。
假如,你所开发的APP可以有稳定的高保活方案,走后台推送还是不错的。毕竟,app接收到推送通知后,可做的事情太多了,用户体验当然是很好的。

但是,假如你的APP没有做到或做过可靠的长时间高保活,那么,这个方案是不推荐的。APP死掉了,手机收不到推送是没有任何意义的。

(我的理解可能不对,假如京东的工程师们看到了或者对高保活有靠谱方案的同学,还请多都的赐教。)

AlarmReceiver

2. 本地定时

本地定时服务,面临和推送同样的问题,怎么让服务杀不死可以监听到定时。这里不多说了。

package com.example.lenovo.clock2; 

import android.app.AlarmManager; 
import android.app.PendingIntent; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 

/** 
 * Created by lenovo on 2017/11/23. 
 */ 

public class AlarmReceiver extends BroadcastReceiver { 
 @Override 
 public void onReceive(Context context, Intent intent) { 

  AlarmManager am= (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
  am.cancel(PendingIntent.getBroadcast(context,getResultCode(),new Intent(context,AlarmReceiver.class),0)); 

 Intent i=new Intent(context,PlayAlarmAty.class); 
 i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
 context.startActivity(i); 

 } 
} 

3. 系统闹钟

我开始是使用的系统闹钟,本来打算的挺好:设置好定时的闹钟,然后通过APP提前在清单文件中注册好的静态BroadCastReceiver来监听闹钟的系统广播。可是实验发现,这个方案是走不通的或者是我走的姿势不对?

  • 第一:APP调用AlarmMannager来设定的定时是绑定了APP的。什么意思?意思就是,你的app挂了的话,app之前设置的定时闹钟也都被系统清理掉了。
  • 第二:是谁告诉我说通过清单文件静态注册的广播接收者在APP挂了之后还在系统中继续存活监听广播来?坑我不浅啊。

可能是我走路姿势不对?反正这条路在我尝试了一番之后也被我给毙掉了

这是我从网上看到的一篇闹钟的实现方案:http://www.jianshu.com/p/fdb4e8c009b7,尝试了下,发现不管用,而且看作者使用的方法,可能针对的安卓系统版本较早。

贴一下我当初研究闹钟方案时参考的文章:《关于Android中设置闹钟的相对比较完善的解决方案》

MainActivity

4. 系统日历

通过app中设定系统日历的日历事件,并对日历事件设置提醒。不论app是否存活,提醒的时间到了,系统日历总能按时的弹出提醒,唯一的问题是,点击日历的提醒,会进入系统日历的日历事件界面,而无法直接唤醒APP并跳转到相关界面的;系统日历也是没有响应的广播的;

通过从网上搜集资料,我也采用了折中方案:

  • APP设置定时提醒到系统日历(日历的日历事件并设定提醒、描述中填入需要跳转的URL、事件的标题);
  • 定时到达,系统日历主动弹窗或通知栏提醒用户(不同的安卓手机形式不太一样);
  • 用户点击日历提示界面,进入日历事件详情界面
  • 点击日历事件备注中的跳转链接唤起系统选择器;
  • 选择器展示可以处理跳转URL的app
  • 选择浏览器,跳到wap页;选择APP,使用deeplink跳转到相关的原生界面。
package com.example.lenovo.clock2; 

import android.app.Activity; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.widget.TabHost; 

public class MainActivity extends Activity { 

 @Override 
 protected void onCreate(Bundle savedInstanceState) { 
  super.onCreate(savedInstanceState); 
  setContentView(R.layout.activity_main); 

  tabHost= (TabHost) findViewById(R.id.tabhost); 
  tabHost.setup(); 
//setContent()为声明内容 
  tabHost.addTab(tabHost.newTabSpec("tabTime").setIndicator("时钟").setContent(R.id.tabTime)); 
  tabHost.addTab(tabHost.newTabSpec("tabAlarm").setIndicator("闹钟").setContent(R.id.tabAlarm)); 
  tabHost.addTab(tabHost.newTabSpec("tabTimer").setIndicator("计时器").setContent(R.id.tabTimer)); 
  tabHost.addTab(tabHost.newTabSpec("tabStopWatch").setIndicator("秒表").setContent(R.id.tabStopWatch)); 
 } 
 private TabHost tabHost; 
} 

4.1 Deeplink

使用系统日历需要使用到的关键技术是Deeplink,
这个大家自己去百度,资料很多,而且不难。
另一个关键的点是:定义deeplink的scheme时,要注意下格式,有的格式系统日历可能不能识别。
推荐大家使用

PlayAlarmAty

4.2 代码

下面给出设置系统日历的关键代码:

/**
 * 作者: Xiao Danchen.
 * 工具类:
 * 通过日历添加事件提醒的方式实现秒杀、抢购等提醒功能。
 * 要求内部实现:
 * 1,新增提醒是否是重复提醒,是则添加到相关事件下;否则添加到新事件
 * 2,过期事件、提醒的清理能力
 *
 * 日历相关的资料:https://developer.android.com/guide/topics/providers/calendar-provider.html?hl=zh-cn#calendar
 */
public class CalendarUtils {
    private static String calanderURL;
    private static String calanderEventURL;
    private static String calanderRemiderURL;

    private static String CALENDARS_NAME = "XXXX";
    private static String CALENDARS_ACCOUNT_NAME = "XXXX";
    private static String CALENDARS_ACCOUNT_TYPE = "XXXXX";
    private static String CALENDARS_DISPLAY_NAME = "XXXXX";

    /**
     * 初始化uri
     */
    static {
        if (Build.VERSION.SDK_INT >= 8) {
            calanderURL = "content://com.android.calendar/calendars";
            calanderEventURL = "content://com.android.calendar/events";
            calanderRemiderURL = "content://com.android.calendar/reminders";
        } else {
            calanderURL = "content://calendar/calendars";
            calanderEventURL = "content://calendar/events";
            calanderRemiderURL = "content://calendar/reminders";
        }
    }

    /**
     * 获取日历ID
     * @param context
     * @return 日历ID
     */
    private static int checkAndAddCalendarAccounts(Context context){
        int oldId = checkCalendarAccounts(context);
        if( oldId >= 0 ){
            return oldId;
        }else{
            long addId = addCalendarAccount(context);
            if (addId >= 0) {
                return checkCalendarAccounts(context);
            } else {
                return -1;
            }
        }
    }

    /**
     * 检查是否存在日历账户
     * @param context
     * @return
     */
    private static int checkCalendarAccounts(Context context) {

        Cursor userCursor = context.getContentResolver().query(Uri.parse(calanderURL), null, null, null, CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL + " ASC ");
        try {
            if (userCursor == null)//查询返回空值
                return -1;
            int count = userCursor.getCount();
            if (count > 0) {//存在现有账户,取第一个账户的id返回
                userCursor.moveToLast();
                return userCursor.getInt(userCursor.getColumnIndex(CalendarContract.Calendars._ID));
            } else {
                return -1;
            }
        } finally {
            if (userCursor != null) {
                userCursor.close();
            }
        }
    }

    /**
     * 添加一个日历账户
     * @param context
     * @return
     */
    private static long addCalendarAccount(Context context) {
        TimeZone timeZone = TimeZone.getDefault();
        ContentValues value = new ContentValues();
        value.put(CalendarContract.Calendars.NAME, CALENDARS_NAME);

        value.put(CalendarContract.Calendars.ACCOUNT_NAME, CALENDARS_ACCOUNT_NAME);
        value.put(CalendarContract.Calendars.ACCOUNT_TYPE, CALENDARS_ACCOUNT_TYPE);
        value.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, CALENDARS_DISPLAY_NAME);
        value.put(CalendarContract.Calendars.VISIBLE, 1);
        value.put(CalendarContract.Calendars.CALENDAR_COLOR, Color.BLUE);
        value.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER);
        value.put(CalendarContract.Calendars.SYNC_EVENTS, 1);
        value.put(CalendarContract.Calendars.CALENDAR_TIME_ZONE, timeZone.getID());
        value.put(CalendarContract.Calendars.OWNER_ACCOUNT, CALENDARS_ACCOUNT_NAME);
        value.put(CalendarContract.Calendars.CAN_ORGANIZER_RESPOND, 0);

        Uri calendarUri = Uri.parse(calanderURL);
        calendarUri = calendarUri.buildUpon()
                .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
                .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, CALENDARS_ACCOUNT_NAME)
                .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, CALENDARS_ACCOUNT_TYPE)
                .build();

        Uri result = context.getContentResolver().insert(calendarUri, value);
        long id = result == null ? -1 : ContentUris.parseId(result);
        return id;
    }

    /**
     * 向日历中添加一个事件
     * @param context
     * @param calendar_id (必须参数)
     * @param title
     * @param description
     * @param begintime 事件开始时间,以从公元纪年开始计算的协调世界时毫秒数表示。 (必须参数)
     * @param endtime 事件结束时间,以从公元纪年开始计算的协调世界时毫秒数表示。(非重复事件:必须参数)
     * @return
     */
    private static Uri insertCalendarEvent(Context context, long calendar_id, String title, String description , long begintime, long endtime){
        ContentValues event = new ContentValues();
        event.put("title", title);
        event.put("description", description);
        // 插入账户的id
        event.put("calendar_id", calendar_id);
        event.put(CalendarContract.Events.DTSTART, begintime);//必须有
        event.put(CalendarContract.Events.DTEND, endtime);//非重复事件:必须有
        event.put(CalendarContract.Events.HAS_ALARM, 1);//设置有闹钟提醒
        event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());//这个是时区,必须有,
        //添加事件
        Uri newEvent = context.getContentResolver().insert(Uri.parse(calanderEventURL), event);
        return newEvent;
    }

    /**
     * 查询日历事件
     * @param context
     * @param title 事件标题
     * @return 事件id,查询不到则返回""
     */
    private static String queryCalendarEvent(Context context, long calendar_id, String title, String description, long start_time, long end_time){
        // 根据日期范围构造查询
        Uri.Builder builder = CalendarContract.Instances.CONTENT_URI.buildUpon();
        ContentUris.appendId(builder, start_time);
        ContentUris.appendId(builder, end_time);
        Cursor cursor = context.getContentResolver().query(builder.build(), null, null, null, null);
        String tmp_title;
        String tmp_desc;
        long temp_calendar_id;
        if(cursor.moveToFirst()){
            do{
                tmp_title = cursor.getString(cursor.getColumnIndex("title"));
                tmp_desc = cursor.getString(cursor.getColumnIndex("description"));
                temp_calendar_id = cursor.getLong(cursor.getColumnIndex("calendar_id"));
                long dtstart = cursor.getLong(cursor.getColumnIndex("dtstart"));
                if(TextUtils.equals(title,tmp_title) && TextUtils.equals(description,tmp_desc) && calendar_id == temp_calendar_id && dtstart==start_time){
                    String eventId = cursor.getString(cursor.getColumnIndex("event_id"));
                    return eventId;
                }
            }while(cursor.moveToNext());
        }
        return  "";
    }

    /**
     * 添加日历提醒:标题、描述、开始时间共同标定一个单独的提醒事件
     * @param context
     * @param title 日历提醒的标题,不允许为空
     * @param description 日历的描述(备注)信息
     * @param begintime 事件开始时间,以从公元纪年开始计算的协调世界时毫秒数表示。
     * @param endtime 事件结束时间,以从公元纪年开始计算的协调世界时毫秒数表示。
     * @param remind_minutes 提前remind_minutes分钟发出提醒
     * @param callback 添加提醒是否成功结果监听
     */
    public static void addCalendarEventRemind(Context context, @NonNull String title, String description, long begintime, long endtime, int remind_minutes, onCalendarRemindListener callback){
        long calendar_id = checkAndAddCalendarAccounts(context);
        if(calendar_id < 0){
            // 获取日历失败直接返回
            if(null != callback){
                callback.onFailed(onCalendarRemindListener.Status.CALENDAR_ERR);
            }
            return;
        }
        //根据标题、描述、开始时间查看提醒事件是否已经存在
        String event_id = queryCalendarEvent(context,calendar_id,title,description,begintime,endtime);
        //如果提醒事件不存在,则新建事件
        if(TextUtils.isEmpty(event_id)){
            Uri newEvent = insertCalendarEvent(context,calendar_id,title,description,begintime,endtime);
            if (newEvent == null) {
                // 添加日历事件失败直接返回
                if(null != callback){
                    callback.onFailed(onCalendarRemindListener.Status.EVENT_ERROR);
                }
                return;
            }
            event_id = ContentUris.parseId(newEvent)+"";
        }
        //为事件设定提醒
        ContentValues values = new ContentValues();
        values.put(CalendarContract.Reminders.EVENT_ID, event_id);
        // 提前remind_minutes分钟有提醒
        values.put(CalendarContract.Reminders.MINUTES, remind_minutes);
        values.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
        Uri uri = context.getContentResolver().insert(Uri.parse(calanderRemiderURL), values);
        if(uri == null) {
            // 添加提醒失败直接返回
            if(null != callback){
                callback.onFailed(onCalendarRemindListener.Status.REMIND_ERROR);
            }
            return;
        }

        //添加提醒成功
        if(null != callback){
            callback.onSuccess();
        }
    }

    /**
     * 删除日历提醒事件:根据标题、描述和开始时间来定位日历事件
     * @param context
     * @param title 提醒的标题
     * @param description 提醒的描述:deeplink URI
     * @param startTime 事件的开始时间
     * @param callback 删除成功与否的监听回调
     */
    public static void deleteCalendarEventRemind(Context context, String title, String description, long startTime,onCalendarRemindListener callback){
        Cursor eventCursor = context.getContentResolver().query(Uri.parse(calanderEventURL), null, null, null, null);
        try {
            if (eventCursor == null)//查询返回空值
                return;
            if (eventCursor.getCount() > 0) {
                //遍历所有事件,找到title、description、startTime跟需要查询的title、descriptio、dtstart一样的项
                for (eventCursor.moveToFirst(); !eventCursor.isAfterLast(); eventCursor.moveToNext()) {
                    String eventTitle = eventCursor.getString(eventCursor.getColumnIndex("title"));
                    String eventDescription = eventCursor.getString(eventCursor.getColumnIndex("description"));
                    long dtstart = eventCursor.getLong(eventCursor.getColumnIndex("dtstart"));
                    if (!TextUtils.isEmpty(title) && title.equals(eventTitle) && !TextUtils.isEmpty(description) && description.equals(eventDescription) && dtstart==startTime ) {
                        int id = eventCursor.getInt(eventCursor.getColumnIndex(CalendarContract.Calendars._ID));//取得id
                        Uri deleteUri = ContentUris.withAppendedId(Uri.parse(calanderEventURL), id);
                        int rows = context.getContentResolver().delete(deleteUri, null, null);
                        if (rows == -1) {
                            // 删除提醒失败直接返回
                            if(null != callback){
                                callback.onFailed(onCalendarRemindListener.Status.REMIND_ERR);
                            }
                            return;
                        }
                        //删除提醒成功
                        if(null != callback){
                            callback.onSuccess();
                        }
                    }
                }
            }
        } finally {
            if (eventCursor != null) {
                eventCursor.close();
            }
        }
    }

    /**
     * 日历提醒添加成功与否监控器
     */
    public static interface onCalendarRemindListener{
        enum Status {
            _CALENDAR_ERROR,
            _EVENT_ERROR,
            _REMIND_ERROR
        }
        void onFailed(Status error_code);
        void onSuccess();
    }

    /**
     * 辅助方法:获取设置时间起止时间的对应毫秒数
     * @param year
     * @param month 1-12
     * @param day 1-31
     * @param hour 0-23
     * @param minute 0-59
     * @return
     */
    public static long remindTimeCalculator(int year,int month,int day,int hour,int minute){
        Calendar calendar = Calendar.getInstance();
        calendar.set(year,month-1,day,hour,minute);
        return calendar.getTimeInMillis();
    }
}

分享、共赢
欢迎大家加入 学习小组 QQ群: 193765960

package com.example.lenovo.clock2; 

import android.app.Activity; 
import android.media.MediaPlayer; 
import android.os.Bundle; 
import android.support.annotation.Nullable; 

/** 
 * Created by lenovo on 2017/11/25. 
 */ 

public class PlayAlarmAty extends Activity { 
 @Override 
 protected void onCreate(@Nullable Bundle savedInstanceState) { 
  super.onCreate(savedInstanceState); 
  setContentView(R.layout.alarm_player_aty); 

  mp=MediaPlayer.create(this,R.raw.mine); 
  mp.start(); 

 } 

 @Override 
 protected void onPause() { 
  super.onPause(); 
  finish(); 
 } 

 @Override 
 protected void onDestroy() { 
  super.onDestroy(); 
  mp.stop(); 
  mp.release(); 

 } 

 private MediaPlayer mp; 
 //音乐播放器 
} 

运行效果图

冠亚体育手机网站 1

冠亚体育手机网站 2

冠亚体育手机网站 3

冠亚体育手机网站 4

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:

  • Android使用CountDownTimer类实现倒计时闹钟
  • Android如何在App中启动系统闹钟
  • 冠亚体育手机网站,Android仿正点闹钟时间齿轮滑动效果
  • Android闹钟机制实现定时任务功能
  • Android自定义View
    实现闹钟唤起播放闹钟铃声功能
  • Android编程闹钟设置方法详解
  • Android闹钟设置的解决方案
  • 简单实现Android闹钟程序
    附源码
  • Android手机闹钟服务AlarmManagerk开发案例
  • android用闹钟定时做http请求推送的解决方案

Post Author: admin

发表评论

电子邮件地址不会被公开。 必填项已用*标注