11

我正在开发一个 Android 应用程序,我们需要在某些情况下关闭设备。

我在很多地方都读到过,你需要一个有根电话才能这样做。然后,您可以使用 Java 的 API 发出“重启”命令:

try {
    Process proc = Runtime.getRuntime()
                .exec(new String[]{ "su", "-c", "reboot -p" });
    proc.waitFor();
} catch (Exception ex) {
    ex.printStackTrace();
}

我实际上已经在 Cyanogenmod 10 设备(Samsung Galaxy S3)中尝试过这个,它可以工作。但是,我们不希望有根设备来关闭它,因为最终用户将能够做我们公司不允许的意外事情。

另一方面,我们的申请由制造商的证书签署,在这种情况下是 Cyanogen 的。我已经读过,通过使用制造商的证书签署您的应用程序,您应该能够发出特权命令(就像 root 一样)。但是,即使我将我的应用程序安装为使用制造商证书签名的系统应用程序,上述代码也不起作用:

  • 如果我离开命令的“su”部分,则会显示“超级用户请求”屏幕,但这是我们试图避免的事情。

  • 如果我删除“su”部分(只留下“rebo​​ot -p”),该命令将被忽略。

因此,我们无法使用使用制造商证书签名的系统应用程序关闭设备。所以我的问题是,我应该怎么做?

已编辑

而且,顺便说一句,以防有人不确定:应用程序已正确签名并作为系统应用程序安装,因为我们实际上可以访问一些受限制的 API,例如 PowerManager.goToSleep()

4

3 回答 3

9

如果您希望设备重新启动(关闭和打开电源),请尝试PowerManager.reboot()

PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
powerManager.reboot(null);

android.os.PowerManager

/**
 * Reboot the device.  Will not return if the reboot is successful.
 * <p>
 * Requires the {@link android.Manifest.permission#REBOOT} permission.
 * </p>
 *
 * @param reason code to pass to the kernel (e.g., "recovery") to
 *               request special boot modes, or null.
 */
public void reboot(String reason) {
    try {
        mService.reboot(false, reason, true);
    } catch (RemoteException e) {
    }
}

更新

如果您希望设备完全关闭,请使用PowerManagerService.shutdown()

IPowerManager powerManager = IPowerManager.Stub.asInterface(
        ServiceManager.getService(Context.POWER_SERVICE));
try {
    powerManager.shutdown(false, false);
} catch (RemoteException e) {
}

com.android.server.power.PowerManagerService

/**
 * Shuts down the device.
 *
 * @param confirm If true, shows a shutdown confirmation dialog.
 * @param wait If true, this call waits for the shutdown to complete and does not return.
 */
@Override // Binder call
public void shutdown(boolean confirm, boolean wait) {
    mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);

    final long ident = Binder.clearCallingIdentity();
    try {
        shutdownOrRebootInternal(true, confirm, null, wait);
    } finally {
        Binder.restoreCallingIdentity(ident);
    }
}
于 2013-06-19T11:58:58.763 回答
4

这对我来说很好用:

startActivity(new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN"));

您需要此权限(取决于系统应用程序):

 <uses-permission android:name="android.permission.SHUTDOWN"/>

来源: https ://github.com/sas101/shutdown-android-app/wiki

于 2015-04-07T13:33:28.877 回答
0

好吧,我的错。

当我执行一些测试时,我没有意识到我已经从清单中删除了“android:sharedUserId="android.uid.system"。

包含 sharedUserId 后,以下代码将在不提示用户确认 root 访问的情况下工作:

try {
    Process proc = Runtime.getRuntime()
            .exec(new String[]{ "su", "-c", "reboot -p" });
    proc.waitFor();
} catch (Exception ex) {
    ex.printStackTrace();
}

我试图删除“su”(因为系统可能没有提供这样的命令),但在这种情况下它不起作用。令人惊讶的是,文件系统以只读模式重新挂载,所以我必须再次使用写权限重新挂载它。

于 2013-06-19T13:03:52.337 回答