Frage Schalten Sie das Android-Gerät mit der vom System signierten Anwendung aus


Ich entwickle eine Android-Anwendung und wir müssen das Gerät unter bestimmten Umständen ausschalten.

Ich habe an vielen Stellen gelesen, dass Sie ein gerootetes Telefon benötigen, um dies zu tun. Dann können Sie den Befehl "reboot" mit der Java-API ausführen:

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

Ich habe dies tatsächlich in einem Cyanogenmod 10 Gerät (Samsung Galaxy S3) versucht, und es funktioniert. Wir wollen jedoch kein gerootetes Gerät, um es auszuschalten, da der Endbenutzer dann in der Lage ist, unbeabsichtigte Dinge zu tun, die von unserer Firma nicht erlaubt sind.

Auf der anderen Seite ist unser Antrag durch das Zertifikat des Herstellers unterzeichnet, in diesem Fall Cyanogen. Ich habe gelesen, dass Sie, indem Sie Ihre Anwendung mit dem Zertifikat des Herstellers signieren, in der Lage sein sollten, privilegierte Befehle (als root) auszugeben. Aber selbst wenn ich meine App als System-App installiere, die mit dem Zertifikat des Herstellers signiert ist, funktioniert der obige Code nicht:

  • Wenn ich den "su" -Teil des Befehls belasse, wird der "Superuser Request" -Bildschirm angezeigt, aber das versuchen wir zu vermeiden.

  • Wenn ich den "su" -Teil entferne (einfach "reboot -p" belassen), wird der Befehl still ignoriert.

Daher können wir unser Gerät nicht mit unserer System-App, die mit dem Zertifikat des Herstellers signiert ist, ausschalten. Meine Frage ist also, wie soll ich das machen?

BEARBEITET

Übrigens, falls jemand sich nicht sicher ist: Die Anwendung wird ordnungsgemäß signiert und als Systemanwendung installiert, da wir tatsächlich auf einige eingeschränkte APIs zugreifen können, z. B. PowerManager.goToSleep ().


10
2018-06-19 11:32


Ursprung


Antworten:


Wenn das Gerät neu gestartet werden soll (aus- und wieder einschalten), versuchen Sie es 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) {
    }
}

AKTUALISIEREN

Wenn Sie möchten, dass sich das Gerät vollständig ausschaltet, verwenden Sie 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);
    }
}

8
2018-06-19 11:58



Das hat gut für mich funktioniert:

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

Sie benötigen diese Berechtigung (abhängig von der System-App):

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

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


3
2018-04-07 13:33



OK, mein Fehler.

Als ich einige Tests durchführte, war mir nicht klar, dass ich "android: sharedUserId =" android.uid.system "aus dem Manifest entfernt hatte.

Sobald die Datei sharedUserId enthalten ist, funktioniert der folgende Code, ohne dass der Benutzer den Root-Zugriff bestätigen muss:

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

Ich habe versucht, "su" zu entfernen (weil das System einen solchen Befehl nicht zur Verfügung stellt), aber in diesem Fall funktioniert es nicht. Überraschenderweise wird das Dateisystem im schreibgeschützten Modus erneut bereitgestellt, sodass ich es erneut mit Schreibberechtigungen neu mounten muss.


0
2018-06-19 13:03