天天看點

一個沒有停止的android鬧鐘,一旦開始就要把歌唱完 .

現在工作的原因,又要重新學習android。就打算寫個應用。恰好最近不想起床,創意就來了,寫個鬧鐘,一旦開始唱歌,不唱完休想停下來。

我學這個東西的時候還是2.2,現在都4.3了,變了很多。還真有點不适應。是以花了一個晚上才搞定。

首先建立工程。不多說了。

然後寫一個頁面。很簡單,就一個button,一個timepicker。

一個沒有停止的android鬧鐘,一旦開始就要把歌唱完 .

<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裡,把布局搞上去。

一個沒有停止的android鬧鐘,一旦開始就要把歌唱完 .

      @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事件

一個沒有停止的android鬧鐘,一旦開始就要把歌唱完 .

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。

一個沒有停止的android鬧鐘,一旦開始就要把歌唱完 .

01.alarmmgr.set(alarmmanager.rtc_wakeup, cal.gettimeinmillis(), alarmintent);    

rtc_wakeup代表絕對時間方式,切手機處于休眠狀态時也會fire,第二個參數得到要fire的絕對時間,就是我們剛剛設定的時間,第三個參數是到時候抛出的intent。

代碼跑到這裡,intent應該能抛出來了,還得設計一個broadcastrecevier來接這個intent。認真看代碼的應該已經看到了,這個intent已經寫明白了,将被傳遞給alarmreceiver.class,就是它。下面是代碼:

一個沒有停止的android鬧鐘,一旦開始就要把歌唱完 .

@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);   

    }  

如果細心應該發現我在上一個代碼段中有一行注釋

一個沒有停止的android鬧鐘,一旦開始就要把歌唱完 .

/*alarmmgr.setinexactrepeating(alarmmanager.rtc_wakeup, cal.gettimeinmillis(), 

這是官方的推薦方法。是以首先是用的這個,但是不知道為什麼總是不成功。是以我還是得好好研究下。

回到原來話題,認真看下上邊代碼發現他夠簡單,隻是打開了一個service。恩,播放音樂就放在這個service裡邊。

一個沒有停止的android鬧鐘,一旦開始就要把歌唱完 .

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代碼如下

一個沒有停止的android鬧鐘,一旦開始就要把歌唱完 .

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,每天早上都要被嘈雜的電吉他身影弄醒,痛苦不堪。

是以最後的結果是,我用了兩天,早起了兩天後,把這個應用解除安裝了。。。。。

繼續閱讀