一些常用物理按键电源键:
KEYCODE_POWER 电源键
KEYCODE_BACK 后退键
KEYCODE_MENU 菜单键
KEYCODE_HOME HOME键
KEYCODE_CAMERA相机键
KEYCODE_VOLUME_UP / KEYCODE_VOLUME_DOWM 音量键
KEYCODE_SEARCH 搜索键
KEYCODE_DPAD_CENTER 确定键
方向键
KEYCODE_DPAD_UP
KEYCODE_DPAD_DOWN
KEYCODE_DPAD_LEFT
KEYCODE_DPAD_RIGHT
键盘键
KEYCODE_0...KEYCODE_9
KEYCODE_A....KEYCODE_Z
就目前的Android手机比较常用的就是电源键,后退键,菜单键,HOME键音量键,后退键和音量上下键比较简单,
重写 onKeyDown方法
重写以上代码可以禁用返回键菜单键,音量上下键有些恶意代码通过修改返回键达到HOME键效果,达到进程还保留在系统中
关键代码如下 监听返回键,相当于点击 home 键 :
电源键开机关机监听 :
开关机监听主要用于APP程序开机自启,数据缓存 可以通过接收系统广播实现,接收广播需要注册,有两种注册方式,一种是静态注册,在AndroidMainfest.xml 设置 receiver,
另外一种是动态注册通过在代码中实现,两种广播分别是:android.intent.action.BOOT_COMPLETED 开机android.intent.action.ACTION_SHUTDOWN关机
关键代码:
接收广播通过继承BroadcastReceiver,重写onReceive方法,
关键代码:
关机监听
开机监听:
权限申请:< uses-permission android :name= "android.permission.RECEIVE_BOOT_COMPLETED" />
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键 ,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
第二种:想要完全监听home键需要在framework层去处理。 /frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
里面去修改private void handleLongPressOnHome() 这个方法。
只要把handleLongPressOnHome里面做出相对应的处理就ok记得加上权限:< uses-permission android :name= "android.permission.DISABLE_KEYGUARD" />
恶意代码可以通过监听home键达到退出自启,或则通过禁用HOME,返回键,菜单键,下拉菜单等等达到锁屏目的在2.3版本以下重写下面方法就能重写home键,
关键代码:
4.0以上可以通过设置透明覆盖层AlertDialog达到禁用HOME键目的
关键代码:
涉及到安全性具体代码就不贴了,主要是给大家一个思路,遇到类似问题知道怎么解决
禁用下拉栏关键代码:
修改SystemUI 路径:==/frameworks/base/packages/SystemUI//src/com/android/systemui/statusbar/phone/PhoneStatusBar.Java==通过在PhoneStatusBar.java类中注册一个广播的方式来实现状态栏的禁用和解除,其核心方法就是调用了disable() 方法。disable()是 SystemUI 自定义的方法,感兴趣的同学可以去看其具体实现。
SystemUI中的具体实现代码:
示隐藏的广播我们已经注册好了
关键代码:
在Activity中重写onResume 和 onPause 方法实现状态栏的禁用和解除禁用。另: StatusBarManager 是一个隐藏类,所以调用的时候可能导入不了包会报错 有源码的朋友,可以使用系统编译的后framework jar包作为APP的lib就可以直接使用StatusBarManager方法了。其路径为/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar。将classes.jar改为framework.jar导入工程就OK了。通过上面的步骤我们知道最关键的就是调用 PhoneStatusBar 中disable()方法,我们这里是以广播的方式实现的,只要能实现调用到disable()就可以禁用状态栏。
需要用到的权限
<uses-permission android:name="android.permission.STATUS_BAR"/>
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>
但是android.permission.STATUS_BAR编译会报错,因为这个权限只有系统用户或则ROOT用户才可以使用.需要使用该权限需要把应用伪装成系统应用并使用系统签名
1. 在应用程序的AndroidManifest.xml中的manifest节点中加入 android:sharedUserId="android.uid.system" 这个属性。
2. 修改Android.mk文件,加入 LOCAL_CERTIFICATE := platform 这一行 让程序运行到系统进程中,就可以了! Android中应用程序如何获得系统签名权限:有些库的使用条件比较苛刻,要求同一签名的程序才可以获得访问权。此时即便是在AndroidManifest.xml中添加了相应的permission,依旧会得到没有xx访问权限的问题!第一个方法简单点,不过需要在Android系统源码的环境下用make来编译:
1. 在应用程序的AndroidManifest.xml中的manifest节点中加入 android:sharedUserId="android.uid.system" 这个属性。
2. 修改Android.mk文件,加入 LOCAL_CERTIFICATE := platform 这一行
3. 使用mm命令来编译,生成的apk就有修改系统时间的权限了。
第二个方法麻烦点,不过不用开 虚拟机 跑到源码环境下用make来编译:
1. 同上,加入 android:sharedUserId="android.uid.system" 这个属性。
2. 使用eclipse编译出apk文件,但是这个apk文件是不能用的。
3. 用压缩软件打开apk文件,删掉META-INF目录下的CERT.SF和CERT.RSA两个文件。
4. 使用 目标系统的platform密钥 来重新给apk文件签名。这步比较麻烦,首先找到密钥文件,在我的Android源码目录中的位置是"build\target\product\security",下面的 platform.pk8和platform.x509.pem 两个文件。然后用Android提供的Signapk工具来签名,signapk的源代码是在"build\tools\signapk"下,用法为" signapkplatform.x509.pem platform.pk8 input.apk output.apk ",文件名最好使用绝对路径防止找不到,也可以修改源代码直接使用。
这样最后得到的apk和第一个方法是一样的。
最后解释一下原理,
首先加入android:sharedUserId="android.uid.system"这个属性。通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。那么把程序的UID配成android.uid.system,也就是要让程序运行在系统进程中,这样就有权限来修改系统时间了。
只是加入UID还不够,如果这时候安装APK的话发现无法安装,提示签名不符,原因是程序想要运行在系统进程中还要有目标系统的platform. key,就是上面第二个方法提到的platform.pk8和platform.x509.pem两个文件。
用这两个key签名后apk才真正可以放入系统进程中。第一个方法中加入LOCAL_CERTIFICATE := platform其实就是用这两个key来签名。
这也有一个问题,就是这样生成的程序只有在原始的Android系统或者是自己编译的系统中才可以用,因为这样的系统才可以拿到platform.pk8 和platform.x509.pem两个文件。
要是别家公司做的Android上连安装都安装不了。试试原始的Android中的key来签名,程序在模拟器上运行OK,不过放到G3上安装直接提示"Package ... has no signatures that match those in shared user android.uid.system",这样也是保护了系统的安全。
这个android:sharedUserId属性不只可以把apk放到系统进程中,也可以配置多个APK运行在一个进程中,这样可以共享数据,应该会很有用的!
KEYCODE_POWER 电源键
KEYCODE_BACK 后退键
KEYCODE_MENU 菜单键
KEYCODE_HOME HOME键
KEYCODE_CAMERA相机键
KEYCODE_VOLUME_UP / KEYCODE_VOLUME_DOWM 音量键
KEYCODE_SEARCH 搜索键
KEYCODE_DPAD_CENTER 确定键
方向键
KEYCODE_DPAD_UP
KEYCODE_DPAD_DOWN
KEYCODE_DPAD_LEFT
KEYCODE_DPAD_RIGHT
键盘键
KEYCODE_0...KEYCODE_9
KEYCODE_A....KEYCODE_Z
就目前的Android手机比较常用的就是电源键,后退键,菜单键,HOME键音量键,后退键和音量上下键比较简单,
重写 onKeyDown方法
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
|
if
(keyCode == event.KEYCODE_BACK) {
return
true
;
}
else
if
(keyCode == event.KEYCODE_MENU){
return
true
;
}
else
if
(keyCode == event.KEYCODE_VOLUME_UP){
return
true
;
}
else
if
(keyCode == event.KEYCODE_VOLUME_DOWN){
return
true
;
}
else
{
return
super
.onKeyDown(keyCode, event);
}
|
重写以上代码可以禁用返回键菜单键,音量上下键有些恶意代码通过修改返回键达到HOME键效果,达到进程还保留在系统中
关键代码如下 监听返回键,相当于点击 home 键 :
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
PackageManager pm = getPackageManager();
ResolveInfo homeInfo = pm.resolveActivity(
new
Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME),
0
);
if
(keyCode == KeyEvent.KEYCODE_BACK) {
ActivityInfo ai = homeInfo.activityInfo;
Intent startIntent =
new
Intent(Intent.ACTION_MAIN);
startIntent.addCategory(Intent.CATEGORY_LAUNCHER);
startIntent
.setComponent(
new
ComponentName(ai.packageName, ai.name));
startActivitySafely(startIntent);
return
true
;
}
else
return
super
.onKeyDown(keyCode, event);
|
电源键开机关机监听 :
开关机监听主要用于APP程序开机自启,数据缓存 可以通过接收系统广播实现,接收广播需要注册,有两种注册方式,一种是静态注册,在AndroidMainfest.xml 设置 receiver,
另外一种是动态注册通过在代码中实现,两种广播分别是:android.intent.action.BOOT_COMPLETED 开机android.intent.action.ACTION_SHUTDOWN关机
关键代码:
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
|
<receiver android:name=
".BootBroadcastReceiver"
>
<intent-filter>
<action android:name=
"android.intent.action.BOOT_COMPLETED"
/>
<category android:name=
"android.intent.category.HOME"
/>
</intent-filter>
</receiver>
<receiver android:name=
".ShutdownBroadcastReceiver"
>
<intent-filter>
<action android:name=
"android.intent.action.ACTION_SHUTDOWN"
/>
<category android:name=
"android.intent.category.HOME"
/>
</intent-filter>
</receiver>
|
接收广播通过继承BroadcastReceiver,重写onReceive方法,
关键代码:
关机监听
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
|
public
class
ShutdownBroadcastReceiver
extends
BroadcastReceiver {
private
static
final
String TAG =
"ShutdownBroadcastReceiver"
;
private
static
final
String ACTION_SHUTDOWN =
"android.intent.action.ACTION_SHUTDOWN"
;
@Override
public
void
onReceive(Context context, Intent intent) {
if
(intent.getAction().equals(ACTION_SHUTDOWN)){
Log.d(TAG,
"手机即将光机"
);
Toast.makeText(context,
"手机即将关机"
, Toast.LENGTH_SHORT).show();
}
}
}
|
开机监听:
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
public
class
BootBroadcastReceiver
extends
BroadcastReceiver {
private
static
final
String TAG =
"BootBroadcastReceiver"
;
private
static
final
String ACTION_BOOT =
"android.intent.action.BOOT_COMPLETED"
;
@Override
public
void
onReceive(Context context, Intent intent) {
if
(intent.getAction().equals(ACTION_BOOT)){
Log.d(TAG,
"手机开机了"
);
Toast.makeText(context,
"手机开机了"
, Toast.LENGTH_SHORT).show();
Intent i =
new
Intent(context, MainActivity.
class
);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
}
|
权限申请:< uses-permission android :name= "android.permission.RECEIVE_BOOT_COMPLETED" />
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键 ,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
[Java]
纯文本查看
复制代码
1
2
3
4
5
|
//注册Receiver
HomeKeyEventBroadCastReceiver receiver =
new
HomeKeyEventBroadCastReceiver();
registerReceiver(receiver,
new
IntentFilter(
Intent. ACTION_CLOSE_SYSTEM_DIALOGS));
|
第二种:想要完全监听home键需要在framework层去处理。 /frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
里面去修改private void handleLongPressOnHome() 这个方法。
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
private
void
handleLongPressOnHome() {
// We can't initialize this in init() since the configuration hasn't been loaded yet.
if
(mLongPressOnHomeBehavior <
0
) {
mLongPressOnHomeBehavior
= mContext.getResources().getInteger(R.integer.config_longPressOnHomeBehavior);
if
(mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
mLongPressOnHomeBehavior > LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
}
}
if
(mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
performHapticFeedbackLw(
null
, HapticFeedbackConstants.LONG_PRESS,
false
);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
// Eat the longpress so it won't dismiss the recent apps dialog when
// the user lets go of the home key
mHomeLongPressed =
true
;
}
if
(mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
}
else
if
(mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
try
{
IStatusBarService statusbar = getStatusBarService();
if
(statusbar !=
null
) {
statusbar.toggleRecentApps();
}
}
catch
(RemoteException e) {
Slog.e(TAG,
"RemoteException when showing recent apps"
, e);
// re-acquire status bar service next time it is needed.
mStatusBarService =
null
;
}
}
}
|
只要把handleLongPressOnHome里面做出相对应的处理就ok记得加上权限:< uses-permission android :name= "android.permission.DISABLE_KEYGUARD" />
恶意代码可以通过监听home键达到退出自启,或则通过禁用HOME,返回键,菜单键,下拉菜单等等达到锁屏目的在2.3版本以下重写下面方法就能重写home键,
关键代码:
[Java]
纯文本查看
复制代码
1
2
3
4
|
public
void
onAttachedToWindow() {
this
.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);
super
.onAttachedToWindow();
}
|
4.0以上可以通过设置透明覆盖层AlertDialog达到禁用HOME键目的
关键代码:
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
|
WindowManager.LayoutParams params = getWindow().getAttributes();
params.type = TYPE_SYSTEM_ERROR;
params.dimAmount =
0
.0F;
// transparent
params.width =
0
;
params.height =
0
;
params.gravity = Gravity.BOTTOM;
getWindow().setAttributes(params);
getWindow().setFlags(FLAG_SHOW_WHEN_LOCKED | FLAG_NOT_TOUCH_MODAL,
0xffffff
);
setOwnerActivity(activity);
setCancelable(
false
);
|
涉及到安全性具体代码就不贴了,主要是给大家一个思路,遇到类似问题知道怎么解决
禁用下拉栏关键代码:
修改SystemUI 路径:==/frameworks/base/packages/SystemUI//src/com/android/systemui/statusbar/phone/PhoneStatusBar.Java==通过在PhoneStatusBar.java类中注册一个广播的方式来实现状态栏的禁用和解除,其核心方法就是调用了disable() 方法。disable()是 SystemUI 自定义的方法,感兴趣的同学可以去看其具体实现。
SystemUI中的具体实现代码:
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
@@ -
494
,
6
+
494
,
31
@@
public
class
PhoneStatusBar
extends
BaseStatusBar
implements
DemoMode {
}
+
//add steven zhang by 20160701
+
private
BroadcastReceiver mStatusShowHide =
new
BroadcastReceiver() {
+
+
@Override
+
public
void
onReceive(
final
Context context, Intent intent) {
+
// TODO Auto-generated method stub
+ String action = intent.getAction();
+
+
if
(
"com.aura.statusbar.SHOW_OR_HIDE"
.equals(action)) {
+
// StatusBarManager.DISABLE_NONE
+
// StatusBarManager.DISABLE_EXPAND
+
final
int
mode = intent.getIntExtra(
"mode"
, StatusBarManager.DISABLE_NONE);
+
if
(mNavigationBarView !=
null
) {
+ mHandler.post(
new
Runnable() {
+
+
@Override
+
public
void
run() {
+
+ disable(mode);
+ }
+ });
+ }
+ }
+ }
+ };
//micheal add the Broadcast interface for Control the wifi sleep mode change begin 20150514
private
BroadcastReceiver wifiSleepModeChangeReceiver =
new
BroadcastReceiver(){
@Override
@@ -
519
,
6
+
544
,
10
@@
public
class
PhoneStatusBar
extends
BaseStatusBar
implements
DemoMode {
// ================================================================================
protected
PhoneStatusBarView makeStatusBarView() {
final
Context context = mContext;
+
// add steven zhang by 20160701
+ IntentFilter statusFilter =
new
IntentFilter();
+ statusFilter.addAction(
"com.aura.statusbar.SHOW_OR_HIDE"
);
+ context.registerReceiver(mStatusShowHide, statusFilter);
|
示隐藏的广播我们已经注册好了
关键代码:
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
@Override
protected
void
onResume() {
super
.onResume();
Intent i =
new
Intent(
"com.aura.statusbar.SHOW_OR_HIDE"
);
i.putExtra(
"mode"
, StatusBarManager.DISABLE_EXPAND);
sendBroadcast(i);
}
@Override
protected
void
onPause() {
super
.onPause();
Intent i =
new
Intent(
"com.aura.statusbar.SHOW_OR_HIDE"
);
i.putExtra(
"mode"
, StatusBarManager.DISABLE_NONE);
sendBroadcast(i);
}
|
在Activity中重写onResume 和 onPause 方法实现状态栏的禁用和解除禁用。另: StatusBarManager 是一个隐藏类,所以调用的时候可能导入不了包会报错 有源码的朋友,可以使用系统编译的后framework jar包作为APP的lib就可以直接使用StatusBarManager方法了。其路径为/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar。将classes.jar改为framework.jar导入工程就OK了。通过上面的步骤我们知道最关键的就是调用 PhoneStatusBar 中disable()方法,我们这里是以广播的方式实现的,只要能实现调用到disable()就可以禁用状态栏。
需要用到的权限
<uses-permission android:name="android.permission.STATUS_BAR"/>
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>
但是android.permission.STATUS_BAR编译会报错,因为这个权限只有系统用户或则ROOT用户才可以使用.需要使用该权限需要把应用伪装成系统应用并使用系统签名
1. 在应用程序的AndroidManifest.xml中的manifest节点中加入 android:sharedUserId="android.uid.system" 这个属性。
2. 修改Android.mk文件,加入 LOCAL_CERTIFICATE := platform 这一行 让程序运行到系统进程中,就可以了! Android中应用程序如何获得系统签名权限:有些库的使用条件比较苛刻,要求同一签名的程序才可以获得访问权。此时即便是在AndroidManifest.xml中添加了相应的permission,依旧会得到没有xx访问权限的问题!第一个方法简单点,不过需要在Android系统源码的环境下用make来编译:
1. 在应用程序的AndroidManifest.xml中的manifest节点中加入 android:sharedUserId="android.uid.system" 这个属性。
2. 修改Android.mk文件,加入 LOCAL_CERTIFICATE := platform 这一行
3. 使用mm命令来编译,生成的apk就有修改系统时间的权限了。
第二个方法麻烦点,不过不用开 虚拟机 跑到源码环境下用make来编译:
1. 同上,加入 android:sharedUserId="android.uid.system" 这个属性。
2. 使用eclipse编译出apk文件,但是这个apk文件是不能用的。
3. 用压缩软件打开apk文件,删掉META-INF目录下的CERT.SF和CERT.RSA两个文件。
4. 使用 目标系统的platform密钥 来重新给apk文件签名。这步比较麻烦,首先找到密钥文件,在我的Android源码目录中的位置是"build\target\product\security",下面的 platform.pk8和platform.x509.pem 两个文件。然后用Android提供的Signapk工具来签名,signapk的源代码是在"build\tools\signapk"下,用法为" signapkplatform.x509.pem platform.pk8 input.apk output.apk ",文件名最好使用绝对路径防止找不到,也可以修改源代码直接使用。
这样最后得到的apk和第一个方法是一样的。
最后解释一下原理,
首先加入android:sharedUserId="android.uid.system"这个属性。通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。那么把程序的UID配成android.uid.system,也就是要让程序运行在系统进程中,这样就有权限来修改系统时间了。
只是加入UID还不够,如果这时候安装APK的话发现无法安装,提示签名不符,原因是程序想要运行在系统进程中还要有目标系统的platform. key,就是上面第二个方法提到的platform.pk8和platform.x509.pem两个文件。
用这两个key签名后apk才真正可以放入系统进程中。第一个方法中加入LOCAL_CERTIFICATE := platform其实就是用这两个key来签名。
这也有一个问题,就是这样生成的程序只有在原始的Android系统或者是自己编译的系统中才可以用,因为这样的系统才可以拿到platform.pk8 和platform.x509.pem两个文件。
要是别家公司做的Android上连安装都安装不了。试试原始的Android中的key来签名,程序在模拟器上运行OK,不过放到G3上安装直接提示"Package ... has no signatures that match those in shared user android.uid.system",这样也是保护了系统的安全。
这个android:sharedUserId属性不只可以把apk放到系统进程中,也可以配置多个APK运行在一个进程中,这样可以共享数据,应该会很有用的!