One of the key feature of Android Lollipop “For Workplace And Education” is a new Screen mode called “Screen Pinning”. This new mode offers a true way to create Kiosk applications within the android Lollipop platform.
In the next chapters, we’ll see in more details how to use them in Android 5 (API 21).
Pin an app : the manual way
Pinning an application is not enabled by default. You’ll have to enable it by going to : Settings > Security > Advanced > Screen Pinning : On. These step only need to be done once.
You can pin an app by :
- Launch your app
- touch on the Overview Button ()
- select your app and touch the pin icon at the bottom of the app.
A confirmation message will appear. You need to confirm this dialog message to start the pinning mode :
To exit the screen pinning mode :
- Touch and hold Back () and Overview() buttons at the same time for 2-3 seconds.
7 Things to know about the manual pinning mode
- Home () and Overview () buttons are disabled, but every time you touch one of them, you’ll get a message to help you exit the pinning mode.
- If a Screen Lock (Pattern, Pin or Password) is activated, you can force the user to unlock the Screen before unpinning. The confirmation dialog shown when starting a app pinning will provide an extra option “Ask for unlock pattern before unpinning”.
- If a Screen lock is activated and this option is set, you’ll go to this Screen Lock and need to unlock your screen to go Home. Once the Screen Lock is displayed, You have no way to go back your app.
- No notifications will be shown. Even your own app’s notifications won’t show.
- From a pinned app, you cannot start a secondary app, unless this one has the same shared user ID (which means that the
sharedUserId
is set in theAndroidManifest.xml
and that second application is packaged with the same certificate). Other apps’ Activities won’t be allowed to be started and doing so (by usingContext.startActivity()
) will simply be ignored. - the Status bar is invisible. No notification, time, battery charge or other status information is displayed.
- It’s always possible to turn the device off, or to turn the volume.
This fact that the user can unpin the application and go back to the Screen Lock is annoying, we’ll see, in the next chapter, how we programmatically pin an to go even further in pinning apps.
Pin an app : the programmatic way
Screen pinning is referred as “Lock Task mode” in the documentation API.
This mode is mainly referred in 3 public API available in Activity
through startLockTask()
/startLockTask()
and DevicePolicyManager
through setLockTaskPackages()
. We’ll see also see other API useful to subscribe to Lock Task’s events, and to get current’s activity state.
There are actually two Lock Task modes, depending on whether you are “authorized” by a Device Owner App or not. These two modes also have impacts on the behavior of the pinning.
Note : “Authorized” is clearly not the best word of choice for this because its sense is not clear in this context. This is however used in the API’s documentation to refer to the different level of restriction a user will have when entering in the Screen Pinning mode. Both modes can indeed pin the app, but the authorized one will put the user in a more restricted experience as we’ll see later.
Before going further, some things to know about the API :
- It’s only possible for an app to pin itself. There is no public API to tell another app to pin (except for system-apps, which we’ll discuss later).
- Because of this last restriction, you can only pin in authorized mode an app that you own.
- Rebooting the device will always bring you back to the original mode : no application pinned.
- No special permission is required.
Un-authorized Task Lock mode
Any application’s Activity
can programmatically be pinned by using Activity.startLockTask()
.
A use-case for this is to pin the screen when a user touch a button. You could go further and only call this method if the app is not already pinned. You can check its status by using ActivityManager.isInLockTaskMode()
. For example :
// Main Activity
protected void onCreate(Bundle savedInstanceState) {
// ...
am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
lockBtn = (Button) findViewById(R.id.btn_lock);
lockBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
pin();
}
});
// ...
}
void pin() {
if(!am.isInLockTaskMode()) {
startLockTask();
}
}
Exiting the Pinning mode is reversely done by using Activity.stopLockTask()
:
void unlockClicked() {
stopLockTask();
}
Because this mode you can be used freely by any developer, a confirmation message will appear to the end user to confirm entering in this mode. Additionnaly, this mode is not totally restricted compared to the “Authorized Task Lock mode”. Here are some points to know when using pinning in unauthorized mode :
- Just after the
startLockTask()
is executed, the user will get the confirmation dialog “Use Screen Pinning ?”. - You can manually unlock the app at anytime : Touch and hold Back () and Overview() buttons at the same time for 2-3 seconds.
- Unlock (manually or programmatically) will bring you back to the Screen lock if a Keyguard is set and the option “Ask for unlock pattern before unpinning” has been set.
Authorized Task Lock mode
Only a Device Owner app can specify which apps are authorized to pin. So this mode is typically useful for “Organizations” who want to restrict their user to only one app without no way to manually exit the app.
DevicePolicyManager.setLockTaskPackages()
is used to specify which apps (though their package names) are pinnable. In other words, it specify which apps are authorized to be pinned in a more restrictive way.
This method has to be called from a Device Owner application (Setting an application as a Device Owner App is beyond the scope of this article, and is probably be an idea for a future article).
If you try to use from an application that is not set as a device or profile owner, you’ll get a SecurityException.
setLockTaskPackages()
is used with a ComponentName
referring to your DeviceAdminReceiver
’s implementation. You also pass it an Array of authorized packages as a last parameter :
DevicePolicyManager mDPM = (DevicePolicyManager) this.getSystemService(DEVICE_POLICY_SERVICE);
ComponentName mDeviceAdminRcvr = new ComponentName(this, MyDeviceAdminReceiver.class);
mDPM.setLockTaskPackages(mDeviceAdminRcvr, {"com.android.test.authorizedpinningapp"});
Once your application is authorized in your Device Admin App, you can then call the Activity.startLockTask()
from the app you want to pin (as presented in earlier chapter).
6 Things to know about the Authorized Pinning mode :
- Only the Back() button remains visible in the navigation bar. Home() and Overview() buttons are not visible…
- … and because of this, it’s impossible to unpin the application manually…
- You’ll have to provide a way to programmatically unpin your app. (otherwise, you’ll have no way to go back Home, unless you reboot the device)
- You can enter the pin mode without user confirmation.
- An app which is authorized though the use of
setLockTaskPackages
can still be pinned manually by going to Overview () and click on the Pin icon. In this case, the behavior is the same as a manual pinning (confirmation message, etc.). - If the Back button is going back to another activity, a Toast appears “Unpinning is not allowed by your Organization”
Task Lock events
DeviceAdminReceiver’s onLockTaskModeEntering and onLockTaskExiting methods can be used in your Device Owner App to subscribe to events relative to entering and exiting “Lock Task mode”.
All pinning events are raised the same way, no matter if they are authorized or not, manually or programmatically pinned.
Here’s a short example :
public class MyDeviceAdminReceiver extends DeviceAdminReceiver {
public void onLockTaskModeEntering(Context context, Intent intent, String pkg) {
Toast.makeText(context, "Lock task mode entered", LENGTH_LONG).show();
// ....
}
public void onLockTaskModeExiting(Context context, Intent intent) {
Toast.makeText(context, "Lock task mode exited", LENGTH_LONG).show();
// ...
}
}
The second parameter of onLockTaskModeEntering
and onLockTaskModeExiting
is relative to the sender’s intent. You can retrieve two useful information from this intent :
- The corresponding Action by calling
intent.getAction()
. Depending on which method your are, you’ll get DeviceAdminReceiver.ACTION_LOCK_TASK_ENTERING or DeviceAdminReceiver.ACTION_LOCK_TASK_EXITING value. - The corresponding App Package by calling … no, no it’s a trap !
getPackage()
will return null here. To get the package of the app whose Lock Task has changed, you’ll have to useintent.getStringExtra(DeviceAdminReceiver.EXTRA_LOCK_TASK_PACKAGE)
.
Going further :
The source code of this article is available on my Github’s repository.
The announcement on Android’s developers site.
Android Source Code on Github.
Android API : DevicePolicyManager, Activity, DeviceAdminReceiver, ActivityManager
nice article
RépondreSupprimerVery impressive blog...
RépondreSupprimerI tried integrating the above code, but I am not getting the call backs for onLockTaskModeEntering, Exiting in DeviceAdmin receiver. Also can I make any package as a Authorised Admin App? It always trows the exception when I do setLockTaskPackages saying you not a owned profile. Sooner response is appreciated.
RépondreSupprimerEven I pulled your code from Git but failing with the same exception.
I know for sure that on some device, this doesn't work. I made my tests on a Google Nexus 9 and it worked fine. On some devices, depending on vendor's implementations, it may not work and provisioning may fail.
SupprimerIts on Nexus 5 stock device on 5.0OS. Even tried on 6.0 as well same issue.
SupprimerThis is nice, but there is a way to handle a crash in the app, it will just close the pinned app, shouldnt it be restarted?
RépondreSupprimerNo idea. If you test it, don't hesitate to tell me what happened, I could update the article with this info. thx
SupprimerThanks
RépondreSupprimerIf I have a simple DeviceOwnwer app that calls setLockTaskPackages for my other more complicated home app does the DeviceOwnwer app have to call setLockTaskPackages on every boot.
Also how to I make sure DeviceOwnwer calls setLockTaskPackages before My pinned app starts ?
Thanks
the setLockTaskPackages() has only to be called once. In your case, you should consider calling it inside your MyDeviceAdminReceiver.onEnabled() method.
SupprimerBasically, it's done during the provisioning of the device, so at this step, the device is not yet started completely and then no other app can be started.
Thanks. Seems to work fine.
SupprimerMy only concern about this is how long will it take OEM to start abusing this and shipping with one of their apps as device owner. Am I write in thinking only root could get rid of it. I assume a device reset would go back to their initial setup.
Thanks for the help.
Hello Florent,
RépondreSupprimerThanks a lot for your work. The article is very clear and pedagogic compare to the other sites.
But I have a problem to test the DeviceOwnerApp. You wrote "This app as to be set as a Device Admin App to work correctly." I am testing on a ZTE Blade L3, (android without any vendor covers).
When I press "Set Authorized Apps", it crash.
I have the following message in my logcat : java.lang.SecurityException: No active admin ComponentInfo{com.android.test.deviceownerapp/com.android.test.deviceownerapp.MyDeviceAdminReceiver}
Do I need to modify or add something to your code to make the app a Device Admin App ?
Thanks for your help,
Olivier
I could fixed my problem thanks to your article :
Supprimerhttp://florent-dupont.blogspot.fr/2015/01/android-shell-command-dpm-device-policy.html
Hi Florent,
RépondreSupprimerYou mentioned "There is no public API to tell another app to pin (except for system-apps, which we’ll discuss later)."
Can you elaborate on how to pin a system app?
Thanks a lot.
By that, I mean only system apps can pin other apps.
SupprimerIf your app is not a system app, you can only app your own app, not another one.
Great article! But I'm stuck...What about the case that the device has hardware(physical) navigation bar(home, back, overview). I use startLockTask() programamtically and everything works fine, but the user is able to exit the kiosk mode by manual way(off in settings). Any thoughts?
RépondreSupprimerI understand. Before planning to make a device available publicly (for instance, on public areas like bank agencies, train station halls, etc..), you should study what device fits the best for your need.
SupprimerAnother approach is to consider which totem will be used to protect your devide (this site provides many types of totem..http://www.elockstore.com/73-borne-totem-tablette-maclocks-compulocks it's in french but you should find equivalent providers in many countries). Some of these totems may fits your need by hiding the physical buttons.
Hi Florent. Thank for your posts! I use authorized Screen pinning in my app and on LG G4s (Android 6.0) works perfect. I start first activity, call method startLockTask and navigate to second activity in my app. All activities always opens in my app. But on Alcatel Idol 3 (Android 5.0.1) I can't go to another activity after calling startLockTask. I don't understand what's wrong and where mistake.
RépondreSupprimerI found solution)
SupprimerThe problem was in launchMode of element in manifest.
Hello Florent,
RépondreSupprimerIs there a way to set status bar to visible when an app enters "lock task" mode?
Regards,
Novak
Could you tell me which device-policy you have used in device-admin?
RépondreSupprimer"Setting an application as a Device Owner App is beyond the scope of this article, and is probably be an idea for a future article"
RépondreSupprimerCould you please help me with setting my app as the device owner.
I have used Google as my EMM and do not know how to proceed further.
yurtdışı kargo
RépondreSupprimerresimli magnet
instagram takipçi satın al
yurtdışı kargo
sms onay
dijital kartvizit
dijital kartvizit
https://nobetci-eczane.org/
KJT4M
salt likit
RépondreSupprimersalt likit
dr mood likit
big boss likit
dl likit
dark likit
RUS3
شركة مكافحة حشرات بالهفوف
RépondreSupprimerشركة مكافحة حشرات
شركة تسليك مجاري بالهفوف NbtGmbj2zm
RépondreSupprimer