-
-
[原创] Android物理按键监听以及恶意代码分析
-
发表于: 2018-3-1 11:43 6182
-
一些常用物理按键电源键:
KEYCODE_POWER电源键
KEYCODE_BACK后退键
KEYCODE_MENU菜单键
KEYCODE_HOMEHOME键
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方法
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键:
关键代码如下监听返回键,相当于点击home键:
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关机
关键代码:
开关机监听主要用于APP程序开机自启,数据缓存可以通过接收系统广播实现,接收广播需要注册,有两种注册方式,一种是静态注册,在AndroidMainfest.xml 设置receiver,
另外一种是动态注册通过在代码中实现,两种广播分别是:android.intent.action.BOOT_COMPLETED 开机android.intent.action.ACTION_SHUTDOWN关机
关键代码:
<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方法,
关键代码:
关机监听
关键代码:
关机监听
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(); } } }
开机监听:
第二种:想要完全监听home键需要在framework层去处理。/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.javapublic 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-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
//注册Receiver HomeKeyEventBroadCastReceiver receiver = new HomeKeyEventBroadCastReceiver(); registerReceiver(receiver, new IntentFilter( Intent. ACTION_CLOSE_SYSTEM_DIALOGS));
里面去修改private void handleLongPressOnHome() 这个方法。
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; } } }
恶意代码可以通过监听home键达到退出自启,或则通过禁用HOME,返回键,菜单键,下拉菜单等等达到锁屏目的在2.3版本以下重写下面方法就能重写home键,
关键代码:
public void onAttachedToWindow() { this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD); super.onAttachedToWindow(); }
4.0以上可以通过设置透明覆盖层AlertDialog达到禁用HOME键目的
关键代码:
关键代码:
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中的具体实现代码:
@@ -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);
示隐藏的广播我们已经注册好了
关键代码:
关键代码:
@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); }
需要用到的权限
<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运行在一个进程中,这样可以共享数据,应该会很有用的!
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键:
关键代码如下监听返回键,相当于点击home键:
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关机
关键代码:
开关机监听主要用于APP程序开机自启,数据缓存可以通过接收系统广播实现,接收广播需要注册,有两种注册方式,一种是静态注册,在AndroidMainfest.xml 设置receiver,
另外一种是动态注册通过在代码中实现,两种广播分别是:android.intent.action.BOOT_COMPLETED 开机android.intent.action.ACTION_SHUTDOWN关机
关键代码:
<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方法,
关键代码:
关机监听
关键代码:
关机监听
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(); } } }
开机监听:
第二种:想要完全监听home键需要在framework层去处理。/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.javapublic 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-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
//注册Receiver HomeKeyEventBroadCastReceiver receiver = new HomeKeyEventBroadCastReceiver(); registerReceiver(receiver, new IntentFilter( Intent. ACTION_CLOSE_SYSTEM_DIALOGS));
里面去修改private void handleLongPressOnHome() 这个方法。
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; } } }
恶意代码可以通过监听home键达到退出自启,或则通过禁用HOME,返回键,菜单键,下拉菜单等等达到锁屏目的在2.3版本以下重写下面方法就能重写home键,
关键代码:
public void onAttachedToWindow() { this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD); super.onAttachedToWindow(); }
4.0以上可以通过设置透明覆盖层AlertDialog达到禁用HOME键目的
关键代码:
关键代码:
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中的具体实现代码:
@@ -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);
示隐藏的广播我们已经注册好了
关键代码:
关键代码:
@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); }
需要用到的权限
<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运行在一个进程中,这样可以共享数据,应该会很有用的!
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关机
关键代码:
开关机监听主要用于APP程序开机自启,数据缓存可以通过接收系统广播实现,接收广播需要注册,有两种注册方式,一种是静态注册,在AndroidMainfest.xml 设置receiver,
另外一种是动态注册通过在代码中实现,两种广播分别是:android.intent.action.BOOT_COMPLETED 开机android.intent.action.ACTION_SHUTDOWN关机
关键代码:
<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方法,
关键代码:
关机监听
关键代码:
关机监听
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(); } } }
开机监听:
第二种:想要完全监听home键需要在framework层去处理。/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.javapublic 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-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
//注册Receiver HomeKeyEventBroadCastReceiver receiver = new HomeKeyEventBroadCastReceiver(); registerReceiver(receiver, new IntentFilter( Intent. ACTION_CLOSE_SYSTEM_DIALOGS));
里面去修改private void handleLongPressOnHome() 这个方法。
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; } } }
恶意代码可以通过监听home键达到退出自启,或则通过禁用HOME,返回键,菜单键,下拉菜单等等达到锁屏目的在2.3版本以下重写下面方法就能重写home键,
关键代码:
public void onAttachedToWindow() { this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD); super.onAttachedToWindow(); }
4.0以上可以通过设置透明覆盖层AlertDialog达到禁用HOME键目的
关键代码:
关键代码:
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中的具体实现代码:
@@ -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);
示隐藏的广播我们已经注册好了
关键代码:
关键代码:
@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); }
需要用到的权限
<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运行在一个进程中,这样可以共享数据,应该会很有用的!
<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方法,
关键代码:
关机监听
关键代码:
关机监听
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(); } } }
开机监听:
第二种:想要完全监听home键需要在framework层去处理。/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.javapublic 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-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
//注册Receiver HomeKeyEventBroadCastReceiver receiver = new HomeKeyEventBroadCastReceiver(); registerReceiver(receiver, new IntentFilter( Intent. ACTION_CLOSE_SYSTEM_DIALOGS));
里面去修改private void handleLongPressOnHome() 这个方法。
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(); } } }
开机监听:
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-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
//注册Receiver HomeKeyEventBroadCastReceiver receiver = new HomeKeyEventBroadCastReceiver(); registerReceiver(receiver, new IntentFilter( Intent. ACTION_CLOSE_SYSTEM_DIALOGS));
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-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
开机自启就是通过接收到开机广播后打开该程序的Activity实现开机自启.
home键是系统键,情况比较特殊,有2种监听方式第一种:在使用广播监听方面可以使用ACTION_CLOSE_SYSTEM_DIALOGS
//注册Receiver HomeKeyEventBroadCastReceiver receiver = new HomeKeyEventBroadCastReceiver(); registerReceiver(receiver, new IntentFilter( Intent. ACTION_CLOSE_SYSTEM_DIALOGS));
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; } } }
恶意代码可以通过监听home键达到退出自启,或则通过禁用HOME,返回键,菜单键,下拉菜单等等达到锁屏目的在2.3版本以下重写下面方法就能重写home键,
关键代码:
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; } } }
public void onAttachedToWindow() { this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD); super.onAttachedToWindow(); }
4.0以上可以通过设置透明覆盖层AlertDialog达到禁用HOME键目的
关键代码:
关键代码:
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中的具体实现代码:
@@ -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);
示隐藏的广播我们已经注册好了
关键代码:
关键代码:
@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); }
需要用到的权限
<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运行在一个进程中,这样可以共享数据,应该会很有用的!
public void onAttachedToWindow() { this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD); super.onAttachedToWindow(); }
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2019-1-11 19:37
被kanxue编辑
,原因:
赞赏
他的文章
- [原创]【Android】利用爬虫将电影网站打包成一个APP 11242
- [原创]深入分析RIL通信初始化原理 5246
- [原创]魔性游戏-熱血!胴上げ(举高高)破解教程 4514
看原图
赞赏
雪币:
留言: