我正试图找到一种以编程方式干净利落地关闭设备的方法。我的应用程序具有root / system权限,因此我不想使用建议in other answers的方法来执行此操作,而是希望“正确”执行此操作,因为系统会...
使用反射,我正在尝试访问类com.android.internal.app.ShutdownThread及其中的关闭方法。
private static final String SHUTDOWN_CLASS = "com.android.internal.app.ShutdownThread";
private static final String SHUTDOWN_METHOD = "shutdown";
Class<?> sdClass;
Method shutdown;
boolean sd;
boolean success = false;
try {
sdClass = Class.forName(SHUTDOWN_CLASS);
Object obj = sdClass.newInstance();
shutdown = sdClass.getDeclaredMethod(SHUTDOWN_METHOD);
shutdown.setAccessible(true);
sd = (Boolean) shutdown.invoke(obj, ctx, false);
success = sd;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
我已经看过other answers我需要的状态“确保编译的类文件实际上在类路径上” - 我认为它是(尽管有异常!),但也许我误解了它的含义'类路径'。
我也不确定扩展'Thread'的Class是否也有问题?
我可以使用以下代码重新启动或重新启动到recovery / bootloader:
((PowerManager) ctx.getSystemService(Context.POWER_SERVICE)).reboot(action);
我使用的操作字符串是null,bootloader或recovery。我试着很有希望“关机”,但它没有用。这些显然是发送到内核的消息,但我找不到哪些可以在任何地方使用的参考...
注意:在发布'您不应该以编程方式执行此操作'之前,我的用户已经请求它并且完全了解我的应用程序具有的系统和root权限。这就是他们安装它的原因!
如果有人能够指出我做的事情是不可能的,或者我第一次尝试使用反射我出错了,我很感激。
CommonsWare的评论当然绝对正确,Class路径不再存在。在Jelly Bean源代码中,它现在是com.android.server.power.ShutdownThread
尽我所能,但是使用以下代码无法解决错误的窗口令牌问题。
boolean sd = false;
boolean success = false;
try {
Class<?> sdClass = Class.forName("com.android.server.power.ShutdownThread");
for (Constructor<?> ctor : sdClass.getDeclaredConstructors()) {
// Log output
}
Constructor<?> con = sdClass.getDeclaredConstructors()[0];
con.setAccessible(true);
for (Method m : sdClass.getDeclaredMethods()) {
if (m.getName().matches("shutdown")) {
m.setAccessible(true);
sd = (Boolean) m.invoke(ctx, ctx, false);
}
}
success = sd;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return success;
我现在得到的错误是:
W / System.err(17002):引起: android.view.WindowManager $ BadTokenException:无法添加窗口 android.view.ViewRootImpl$W@41ae4a10 - 此权限被拒绝 窗口类型
W / System.err(17002):at com.android.server.power.ShutdownThread.beginShutdownSequence(ShutdownThread.java:222)
我认为这是因为我正在从服务执行此操作,而它可能需要从Foreground Activity执行?如果有人有任何线索,我很想知道......