現在工作的原因,又要重新學習android。就打算寫個應用。恰好最近不想起床,創意就來了,寫個鬧鐘,一旦開始唱歌,不唱完休想停下來。
我學這個東西的時候還是2.2,現在都4.3了,變了很多。還真有點不适應。是以花了一個晚上才搞定。
首先建立工程。不多說了。
然後寫一個頁面。很簡單,就一個button,一個timepicker。

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
>
<timepicker
android:id="@+id/timepicker"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<button
android:id="@+id/timebtn"
android:text="@string/done"
android:textsize="20sp"
android:onclick="setalarm"
</linearlayout>
就像這樣,線性布局,timepicker在上,button在下。我們要實作的就是上邊選一個時間,然後點一下button,這個鬧鐘就在你設定的時間響起來,想停都停不了。
然後再oncreate裡,把布局搞上去。

@override
rotected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
timepicker = (timepicker)findviewbyid(r.id.timepicker);
time = (button)findviewbyid(r.id.timebtn);
timepicker.setis24hourview(true);
然後注冊button事件

public void setalarm(view view) {
int hour = timepicker.getcurrenthour();
int minu = timepicker.getcurrentminute();
calendar cal = calendar.getinstance();
cal.set(calendar.hour_of_day, hour);
cal.set(calendar.minute, minu);
if(cal.before(calendar.getinstance())){
cal.add(calendar.date, 1);
}
toast.maketext(this, cal.gettime().tostring(), toast.length_long).show();
alarmmgr = (alarmmanager)getsystemservice(context.alarm_service);
intent intent = new intent(this, alarmreceiver.class);
alarmintent = pendingintent.getbroadcast(this, 0, intent, 0);
alarmmgr.set(alarmmanager.rtc_wakeup, cal.gettimeinmillis(), alarmintent);
/*alarmmgr.setinexactrepeating(alarmmanager.rtc_wakeup, cal.gettimeinmillis(),
alarmmanager.interval_day, alarmintent);*/
}
首先從timepicker中取到小時和分鐘,分别是hour 和minu。
建立一個calendar對象,然後把calendar中的hour和minu替換成我們設定的時間,然後對現在的時間比較一下,如果在現在時間之後,就設定為calendar中儲存的時間,如果是在之前,就把calendar中的時間加一天。
然後是鬧鐘比較重要的幾個類。首先得到alarmmanager這個系統服務。然後建立一個pendingintent,alarmmanager通過set方法設定喚醒方式,時間和到時候抛出的intent。

01.alarmmgr.set(alarmmanager.rtc_wakeup, cal.gettimeinmillis(), alarmintent);
rtc_wakeup代表絕對時間方式,切手機處于休眠狀态時也會fire,第二個參數得到要fire的絕對時間,就是我們剛剛設定的時間,第三個參數是到時候抛出的intent。
代碼跑到這裡,intent應該能抛出來了,還得設計一個broadcastrecevier來接這個intent。認真看代碼的應該已經看到了,這個intent已經寫明白了,将被傳遞給alarmreceiver.class,就是它。下面是代碼:

@override
public void onreceive(context context, intent intent) {
// todo auto-generated method stub
log.d("rec", "the time is up,start the alarm...");
toast.maketext(context, "this the time", toast.length_long).show();
intent serviceintent = new intent(context, musicservice.class);
context.startservice(serviceintent);
}
如果細心應該發現我在上一個代碼段中有一行注釋

/*alarmmgr.setinexactrepeating(alarmmanager.rtc_wakeup, cal.gettimeinmillis(),
這是官方的推薦方法。是以首先是用的這個,但是不知道為什麼總是不成功。是以我還是得好好研究下。
回到原來話題,認真看下上邊代碼發現他夠簡單,隻是打開了一個service。恩,播放音樂就放在這個service裡邊。

public class musicservice extends service implements oncompletionlistener {
//為日志工具設定标簽
private static string tag = "musicservice";
//定義音樂播放器變量
private mediaplayer mplayer;
@override
public void oncreate() {
log.d(tag, "musicserice oncreate()");
mplayer = mediaplayer.create(getapplicationcontext(), r.raw.smoke);
mplayer.setwakemode(getapplicationcontext(), powermanager.partial_wake_lock);
super.oncreate();
public int onstartcommand(intent intent, int flags, int startid) {
log.d(tag, "musicserice onstart()");
mplayer.start();
return super.onstartcommand(intent, flags, startid);
public void ondestroy() {
log.d(tag, "musicserice ondestroy()");
mplayer.stop();
super.ondestroy();
public void oncompletion(mediaplayer player) {
stopself();
}
oncreate的時候建立mediaplayer對象。onstartcommand時開始播放。oncompletion在播放完畢時調用,于是在這裡stop這個service。很簡單。
這麼快,功能都實作了。
在設定裡看到service并沒有自己停掉,這個有點奇怪,需要重新研究下。
大意了。。忘記了給mediaplayer注冊listener導緻的oncompletion方法沒有被調用,是以歌曲播放完畢後service并沒有被停掉。修改後的service代碼如下

public void oncreate() {
// todo auto-generated method stub
log.e(tag, "musicserice oncreate()");
mplayer = mediaplayer.create(getapplicationcontext(), r.raw.smoke);
mplayer.setwakemode(getapplicationcontext(), powermanager.partial_wake_lock);
<span style="color: #ff0000">mplayer.setoncompletionlistener(this);
</span> super.oncreate();
大功告成。核心功能都實作了,就剩下互動設計和ui了。慢慢豐滿吧。
ps:我是直接把音樂資源功能打包在apk裡的,是以鬧鈴是不能換的,而我打包了一首smoke on the water,每天早上都要被嘈雜的電吉他身影弄醒,痛苦不堪。
是以最後的結果是,我用了兩天,早起了兩天後,把這個應用解除安裝了。。。。。