Выключите Android-устройство с помощью приложения, подписанного системой
Я разрабатываю приложение для Android, и мы должны отключить его при определенных обстоятельствах.
Я читал во многих местах, что для этого вам нужен корневой телефон. Затем вы можете выполнить команду "reboot" с помощью 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's. Я прочитал, что, подписав ваше приложение с сертификатом производителя, вы должны иметь возможность выдавать привилегированные команды (как root). Однако, даже если я устанавливаю приложение как системное приложение, подписанное с сертификатом производителя, вышеуказанный код не работает:
-
Если я оставлю часть команды su, появится экран "Запрос суперпользователя", но это то, что мы пытаемся избежать.
-
Если я удалю часть "su" (просто оставив "reboot -p" ), команда молча игнорируется.
В результате мы не можем отключить наше устройство с помощью нашего системного приложения, которое подписано с сертификатом разработчика. Итак, мой вопрос: как я должен это делать?
EDITED
И, кстати, на всякий случай кто-то не уверен в этом: приложение правильно подписано и установлено как системное приложение, потому что мы можем фактически получить доступ к некоторым ограниченным API, таким как PowerManager.goToSleep()
Ответы
Ответ 1
Если вы хотите перезагрузить устройство (выключение и выключение), попробуйте 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) {
}
}
UPDATE
Если вы хотите, чтобы устройство полностью отключилось, используйте 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);
}
}
Ответ 2
Это работало отлично для меня:
startActivity(new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN"));
вам нужно это разрешение (зависит от того, системное приложение):
<uses-permission android:name="android.permission.SHUTDOWN"/>
Источник:
https://github.com/sas101/shutdown-android-app/wiki
Ответ 3
Хорошо, моя ошибка.
Когда я выполнил некоторые тесты, я не понял, что я удалил из манифеста "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" (потому что система может не предоставлять такую команду), но в этом случае она не работает. Удивительно, но файловая система перезагружается в режиме только для чтения, поэтому я должен снова установить ее снова с разрешениями на запись.