利用android传感器实现摇一摇解除闹铃的程序

一个有点小意思的闹钟诞生了,哈哈哈……

如果你是用手机做闹钟的,是不是经常在迷迷糊糊中将闹钟关了又继续睡啊?特别是像我们这群大学生们,反正我就是有这个坏毛病,这都已经成为条件反射了,所以经常睡过头。

这个闹钟程序就是利用了手机传感器的重力加速度数据,实现摇一摇解除闹铃的,相信经过那么一阵剧烈的摇晃过后,头脑就会清醒不少,自然而然地也就不容易赖床了。该程序是由android 2.3的源代码提供的原生DeskClock程序修改而来,由于本人时间很有限,一切采取了最简单的实现方法,主要是突出这个小创意,如果有谁感兴趣的话可以自己做更多的效果。好了,废话少说,下面就讲讲本程序的具体思路吧(整个项目源代码下载地址见最后):

主要是修改了DeskClock中的AlarmAlertFullScreen类来实现,因为指定时间到过后会启动该activity来选择取消闹铃或是延时提示。将这activity上的两个按钮的状态设置成不可用(setEnabled(false)),然后通过检测系统传感器加速度改变情况,判断手机是否摇晃,当手机摇晃次数达到一定数值过后还原两个按钮的可用状态。具体代码如下:

一、在AndroidManifest.xml 中添加传感器的操作权限

[html]  view plain copy
  1. <uses-permissionandroid:nameuses-permissionandroid:name="android.permission.VIBRATE"/>  


 

二、添加如下成员变量

private SensorManager sensorManager;    //传感器管理类

   

    private static final intSENSOR_SHAKE = 10;   

    private int total =10;      //手机摇晃的大概次数

    private Button snooze;  //原生代码中这两个按钮是局部变量,这里改成成员

    private Button dismiss;

 

三、在onCreate()中添加

sensorManager= (SensorManager) getSystemService(SENSOR_SERVICE);

 

在onResume()中添加

if(sensorManager != null) {// 注册监听器 

            sensorManager.registerListener(sensorEventListener,sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);

 

在onPause()中添加

 if (sensorManager != null) {// 取消监听器 

           sensorManager.unregisterListener(sensorEventListener);

          

           

        }  

四、添加传感器监听和相关处理过程

 

[java]  view plain copy
  1. **  
  2.      * 重力感应监听  
  3.      */   
  4.     private SensorEventListenersensorEventListener = new SensorEventListener() {   
  5.    
  6.         @Override   
  7.         public void onSensorChanged(SensorEventevent) {   
  8.             // 传感器信息改变时执行该方法   
  9.             float[] values = event.values;   
  10.             float x = values[0]; // x轴方向的重力加速度,向右为正   
  11.             float y = values[1]; // y轴方向的重力加速度,向前为正   
  12.             float z = values[2]; // z轴方向的重力加速度,向上为正   
  13.             //Log.i(TAG, "x轴方向的重力加速度" + x +  ";y轴方向的重力加速度" + y +  ";z轴方向的重力加速度" + z);  
  14.             // 一般在这三个方向的重力加速度达到14就达到了摇晃手机的状态。   
  15.             int medumValue = 13;  
  16.              
  17.             if (Math.abs(x) > medumValue ||Math.abs(y) > medumValue || Math.abs(z) > medumValue) {    
  18.                 Message msg = new Message();   
  19.                 msg.what = SENSOR_SHAKE;   
  20.                 handler.sendMessage(msg);  
  21.             }   
  22.    
  23.         }   
  24.    
  25.         @Override   
  26.         public void onAccuracyChanged(Sensorsensor, int accuracy) {   
  27.    
  28.         }   
  29.     };   
  30.    
  31.     /** 
  32.      * 动作执行 
  33.      */   
  34.     Handler handler = new Handler() {   
  35.    
  36.         @Override   
  37.         public void handleMessage(Message msg){   
  38.             super.handleMessage(msg);   
  39.             switch (msg.what) {   
  40.             case SENSOR_SHAKE:   
  41.                 Log.v("检测到摇晃,执行操作!");  
  42.                 if(total>0){  
  43.                   total--;  
  44.                   snooze.setText("努力摇"+total+" 次");  
  45.                     dismiss.setText("努力摇 "+total+" 次");  
  46.                 }  
  47.                 else if (total==0){  
  48.                     snooze.setText(AlarmAlertFullScreen.this.getString(R.string.alarm_alert_snooze_text));  
  49.                     dismiss.setText(AlarmAlertFullScreen.this.getString(R.string.alarm_alert_dismiss_text));  
  50.                   snooze.setEnabled(true);  
  51.                   dismiss.setEnabled(true);  
  52.                 }  
  53.                 break;   
  54.             }   
  55.         }   
  56.    
  57.     };   
  58.      
  59.      
五、 使用 onKeyDown()来过滤实体按键的消息,不然闹铃响的时候按音量键也会解除闹铃。


AlarmAlertFullScreen.java的全部代码如下:

[java]  view plain copy
  1. /* 
  2.  * Copyright (C) 2009 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package com.android.superdeskclock;  
  18.   
  19. import java.util.Calendar;  
  20.   
  21.   
  22. import android.app.Activity;  
  23. import android.app.Notification;  
  24. import android.app.NotificationManager;  
  25. import android.app.PendingIntent;  
  26. import android.content.BroadcastReceiver;  
  27. import android.content.Context;  
  28. import android.content.Intent;  
  29. import android.content.IntentFilter;  
  30. import android.hardware.Sensor;  
  31. import android.hardware.SensorEvent;  
  32. import android.hardware.SensorEventListener;  
  33. import android.hardware.SensorManager;  
  34. import android.os.Bundle;  
  35. import android.os.Handler;  
  36. import android.os.Message;  
  37. import android.os.PowerManager;  
  38. import android.preference.PreferenceManager;  
  39. import android.view.KeyEvent;  
  40. import android.view.LayoutInflater;  
  41. import android.view.View;  
  42. import android.view.Window;  
  43. import android.view.WindowManager;  
  44. import android.widget.Button;  
  45. import android.widget.TextView;  
  46. import android.widget.Toast;  
  47.   
  48. /** 
  49.  * Alarm Clock alarm alert: pops visible indicator and plays alarm 
  50.  * tone. This activity is the full screen version which shows over the lock 
  51.  * screen with the wallpaper as the background. 
  52.  */  
  53. public class AlarmAlertFullScreen extends Activity {  
  54.   
  55.     // These defaults must match the values in res/xml/settings.xml  
  56.     private static final String DEFAULT_SNOOZE = "10";  
  57.     private static final String DEFAULT_VOLUME_BEHAVIOR = "2";  
  58.     protected static final String SCREEN_OFF = "screen_off";  
  59.   
  60.     //  
  61.       
  62.     private SensorManager sensorManager;  
  63.       
  64.     private static final int SENSOR_SHAKE = 10;  
  65.     private int total =10;  
  66.     private Button snooze;    
  67.     private Button dismiss;   
  68.       
  69.       
  70.     //  
  71.       
  72.     protected Alarm mAlarm;  
  73.     private int mVolumeBehavior;  
  74.       
  75.       
  76.       
  77.       
  78.       
  79.     //  
  80.       
  81.       
  82.     @Override  
  83.     protected void onPause() {  
  84.         // TODO Auto-generated method stub  
  85.         super.onPause();  
  86.         if (sensorManager != null) {// 取消监听器    
  87.             sensorManager.unregisterListener(sensorEventListener);  
  88.              
  89.               
  90.         }    
  91.     }  
  92.   
  93.         
  94.     @Override  
  95.     public boolean onKeyDown(int keyCode,KeyEvent keyEvent){  
  96.         switch (keyCode){  
  97.             case KeyEvent.KEYCODE_BACK:  
  98.             case KeyEvent.KEYCODE_HOME:  
  99.             case KeyEvent.KEYCODE_MENU:  
  100.             case KeyEvent.KEYCODE_DEL:  
  101.             case KeyEvent.KEYCODE_CAMERA:  
  102.             case KeyEvent.KEYCODE_CALL:  
  103.             case KeyEvent.KEYCODE_MUTE:  
  104.             case KeyEvent.KEYCODE_VOLUME_DOWN:  
  105.             case KeyEvent.KEYCODE_POWER:  
  106.             case KeyEvent.KEYCODE_SOFT_RIGHT:  
  107.                 return true;  
  108.             default:  
  109.                 return false;  
  110.         }  
  111.     }  
  112.   
  113.       
  114.     //  
  115.       
  116.       
  117.     
  118.   
  119.   
  120.     // Receives the ALARM_KILLED action from the AlarmKlaxon,  
  121.     // and also ALARM_SNOOZE_ACTION / ALARM_DISMISS_ACTION from other applications  
  122.     private BroadcastReceiver mReceiver = new BroadcastReceiver() {  
  123.         @Override  
  124.         public void onReceive(Context context, Intent intent) {  
  125.             String action = intent.getAction();  
  126.             if (action.equals(Alarms.ALARM_SNOOZE_ACTION)) {  
  127.                 snooze();  
  128.             } else if (action.equals(Alarms.ALARM_DISMISS_ACTION)) {  
  129.                 dismiss(false);  
  130.             } else {  
  131.                 Alarm alarm = intent.getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);  
  132.                 if (alarm != null && mAlarm.id == alarm.id) {  
  133.                     dismiss(true);  
  134.                 }  
  135.             }  
  136.         }  
  137.     };  
  138.   
  139.     @Override  
  140.     protected void onCreate(Bundle icicle) {  
  141.         super.onCreate(icicle);  
  142.   
  143.         mAlarm = getIntent().getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);  
  144.           
  145.         //  
  146.         sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);  
  147.         total = mAlarm.times;  
  148.         /  
  149.         // Get the volume/camera button behavior setting  
  150.         final String vol =  
  151.                 PreferenceManager.getDefaultSharedPreferences(this)  
  152.                 .getString(SettingsActivity.KEY_VOLUME_BEHAVIOR,  
  153.                         DEFAULT_VOLUME_BEHAVIOR);  
  154.         mVolumeBehavior = Integer.parseInt(vol);  
  155.   
  156.         requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);  
  157.   
  158.         final Window win = getWindow();  
  159.         win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED  
  160.                 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);  
  161.         // Turn on the screen unless we are being launched from the AlarmAlert  
  162.         // subclass.  
  163.         if (!getIntent().getBooleanExtra(SCREEN_OFF, false)) {  
  164.             win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON  
  165.                     | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON  
  166. //                    | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON  
  167.                     );  
  168.         }  
  169.   
  170.         updateLayout();  
  171.   
  172.         // Register to get the alarm killed/snooze/dismiss intent.  
  173.         IntentFilter filter = new IntentFilter(Alarms.ALARM_KILLED);  
  174.         filter.addAction(Alarms.ALARM_SNOOZE_ACTION);  
  175.         filter.addAction(Alarms.ALARM_DISMISS_ACTION);  
  176.         registerReceiver(mReceiver, filter);  
  177.     }  
  178.   
  179.     private void setTitle() {  
  180.         String label = mAlarm.getLabelOrDefault(this);  
  181.         TextView title = (TextView) findViewById(R.id.alertTitle);  
  182.         title.setText(label);  
  183.     }  
  184.   
  185.     private void updateLayout() {  
  186.         LayoutInflater inflater = LayoutInflater.from(this);  
  187.   
  188.         setContentView(inflater.inflate(R.layout.alarm_alert, null));  
  189.   
  190.         /* snooze behavior: pop a snooze confirmation view, kick alarm 
  191.            manager. */  
  192.         snooze = (Button) findViewById(R.id.snooze);  
  193.         dismiss = (Button) findViewById(R.id.dismiss);  
  194.         snooze.setEnabled(false);  
  195.         dismiss.setEnabled(false);  
  196.         snooze.setText("努力摇 "+total+" 次");  
  197.         dismiss.setText("努力摇 "+total+" 次");  
  198.         snooze.requestFocus();  
  199.         snooze.setOnClickListener(new Button.OnClickListener() {  
  200.             public void onClick(View v) {  
  201.                 snooze();  
  202.             }  
  203.         });  
  204.   
  205.         /* dismiss button: close notification */  
  206.         dismiss.setOnClickListener(  
  207.                 new Button.OnClickListener() {  
  208.                     public void onClick(View v) {  
  209.                         dismiss(false);  
  210.                     }  
  211.                 });  
  212.   
  213.         /* Set the title from the passed in alarm */  
  214.         setTitle();  
  215.     }  
  216.   
  217.     // Attempt to snooze this alert.  
  218.     private void snooze() {  
  219.         // Do not snooze if the snooze button is disabled.  
  220.         if (!findViewById(R.id.snooze).isEnabled()) {  
  221.             dismiss(false);  
  222.             return;  
  223.         }  
  224.         final String snooze =  
  225.                 PreferenceManager.getDefaultSharedPreferences(this)  
  226.                 .getString(SettingsActivity.KEY_ALARM_SNOOZE, DEFAULT_SNOOZE);  
  227.         int snoozeMinutes = Integer.parseInt(snooze);  
  228.   
  229.         final long snoozeTime = System.currentTimeMillis()  
  230.                 + (1000 * 60 * snoozeMinutes);  
  231.         Alarms.saveSnoozeAlert(AlarmAlertFullScreen.this, mAlarm.id,  
  232.                 snoozeTime);  
  233.   
  234.         // Get the display time for the snooze and update the notification.  
  235.         final Calendar c = Calendar.getInstance();  
  236.         c.setTimeInMillis(snoozeTime);  
  237.   
  238.         // Append (snoozed) to the label.  
  239.         String label = mAlarm.getLabelOrDefault(this);  
  240.         label = getString(R.string.alarm_notify_snooze_label, label);  
  241.   
  242.         // Notify the user that the alarm has been snoozed.  
  243.         Intent cancelSnooze = new Intent(this, AlarmReceiver.class);  
  244.         cancelSnooze.setAction(Alarms.CANCEL_SNOOZE);  
  245.         cancelSnooze.putExtra(Alarms.ALARM_ID, mAlarm.id);  
  246.         PendingIntent broadcast =  
  247.                 PendingIntent.getBroadcast(this, mAlarm.id, cancelSnooze, 0);  
  248.         NotificationManager nm = getNotificationManager();  
  249.         Notification n = new Notification(R.drawable.stat_notify_alarm,  
  250.                 label, 0);  
  251.         n.setLatestEventInfo(this, label,  
  252.                 getString(R.string.alarm_notify_snooze_text,  
  253.                     Alarms.formatTime(this, c)), broadcast);  
  254.         n.flags |= Notification.FLAG_AUTO_CANCEL  
  255.                 | Notification.FLAG_ONGOING_EVENT;  
  256.         nm.notify(mAlarm.id, n);  
  257.   
  258.         String displayTime = getString(R.string.alarm_alert_snooze_set,  
  259.                 snoozeMinutes);  
  260.         // Intentionally log the snooze time for debugging.  
  261.         Log.v(displayTime);  
  262.   
  263.         // Display the snooze minutes in a toast.  
  264.         Toast.makeText(AlarmAlertFullScreen.this, displayTime,  
  265.                 Toast.LENGTH_LONG).show();  
  266.         stopService(new Intent(Alarms.ALARM_ALERT_ACTION));  
  267.         finish();  
  268.     }  
  269.   
  270.     private NotificationManager getNotificationManager() {  
  271.         return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);  
  272.     }  
  273.   
  274.     // Dismiss the alarm.  
  275.     private void dismiss(boolean killed) {  
  276.         Log.i(killed ? "Alarm killed" : "Alarm dismissed by user");  
  277.         // The service told us that the alarm has been killed, do not modify  
  278.         // the notification or stop the service.  
  279.         if (!killed) {  
  280.             // Cancel the notification and stop playing the alarm  
  281.             NotificationManager nm = getNotificationManager();  
  282.             nm.cancel(mAlarm.id);  
  283.             stopService(new Intent(Alarms.ALARM_ALERT_ACTION));  
  284.         }  
  285.         finish();  
  286.     }  
  287.   
  288.     /** 
  289.      * this is called when a second alarm is triggered while a 
  290.      * previous alert window is still active. 
  291.      */  
  292.     @Override  
  293.     protected void onNewIntent(Intent intent) {  
  294.         super.onNewIntent(intent);  
  295.   
  296.         if (Log.LOGV) Log.v("AlarmAlert.OnNewIntent()");  
  297.   
  298.         mAlarm = intent.getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);  
  299.   
  300.         setTitle();  
  301.     }  
  302.   
  303.     @Override  
  304.     protected void onResume() {  
  305.         super.onResume();  
  306.         // If the alarm was deleted at some point, disable snooze.  
  307.         if (Alarms.getAlarm(getContentResolver(), mAlarm.id) == null) {  
  308.             snooze = (Button) findViewById(R.id.snooze);  
  309.             snooze.setEnabled(false);  
  310.         }  
  311.           
  312.         ///  
  313.         if (sensorManager != null) {// 注册监听器    
  314.             sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);    
  315.             // 第一个参数是Listener,第二个参数是所得传感器类型,第三个参数值获取传感器信息的频率    
  316.         }   
  317.         ///  
  318.     }  
  319.   
  320.     @Override  
  321.     public void onDestroy() {  
  322.         super.onDestroy();  
  323.         if (Log.LOGV) Log.v("AlarmAlert.onDestroy()");  
  324.         // No longer care about the alarm being killed.  
  325.         unregisterReceiver(mReceiver);  
  326.     }  
  327.   
  328.     /*@Override 
  329.     public boolean dispatchKeyEvent(KeyEvent event) { 
  330.         // Do this on key down to handle a few of the system keys. 
  331.         boolean up = event.getAction() == KeyEvent.ACTION_UP; 
  332.         switch (event.getKeyCode()) { 
  333.             // Volume keys and camera keys dismiss the alarm 
  334.             case KeyEvent.KEYCODE_VOLUME_UP: 
  335.             case KeyEvent.KEYCODE_VOLUME_DOWN: 
  336.             case KeyEvent.KEYCODE_CAMERA: 
  337.             case KeyEvent.KEYCODE_FOCUS: 
  338.                 if (up) { 
  339.                     switch (mVolumeBehavior) { 
  340.                         case 1: 
  341.                             snooze(); 
  342.                             break; 
  343.  
  344.                         case 2: 
  345.                             dismiss(false); 
  346.                             break; 
  347.  
  348.                         default: 
  349.                             break; 
  350.                     } 
  351.                 } 
  352.                 return true; 
  353.             default: 
  354.                 break; 
  355.         } 
  356.         return super.dispatchKeyEvent(event); 
  357.     }*/  
  358.   
  359.     @Override  
  360.     public void onBackPressed() {  
  361.         // Don't allow back to dismiss. This method is overriden by AlarmAlert  
  362.         // so that the dialog is dismissed.  
  363.         return;  
  364.     }  
  365.       
  366.       
  367.     /  
  368.   
  369.     /**  
  370.      * 重力感应监听  
  371.      */    
  372.     private SensorEventListener sensorEventListener = new SensorEventListener() {    
  373.     
  374.         @Override    
  375.         public void onSensorChanged(SensorEvent event) {    
  376.             // 传感器信息改变时执行该方法    
  377.             float[] values = event.values;    
  378.             float x = values[0]; // x轴方向的重力加速度,向右为正    
  379.             float y = values[1]; // y轴方向的重力加速度,向前为正    
  380.             float z = values[2]; // z轴方向的重力加速度,向上为正    
  381.             //Log.i(TAG, "x轴方向的重力加速度" + x +  ";y轴方向的重力加速度" + y +  ";z轴方向的重力加速度" + z);  
  382.             // 一般在这三个方向的重力加速度达到14就达到了摇晃手机的状态。    
  383.             int medumValue = 13;  
  384.               
  385.             if (Math.abs(x) > medumValue || Math.abs(y) > medumValue || Math.abs(z) > medumValue) {     
  386.                 Message msg = new Message();    
  387.                 msg.what = SENSOR_SHAKE;    
  388.                 handler.sendMessage(msg);  
  389.             }    
  390.   
  391.         }    
  392.     
  393.         @Override    
  394.         public void onAccuracyChanged(Sensor sensor, int accuracy) {    
  395.     
  396.         }    
  397.     };    
  398.     
  399.     /**  
  400.      * 动作执行  
  401.      */    
  402.     Handler handler = new Handler() {    
  403.     
  404.         @Override    
  405.         public void handleMessage(Message msg) {    
  406.             super.handleMessage(msg);    
  407.             switch (msg.what) {    
  408.             case SENSOR_SHAKE:    
  409.                 Log.v("检测到摇晃,执行操作!");  
  410.                 if(total>0){  
  411.                     total--;  
  412.                     snooze.setText("努力摇 "+total+" 次");  
  413.                     dismiss.setText("努力摇 "+total+" 次");  
  414.                 }  
  415.                 else if (total==0){  
  416.                     snooze.setText(AlarmAlertFullScreen.this.getString(R.string.alarm_alert_snooze_text));  
  417.                     dismiss.setText(AlarmAlertFullScreen.this.getString(R.string.alarm_alert_dismiss_text));  
  418.                     snooze.setEnabled(true);  
  419.                     dismiss.setEnabled(true);  
  420.                 }  
  421.                 break;    
  422.             }    
  423.         }    
  424.     
  425.     };    
  426.       
  427.       
  428.       
  429.       
  430. }  

这是我第一次写和专业相关的博客,有很多不足指出请大家谅解啊,也希望大家能指出我存在的错误。

整个项目源代码下载地址:http://download.csdn.net/detail/ystgx/5451207

Github下载地址:https://github.com/ystgx/ShakingClock

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值