天天看点

一个没有停止的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,每天早上都要被嘈杂的电吉他身影弄醒,痛苦不堪。

所以最后的结果是,我用了两天,早起了两天后,把这个应用卸载了。。。。。

继续阅读