27

I am writing an App that is designed to run on one specific device model (an Android set-top device that runs Amlogic based firmware). I have both root capability and my App is signed with the firmware certificate.

My App is the main focus of the device, and it would be helpful to be able to initiate a complete power-off.

I do not have the shutdown command. I do have the reboot command.

reboot -p does not help. It simply freezes the device while remaining powered on.

The PowerManager is one step better, but it sets the device into sleep mode, instead of a complete shutdown:

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

I am open to all suggestions - hacky or otherwise. The version of Android is expected to remain at 4.2.2.


Intents

This command will cause the device to reboot. Intent.ACTION_SHUTDOWN does not appear to do anything. Is this Intent perhaps only to report a shutdown, and not to initiate one?

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

The most luck I had with this was to request a shutdown by Intent:

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

Shutdown Thread

That is a bit closer. Definitely interesting. Can you find an example of using it?

So far I have come up with this:

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 and beginShutdownSequence create NullPointerExceptions (do you see why?) and rebootOrShutdown creates an InvocationTargetException due to an UnsatisfiedLinkError... It cannot find a native method:

java.lang.UnsatisfiedLinkError: Native method not found: com.android.server.power.PowerManagerService.nativeShutdown:()V at com.android.server.power.PowerManagerService.nativeShutdown(Native Method) at com.android.server.power.PowerManagerService.lowLevelShutdown(PowerManagerService.java:2163) at com.android.server.power.ShutdownThread.rebootOrShutdown(ShutdownThread.java:543) at com.android.server.power.ShutdownThread.run(ShutdownThread.java:393)

lowLevelShutdown is the function that all the functions eventually reach, when configured to shutdown (and not reboot). So figuring out how to avoid this link error may be key.

Knossos
  • 15,802
  • 10
  • 54
  • 91
  • Will this help you ? http://stackoverflow.com/questions/10411650/how-to-shutdown-an-android-mobile-programatically – hungr Jul 11 '14 at 08:54
  • No. The shutdown command is missing. Reboot freezes the device. The Power Manager has no option for actually turning the device off. Only sleep and reboot. – Knossos Jul 11 '14 at 08:56
  • please have a look on the answer from Manty and comments below it, seems there is shutdown command. – hungr Jul 11 '14 at 08:59
  • you need root access and you can follow the link posted by @hungr.. – Govind Jul 11 '14 at 09:21
  • @Manty: That answer uses "shutdown". As previously stated, I do not have that available to me. None of the results of that link work for me. – Knossos Jul 11 '14 at 09:36
  • @Knossos How about `android.internal.app.ShutdownThread` ? And Here is a link for reference http://www.phonesdevelopers.com/1695516/ – hungr Jul 11 '14 at 10:09
  • I added my findings about the ShutdownThread above. – Knossos Jul 11 '14 at 12:07
  • The solution to your problem is to examine how the device is shut down by the user, find (or debug) the code which implements that, and copy the mechanism. – Chris Stratton Jul 11 '14 at 14:40
  • The only way it can be shut down FULLY right now, is to hold the power button on the front of the device. There may be a hardware component in getting the device to power off completely. The usual mechanism employed is actually an energy saving mode. It isn't completely off. So when you start it again, it is almost instantly available. – Knossos Jul 11 '14 at 15:21

6 Answers6

20

In my case, I do not think it is possible to shut the device down how I would like to.

The closest that I managed to get to my target was using:

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

That brings up a dialog to turn the device off. This is the perfect solution, but in my case, using it causes the device to crash. It may be that my device is somewhat special, and other devices will not have these restrictions.

In any case, I hope that my testing will help others in their quest.

Knossos
  • 15,802
  • 10
  • 54
  • 91
  • is there any way to prevent the device to shutdown or restart by pressing power button. Also i need to restrict the the device to silent mode. – rupesh Sep 03 '15 at 07:09
  • 2
    You should really start a new question for that. – Knossos Sep 03 '15 at 08:37
  • @rup35h: You have two questions. Google a bit. If you don't find answers, please post two new Stack Overflow questions. So that you have a better chance of getting upvotes and answers: 1. Explain why you want these things. 2. Be very careful about spelling and grammar. – unforgettableidSupportsMonica Jun 06 '16 at 00:42
  • 1
    @unforgettableid Was it really necessary to poke a 2 year old question comment? I doubt he is still looking for an answer to those questions. – Knossos Jun 06 '16 at 09:30
  • 2
    this solution would require the permission `android.permission.SHUTDOWN` and that permission is only available for system apps, see also http://stackoverflow.com/a/14065879/1545993 – Taifun Nov 21 '16 at 16:21
10

It work for me on rooted device. If your device is rooted then you can use below approach

Shutdown:

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

Restart:

Same code, just use "reboot" instead of "reboot -p".

Yogesh Rathi
  • 6,331
  • 4
  • 51
  • 81
6
Runtime.getRuntime().exec(new String[]{ "su", "-c", "reboot -p" });

it works, just with rooted devices!!

Halvor Holsten Strand
  • 19,829
  • 17
  • 83
  • 99
Perestroico
  • 61
  • 1
  • 1
6

To use this code, you need Super User! Works on 4.0 and above!

  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);

and put this permission on manifest:

<uses-permission android:name="android.permission.SHUTDOWN" /> 
Rodrigo Gontijo
  • 587
  • 1
  • 9
  • 21
  • 1
    This required the app to be a system app for me. Instead running a `reboot -p` subprocess worked without that need. – theicfire Mar 22 '18 at 23:36
  • Yes, it do the work, but using the intent is a better code! Works in any android! – Rodrigo Gontijo Mar 23 '18 at 04:19
  • I get the error: `Permission Denial: starting Intent { act=com.android.internal.intent.action.REQUEST_SHUTDOWN flg=0x10000000 cmp=android/com.android.internal.app.ShutdownActivity (has extras) } from ProcessRecord{***/u0a194} (pid=13671, uid=10194) requires android.permission.SHUTDOWN` what could it be? My app is the device owner, so I shouldn't have any issues about the permission. – Alberto M Feb 05 '21 at 10:23
  • @AlbertoM did u put the permission in the manifest? It seems to be the problem... upvote the answers please! – Rodrigo Gontijo Feb 08 '21 at 17:01
  • yes, I put the permission and used your same code. Did you recently try to run this code? why do you ask for an upvote if your code didn't help me? – Alberto M Feb 09 '21 at 04:40
3

An update: for newer Android version, in my case is Android 8.1, they changed the action name. See below:

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

Good luck!

Silver
  • 77
  • 10
  • this doesn't work anymore. I get the error: Permission Denial: starting Intent xxx requires android.permission.SHUTDOWN – Alberto M Feb 08 '21 at 10:55
1

In newer android versions you aren't allowed to shut down the device from the nonSystem app.

Mohsen mokhtari
  • 2,841
  • 1
  • 30
  • 39
Šimon Vyhnis
  • 408
  • 3
  • 9
  • 1
    I expected that my DeviceOwner app would've been recognized as a system-app, but apparently nothing works from this set of answers (on a non-rooted device). – Alberto M Feb 08 '21 at 10:57