zoukankan      html  css  js  c++  java
  • 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();
        }
    }
  • 相关阅读:
    python @ 修饰符
    收集一些NOSQL网站,以后有时间再来写NOSQL的一些心得
    网站性能问答
    CSLA筆記
    Google PR值原理和详细解说
    通天塔导游:各种编程语言优缺点
    网站访客行为和心理分析--决定网站的回头率
    pymongo 基本操作
    [摘]如何成为python高手
    用数组,列表或字典来代替选择语句
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/6065947.html
Copyright © 2011-2022 走看看