我正在尝试找到一种以编程方式和干净地关闭设备的方法。我的应用程序具有根/系统权限,因此我不想使用其他答案中建议的方法来执行此操作,而是希望“正确”地执行此操作,因为系统会...
使用反射,我试图访问类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();
}
我查看了其他答案,指出我需要“确保编译的类文件实际上在类路径上” - 我认为它是(尽管有异常!),但也许我误解了“类路径”的含义。
我也不确定扩展“线程”的类是否也是一个问题?
我可以使用以下代码重新启动或重新启动到恢复/引导加载程序:
((PowerManager) ctx.getSystemService(Context.POWER_SERVICE)).reboot(action);
我使用的操作字符串是 null、bootloader 或 recovery。我很有希望地尝试“关闭”,但它没有用。这些显然是发送到内核的消息,但我找不到在任何地方都可以使用的参考......
注意:在您发布“您不应该以编程方式执行此操作”之前,我的用户已经请求它并且完全了解我的应用程序具有的系统和 root 权限。这就是他们安装它的原因!
如果有人能指出我在做什么是不可能的,或者我第一次尝试使用反射时哪里出错了,我会很感激的。
更新
CommonsWare 的评论当然是绝对正确的,类路径不再存在。在 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):在 com.android.server.power.ShutdownThread.beginShutdownSequence(ShutdownThread.java:222)
我认为这是因为我是从服务中执行的,而它可能需要从前台活动中执行?如果有人有任何线索,我很想知道...