一. 发送系统广播方式
Broadcast是Android的四大基本组件之中的一个。也就是我们常说的广播。Android系统本身就包括了很多广播,时时刻刻在监听着系统中注冊的每个广播并随时准备响应操作。
当中,就有关于关机或重新启动的广播:Intent.ACTION_REQUEST_SHUTDOWN和Intent.ACTION_REBOOT,通过发送这两个广播。Android就能自己主动接收广播。并响应关机或重新启动的操作。ACTION_REQUEST和ACTION_REBOOT是Intent.java是声明的两个字符串常量
public static final String ACTION_REBOOT ="android.intent.action.REBOOT ";public static final String ACTION_REQUEST_SHUTDOWN = "android.intent.action.ACTION_REQUEST_SHUTDOWN ";
Intent.java位于源代码/frameworks/base/core/java/android/content/Intent.java以下。详细实现方法例如以下
//广播方式关机重新启动case R.id.shutdown_btn1:Log.v(TAG, "broadcast->shutdown ");Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);//当中false换成true,会弹出是否关机的确认窗体intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(intent);break;case R.id.reboot_btn1:Log.v(TAG, "broadcast->reboot ");Intent intent2 = new Intent(Intent.ACTION_REBOOT);intent2.putExtra("nowait ", 1);intent2.putExtra("interval ", 1);intent2.putExtra("window ", 0);sendBroadcast(intent2); break;
须要注意的几点是:
第一。如前面所说,须要将APP提升至系统权限,详细做法是在AndroidMenifest.xml中加入例如以下代码
android:sharedUserId="android.uid.system "
第二,同一时候须要加入关机权限
<uses-permission android:name="android.permission.SHUTDOWN " />
第三,在Eclipse中,代码中的Intent.ACTION_REQUEST_SHUTDOWN 及 Intent.EXTRA_KEY_CONFIRM 在Eclipse IDE中报错,还是和前面说的一样,这两个属性不正确上层开放,假设把项目放在源代码中进行编译,是能够编译通过的。
第四,因为须要在源代码中编译项目,所以须要为项目编写mk文件,在项目根文件夹下加入Android.mk文件。内容例如以下所看到的:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)LOCAL_MODULE_TAGS := optionalLOCAL_SRC_FILES := $(call all-java-files-under, src)LOCAL_PACKAGE_NAME := PowerActionDemo
LOCAL_CERTIFICATE := platforminclude $(BUILD_PACKAGE)
最后,将编译生成的apk文件,通过adb push到机器上就能够验证功能了。
二 . PowerManager reboot以及反射调用PowerManagerService shutdown
1. PowerManager提供了reboot等接口,因此,利用PowerManager实现重新启动,就比較简单。
PowerManager pManager=(PowerManager) getSystemService(Context.POWER_SERVICE); //重新启动到fastboot模式pManager.reboot(" ");
2. PowerManager类并没有提供关机的shutdown接口。而是通过IBinder这样的Android中特有的通信模式,与PowerManagerService 类进行通信。PowerManagerService是PowerManager 类中定义的接口的详细实现,并进一步调用Power 类来与下一层进行通信. 在PowerManagerService实现了shutdown接口,power服务实现了关机功能
PowerManager的实现通过IPowerManager来调用Power服务的接口。
IPowerManager是AIDL文件自己主动生成的类,便于远程通信。IPowerManage.aidl文件文件夹
framework/base/core/java/android/os/IPowerManage.aidl
IPowerManager实现了shutdown接口。所以,假设我们可以获得Power服务的IBinder。通过反射调用shutdown方法就能实现关机功能。
须要注意的是,ServiceManager管理着系统的服务程序。它保存着全部服务的IBinder。通过服务名就能获取到这个服务的IBinder。
但ServiceManager这个类也是HIDE的。也须要反射进行调用。两次。通过两次反射调用,就能调用power服务实现的关机功能。
try {//获得ServiceManager类Class<?> ServiceManager = Class.forName("android.os.ServiceManager ");//获得ServiceManager的getService方法Method getService = ServiceManager.getMethod("getService ", java.lang.String.class);//调用getService获取RemoteServiceObject oRemoteService = getService.invoke(null,Context.POWER_SERVICE);//获得IPowerManager.Stub类Class<?> cStub = Class.forName("android.os.IPowerManager$Stub ");//获得asInterface方法Method asInterface = cStub.getMethod("asInterface ", android.os.IBinder.class);//调用asInterface方法获取IPowerManager对象Object oIPowerManager = asInterface.invoke(null, oRemoteService);//获得shutdown()方法Method shutdown = oIPowerManager.getClass().getMethod("shutdown ",boolean.class,boolean.class);//调用shutdown()方法shutdown.invoke(oIPowerManager,false,true); } catch (Exception e) { Log.e(TAG, e.toString(), e); }