Android系统应用开发(七)屏蔽Home键和屏幕的唤醒和休眠,AlarmManager
2016-09-13 10:05
816 查看
基于android4.4
一、屏幕的HOME键
做了一个锁屏app替换系统的app ,但是在应用层是无法屏蔽home键的,找了资料,改了源码,终于解决
代码位置
frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindowManager.java下的
定位到名为interceptKeyBeforeDispatching 的函数
从函数名我们可以知道此函数是是在分发按键消息之前进行拦截。
查看对KEYCODE_HOME home键的处理
上层app处理:重写onKeyDown屏蔽home和back
查看对KEYCODE_HOME home键的处理
参考文章:http://www.cnblogs.com/sphere/archive/2014/12/02/4137814.html
参考文章:http://blog.csdn.net/fulinwsuafcie/article/details/7717408
二、屏幕休眠和唤醒
参考文章:http://blog.csdn.net/hufeng882412/article/details/7640123
一般情况下都是手动按电源键来休眠屏幕(使屏幕黑屏)或者唤醒屏幕(使屏幕亮屏),但是一些特殊需求要代码控制屏幕的亮屏和休眠,需求明确了,具体操作如下:
附录:Android中的AlarmManager的使用
1、AlarmManager,顾名思义,就是“提醒”,是Android中常用的一种系统级别的提示服务,在特定的时刻为我们广播一个指定的Intent。简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager为我们广播一个我们设定的Intent,通常我们使用 PendingIntent,PendingIntent可以理解为Intent的封装包,简单的说就是在Intent上在加个指定的动作。在使用Intent的时候,我们还需要在执行startActivity、startService或sendBroadcast才能使Intent有用。而PendingIntent的话就是将这个动作包含在内了。
定义一个PendingIntent对象。
PendingIntent pi = PendingIntent.getBroadcast(this,0,intent,0);
2、AlarmManager的常用方法有三个:
(1)set(int type,long startTime,PendingIntent pi);
该方法用于设置一次性闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟执行时间,第三个参数表示闹钟响应动作。
(2)setRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
该方法用于设置重复闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟首次执行时间(SystemClock.uptimeMillis():表示系统当前时间,如果参数为这个,闹钟会立即执行一次;SystemClock.uptimeMillis()+60000,则表示首次的执行时间为一分钟后后),第三个参数表示闹钟两次执行的间隔时间,第三个参数表示闹钟响应动作。
(3)setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
该方法也用于设置重复闹钟,与第二个方法相似,不过其两个闹钟执行的间隔时间不是固定的而已。
3、三个方法各个参数详悉:
(1)int type: 闹钟的类型,常用的有5个值:AlarmManager.ELAPSED_REALTIME、 AlarmManager.ELAPSED_REALTIME_WAKEUP、AlarmManager.RTC、 AlarmManager.RTC_WAKEUP、AlarmManager.POWER_OFF_WAKEUP。
AlarmManager.ELAPSED_REALTIME表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始),状态值为3;
AlarmManager.ELAPSED_REALTIME_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间,状态值为2;
AlarmManager.RTC表示闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间,即当前系统时间,状态值为1;
AlarmManager.RTC_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,状态值为0;
AlarmManager.POWER_OFF_WAKEUP表示闹钟在手机关机状态下也能正常进行提示功能,所以是5个状态中用的最多的状态之一,该状态下闹钟也是用绝对时间,状态值为4;不过本状态好像受SDK版本影响,某些版本并不支持;
(2)long startTime: 闹钟的第一次执行时间,以毫秒为单位,可以自定义时间,不过一般使用当前时间。需要注意的是,本属性与第一个属性(type)密切相关,如果第一个参数对 应的闹钟使用的是相对时间(ELAPSED_REALTIME和ELAPSED_REALTIME_WAKEUP),那么本属性就得使用相对时间(相对于 系统启动时间来说),比如当前时间就表示为:SystemClock.elapsedRealtime();如果第一个参数对应的闹钟使用的是绝对时间 (RTC、RTC_WAKEUP、POWER_OFF_WAKEUP),那么本属性就得使用绝对时间,比如当前时间就表示
为:System.currentTimeMillis()。
(3)long intervalTime:对于后两个方法来说,存在本属性,表示两次闹钟执行的间隔时间,也是以毫秒为单位。
(4)PendingIntent pi: 绑定了闹钟的执行动作,比如发送一个广播、给出提示等等。PendingIntent是Intent的封装类。需要注意的是,如果是通过启动服务来实现闹钟提 示的话,PendingIntent对象的获取就应该采用Pending.getService(Context c,int i,Intent intent,int j)方法;如果是通过广播来实现闹钟提示的话,PendingIntent对象的获取就应该采用 PendingIntent.getBroadcast(Context
c,int i,Intent intent,int j)方法;如果是采用Activity的方式来实现闹钟提示的话,PendingIntent对象的获取就应该采用 PendingIntent.getActivity(Context c,int i,Intent intent,int j)方法。如果这三种方法错用了的话,虽然不会报错,但是看不到闹钟提示效果。
4.举例说明:定义一个闹钟,5秒钟重复响应。
(1)MainActivity,在onCreate中完成:
(2)定义一个广播接收器类MyReceiver,重写onReceive()函数。
一、屏幕的HOME键
做了一个锁屏app替换系统的app ,但是在应用层是无法屏蔽home键的,找了资料,改了源码,终于解决
代码位置
frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindowManager.java下的
定位到名为interceptKeyBeforeDispatching 的函数
从函数名我们可以知道此函数是是在分发按键消息之前进行拦截。
查看对KEYCODE_HOME home键的处理
// First we always handle the home key here, so applications // can never break it, although if keyguard is on, we do let // it handle it, because that gives us the correct 5 second // timeout. if (keyCode == KeyEvent.KEYCODE_HOME) { // If we have released the home key, and didn't do anything else // while it was pressed, then it is time to go home! if (!down) { cancelPreloadRecentApps(); mHomePressed = false; if (mHomeConsumed) { mHomeConsumed = false; return -1; } if (canceled) { Log.i(TAG, "Ignoring HOME; event canceled."); return -1; } // If an incoming call is ringing, HOME is totally disabled. // (The user is already on the InCallScreen at this point, // and his ONLY options are to answer or reject the call.) try { ITelephony telephonyService = getTelephonyService(); if (telephonyService != null && telephonyService.isRinging()) { Log.i(TAG, "Ignoring HOME; there's a ringing incoming call."); return -1; } } catch (RemoteException ex) { Log.w(TAG, "RemoteException from getPhoneInterface()", ex); } // Delay handling home if a double-tap is possible. if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) { mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case mHomeDoubleTapPending = true; mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable, ViewConfiguration.getDoubleTapTimeout()); return -1; } // Go home! wdh add 我在此处屏蔽系统的launcher并且return 0,原来是return -1,改为return 0 交由上层app处理home键 //launchHomeFromHotKey(); return 0;
上层app处理:重写onKeyDown屏蔽home和back
/** * * 屏蔽掉返回键 * */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub if(keyCode==KeyEvent.KEYCODE_BACK || keyCode==KeyEvent.KEYCODE_HOME){ return true; }else { return super.onKeyDown(keyCode, event); } }
查看对KEYCODE_HOME home键的处理
参考文章:http://www.cnblogs.com/sphere/archive/2014/12/02/4137814.html
参考文章:http://blog.csdn.net/fulinwsuafcie/article/details/7717408
二、屏幕休眠和唤醒
参考文章:http://blog.csdn.net/hufeng882412/article/details/7640123
一般情况下都是手动按电源键来休眠屏幕(使屏幕黑屏)或者唤醒屏幕(使屏幕亮屏),但是一些特殊需求要代码控制屏幕的亮屏和休眠,需求明确了,具体操作如下:
//监听灭屏广播,监听到就启动activity,写在server中 private BroadcastReceiver MyLockScreenReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub System.out.println("receiver--action="+intent.getAction()); /** * ACTION_SCREEN_OFF表示按下电源键,屏幕黑屏 * ACTION_SCREEN_ON 屏幕黑屏情况下,按下电源键 */ if ( intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { System.out.println("receiver................."); keyguardManager = (KeyguardManager) context .getSystemService(Context.KEYGUARD_SERVICE); // 取消默认的锁屏 keyguardLock = keyguardManager.newKeyguardLock(""); keyguardLock.disableKeyguard(); startActivity(startIntent); } } }; /** * 启动闹玲,设置闹玲,发送广播唤醒屏幕,放在activity的oncreat中 * */ private void setAlarm(){ Intent intent = new Intent("WakeUpScreen"); intent.setClass(this, AlarmBroadcastReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0); alarmManager = (AlarmManager)getSystemService(Service.ALARM_SERVICE); alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),10000, pendingIntent); } /** * 唤醒屏幕的广播,唤醒和休眠主要是用了电源管理器,上面的是根据具体需求,我的做法而已 * */ public static class AlarmBroadcastReceiver extends BroadcastReceiver { @SuppressLint("Wakelock") @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub //获取电源管理器对象 PowerManager pm=(PowerManager) context.getSystemService(Context.POWER_SERVICE); //获取PowerManager.WakeLock对象,后面的参数|表示同时传入两个值,最后的是LogCat里用的Tag final PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK, "bright"); String msg = intent.getAction(); if (msg.equals("WakeUpScreen")) { viewFlipper.startFlipping();//我切换图片的代码,可以不要 LogUtils.i(Tag, "AlarmBroadcastReceiver"+"AlarmBroadcastReceiver"); wl.acquire();//亮屏 Handler handler = new Handler();//handle用于自动灭屏 handler.postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub wl.release();//灭屏 } }, 3000); } } } 权限: <uses-permission android:name="android.permission.WAKE_LOCK"/>
附录:Android中的AlarmManager的使用
1、AlarmManager,顾名思义,就是“提醒”,是Android中常用的一种系统级别的提示服务,在特定的时刻为我们广播一个指定的Intent。简单的说就是我们设定一个时间,然后在该时间到来时,AlarmManager为我们广播一个我们设定的Intent,通常我们使用 PendingIntent,PendingIntent可以理解为Intent的封装包,简单的说就是在Intent上在加个指定的动作。在使用Intent的时候,我们还需要在执行startActivity、startService或sendBroadcast才能使Intent有用。而PendingIntent的话就是将这个动作包含在内了。
定义一个PendingIntent对象。
PendingIntent pi = PendingIntent.getBroadcast(this,0,intent,0);
2、AlarmManager的常用方法有三个:
(1)set(int type,long startTime,PendingIntent pi);
该方法用于设置一次性闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟执行时间,第三个参数表示闹钟响应动作。
(2)setRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
该方法用于设置重复闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟首次执行时间(SystemClock.uptimeMillis():表示系统当前时间,如果参数为这个,闹钟会立即执行一次;SystemClock.uptimeMillis()+60000,则表示首次的执行时间为一分钟后后),第三个参数表示闹钟两次执行的间隔时间,第三个参数表示闹钟响应动作。
(3)setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
该方法也用于设置重复闹钟,与第二个方法相似,不过其两个闹钟执行的间隔时间不是固定的而已。
3、三个方法各个参数详悉:
(1)int type: 闹钟的类型,常用的有5个值:AlarmManager.ELAPSED_REALTIME、 AlarmManager.ELAPSED_REALTIME_WAKEUP、AlarmManager.RTC、 AlarmManager.RTC_WAKEUP、AlarmManager.POWER_OFF_WAKEUP。
AlarmManager.ELAPSED_REALTIME表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始),状态值为3;
AlarmManager.ELAPSED_REALTIME_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间,状态值为2;
AlarmManager.RTC表示闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间,即当前系统时间,状态值为1;
AlarmManager.RTC_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,状态值为0;
AlarmManager.POWER_OFF_WAKEUP表示闹钟在手机关机状态下也能正常进行提示功能,所以是5个状态中用的最多的状态之一,该状态下闹钟也是用绝对时间,状态值为4;不过本状态好像受SDK版本影响,某些版本并不支持;
(2)long startTime: 闹钟的第一次执行时间,以毫秒为单位,可以自定义时间,不过一般使用当前时间。需要注意的是,本属性与第一个属性(type)密切相关,如果第一个参数对 应的闹钟使用的是相对时间(ELAPSED_REALTIME和ELAPSED_REALTIME_WAKEUP),那么本属性就得使用相对时间(相对于 系统启动时间来说),比如当前时间就表示为:SystemClock.elapsedRealtime();如果第一个参数对应的闹钟使用的是绝对时间 (RTC、RTC_WAKEUP、POWER_OFF_WAKEUP),那么本属性就得使用绝对时间,比如当前时间就表示
为:System.currentTimeMillis()。
(3)long intervalTime:对于后两个方法来说,存在本属性,表示两次闹钟执行的间隔时间,也是以毫秒为单位。
(4)PendingIntent pi: 绑定了闹钟的执行动作,比如发送一个广播、给出提示等等。PendingIntent是Intent的封装类。需要注意的是,如果是通过启动服务来实现闹钟提 示的话,PendingIntent对象的获取就应该采用Pending.getService(Context c,int i,Intent intent,int j)方法;如果是通过广播来实现闹钟提示的话,PendingIntent对象的获取就应该采用 PendingIntent.getBroadcast(Context
c,int i,Intent intent,int j)方法;如果是采用Activity的方式来实现闹钟提示的话,PendingIntent对象的获取就应该采用 PendingIntent.getActivity(Context c,int i,Intent intent,int j)方法。如果这三种方法错用了的话,虽然不会报错,但是看不到闹钟提示效果。
4.举例说明:定义一个闹钟,5秒钟重复响应。
(1)MainActivity,在onCreate中完成:
1. //创建Intent对象,action为ELITOR_CLOCK,附加信息为字符串“你该打酱油了” 2. Intent intent = new Intent("ELITOR_CLOCK"); 3. intent.putExtra("msg","你该打酱油了"); 4. 5. //定义一个PendingIntent对象,PendingIntent.getBroadcast包含了sendBroadcast的动作。 6. //也就是发送了action 为"ELITOR_CLOCK"的intent 7. PendingIntent pi = PendingIntent.getBroadcast(this,0,intent,0); 8. 9. //AlarmManager对象,注意这里并不是new一个对象,Alarmmanager为系统级服务 10. AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE); 11. 12. //设置闹钟从当前时间开始,每隔5s执行一次PendingIntent对象pi,注意第一个参数与第二个参数的关系 13. // 5秒后通过PendingIntent pi对象发送广播 14. am.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),5*1000,pi);那么启动MainActivity之后,由于定义了AlarmManager am,并且调用了am.setRepeating(...)函数,则系统每隔5s将会通过pi启动intent发送广播,其action为ELITOR_CLOCK。所以我们需要在Manifest.xml中注册一个receiver,同时自己定义一个广播接收器类。
(2)定义一个广播接收器类MyReceiver,重写onReceive()函数。
1. public class MyReceiver extends BroadcastReceiver 2. { 3. 4. @Override 5. public void onReceive(Context context, Intent intent) 6. { 7. // TODO Auto-generated method stub 8. Log.d("MyTag", "onclock......................"); 9. String msg = intent.getStringExtra("msg"); 10. Toast.makeText(context,msg,Toast.LENGTH_SHORT).show(); 11. } 12. 13. }(3)在Manifest.xml中注册广播接收器:
[html] view plaincopy? 1. <receiver android:name=".MyReceiver"> 2. <intent-filter> 3. <action android:name="ELITOR_CLOCK" /> 4. </intent-filter> 5. </receiver>
相关文章推荐
- Android系统应用开发(九)屏蔽状态栏下拉
- Android应用开发-- 如何在页面切换的过程中屏蔽屏幕事件?
- Android Alarm会唤醒系统,但不会唤醒屏幕!
- Android应用开发——系统自带样式Android:theme
- 使用Eclispe进行Android系统应用的开发和调试 推荐
- Android系统的应用开发与运行环境构建
- android 中对 gps 默认关闭+语言默认中文的设置+时区设置+修改系统名字+修改系统默认时间+修改屏幕休眠时间
- Android应用开发——系统自带样式Android:theme
- Eclipse中开发Android系统的内置应用
- 在Android系统上开发基于WebSocket的聊天室应用
- 一步一步的学习android应用开发到系统底层开发之android数据解析JSON篇
- Android应用开发——系统自带样式Android:theme
- Android 禁止系统休眠,使屏幕不变暗
- 做Android 系统/应用开发怎么可以不懂自动化测试
- 做Android 系统/应用开发怎么可以不懂自动化测试
- 做Android 系统/应用开发怎么可以不懂自动化测试
- android 系统应用 开发 注意事项(该版本采用方法效率较高)
- Android应用开发——系统自带样式Android:theme
- Android应用开发之(支持各种密度的屏幕)
- Android应用开发——系统自带样式Android:theme