对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,