Apague el dispositivo mediante progtwigción

Estoy escribiendo una aplicación que está diseñada para ejecutarse en un modelo de dispositivo específico (un dispositivo Android que ejecuta un firmware basado en Amlogic). Tengo ambas capacidades de raíz y mi aplicación está firmada con el certificado de firmware.

Mi aplicación es el foco principal del dispositivo, y sería útil poder iniciar un apagado completo.

No tengo el comando de shutdown . Tengo el comando de reboot .

reboot -p no ayuda. Simplemente congela el dispositivo mientras permanece encendido.

El PowerManager es un paso mejor, pero establece el dispositivo en modo de suspensión, en lugar de un apagado completo:

 PowerManager pm = (PowerManager)getSystemService(Service.POWER_SERVICE); pm.goToSleep(SystemClock.uptimeMillis()); 

Estoy abierto a todas las sugerencias, hacky o no. Se espera que la versión de Android permanezca en 4.2.2 .


Intentos

Este comando hará que el dispositivo se reinicie. Intent.ACTION_SHUTDOWN no parece hacer nada. ¿Es esta intención tal vez solo para informar un cierre y no para iniciar uno?

 Intent i = new Intent(Intent.ACTION_REBOOT); i.putExtra("nowait", 1); i.putExtra("interval", 1); i.putExtra("window", 0); sendBroadcast(i); 

La mayor suerte que tuve con esto fue solicitar el cierre por intención:

 Intent i = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN"); i.putExtra("android.intent.extra.KEY_CONFIRM", true); startActivity(i); 

Hilo de cierre

Eso está un poco más cerca. Definitivamente interesante. ¿Puedes encontrar un ejemplo de usarlo?

Hasta ahora he llegado a esto:

 Class sdClass = Class.forName("com.android.server.power.ShutdownThread"); Constructor con = sdClass.getDeclaredConstructors()[0]; con.setAccessible(true); for (Method m : sdClass.getDeclaredMethods()) { if (m.getName().matches("shutdown")) { m.setAccessible(true); m.invoke(sdClass, PlayerActivity.this, false); } else if (m.getName().matches("rebootOrShutdown")) { m.setAccessible(true); m.invoke(sdClass, PlayerActivity.this, false); } else if (m.getName().matches("beginShutdownSequence")) { m.setAccessible(true); m.invoke(sdClass, PlayerActivity.this, false); } } 

shutdown y beginShutdownSequence crean NullPointerException s (¿ves por qué?) y rebootOrShutdown crea una InvocationTargetException debido a un UnsatisfiedLinkError … No puede encontrar un método nativo:

java.lang.UnsatisfiedLinkError: método nativo no encontrado: com.android.server.power.PowerManagerService.nativeShutdown :() V en com.android.server.power.PowerManagerService.nativeShutdown (método nativo) en com.android.server.power .PowerManagerService.lowLevelShutdown (PowerManagerService.java:2163) en com.android.server.power.ShutdownThread.rebootOrShutdown (ShutdownThread.java:543) en com.android.server.power.ShutdownThread.run (ShutdownThread.java:393)

lowLevelShutdown es la función que finalmente alcanzan todas las funciones, cuando se configura para apagar (y no para reiniciar). Así que descubrir cómo evitar este error de enlace puede ser la clave.

En mi caso, no creo que sea posible apagar el dispositivo como me gustaría.

Lo más cerca que pude llegar a mi objective fue usar:

 Intent i = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN"); i.putExtra("android.intent.extra.KEY_CONFIRM", true); startActivity(i); 

Eso abre un cuadro de diálogo para apagar el dispositivo. Esta es la solución perfecta, pero en mi caso, su uso hace que el dispositivo se bloquee. Puede ser que mi dispositivo sea algo especial, y otros dispositivos no tendrán estas restricciones.

En cualquier caso, espero que mi prueba ayude a otros en su búsqueda.

 Runtime.getRuntime().exec(new String[]{ "su", "-c", "reboot -p" }); 

funciona, solo con dispositivos rooteados !!

Funciona para mí en dispositivo rooteado. Si su dispositivo está rooteado, puede usar el siguiente método

Apagar:

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

Reiniciar:

El mismo código, simplemente use "reboot" lugar de "reboot -p" .

Para usar este código, ¡necesitas Super Usuario! Funciona en 4.0 y superior!

  Intent i = new Intent("android.intent.action.ACTION_REQUEST_SHUTDOWN"); i.putExtra("android.intent.extra.KEY_CONFIRM", false); i.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); 

y pon este permiso en manifiesto: