4

I'm aware that I can go to Settings → Security → Screen pinning → On, and then tap Overview → touch the pin icon on the app listed there and it would be pinned, effectively putting the app into .

(Click image to enlarge; hover to know details)

IMG: An app in focus IMG: Pin icon to pin the app IMG: Screen pinned app

But how do I pin an app using command line? I tried input command but with no success.

I'm using rooted OnePlus One running CM12.

1 Answer 1

11

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

IMG: Confirmation

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:

    •  dumpsys window displays
      
    •  dumpsys window tokens
      
    •  dumpsys window | grep mFocusedApp
      

There may be more ways but the ones I mentioned should suffice.

Cheers!

3
  • I suspect that TASK_ID is assigned to a component of an app and not the whole app itself, but I don't have a source to support my claim.
    – Firelord
    Commented Aug 10, 2015 at 2:32
  • @Firelord.....great detail and documentation +1
    – beeshyams
    Commented Dec 22, 2015 at 15:17
  • Readers: I now noticed that I've used cut tool in some of my commands which is not natively available in Android versions prior to MarshMallow. Consider adding busybox in your system to take care of cut not found issue and make appropriate changes in the commands.
    – Firelord
    Commented Feb 25, 2016 at 22:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .