Android 闹钟最终版

以下是我发现的几点闹钟中重要的点,分享一下:

(1)在闹钟中有AudioManager管理机制,这个机制可以申请和释放OnAudioFocusChangeListener监听。

还有mTelephonyManager对象,处理在闹钟响的时候,来电铃声的切换。

(2)广播接收闹钟,通过广播启动AlarmKlaxon这个Service,隐式启动service:

public static final String ALARM_INTENT_EXTRA = "intent.extra.alarm";

       // Play the alarm alert and vibrate the device.
        Intent playAlarm = new Intent(Alarms.ALARM_ALERT_ACTION);
        playAlarm.putExtra(Alarms.ALARM_INTENT_EXTRA, alarm);
        context.startService(playAlarm);

在mainfest中,AlarmKlaxon这个服务的定义如下:

        <service android:name="AlarmKlaxon"
                android:description="@string/alarm_klaxon_service_desc"
                >
            <intent-filter>
                <action android:name="com.cn.daming.deskclock.ALARM_ALERT" />
            </intent-filter>
        </service>

这个service做的是允许别的Activity打断正在响铃的铃声,播放其他的铃声,例如,闹钟响的时候来电话了。

(3)在listview中包含checkbox,这时候闹钟的处理时,activity实现一个OnItemClickListener的监听,点击每一项的监听。然后在checkbox单独拿出去写一个类,继承LinearLayout,重写setPressed()这个方法,以实现“当点击checkbox的时候不触发parent的click事件”。关键代码如下:

    @Override
    public void setPressed(boolean pressed) {
        // If the parent is pressed, do not set to pressed.
        if (pressed && ((View) getParent()).isPressed()) {
            return;
        }
        super.setPressed(pressed);
    }

下面看看我的程序截图:

红色圈的图标为我的闹钟。              点击“玲闹钟”后的界面

              

点击新建闹钟出现的界面               设置好时间弹出的toast。

              

下面我把我的主要入口类的代码贴出来:

DeskClockMainActivity.Java

package com.cn.daming.deskclock;

import java.util.Calendar;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CheckBox;
import android.widget.CursorAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class DeskClockMainActivity extends Activity implements OnItemClickListener{

    static final String PREFERENCES = "AlarmClock";

    /** This must be false for production.  If true, turns on logging,
        test code, etc. */
    static final boolean DEBUG = false;

    private SharedPreferences mPrefs;
    private LayoutInflater mFactory;
    private ListView mAlarmsList;
    private Cursor mCursor;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //取自定义布局的LayoutInflater
        mFactory = LayoutInflater.from(this);
        //取getSharedPreferences中key==“AlarmClock”的值
        mPrefs = getSharedPreferences(PREFERENCES, 0);
        //获取闹钟的cursor
        mCursor = Alarms.getAlarmsCursor(getContentResolver());

        //更新布局界面
        updateLayout();

    }

    //加载更新界面布局
    private void updateLayout() {
        setContentView(R.layout.alarm_clock);
        mAlarmsList = (ListView) findViewById(R.id.alarms_list);
        AlarmTimeAdapter adapter = new AlarmTimeAdapter(this, mCursor);
        mAlarmsList.setAdapter(adapter);
        mAlarmsList.setVerticalScrollBarEnabled(true);
        mAlarmsList.setOnItemClickListener(this);
        mAlarmsList.setOnCreateContextMenuListener(this);

        View addAlarm = findViewById(R.id.add_alarm);
        addAlarm.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    addNewAlarm();
                }
            });
        // Make the entire view selected when focused.
        addAlarm.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                public void onFocusChange(View v, boolean hasFocus) {
                    v.setSelected(hasFocus);
                }
        });

        ImageButton deskClock =
                (ImageButton) findViewById(R.id.desk_clock_button);
        deskClock.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {

                }
        });
    }

    private void addNewAlarm() {
        startActivity(new Intent(this, SetAlarm.class));
    }

    /**
     * listview的适配器继承CursorAdapter
     * @author wangxianming
     * 也可以使用BaseAdapter
     */
    private class AlarmTimeAdapter extends CursorAdapter {
        public AlarmTimeAdapter(Context context, Cursor cursor) {
            super(context, cursor);
        }

        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            View ret = mFactory.inflate(R.layout.alarm_time, parent, false);

            DigitalClock digitalClock =
                    (DigitalClock) ret.findViewById(R.id.digitalClock);
            digitalClock.setLive(false);
            return ret;
        }

        //把view绑定cursor的每一项
        public void bindView(View view, Context context, Cursor cursor) {
            final Alarm alarm = new Alarm(cursor);

            View indicator = view.findViewById(R.id.indicator);

            // Set the initial resource for the bar image.
            final ImageView barOnOff =
                    (ImageView) indicator.findViewById(R.id.bar_onoff);
            barOnOff.setImageResource(alarm.enabled ?
                    R.drawable.ic_indicator_on : R.drawable.ic_indicator_off);

            // Set the initial state of the clock "checkbox"
            final CheckBox clockOnOff =
                    (CheckBox) indicator.findViewById(R.id.clock_onoff);
            clockOnOff.setChecked(alarm.enabled);

            // Clicking outside the "checkbox" should also change the state.
            //对checkbox设置监听,使里外一致
            indicator.setOnClickListener(new OnClickListener() {
                    public void onClick(View v) {
                        clockOnOff.toggle();
                        updateIndicatorAndAlarm(clockOnOff.isChecked(),
                                barOnOff, alarm);
                    }
            });

            DigitalClock digitalClock =
                    (DigitalClock) view.findViewById(R.id.digitalClock);

            // set the alarm text
            final Calendar c = Calendar.getInstance();
            c.set(Calendar.HOUR_OF_DAY, alarm.hour);
            c.set(Calendar.MINUTE, alarm.minutes);
            digitalClock.updateTime(c);
            digitalClock.setTypeface(Typeface.DEFAULT);

            // Set the repeat text or leave it blank if it does not repeat.
            TextView daysOfWeekView =
                    (TextView) digitalClock.findViewById(R.id.daysOfWeek);
            final String daysOfWeekStr =
                    alarm.daysOfWeek.toString(DeskClockMainActivity.this, false);
            if (daysOfWeekStr != null && daysOfWeekStr.length() != 0) {
                daysOfWeekView.setText(daysOfWeekStr);
                daysOfWeekView.setVisibility(View.VISIBLE);
            } else {
                daysOfWeekView.setVisibility(View.GONE);
            }

            // Display the label
            TextView labelView =
                    (TextView) view.findViewById(R.id.label);
            if (alarm.label != null && alarm.label.length() != 0) {
                labelView.setText(alarm.label);
                labelView.setVisibility(View.VISIBLE);
            } else {
                labelView.setVisibility(View.GONE);
            }
        }
    };

    //更新checkbox
    private void updateIndicatorAndAlarm(boolean enabled, ImageView bar,
            Alarm alarm) {
        bar.setImageResource(enabled ? R.drawable.ic_indicator_on
                : R.drawable.ic_indicator_off);
        Alarms.enableAlarm(this, alarm.id, enabled);
        if (enabled) {
            SetAlarm.popAlarmSetToast(this, alarm.hour, alarm.minutes,
                    alarm.daysOfWeek);
        }
    }

    /*
     * (non-Javadoc)
     * @see android.app.Activity#onContextItemSelected(android.view.MenuItem)
     * 创建上下文菜单
     */
    @Override
    public boolean onContextItemSelected(final MenuItem item) {
        final AdapterContextMenuInfo info =
                (AdapterContextMenuInfo) item.getMenuInfo();
        final int id = (int) info.id;
        // Error check just in case.
        if (id == -1) {
            return super.onContextItemSelected(item);
        }
        switch (item.getItemId()) {
            case R.id.delete_alarm:
                // Confirm that the alarm will be deleted.
                new AlertDialog.Builder(this)
                        .setTitle(getString(R.string.delete_alarm))
                        .setMessage(getString(R.string.delete_alarm_confirm))
                        .setPositiveButton(android.R.string.ok,
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface d,
                                            int w) {
                                        Alarms.deleteAlarm(DeskClockMainActivity.this, id);
                                    }
                                })
                        .setNegativeButton(android.R.string.cancel, null)
                        .show();
                return true;

            case R.id.enable_alarm:
                final Cursor c = (Cursor) mAlarmsList.getAdapter()
                        .getItem(info.position);
                final Alarm alarm = new Alarm(c);
                Alarms.enableAlarm(this, alarm.id, !alarm.enabled);
                if (!alarm.enabled) {
                    SetAlarm.popAlarmSetToast(this, alarm.hour, alarm.minutes,
                            alarm.daysOfWeek);
                }
                return true;

            case R.id.edit_alarm:
                Intent intent = new Intent(this, SetAlarm.class);
                intent.putExtra(Alarms.ALARM_ID, id);
                startActivity(intent);
                return true;

            default:
                break;
        }
        return super.onContextItemSelected(item);
    }

    /*
     * (non-Javadoc)
     * @see android.app.Activity#onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo)
     * 创建菜单
     */
    @Override
    public void onCreateContextMenu(ContextMenu menu, View view,
            ContextMenuInfo menuInfo) {
        // Inflate the menu from xml.
        getMenuInflater().inflate(R.menu.context_menu, menu);

        // Use the current item to create a custom view for the header.
        final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
        final Cursor c =
                (Cursor) mAlarmsList.getAdapter().getItem((int) info.position);
        final Alarm alarm = new Alarm(c);

        // Construct the Calendar to compute the time.
        final Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, alarm.hour);
        cal.set(Calendar.MINUTE, alarm.minutes);
        final String time = Alarms.formatTime(this, cal);

        // Inflate the custom view and set each TextView‘s text.
        final View v = mFactory.inflate(R.layout.context_menu_header, null);
        TextView textView = (TextView) v.findViewById(R.id.header_time);
        textView.setText(time);
        textView = (TextView) v.findViewById(R.id.header_label);
        textView.setText(alarm.label);

        // Set the custom view on the menu.
        menu.setHeaderView(v);
        // Change the text based on the state of the alarm.
        if (alarm.enabled) {
            menu.findItem(R.id.enable_alarm).setTitle(R.string.disable_alarm);
        }
    }

    /*
     * (non-Javadoc)
     * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
     * 设置菜单的点击事件的处理
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_item_settings:
                startActivity(new Intent(this, SettingsActivity.class));
                return true;
            case R.id.menu_item_desk_clock:
                //modify by wangxianming in 2012-4-14
//                startActivity(new Intent(this, DeskClock.class));
                return true;
            case R.id.menu_item_add_alarm:
                addNewAlarm();
                return true;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    /*
     * (non-Javadoc)
     * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
     * 创建菜单
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.alarm_list_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    /*
     * (non-Javadoc)
     * @see android.widget.AdapterView.OnItemClickListener#onItemClick(android.widget.AdapterView, android.view.View, int, long)
     * 创建菜单的点击事件响应
     */
    public void onItemClick(AdapterView<?> adapterView, View v, int pos, long id) {
        Intent intent = new Intent(this, SetAlarm.class);
        intent.putExtra(Alarms.ALARM_ID, (int) id);
        startActivity(intent);

    }

   @Override
    protected void onDestroy() {
        super.onDestroy();
        ToastMaster.cancelToast();
        mCursor.close();
    }
}
时间: 2024-10-10 22:03:46

Android 闹钟最终版的相关文章

结对项目--四则运算图形化最终版

四则运算器图形化最终版 (然而被我做成了奇怪的东西 组员:13070030张博文 13070033刘云峰 一.概念阶段 最初是想试试用android做个计算器app,无奈从零学起着实太赶,而且这个计划在试用了无比卡顿占内存的android studio后就彻底搁浅了. 然后就被路人谣传说MFC好用,无奈从零学起着实太赶,而且这个计划在无人指导的摸黑下也顺手搁浅了. 最终便沦为了EasyX旧传统,好歹有点基础,但果然还是不太甘心. 以及因为当初想做app,所以抠了iphone计算器的图想当UI,结

Android闹钟设置的解决方案

Android设置闹钟并不像IOS那样这么简单,做过Android设置闹钟的开发者都知道里面的坑有多深.下面记录一下,我解决Android闹钟设置的解决方案. 主要问题 API19开始AlarmManager的机制修改. 应用程序被Kill掉后,设置的闹钟不响. 6.0以上进入Doze模式会使JobScheduler停止工作. 手机设置重启后,闹钟失效问题. API19以上AlarmManager机制的修改 API19之前AlarmManager提供了三个设置闹钟的方法,由于业务需求闹钟只需要一

jQuery 3.0最终版发布,十大新特性眼前一亮

jQuery 3.0在日前发布了最终的全新版本.从2014年10月,jQuery团队对这个主要大版本进行维护开始,web开发者社区便一直在期待着这一刻的到来,终于在2016年6月他们迎来了这一个最终版www.lampbrother.net. 通过jQuery 3.0的版本更新说明,我们看到了一个保持着向后兼容的更轻便,更快速的jQuery.在本文中,我们将介绍一些令人眼前一亮的jQuery 3.0全新特性. 开始前的说明 如果你想要下载jQuery 3.0进行亲自实验,可以通过该页面进行下载.另

最终版的Web(Python实现)

天啦,要考试了,要期末考试了,今天把最终版的Python搭建Web代码先写这里记下了.详细的过程先不写了. 这次是在前面的基础上重写 HTTPServer 与 BaseHTTPRequestHandler,主要利用 python 提供 的 socket 进行编程,从而实现消息的接收与相应:然后再接着引入多线程,分别处理来自客户端的请求:最后实现根据客户端传递的参数动态生成页面的功能. 主要步骤如下: 一. .重写 HTTPServer 与 BaseHTTPRequestHandlerPython

android闹钟小案例之功能阐述

最近花了一个星期左右的时间做了一个小闹钟,现在回过头来进行总结下.刚开始接触这个案例,总体觉着没有太大的难度,都是一些基础知识的堆砌,可现实总比理想残酷啊,这几天下来,每天都会有意料之外的bug出现.在debug的过程中,深深体会到了百度一下和谷歌谷歌的用处,基本常见的问题都可以在这里得到提示甚至答案.这篇文章先来介绍下这个案例所实现的功能,接下来再用几遍文章记录所用到的知识点. 功能简介: 1.闹钟基本功能:和平时的闹钟一样,用户在界面选择闹钟响起的时间,到达所设定时间后执行相应的指定操作.

Android闹钟 AlarmManager的使用

Android闹钟 AlarmManager的使用 AlarmManager介绍 AlarmManager这个类提供对系统闹钟服务的访问接口. 你可以为你的应用设定一个在未来某个时间唤醒的功能. 当闹钟响起,实际上是系统发出了为这个闹钟注册的广播,会自动开启目标应用. 注册的闹钟在设备睡眠的时候仍然会保留,可以选择性地设置是否唤醒设备,但是当设备关机和重启后,闹钟将会被清除. 在alarm的receiver的onReceive()方法被执行的时候,Alarm Manager持有一个CPU唤醒锁,

android闹钟小案例之知识点总结

上一篇文章对近期做的小闹钟做了功能阐述,现在来总结下整个开发过程中所用到的一些知识点: 1.TimePicker的监听 TimePicker控件是整个应用的核心,其它的操作都得基于对该控件的正确操控.对该控件的操作重要就是为其设置监听器,在监听事件中获取用户设置的时间. private Calendar calendar=Calendar.getInstance();//创建calendar对象 private class OnTimeChangedListenerImpl implements

理解《JavaScript设计模式与开发应用》发布-订阅模式的最终版代码

最近拜读了曾探所著的<JavaScript设计模式与开发应用>一书,在读到发布-订阅模式一章时,作者不仅给出了基本模式的通用版本的发布-订阅模式的代码,最后还做出了扩展,给该模式增加了离线空间功能和命名空间功能,以达到先发布再订阅的功能和防止名称冲突的效果.但是令人感到遗憾的是最终代码并没有给出足够的注释.这让像我一样的小白就感到非常的困惑,于是我将这份最终代码仔细研究了一下,并给出了自己的一些理解,鉴于能力有限,文中观点可能并不完全正确,望看到的大大们不吝赐教,谢谢! 下面是添加了个人注释的

Android闹钟程序

原文:Android闹钟程序 源代码下载地址:http://www.zuidaima.com/share/1597010528603136.htm 转自csdn: 版权声明:本文为博主原创文章,未经博主允许不得转载.