闹钟开发:

1、需要时间选择器TimePicker

2、需要Calendar类对日期时间进行操作

3、需要AlarmManager//闹钟管理实质是一个全局定时器, 是Android中常用的一种系统级别的提示服务,在指定时间或周期性启动其它组件(包括Activity,Service,BroadcastReceiver)。

4、PendingIntent的理解

PendingIntent 可以看作是对intent的包装,通常通过getActivity,getBroadcast ,getService来得到pendingintent的实例,当前activity并不能马上启动它所包含的intent,而是在外部执行 pendingintent时,调用intent的。正由于pendingintent中 保存有当前App的Context,使它赋予外部App一种能力,使得外部App可以如同当前App一样的执行pendingintent里的 Intent, 就算在执行时当前App已经不存在了,也能通过存在pendingintent里的Context照样执行Intent。另外还可以处理intent执行后的操作。常和alermanger 和notificationmanager一起使用。 
Intent一般是用作Activity、Sercvice、BroadcastReceiver之间传递数据,而Pendingintent,一般用在 Notification上,可以理解为延迟执行的intent,PendingIntent是对Intent一个包装。 

PendingIntent参数

public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)

public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags)

public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags)

第一个参数为当前Activity.this

第二个参数为请求码,可通过第二个参数判断是哪个PendingIntent。(一般认为没有作用)

第三个参数较为复杂:

FLAG_CANCEL_CURRENT:如果当前系统中已经存在一个相同的PendingIntent对象,那么就将先将已有的PendingIntent取消,然后重新生成一个PendingIntent对象。

FLAG_NO_CREATE:如果当前系统中不存在相同的PendingIntent对象,系统将不会创建该PendingIntent对象而是直接返回null。

FLAG_ONE_SHOT:该PendingIntent只作用一次。在该PendingIntent对象通过send()方法触发过后,PendingIntent将自动调用cancel()进行销毁,那么如果你再调用send()方法的话,系统将会返回一个SendIntentException。

FLAG_UPDATE_CURRENT:如果系统中有一个和你描述的PendingIntent对等的PendingInent,那么系统将使用该PendingIntent对象,但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据,例如更新Intent中的Extras。

FLAG_CANCEL_CURRENT和FLAG_UPDATE_CURRENT的区别在于能否新new一个Intent,FLAG_CANCEL_CURRENT能够新new一个Intent,而FLAG_UPDATE_CURRENT则不能,只能使用第一次的Intent。 还有一个问题就是怎么区分PendingIntent,主要取消的时候要用到,requestCode可以区分,但系统还是根据Intent的Action去区分的,如果Intent设置了Class,classData,取消的时候Intent一定要设置要相同的,不然取消不掉就可能出现取消后,Alarm还会响的问题

 

1、TimePicker与Calendar的用法

TimePicker一个可以选取时间的控件,对其设置监听获得所选的时间



1  MainActivity.this.tp.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
 2             @Override
 3             public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
 4                 MainActivity.this.calendar = Calendar.getInstance();//获得一个Calendar的实例
 5                 MainActivity.this.calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);//HOUR_OF_DAY是24小时制
 6                 MainActivity.this.calendar.set(Calendar.MINUTE, minute);
 7                 MainActivity.this.calendar.set(Calendar.SECOND, 0);
 8                 //先保存起来,更新textview时可以用
 9                 MainActivity.this.hourofday = hourOfDay;
10                 MainActivity.this.minute = minute;
11 
12             }
13         });



2、AlarmManager的用法

MainActivity.this.alarmManager = (AlarmManager) MainActivity.this.getSystemService(ALARM_SERVICE);//获得一个AlarmManager服务



1  MainActivity.this.set.setOnClickListener(new View.OnClickListener() {
 2             @Override
 3             public void onClick(View v) {
 4               /*  AlarmManager.RTC,硬件闹钟,不唤醒休眠;
 5                 AlarmManager.RTC_WAKEUP,硬件闹钟,唤醒休眠;
 6                 AlarmManager.ELAPSED_REALTIME,真实时间流逝闹钟,不唤醒休眠;
 7                 AlarmManager.ELAPSED_REALTIME_WAKEUP,真实时间流逝闹钟,唤醒休眠;*/
 8                 Intent intent = new Intent(MainActivity.this, AlarmBroadcastReceiver.class);
 9                 intent.setAction("com.example.hxdn.naozhong");
10                 PendingIntent operation = PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
11                 MainActivity.this.alarmManager.set(AlarmManager.RTC_WAKEUP, MainActivity.this.calendar.getTimeInMillis(), operation);//
//参数1:解释在上面。  参数二:传入时间毫秒   参数三:传入PendingIntent
12                 MainActivity.this.tv.setText("闹钟时间:" + MainActivity.this.hourofday + "时" + MainActivity.this.minute + "分" + "00秒");
13                 Toast.makeText(MainActivity.this, "闹钟设置完毕!", Toast.LENGTH_LONG);
14             }
15         });
16         MainActivity.this.cancle.setOnClickListener(new View.OnClickListener() {
17             @Override
18             public void onClick(View v) {
19                 Intent intent = new Intent(MainActivity.this, AlarmBroadcastReceiver.class);
20                 intent.setAction("com.example.hxdn.naozhong");//要与上面设置的一样,否则会出现取消掉闹钟还是响的问题。
21                 PendingIntent operation = PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
22                 MainActivity.this.alarmManager.cancel(operation);
23                 MainActivity.this.tv.setText("当前闹钟未设置");
24                 Toast.makeText(MainActivity.this, "闹钟已删除!", Toast.LENGTH_SHORT).show();
25             }
26         });



机制:

通过TimePicker设置时间由Calendar获得时间,包装一个PendingIntent(即使当前Activity销毁仍然可以启动广播从而启动AlarmActivity弹出提示框和震动),由alarmManager设置。

注意点:

记得注册BroadcastReceiver和AlamActivity!

震动需要权限!

 

接下来贴出全部的代码:

布局代码:



1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical"
 6     android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
 7 
 8    <TimePicker
 9        android:layout_width="wrap_content"
10        android:layout_height="wrap_content"
11        android:id="@+id/tp"/>
12     <TextView
13         android:layout_width="wrap_content"
14         android:layout_height="wrap_content"
15         android:id="@+id/tv"
16         android:layout_gravity="center"
17         android:text="闹钟时间"/>
18     <LinearLayout
19         android:layout_width="wrap_content"
20         android:layout_height="wrap_content"
21         android:orientation="horizontal">
22         <Button
23             android:layout_width="wrap_content"
24             android:layout_height="wrap_content"
25             android:id="@+id/set"
26             android:layout_marginLeft="50dp"
27             android:text="设置"/>
28         <Button
29             android:layout_width="wrap_content"
30             android:layout_height="wrap_content"
31             android:id="@+id/cancle"
32             android:layout_marginLeft="100dp"
33             android:text="取消"/>
34 
35         </LinearLayout>
36 
37 </LinearLayout>



MainActivity.java



1 package com.example.hxdn.naozhong;
  2 
  3 import android.app.AlarmManager;
  4 import android.app.PendingIntent;
  5 import android.content.Intent;
  6 import android.support.v7.app.AppCompatActivity;
  7 import android.os.Bundle;
  8 import android.util.Log;
  9 import android.view.Menu;
 10 import android.view.MenuItem;
 11 import android.view.View;
 12 import android.widget.Button;
 13 import android.widget.TextView;
 14 import android.widget.TimePicker;
 15 import android.widget.Toast;
 16 
 17 import java.util.Calendar;
 18 
 19 public class MainActivity extends AppCompatActivity {
 20 
 21     private static final String TAG = "MMM";
 22     private Button set = null;
 23     private Button cancle = null;
 24     private TextView tv = null;
 25     private TimePicker tp = null;//时间选择器
 26     private Calendar calendar = null;//日期操作
 27     private AlarmManager alarmManager = null;//闹钟管理AlarmManager实质上是一个全局的定时器,
 28     private int hourofday;
 29     private int minute;
 30 
 31     // 是Android中常用的一种系统级别的提示服务,在指定时间或周期性启动其它组件(包括Activity,Service,BroadcastReceiver)。
 32     @Override
 33     protected void onCreate(Bundle savedInstanceState) {
 34         super.onCreate(savedInstanceState);
 35         setContentView(R.layout.activity_main);
 36         init();
 37         initAction();
 38     }
 39 
 40     @Override
 41     public boolean onCreateOptionsMenu(Menu menu) {
 42         // Inflate the menu; this adds items to the action bar if it is present.
 43         getMenuInflater().inflate(R.menu.menu_main, menu);
 44         return true;
 45     }
 46 
 47     @Override
 48     public boolean onOptionsItemSelected(MenuItem item) {
 49         // Handle action bar item clicks here. The action bar will
 50         // automatically handle clicks on the Home/Up button, so long
 51         // as you specify a parent activity in AndroidManifest.xml.
 52         int id = item.getItemId();
 53 
 54         //noinspection SimplifiableIfStatement
 55         if (id == R.id.action_settings) {
 56             return true;
 57         }
 58 
 59         return super.onOptionsItemSelected(item);
 60     }
 61 
 62     private void initAction() {
 63         MainActivity.this.tp.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
 64             @Override
 65             public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
 66                 MainActivity.this.calendar = Calendar.getInstance();
 67                 MainActivity.this.calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);//HOUR_OF_DAY是24小时制
 68                 MainActivity.this.calendar.set(Calendar.MINUTE, minute);
 69                 MainActivity.this.calendar.set(Calendar.SECOND, 0);
 70                 //更新textview
 71                 MainActivity.this.hourofday = hourOfDay;
 72                 MainActivity.this.minute = minute;
 73 
 74             }
 75         });
 76         MainActivity.this.set.setOnClickListener(new View.OnClickListener() {
 77             @Override
 78             public void onClick(View v) {
 79               /*  AlarmManager.RTC,硬件闹钟,不唤醒休眠;
 80                 AlarmManager.RTC_WAKEUP,硬件闹钟,唤醒休眠;
 81                 AlarmManager.ELAPSED_REALTIME,真实时间流逝闹钟,不唤醒休眠;
 82                 AlarmManager.ELAPSED_REALTIME_WAKEUP,真实时间流逝闹钟,唤醒休眠;*/
 83                 Intent intent = new Intent(MainActivity.this, AlarmBroadcastReceiver.class);
 84                 intent.setAction("com.example.hxdn.naozhong");
 85                 PendingIntent operation = PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
 86                 MainActivity.this.alarmManager.set(AlarmManager.RTC_WAKEUP, MainActivity.this.calendar.getTimeInMillis(), operation);
 87                 MainActivity.this.tv.setText("闹钟时间:" + MainActivity.this.hourofday + "时" + MainActivity.this.minute + "分" + "00秒");
 88                 Toast.makeText(MainActivity.this, "闹钟设置完毕!", Toast.LENGTH_LONG);
 89             }
 90         });
 91         MainActivity.this.cancle.setOnClickListener(new View.OnClickListener() {
 92             @Override
 93             public void onClick(View v) {
 94                 Intent intent = new Intent(MainActivity.this, AlarmBroadcastReceiver.class);
 95                 intent.setAction("com.example.hxdn.naozhong");
 96                 PendingIntent operation = PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
 97                 MainActivity.this.alarmManager.cancel(operation);
 98                 MainActivity.this.tv.setText("当前闹钟未设置");
 99                 Toast.makeText(MainActivity.this, "闹钟已删除!", Toast.LENGTH_SHORT).show();
100             }
101         });
102     }
103 
104     public void init() {
105         set = (Button) findViewById(R.id.set);
106         cancle = (Button) findViewById(R.id.cancle);
107         tv = (TextView) findViewById(R.id.tv);
108         tp = (TimePicker) findViewById(R.id.tp);
109         MainActivity.this.alarmManager = (AlarmManager) MainActivity.this.getSystemService(ALARM_SERVICE);
110     }
111 
112     public void onStart()
113     {
114         Log.i(TAG, "onStart() executed ");
115         super.onStart();
116     }
117     public void onPause()
118     {
119         Log.i(TAG, "onPause() executed ");
120         super.onPause();
121 
122     }
123     public void onDestroy()
124     {
125         Log.i(TAG,"onDestroy() executed ");
126         super.onDestroy();
127     }
128 }



AlarmActivity.java



1 package com.example.hxdn.naozhong;
 2 
 3 import android.app.Activity;
 4 import android.app.AlertDialog;
 5 import android.content.Context;
 6 import android.content.DialogInterface;
 7 import android.os.Bundle;
 8 import android.os.Vibrator;
 9 import android.util.Log;
10 
11 import java.text.SimpleDateFormat;
12 import java.util.Date;
13 
14 /**
15  * Created by hxdn on 2015/9/20.
16  */
17 public class AlarmActivity extends Activity {
18     private Vibrator vibrator=null;
19     @Override
20     protected void onCreate(Bundle savedInstanceState)
21     {
22         super.onCreate(savedInstanceState);
23         Log.i("MMM", "wocao1");
24         vibrator=(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
25         long patten[]={100,800,100,800};
26         vibrator.vibrate(patten,2);
27         Log.i("MMM","wocao2");
28         new AlertDialog.Builder(AlarmActivity.this).setIcon(R.mipmap.ic_launcher).
29                 setTitle("闹钟提醒").
30                 setMessage("当前时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()))
31                 .setNegativeButton("关闭", new DialogInterface.OnClickListener() {
32                     @Override
33                     public void onClick(DialogInterface dialog, int which) {
34                         vibrator.cancel();
35                         AlarmActivity.this.finish();
36                     }
37                 }).show();
38 
39     }
40 }



 

AlarmBroadCReceiver.java



package com.example.hxdn.naozhong;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

/**
 * Created by hxdn on 2015/9/20.
 */
public class AlarmBroadcastReceiver extends BroadcastReceiver {

    public void onReceive(Context context,Intent intent)
    {
        Intent intent1=new Intent(context,AlarmActivity.class);
        intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent1);
    }
}



AndroidManifest.xml



1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.example.hxdn.naozhong" >
 4 
 5     <application
 6         android:allowBackup="true"
 7         android:icon="@mipmap/ic_launcher"
 8         android:label="@string/app_name"
 9         android:theme="@style/AppTheme" >
10         <receiver
11             android:name=".AlarmBroadcastReceiver">
12 
13             </receiver>
14         <activity
15             android:name=".MainActivity"
16             android:label="@string/app_name" >
17             <intent-filter>
18                 <action android:name="android.intent.action.MAIN" />
19 
20                 <category android:name="android.intent.category.LAUNCHER" />
21             </intent-filter>
22         </activity>
23         <activity
24             android:name=".AlarmActivity"
25             android:theme="@android:style/Theme.Dialog"></activity>
26     </application>
27     <uses-permission android:name="android.permission.VIBRATE"></uses-permission>
28 </manifest>