Saturday, 8 March 2014

How-To Create Kiosk Mode on the Google Nexus 7



With Google’s release of the Nexus 7, hackers have access to a very high-quality touchscreen at relatively low cost that runs Google’s latest code.  This makes the Nexus an obvious target for customization and projects.  Some of these applications require what I call “Kiosk Mode” or “Single Application Mode”, where the display is locked into a single application that can not be exited, and normal UI components like the status bar and the navigation bar are inaccessible. Furthermore, restarting the unit should boot you into that application, and power-loss situations should be handled by an automatic restart of the system.

I was surprised that I could find no clear guide to accomplishing this. I did find many incomplete solutions, and I even found several posts claiming it couldn’t be done.  Obviously that wasn’t acceptable, so after some research I came up with a combination of techniques that create a solid and reliable kiosk mode for the Nexus 7.
This tutorial assumes you are already set up for Android development with Eclipse, Netbeans, or some other IDE, and have ADB and the Android SDK’s installed.  Also, the Nexus I am testing with is running Android version 4.2.2.
WARNING: This does involve rooting your Nexus and modifying system settings with an accompanying risk of bricking your device. If that doesn’t scare you off, then read on… I am breaking it down into three easy steps.

Step 1: Suppress the Title Bar & Make 

Your App a Launcher

You build your app more or less like a normal app, but with a couple key exceptions:
  1. AVOID anything that can start another app. For instance, a web link that isn’t handled correctly could launch a browser. Don’t do that.
  2. You must add the HOME intent to your main activity… this will allow it to be set as the default when the phone is powered on.
  3. You must suppress the title bar in your theme or activity.
To suppress the titlebar, I find it easiest to inherit from the theme I want, then put the title bar suppression in my theme file. That way it’s all in one place.
/res/values/themes.xml
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="mytheme" parent="@android:style/android:Theme.Holo.Light">
        <!-- Window attributes -->
        <item name="android:windowFullscreen">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowActionBar">false</item>
        <item name="android:windowNoTitle">true</item>
    </style>
</resources>
These four entries will prevent the status bar and title bar from showing. Once you have created your theme,  reference the it at the application level in your AndroidManifest.XML, see line 9 below.
Also in the manifest, you need to add your HOME intent. This is seen on line 19.  Don’t be confused by the other intents.  DEFAULT means the activity is the default for your app… the activity to run first.  LAUNCHER means an icon for your app will be added to the list of apps in the default launcher. MAIN is just a name for your activity, albeit one commonly used for the default activity.
/AndroidManifest.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="utf-8"?>
          package="com.example.kiosk"
          android:versionCode="1"
          android:versionName="1.0">
    <uses-sdk android:minSdkVersion="17"/>
    <application
            android:label="@string/app_name"
            android:theme="@style/mytheme">
    <activity android:name=".MAIN"
                  android:label="@string/app_name"
                  android:screenOrientation="sensorLandscape"
                  android:hardwareAccelerated="true"
        >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.LAUNCHER" />
                <category android:name="android.intent.category.HOME" />
            </intent-filter>
        </activity>
    </application>
</manifest>
If you upload your app and then hit the HOME button, you will note a popup letting you choose which launcher to use, with your app as one of the options.  Congrats, you just built your first launcher.
Launcher chooser popup

Step 2: Root Your Tablet

There are plenty of guides on how to do this, so I’m not going to cover it in detail.  I used the Nexus 7 Toolkit bymskip of XDA.  Make sure to read carefully, upgrade the Toolkit if necessary, and consider making your life easier by purchasing the paid version.
You will probably lose all your apps and settings when you root, so back up your files if they are important.

Step 3: Modify System Files and Settings

There are only a couple of modifications you need to make.
Change # 1 – Hide the Navigation Bar
The first is a change to /system/build.prop that will permanently hide the Navigation bar (the one with BACK, HOME, and RECENT APPS).  Assuming you have the Android SDK installed and the Android Development Bridge (adb.exe) is in your path, you can download build.prop as follows… open a command window and enter:
1
adb pull /system/build.prop
Then open build.prop in a text editor and add the following line to the end:
1
2
3
4
#
# BLAME THEBITPLAGUE FOR THIS
#
qemu.hw.mainkeys=1
Save the file and exit the text editor, and then do the following to upload it:
1
adb push build.prop /system/build.prop
Note: if you get an error about the file system being read only when you try to push, use the “Pull Files”/”Push Files” options in the Nexus toolkit instead of stock ADB. This makes it easy.
According to some comments I have read, you may need to clear your Dalvik cache, though I didn’t have to. As soon as I rebooted, the navigation bar was gone.
Note: having no Navigation bar can make it difficult to navigate! Consider installing a home button replacement like Button Savior until you are done with your dev process.
Thanks to lesdense from XDA forums for the build.prop entry.
Change # 2 – Change the behavior when plugging in charger
This is an important step if your kiosk or installation is going to cover the hardware buttons. You don’t want a power shortage that results in the battery running down and getting turned off to necessitate opening up your enclosure to hit the power button.  What we want is that anytime the device is in the off state, and then power is added via the USB port, that the unit will automatically turn on. Luckily this is an easy change… start up your command line and then enter the following command:
1
fastboot oem off-mode-charge 0
Now unplug your device and power it off. Then plug it back it in… rather than showing the “charging” animation, it will go straight to powering on.
Kudos to trevd at the XDA forums for this post that provided the off-mode-charge tip.

The Final Result

In this demo, my app just displays a plain background to make it clear there are none of the usual controls. There is no status bar, no menu bar, and the long hold and swipe inputs have no effect. Best of all, the unit powers on by itself  when connected to power.   This Nexus could now be installed into an auto dashboard, a public information kiosk, or other single-use applications.

2 comments:

blog comments powered by Disqus