阅读博客声明:
1) 实例是在 Activity 里面完成,不是 View 或者其它 android 组件。
2) 实例是在 android2.3 下验证的,没有考虑其它版本。
3) 这种方法在 android4.0 上可能不正确,4.0 的改动比较大,鬼才知道 google 怎么想的?!
4) 寻找一种学习方法,不要单纯为了问题而ctrl-cv,过几天你自己都不知道问题是怎么解决的!
你在网上搜索 "屏蔽 Home 按键",能搜索出很多优秀的文章,但是我个人还是有点其它的看法。
项目里面的确有这个需求,可以借鉴一下。
屏蔽 Home 按键,至少做到两点:
1) 重写 onAttachedToWindow
2)重写 onKeyDown
实例代码:
package mark.zhang;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.widget.Toast;
public class Main extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d("mark", "onCreate-- ");
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
Log.d("mark", "onAttachedToWindow-- ");
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
Log.d("mark", "onDetachedFromWindow-- ");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("mark", "onDestroy-- ");
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_HOME:
Toast.makeText(this, "home key is pressed", 1).show();
break;
}
}
return super.onKeyDown(keyCode, event);
}
}
a) 这些回调方法调用顺序,如何?
b) 为什么要重写 onAttachedToWindow 方法,在 onCreate 中怎么样?
c) 为什么要使用 WindowManager.LayoutParams.TYPE_KEYGUARD,神马意思?
解答问题:
a) 直接运行程序之后退出,你会看到
如果你有兴趣,可以把 activity 的 7 个生命周期方法都加上,然后一探究竟:
b) 很遗憾的告诉你,不行!不信,你可以试一试!
onAttachedToWindow 调用时机:
activity 的主窗口连接或者附属到 window manager,就会去调用该方法。
文档原文描述:
Called when the main window associated with the activity has been attached to the window manager.
从另一个角度说明,onCreate方法(或者 onStart、onResume,已试过)结束时候,activity 的主窗口还没有附属到 window manager。
如果你想知道,onAttachedToWindow 方法被谁调用了,究竟是怎么调用的,教你几个方法,用哪个随你:
方法1) 在源码里面搜索,呵呵,这是噩梦!
方法2) 自己写个方法去观察,这里,我给出自己的实现代码:
public void findCaller() {
final Throwable mThrowable = new Throwable();
final StackTraceElement[] elements = mThrowable.getStackTrace();
final int len = elements.length;
StackTraceElement item = null;
for (int i = 0; i < len; i++) {
item = elements[i];
System.out.println("Position: " +
item.getClassName() + "." + item.getMethodName()
+ " ---" + item.getLineNumber() + " line");
}
}
那麽在 onAttachedToWindow 方法里面调用 findCaller 就可以看出端倪。
没错,与 PhoneWindow 有关系,请参考:
http://blog.csdn.net/androidbluetooth/article/details/6692770
Android杂谈--Activity、Window、View的关系
c) 这个问题要从源码着手
2.3/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWidowManager.java
在 interceptKeyBeforeDispatching 方法里面出现两个常量:
indowManager.LayoutParams.TYPE_KEYGUARD
indowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
那麽,是不是使用 indowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
可以替代 indowManager.LayoutParams.TYPE_KEYGUARD_DIALOG ?????
答案是肯定的。
注意:
1. 这里我没有使用任何权限,有些地方说需要权限(估计是 android2.3 之前版本):
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"></uses-permission>
2. 如果你是做系统开发的,就根本没有必要这麽做。
你可以修改源码,在用户点击 Home 按键的时候,发送一条广播就可以了。
需要捕获这个按键信息的时候,注册一个 BroadcastReceiver 即可。
附录---src
package mark.zhang;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.widget.Toast;
public class Main extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
setContentView(R.layout.main);
Log.d("mark", "onCreate-- ");
}
@Override
protected void onStart() {
Log.d("mark", "onStart-- ");
super.onStart();
}
@Override
protected void onResume() {
Log.d("mark", "onResume-- ");
super.onResume();
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
Log.d("mark", "onAttachedToWindow-- ");
findCaller();
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
Log.d("mark", "onDetachedFromWindow-- ");
}
@Override
protected void onPause() {
Log.d("mark", "onPause-- ");
super.onPause();
}
@Override
protected void onStop() {
Log.d("mark", "onStop-- ");
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("mark", "onDestroy-- ");
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_HOME:
Toast.makeText(this, "home key is pressed", 1).show();
break;
}
}
return super.onKeyDown(keyCode, event);
}
public void findCaller() {
final Throwable mThrowable = new Throwable();
final StackTraceElement[] elements = mThrowable.getStackTrace();
final int len = elements.length;
StackTraceElement item = null;
for (int i = 0; i < len; i++) {
item = elements[i];
System.out.println("Position: " + item.getClassName() + "." + item.getMethodName()
+ " ---" + item.getLineNumber() + " line");
}
}
}