簡體   English   中英

關閉帶有系統簽名應用程序的 Android 設備

[英]Power off Android device with system signed application

我正在開發一個 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)中嘗試過這個,並且它有效。 但是,我們不希望通過獲得 root 權限的設備將其關閉,因為最終用戶隨后將能夠執行我們公司不允許的意外操作。

另一方面,我們的應用程序由制造商的證書簽署,在本例中為 Cyanogen 的證書。 我讀過,通過使用制造商的證書簽署您的應用程序,您應該能夠發出特權命令(就像 root 用戶一樣)。 但是,即使我將我的應用程序安裝為使用制造商證書簽名的系統應用程序,上述代碼也不起作用:

  • 如果我離開命令的“su”部分,則會顯示“超級用戶請求”屏幕,但這是我們試圖避免的事情。

  • 如果我刪除“su”部分(只留下“reboot -p”),該命令將被靜默忽略。

因此,我們無法使用使用制造商證書簽名的系統應用程序關閉設備。 所以我的問題是,我該怎么做?

已編輯

順便說一句,以防萬一有人不確定:應用程序已正確簽名並安裝為系統應用程序,因為我們實際上可以訪問一些受限的 API,例如 PowerManager.goToSleep()

如果您希望設備重啟(關閉和打開電源),請嘗試使用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);
    }
}

這對我來說很好:

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

你需要這個權限(取決於是系統應用程序):

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

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

好的,我的錯誤。

當我執行一些測試時,我沒有意識到我從清單中刪除了“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”(因為系統可能不提供這樣的命令),但在這種情況下它不起作用。 令人驚訝的是,文件系統以只讀模式重新裝入,因此我必須使用寫入權限重新安裝它。

這是kotlin

(requireContext().getSystemService(Context.POWER_SERVICE) as PowerManager)
                        .reboot("reason")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM