对service和date,Calendar的使用一直不是很熟练,今天做了一个简单的闹钟来练习一下,主要思路如下
1.设置日期(年月日),为了熟悉DatePickDialog的使用
2.设置时间(小时,分钟),为了熟悉TimePickDialog的使用(发现其实两个是一样的)
3.开始一个service,在service里面监听时间值,时间好了就使用MediaPlayer来播放
首先是MainActivity
package liuije.exercise.alarmclock;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.TimePickerDialog;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.Intent;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.DatePicker;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
public class MainActivity extends Activity {
Activity tActivity;
DatePickerDialog datePickerDialog;
TimePickerDialog timePickerDialog;
TextView t;
Calendar at;
Long time;
boolean thi = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Calendar c = Calendar.getInstance();
t = (TextView) findViewById(R.id.textView1);
at = Calendar.getInstance();
tActivity = this;
datePickerDialog = new DatePickerDialog(this, new OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear,
int dayOfMonth) {
at.set(year, monthOfYear, dayOfMonth);
t.append(new SimpleDateFormat("yyyy年MM月dd日", Locale.CHINA)
.format(at.getTime()));
}
}, c.get(Calendar.YEAR), c.get(Calendar.MONTH),
c.get(Calendar.DAY_OF_MONTH));
// 这里的year,monthofyear和dayofmonth是指出现时显示的时间,是int型的,
// 但是指定的话需要转换,参数写2的话会出现三月,是因为java月份从0开始
timePickerDialog = new TimePickerDialog(tActivity,
new OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay,
int minute) {
t.append(hourOfDay + ":" + minute + "n");
at.set(Calendar.HOUR_OF_DAY, hourOfDay);
at.set(Calendar.MINUTE, minute);
}
}, c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), true);
}
public void setDate(View v) {
datePickerDialog.show();
}
public void setTime(View v) {
timePickerDialog.show();
}
public void start(View v) {
Intent intent = new Intent();
intent.putExtra("time", at.getTimeInMillis());
// intent.putExtra("time", System.currentTimeMillis());
thi = true;
intent.setAction("startAlarmClock");
tActivity.startService(intent);
}
}
注意上面datePickDialog的使用,这个组件的事件处理函数返回的月份是比自然月少一的,是因为java的月份是从零开始的。
然后建立Service类,传入时间参数,判断时间到了之后启动闹钟,主要是用的handler和runnable的回调机制:
实现上述回调检查的方法是:首先new 一个handler,然后在一个runnable的run里面使用这个handlerpostdelay自身,然后使用handler的removeCallback可以除掉回调机制
package liuije.exercise.alarmclock;
import java.io.IOException;
import android.app.Service;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class ClockService extends Service {
Long time;
MediaPlayer alarm;
public ClockService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
alarm = MediaPlayer.create(this, R.raw.alarm);
AssetManager am = getAssets();
AssetFileDescriptor afd = null;
// try {
// afd = am.openFd("alarm.mp3");
// } catch (IOException e1) {
// // TODO Auto-generated catch block
// Log.d("服务", "mes");
// e1.printStackTrace();
// }
// try {
// alarm.setDataSource(afd.getFileDescriptor());
// alarm.prepare();
// } catch (IllegalStateException | IOException e) {
// Log.d("服务", "me");
// e.printStackTrace();
// }
Log.d("服务", "oncreate");
final Handler h = new Handler();
Runnable r = new Runnable() {
@Override
public void run() {
Log.d("时间", "time");
h.postDelayed(this, 1000);
if (System.currentTimeMillis() > time) {
h.removeCallbacks(this);
alarm.start();
}
}
};
h.post(r);
// alarm.start();
}
@Override
@Deprecated
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Log.d("服务", "start");
time = intent.getLongExtra("time", System.currentTimeMillis());
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d("服务", "onDestroy");
alarm.stop();
}
}
service要在manifest里面注册,注册的时候可以指定开启的Action
<service android:name=".ClockService" >
<intent-filter>
<action android:name="startAlarmClock" />
</intent-filter>
</service>这样就实现了一个简单的闹钟,总结一下几个问题
1.Calendar的getInstance()就可以得到代表当前时间的一个Calendar的对象
2.Calendar的getTime可以返回Date对象,使用SimpleDateFormat可以格式化这个Date
3.SimpleDateFormat的初始化使用的是(String,Locale)两个构造函数的,这样的Locale可以传Locale.CHINA
4.在上面格式化输出的时候年必须传小写y,日期传大写D的话会出错,日期会显示那个是一年中的第几天,比如165天,传小写的就行
5.service使用Context的startService之后调用了Service的OnCreate和OnStart,