Activity Manager among other things manage Screen pinning. You can invoke the am
command to pin an app regardless of the Screen pinning being activated under Settings.
However, know that the pinning wouldn't be fully automated this way i.e. you still would have to confirm on the screen whether to pin the app or not, although I provided a way to interact with the screen only the very first time.
Google mentioned here:
(Emphasis mine)
If the requesting app is not a device owner, the user is prompted for confirmation. A device owner app can call the setLockTaskPackages()
method to enable apps to be pinnable without the user confirmation step.
Also note that an app cannot be made device owner just by using some set of commands, unless it fulfills the criteria set for it i.e. it must be a candidate for Device Administration (the apps you see in Settings → Security → Device administrators), which is hard-coded into app's manifest. Google has mentioned here what must be included in an app's manifest to use Device Administration API.
Even then, you still have to make the app the Device Owner -- a specialized type of device administrator who once activated cannot be deactivated unless you have root access or do factory rest on the device. Contrary to simple kiosk mode which you activate by pinning an app from recent tasks list, a device owner app can make it extremely hard for you to evade the kiosk mode which means the normal evading technique like holding down Overview button or Back button or both could be rendered useless.
It is up to you to choose a method for making your favorite app the device owner.
That was just a bit of context to explain why you need to interact with the screen, and why there is no complete command-line way to screen pin an app.
Things to do
Setup adb, connect the phone into PC, enable USB debugging in phone, launch the app you want to screen pin, launch a shell on PC, and enter:
NOTE: It has come to my notice that in Android 6.0 lock-task
has been replaced with task lock
. Hence, make appropriate changes in any command before using the latter.
adb shell
task_id=$(dumpsys activity | grep -A2 "(dumpsys activity recents)"| grep '#'| cut -d ' ' -f 7| cut -c 2-); am lock-task $task_id
As an alternative: This command would work if the app is launched from scratch i.e. not resumed from recent tasks list:
adb shell
cur_act=($(dumpsys activity | grep mFocusedActivity | rev)); task_id=$(echo ${cur_act[0]} | head -c -2 | cut -c 2-| rev); am lock-task $task_id;
You would get an output Activity manager is not in lockTaskMode
. Ignore it, and if you've read the links I mentioned in the context you would know why it has been outputted.
Tap Start on device's screen to confirm screen pinning.
(Click image to enlarge)
I uploaded the screen recording here (5.62MB size) which would show you that the command can also screen pin the launcher app.
As an alternate of going to screen and tapping the confirmation dialog, you can use any of the following approaches:
Issue keyevents to go down, go right, and simulate enter on the confirmation dialog.
adb shell input keyevent 20
adb shell input keyevent 22
adb shell input keyevent 66
(Here are listed some common keyevents)
Enable Pointer Location under Developer options, pin an app and hold Start on the confirmation dialog, and locate the X and Y coordinates.
Alternatively, use adb shell getevent -l
to get X and Y coordinates. Here is a good solution by Tomas.
Once you have them, use this command:
adb shell input touchscreen tap <x> <y>
where <x>
and <y>
are the respective coordinates you noted.
Since the X and Y coordinates will always going to be same whenever the confirmation is shown (provided that you are not trying Landscape mode coordinates on Portrait mode), you can use it for complete screen pinning using command-line.
As for the command doing the screen pinning, it's very simple. The part responsible for activating screen pin is am lock-task
, and its usage goes as:
Type adb shell am
and notice this line:
am lock-task: bring <TASK_ID> to the front and don't allow other tasks to run
Bring <TASK_ID>
(which is the task ID of an app in use) to front while not allowing other tasks to run simply means kiosk mode.
I couldn't come to know what are STACK_ID and TASK_ID in general, but I know how to find them. Use any of the following approaches to get TASK_ID of the app in focus or launched by a user:
dumpsys activity | grep -A20 "(dumpsys activity recents)"
or enter dumpsys activity recents
for detailed output about all recent activities, but would be excessive for out goal. The former's output would be like:
* Recent #0: TaskRecord{68f58f6 #1441 A=com.slovoed.oald U=0 sz=1}
* Recent #1: TaskRecord{9888887 #1415 A=com.cyanogenmod.trebuchet U=0 sz=1}
* Recent #2: TaskRecord{29c6fe30 #1438 A=com.icecoldapps.serversultimatepro U=0 sz=2}
The numeric value before A=
and after #
is the TASK_ID of the app. In the example, it would be: 1441
, 1415
, 1438
. These TASK_IDs would be found in the next command's output.
am stack list
It would list all of the activity stacks of which TASK_ID is part of.
Stack id=1 bounds=[0,0][1080,1920] displayId=0
taskId=1438: com.icecoldapps.serversultimatepro/com.icecoldapps.serversultimatepro.viewStart1
taskId=1441: com.slovoed.oald/com.slovoed.oald.SlovoEdTabActivity
Stack id=0 bounds=[0,0][1080,1920] displayId=0
taskId=1415: com.cyanogenmod.trebuchet/com.android.launcher3.Launcher
dumpsys activity | grep mFocusedActivity
It would give the app's package name which is in focus (simply, the app displayed on the screen dominantly), its task ID, and some other details:
mFocusedActivity: ActivityRecord{30672d7f u0 com.slovoed.oald/.OALDTabActivity t1441}
The value after t
and before }
is the TASK_ID of the app.
You can also get TASK_ID from:
There may be more ways but the ones I mentioned should suffice.
Cheers!