闹钟开发:
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一个可以选取时间的控件,对其设置监听获得所选的时间
MainActivity.this.tp.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
@Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
MainActivity.this.calendar = Calendar.getInstance();//获得一个Calendar的实例
MainActivity.this.calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);//HOUR_OF_DAY是24小时制
MainActivity.this.calendar.set(Calendar.MINUTE, minute);
MainActivity.this.calendar.set(Calendar.SECOND, 0);
//先保存起来,更新textview时可以用
MainActivity.this.hourofday = hourOfDay;
MainActivity.this.minute = minute; }
});
2、AlarmManager的用法
MainActivity.this.alarmManager = (AlarmManager) MainActivity.this.getSystemService(ALARM_SERVICE);//获得一个AlarmManager服务
MainActivity.this.set.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/* AlarmManager.RTC,硬件闹钟,不唤醒休眠;
AlarmManager.RTC_WAKEUP,硬件闹钟,唤醒休眠;
AlarmManager.ELAPSED_REALTIME,真实时间流逝闹钟,不唤醒休眠;
AlarmManager.ELAPSED_REALTIME_WAKEUP,真实时间流逝闹钟,唤醒休眠;*/
Intent intent = new Intent(MainActivity.this, AlarmBroadcastReceiver.class);
intent.setAction("com.example.hxdn.naozhong");
PendingIntent operation = PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
MainActivity.this.alarmManager.set(AlarmManager.RTC_WAKEUP, MainActivity.this.calendar.getTimeInMillis(), operation);//
//参数1:解释在上面。 参数二:传入时间毫秒 参数三:传入PendingIntent
MainActivity.this.tv.setText("闹钟时间:" + MainActivity.this.hourofday + "时" + MainActivity.this.minute + "分" + "00秒");
Toast.makeText(MainActivity.this, "闹钟设置完毕!", Toast.LENGTH_LONG);
}
});
MainActivity.this.cancle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, AlarmBroadcastReceiver.class);
intent.setAction("com.example.hxdn.naozhong");//要与上面设置的一样,否则会出现取消掉闹钟还是响的问题。
PendingIntent operation = PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
MainActivity.this.alarmManager.cancel(operation);
MainActivity.this.tv.setText("当前闹钟未设置");
Toast.makeText(MainActivity.this, "闹钟已删除!", Toast.LENGTH_SHORT).show();
}
});
机制:
通过TimePicker设置时间由Calendar获得时间,包装一个PendingIntent(即使当前Activity销毁仍然可以启动广播从而启动AlarmActivity弹出提示框和震动),由alarmManager设置。
注意点:
记得注册BroadcastReceiver和AlamActivity!
震动需要权限!
接下来贴出全部的代码:
布局代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TimePicker
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv"
android:layout_gravity="center"
android:text="闹钟时间"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/set"
android:layout_marginLeft="50dp"
android:text="设置"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/cancle"
android:layout_marginLeft="100dp"
android:text="取消"/> </LinearLayout> </LinearLayout>
MainActivity.java
package com.example.hxdn.naozhong; import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast; import java.util.Calendar; public class MainActivity extends AppCompatActivity { private static final String TAG = "MMM";
private Button set = null;
private Button cancle = null;
private TextView tv = null;
private TimePicker tp = null;//时间选择器
private Calendar calendar = null;//日期操作
private AlarmManager alarmManager = null;//闹钟管理AlarmManager实质上是一个全局的定时器,
private int hourofday;
private int minute; // 是Android中常用的一种系统级别的提示服务,在指定时间或周期性启动其它组件(包括Activity,Service,BroadcastReceiver)。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
initAction();
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId(); //noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
} return super.onOptionsItemSelected(item);
} private void initAction() {
MainActivity.this.tp.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
@Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
MainActivity.this.calendar = Calendar.getInstance();
MainActivity.this.calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);//HOUR_OF_DAY是24小时制
MainActivity.this.calendar.set(Calendar.MINUTE, minute);
MainActivity.this.calendar.set(Calendar.SECOND, 0);
//更新textview
MainActivity.this.hourofday = hourOfDay;
MainActivity.this.minute = minute; }
});
MainActivity.this.set.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/* AlarmManager.RTC,硬件闹钟,不唤醒休眠;
AlarmManager.RTC_WAKEUP,硬件闹钟,唤醒休眠;
AlarmManager.ELAPSED_REALTIME,真实时间流逝闹钟,不唤醒休眠;
AlarmManager.ELAPSED_REALTIME_WAKEUP,真实时间流逝闹钟,唤醒休眠;*/
Intent intent = new Intent(MainActivity.this, AlarmBroadcastReceiver.class);
intent.setAction("com.example.hxdn.naozhong");
PendingIntent operation = PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
MainActivity.this.alarmManager.set(AlarmManager.RTC_WAKEUP, MainActivity.this.calendar.getTimeInMillis(), operation);
MainActivity.this.tv.setText("闹钟时间:" + MainActivity.this.hourofday + "时" + MainActivity.this.minute + "分" + "00秒");
Toast.makeText(MainActivity.this, "闹钟设置完毕!", Toast.LENGTH_LONG);
}
});
MainActivity.this.cancle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, AlarmBroadcastReceiver.class);
intent.setAction("com.example.hxdn.naozhong");
PendingIntent operation = PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
MainActivity.this.alarmManager.cancel(operation);
MainActivity.this.tv.setText("当前闹钟未设置");
Toast.makeText(MainActivity.this, "闹钟已删除!", Toast.LENGTH_SHORT).show();
}
});
} public void init() {
set = (Button) findViewById(R.id.set);
cancle = (Button) findViewById(R.id.cancle);
tv = (TextView) findViewById(R.id.tv);
tp = (TimePicker) findViewById(R.id.tp);
MainActivity.this.alarmManager = (AlarmManager) MainActivity.this.getSystemService(ALARM_SERVICE);
} public void onStart()
{
Log.i(TAG, "onStart() executed ");
super.onStart();
}
public void onPause()
{
Log.i(TAG, "onPause() executed ");
super.onPause(); }
public void onDestroy()
{
Log.i(TAG,"onDestroy() executed ");
super.onDestroy();
}
}
AlarmActivity.java
package com.example.hxdn.naozhong; import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.Log; import java.text.SimpleDateFormat;
import java.util.Date; /**
* Created by hxdn on 2015/9/20.
*/
public class AlarmActivity extends Activity {
private Vibrator vibrator=null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Log.i("MMM", "wocao1");
vibrator=(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
long patten[]={100,800,100,800};
vibrator.vibrate(patten,2);
Log.i("MMM","wocao2");
new AlertDialog.Builder(AlarmActivity.this).setIcon(R.mipmap.ic_launcher).
setTitle("闹钟提醒").
setMessage("当前时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()))
.setNegativeButton("关闭", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
vibrator.cancel();
AlarmActivity.this.finish();
}
}).show(); }
}
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
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.hxdn.naozhong" > <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver
android:name=".AlarmBroadcastReceiver"> </receiver>
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".AlarmActivity"
android:theme="@android:style/Theme.Dialog"></activity>
</application>
<uses-permission android:name="android.permission.VIBRATE"></uses-permission>
</manifest>