The default SDK does not provide an API interface for application developers to directly shut down or restart the Android system. Generally speaking, high permissions (system permissions or even Root permissions) are required to shut down or restart the Android system. Therefore, in general apps, if you want to realize the shutdown or restart function, you can either declare the system permission in the app, or indirectly realize the system shutdown or restart through some "indirect" way, such as broadcast or reflection. In addition, it is compiled in the source environment. One advantage of this is that it can directly call the non-public API in Android, which is an effect that Eclipse + SDK cannot achieve. Here are some ways I try:
I Broadcast mode of transmission system
Broadcast is one of the four basic components of Android, which is what we often call broadcast. The Android system itself contains many broadcasts. It monitors every broadcast registered in the system all the time and is ready to respond to operations at any time. Among them, there is a broadcast about shutdown or restart: intent ACTION_REQUEST_ Shutdown and intent ACTION_REBOOT: by sending these two broadcasts, Android can automatically receive the broadcasts and respond to the operation of shutdown or restart. ACTION_REQUEST and ACTION_REBOOT is intent Java is the declared two string constants
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 is located in the source code / frameworks / base / core / Java / Android / content / intent Java. The specific implementation method is as follows
//Broadcast mode shutdown and restart
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); //If false is changed to true, a confirmation window will pop up to confirm whether to shut down 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;
The following points need to be noted:
First, as mentioned earlier, the APP needs to be upgraded to the system permission. The specific method is in androidmenifest Add the following code to XML
android:sharedUserId="android.uid.system"
Second, you need to add shutdown permission at the same time
<uses-permission android:name="android.permission.SHUTDOWN" />
Third, in Eclipse, the code for intent ACTION_ REQUEST_ Shutdown and intent EXTRA_ KEY_ Confirm reports an error in the Eclipse IDE. As mentioned above, these two attributes are not open to the upper layer. If the project is compiled in the source code, it can be compiled.
Fourth, because you need to compile the project in the source code, you need to write mk files for the project and add android.com in the root directory of the project mk file, as follows:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_PACKAGE_NAME := PowerActionDemo LOCAL_CERTIFICATE := platform include $(BUILD_PACKAGE)
Finally, you can verify the function by pushing the compiled apk file to the machine through ADB.
II Through init RC starts the system service to run the sh file
After Android starts the file system, the first application that will be called is /init. This document is a very important content that parses init.. RC and init xxx. RC, and then execute the parsed task. And init RC, you can perform some simple initialization operations in the initialization process of the system. Using this, you can write a simple shutdown or restart sh script file, and perform the corresponding shutdown or restart operation through system init analysis.
1. First, write the sh script for shutdown and restart. For example, new
Restart script system_reboot.sh, as follows:
#!/system/bin/sh reboot shutdown script system_shutdown.sh #!/system/bin/sh reboot -p
Note: the shutdown command here is not shutdown, but reboot -p (if there is a shutdown file in the system/bin directory of your android system, you can also use the shutdown command, because my system only reboots, so reboot -p is used instead of shutdown)
2. Write Android MK compilation script is to compile the two sh files together into the / system/bin directory when compiling the source code
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_PREBUILT_EXECUTABLES := system_shutdown.sh system_reboot.sh LOCAL_MODULE_TAGS := optional include $(BUILD_MULTI_PREBUILT)
3. init.rc add shutdown and restart services and open init RC file, add the following content on the last side:
service system_shutdown /system/bin/system_shutdown.sh oneshot disabled service system_reboot /system/bin/system_reboot.sh oneshot disabled
The oneshot option means that the service is started only once. Without the oneshot option, the executable will always exist -- if the executable is killed, it will be restarted.
Disabled indicates that the service is disabled. This service will not start automatically when it is turned on, but it can be started manually in the application.
4. Create a new directory, such as poweraction, and add the above Android mk , system_ shutdown. sh, system_ reboot. Put SH in this directory, and then copy the directory of poweraction to the Android system, such as under the device path. Then, compile the Android source code. After compiling the source code, view the generated out // Does system / bin contain system_shutdown.sh, system_reboot.sh two sh files. If there are, the compilation is successful.
5. Finally, start the system service to shut down or restart.
//Start system services for shutdown or restart
case R.id.shutdown_btn2: Log.v(TAG, "system service->shutdown"); SystemProperties.set("ctl.start", "system_shutdwon"); break; case R.id.reboot_btn2: Log.v(TAG, "system service->reboot"); SystemProperties.set("ctl.start", "system_reboot"); break;
III Runtime calls Linux shell
We know that the Java class Runtime can be used to call and execute shell commands, while the Android virtual machine supports Linux shell language. Based on this, the Runtime can be used to execute shell commands for shutdown or restart, which is roughly the same as the principle of mode 2 described above. The function codes are as follows:
//Runtime execution linux shell case R.id.shutdown_btn3: try{ Log.v(TAG, "root Runtime->shutdown"); //Process proc =Runtime.getRuntime().exec(new String[]{"su","-c","shutdown"}); / / shutdown Process proc =Runtime.getRuntime().exec(new String[]{"su","-c","reboot -p"}); //Shut down proc.waitFor(); }catch(Exception e){ e.printStackTrace(); } break; case R.id.reboot_btn3: try { Log.v(TAG, "root Runtime->reboot"); Process proc =Runtime.getRuntime().exec(new String[]{"su","-c","reboot "}); //Shut down proc.waitFor(); }catch (Exception ex){ ex.printStackTrace(); } break;
Using this method, it should be noted that ordinary users do not have permission to perform reboot and shutdown, and naturally they cannot shut down or restart. The Android device used must have been root. The above code plus the su command is actually to obtain administrator privileges. In addition, it should be noted that the premise that this method can work is that there are reboot and shutdown files in the system/bin directory of your Android system (in fact, it is the same as the above principle, which also calls the files in the bin directory). It is said that most devices have reboot and shutdown files, but the RK Android system I use does not have shutdown files, so, Cannot be used directly
Runtime.getRuntime().exec(new String[]{"su","-c","shutdown"})
You can only execute the following command to shut down (what a magical p parameter)
Runtime.getRuntime().exec(new String[]{"su","-c","reboot -p"});
IV PowerManager reboot and reflection call PowerManagerService shutdown
1. PowerManager provides reboot and other interfaces. Therefore, it is relatively simple to use PowerManager to restart.
PowerManager pManager=(PowerManager) getSystemService(Context.POWER_SERVICE); pManager.reboot(null);//restart
2. PowerManager class does not provide shutdown interface for shutdown, but communicates with PowerManagerService class through IBinder, a unique communication mode in Android. PowerManagerService is the concrete implementation of the interface defined in PowerManager class, and further calls power class to communicate with the next layer The PowerManagerService implements the shutdown interface, and the power service implements the shutdown function
The implementation of PowerManager calls the interface of Power service through IPowerManager. IPowerManager is a class automatically generated by AIDL files, which is convenient for remote communication. IPowerManage.aidl file directory
framework/base/core/java/android/os/IPowerManage.aidl
IPowerManager implements the shutdown interface, so if we can get the IBinder of Power service, we can call the shutdown method through reflection to realize the shutdown function.
It should be noted that the ServiceManager manages the service program of the system. It saves the IBinder of all services. The IBinder of this service can be obtained through the service name.
However, the ServiceManager class is also HIDE and needs to be called by reflection. Twice, through two reflection calls, the shutdown function realized by power service can be called.
try { //Get ServiceManager class Class<?> ServiceManager = Class.forName("android.os.ServiceManager"); //Get the getService method of ServiceManager Method getService = ServiceManager.getMethod("getService", java.lang.String.class); //Call getService to get RemoteService Object oRemoteService = getService.invoke(null,Context.POWER_SERVICE); //Obtain ipowermanager Stub class Class<?> cStub = Class.forName("android.os.IPowerManager$Stub"); //Get asInterface method Method asInterface = cStub.getMethod("asInterface", android.os.IBinder.class); //Call the asInterface method to get the IPowerManager object Object oIPowerManager = asInterface.invoke(null, oRemoteService); //Get shutdown() method Method shutdown = oIPowerManager.getClass().getMethod("shutdown",boolean.class,boolean.class); //Call the shutdown() method shutdown.invoke(oIPowerManager,false,true); } catch (Exception e) { Log.e(TAG, e.toString(), e); }
5, Use shutdown thread (the attempt is unsuccessful, but the idea feels feasible)
In fact, when PowerManager is used to shut down or restart, PowerManager will continue or call the relevant interface of shuttwinthread. such as
Reboot interface provided by PowerManager. In PowerManager, the implementation code of reboot() is as follows:
public void reboot(String reason) { try { mService.reboot(false, reason, true); } catch (RemoteException e) { } }
mService is of IPowerManager type. As we said earlier, PowerManagerService is the specific implementation of PowerManager, and the interface for PowerManager to call PowerManagerService is the interface for PowerManager to call Power service through IPowerManager. Therefore, if you continue to track the code in PowerManagerService, you can know that there is the implementation of reboot ().
@Override // Binder call public void reboot(boolean confirm, String reason, boolean wait) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null); final long ident = Binder.clearCallingIdentity(); try { shutdownOrRebootInternal(false, confirm, reason, wait); } finally { Binder.restoreCallingIdentity(ident); } }
Continue to track shutdown or reboot internal (false, confirm, reason, wait);
private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm, final String reason, boolean wait) { if (mHandler == null || !mSystemReady) { throw new IllegalStateException("Too early to call shutdown() or reboot()"); } Runnable runnable = new Runnable() { @Override public void run() { synchronized (this) { if (shutdown) { ShutdownThread.shutdown(mContext, confirm); } else { ShutdownThread.reboot(mContext, reason, confirm); } } } };
We will know that it finally calls ShutdownThread reboot() in Java. From the above code, we also know that the shutdown thread also provides a shutdown interface.
Therefore, if you can use shutdown thread, everything will be much more convenient
However, Shutdown does not provide a public API. Some people on the Internet say that you can, directly
Import com.android.server.pm.ShutdownThread
Execute through. Shutdown Shutdown () or shutdown Reboot(), you can shut down or restart accordingly.
However, I put it in the source code environment and found that it failed to compile. I didn't delve into the specific reasons. I'll continue to see it when I have time next time. However, I think this approach is also possible. Maybe I missed something, which led to the failure of compilation.