Guide: Developing on ChromeOS (Part 6)

This is a continuation of a multi-part guide. See Part 1 to get started.

What’s probably the most unique aspect of ChromeOS is its native support for Android apps. Apps aren’t run in a virtualized Android OS image as with other operating systems and SDK environments. This is thanks to Android Runtime for Chrome, also known as ARC.

Debugging with Android Runtime for Chrome

In the last section, we left off with a compiled React Native Android app, but fell short of actually running it. Well, if your ChromeOS device supports Android apps, we can utilize ARC to install and debug that app.


We start by making sure by accessing ChromeOS settings and making Google Play Store is enabled. We want to manage the Android preferencesNote that ChromeOS Settings may look different from the screenshot.


From here we’ll want to access About device to unlock Developer Options.


Click Build Number seven (7) times until a toast message appears saying “You are now a developer!”


Return to Android Settings and select Developer options.


Click to enable ADB debugging.


Click OK to allow ADB debugging.

The next phase will enable allow us to SSH into our ChromeOS. Before we can do that, we need to disable rootfs verification.


Open up your crosh shell and run sudo /usr/libexec/debugd/helpers/dev_features_rootfs_verification followed by sudo reboot to disable rootfs vertification and reboot your device. (Remember to press Ctrl+D to skip the warning screen.)


Now that rootfs verification has been disabled, we can enable SSH by performing sudo /usr/libexec/debugd/helpers/dev_features_ssh from shell. The operation will complete silently. At this point we can tell the ChromeOS device to connect to itself (localhost or over the default SSH port (22) with the Android Debug Bridge (ADB) by performing a sudo adb connect command.


You may get a prompt to allow USB debugging. If you notice the icon, this is a prompt from the Android layer asking for permission to connect with ChromeOS device. You can check the checkbox and select OK.

We are now ready to install and run our React Native Android app.


Navigate to your sampleRN project and perform adb install ./android/app/build/outputs/apk/app-debug.apk which will install the app on your ChromeOS device. To allow React Native to communicate with the app, we need to perform adb reverse tcp:8081 tcp:8081 as well.


Finally, perform react-native start to start the packager necessary to send files to the app. Once it’s ready we can start our Android app.


Search for sampleRN in your list of apps (which should have been installed by the adb install command) and open it.


You should see a green progress bar on the top of the screen as well as a progress inside the terminal shell. This means the Android app is remotely loading over React Native’s packager.


Complete! That’s real Android app running on your ChromeOS being managed by a nodeJS app running over crosh shell.

This really shows how much potential ChromeOS has underneath. If there’s more you’d like to see, let me know in the comments!

Part 2 – Crosh and Nano development environment
Part 3 – Creating and modifying files from shell
Part 4 – Creating a web app with nodeJS and Caret
Part 5 – Android Development with React Native


Guide: Developing on ChromeOS (Part 5)

This is a continuation of a multi-part guide. See Part 1 to get started.

In this guide, we’ll be using React Native to build the apps. Please note, you do not need React Native to build Android apps. This is merely a personal choice. Developing Android Apps requires two basic components: Java SDK and Android SDK. Both will be installed and configured by the end of this section.

Android Development with React Native

Following the previous section, we will trigger a second shell window to illustrate we aren’t limited to just one shell environment.


Right Click on Secure Shell and select New Window.

Access the crosh shell as you would normally. We’re going to start by installing the React Native command line tool.


Run npm install -g react-native-cli from the shell install the tool. Next we’ll want to initiate a react-native project. Instead of creating a directory from shell, we’ll let the React Native command line tool do it for us.


From the projects folder run react-native init sampleRN to create the sampleRN project.


This takes a bit of time to set up, but you can monitor progress with the Files app.


Once the installation is complete we can see that the sampleRN folder was created with many files within. Let’s try to build and test the android package. We can type react-native run-android to start the process.


Note that the process fails because Java is not installed. From Chrome, we’ll want to download the latest version of the Java JDK from:

Pick the architecture that matches your machine. For this guide, I used a Samsung Chromebook Pro, so I selected Linux x64. Make sure you chose the .tar.gz file to download.

Once downloaded we will now extract the file in shell.


Let’s start by typing mkdir ~/java to build a java folder in our home path. To make extraction easier, type cd ~/java to navigate to the folder. Now let’s extract with tar -zxvf ~/Downloads/jdk-8u131-linux-x64.tar.gz but not that the filename may not be the same as in this example.


Perform a ls to list the files to ensure that the files extracted properly. Note the folder name and copy it to clipboard. Highlighting it will automatically copy it to clipboard. Now let’s modify our startup script with nano ~/.bashrc to add the necessary environment variables.

Ensure you add the following lines:

export JAVA_HOME="$HOME/java/jdk1.8.0_131"
export PATH="$PATH:$JAVA_HOME/bin"

Note that the folder name be different in your case. You can paste from the clipboard by right clicking the shell window with the mouse.


Here’s what my ~/.bashrc file looks like now. Restart your shell for the changes to take effect. Now we will try building the React Native project again.


We shouldn’t get any Java error this time, but we should now get Android SDK related errors.


Notice that the build process fails because ANDROID_HOME cannot be found. Now let’s the necessary files from the Android website.


While the website mentions Android Studio, we won’t be using it. Instead, scroll down to the command line tools and download the Linux version.


Once the download is complete, open that zip file from the notification window or from the Downloads folder.


You’ll find a tools folder inside the zip file. Drag that over to Downloads and wait for it to finish copying.



Just like with the Java SDK setup, we need to perform similar operations here. Create a folder called .android in the home directory with a mkdir /.android command. Don’t worry if the folder already exists. Now create an sdk subfolder with mkdir ~/.android/sdk where we will hold our SDK. Finally move the tools folder from Downloads to our SDK location with a final mv ~/Downloads/tools ~/.android/sdk/ command. Finally, we will modify our startup script with nano ~/.bashrc again.

Add the following lines to the script:

export ANDROID_HOME="$HOME/.android/sdk"
export PATH="$PATH:$ANDROID_HOME/tools/bin"

Restart the shell to allow these changes to take effect. We will use the sdkmanager application to manage the Android SDK.


If we try to run sdkmanager, it will fail since it doesn’t have the proper permissions. Change directory to $ANDROID_HOME/tools/bin first, and so we can change the sdkmanager mode. Now perform chmod a+x sdkmanager to give it the necessary access to run.

Skipping ahead, if you were to try to perform react-native run-android, the operation would likely fail with the following response:57-AndroidComponentsMissing.png

We’ll tackle these issues step by step.58-CreateEmptyAndroidRepositorySetupPlatform.png

Let’s create a blank repositories.cfg file in /home/chronos/user/.android with a touch /home/chronos/user/.android/repositories.cfg command. Install Android Platform 26 with sdkmanager “platforms;android-26” and accepting the license agreement. The reason we target 26 is so we can use the newer windowing system with ChromeOS.


We’ll also need to install Android Build Tools. Install version 26 to match the API with a sdkmanager “build-tools;26.0.0” command. This is actually more important than change the API since the default React Native Build Tools version (23.0.1) may not run properly on ChromeOS.


We’ll want to modify the sampleRN/android/app/src/build.gradle file and change the compileSdkVersion and buildToolsVersion to match our downloaded files. Note the use of Caret and it’s project management to do so, in the example screenshot.


We now ready to build our React Native Android app.


At first glance it may look like our build failed, but it didn’t! The final error is the lack of a device connected. While we could plug in an Android device over USB, instead let’s use ChromeOS as a native Android device. We’ll cover that in the next part of this guide.

Part 2 – Crosh and Nano development environment
Part 3 – Creating and modifying files from shell
Part 4 – Creating a web app with nodeJS and Caret
Part 6 – Debugging with Android Runtime for Chrome

Guide: Developing on ChromeOS (Part 4)

This is a continuation of a multi-part guide. See Part 1 to get started.

Though many different programming languages can be used on ChromeOS, I’m going to be using nodeJS as an sample. Since we have setup our $HOME path to allow executables, we are going to aim to store nodeJS binaries within the $HOME path, since using  /usr/local/bin may be too small for long-term development.

Instead of using chromebrew to install nodeJS, we are going to use nvm (Node Version Manager) since it will automatically manage nodeJS version and store the library in the ~/.nvm/ path.

Installing nodeJS with nvm


From shell, run the following command to start installing nvm:

wget -qO- | bash


You’ll be see a response like the one in the screenshot. Notice it says that .bashrc has been updated, meaning the shell terminal has to be restarted. Also, you’ll notice that trying to run node won’t work yet. So type exit to get kicked back up to crosh and shell to get back in.


Now that the shell has been restarted, nvm commands should work. Performing nvm list will show nvm is working, but we have no nodeJS installations yet.


Typing npm install v6 will install the latest version of nodeJS 6.xnode -v confirms nodeJS has been installed successfully.

Creating a nodeJS project

Before get started with this project, install Caret from the Chrome Web Store:

This should provide a more familiar development environment compared to nano. Now let’s build a project called sampleApp.


Let’s change directory to our projects folder inside Downloads. Make a directory called sampleApp and create a file called index.js inside it. The ls command will list files inside your current directory.

Now, let’s fire up Caret.


Click Project and select Add DirectoryThis will create a navigable list of files within a directory.


Navigate to the sampleApp folder that was created in shell, select it, and hit Open. Now we can see our index.js file we created on the left, under sampleApp. Double click it to begin editing it.


Now we can write some code! I’ve included some sample code which you can copy and paste:

const express = require('express')
const app = express()

app.get('/', function (req, res) {
 res.send('Hello World!')

app.listen(3000, function () {
 console.log('Example app listening on port 3000!')

Paste it and save your changes with Ctrl+S. We can head back to shell to try to run our code.


To run our code file we can node index.js from our sampleApp folder. We’ll get an error about the express not being found, which we have to install with npm. Fortunately, nvm already installed npm when installing node24-NPMInstallExpress.png

Install the express module by typing npm install express from shell.


We’ll get some warning that we can ignore, but let’s retry running the app by running node index.js again. You should be presented with the console log item saying our app is listening on port 3000. So, let’s try it. Go to the Chrome Browser and access http://localhost:3000/.


Voila! You’ve successfully created a web server, albeit an extremely simple one. Since our source code is inside our Downloads folder, we can also use Chrome Dev Tools straight from Chrome Browser by pressing Ctrl+Shift+I. After mapping to your projects folder, you can modify and test files by using DevTools Workspaces.

In the next part of the guide, we’ll leverage the ability to run Android apps natively on ChromeOS with our development environment to live test and debug Android Apps with React Native.

Part 2 – Crosh and Nano development environment
Part 3 – Creating and modifying files from shell
Part 5 – Android Development with React Native
Part 6 – Debugging with Android Runtime for Chrome

Guide: Developing on ChromeOS (Part 3)

This is a continuation of a multi-part guide. See Part 1 to get started.

With a crosh, nano, and chromebrew setup, we have, at minimum, all we need to build a variety of apps, be it, HTML5, nodeJS, python, ruby, or C++. For this part on getting used to creating and modifying files while also interfacing with the ChromeOS visually layer. We’re also going to make some modifications to .bashrc, to make development a little smoother.

Setting up shell startup scripts

Let’s fire up our shell by opening Secure Shell, access crosh and typing shell, as we’ve done before. Once open, we’re going to type nano ~/.bashrc to start editing our shell’s startup scripts.


You’ll notice that the ChromeOS has add some comments. Let’s go down to the bottom, after # Put your fun stuff here.  Anything with a prefix is not actually run by the script, so pay attention to what doesn’t have that prefix.

I’ve already added some fun stuff related to LD_LIBRARY_PATH. If you had issues running nano or other applications, I suggest you copy the line I put.

More importantly, I remount my $HOME folder to allow files to execute. While chromebrew runs applications in /usr/local/bin, the space there is rather limited and can easily fill up. To do this, add the line:

sudo mount -i -o remount,exec /home/chronos/user

Now every time your access the shell, you’ll have your home folder remounted to allow unix applications to execute. Press Ctrl+X to exit nano followed by Y and ENTER to save your changes.


In order for out startup script changes to take effect, we’ll have to exit crosh by typing exit, which will kick up back up to crosh.

Creating a projects folder


Now that we can create and modify files, we need to store them in a good place. We are going to use a projects folder inside Downloads.

Let’s get back to shell by typing shell and change directory (cd) to our home path (~) by typing cd ~. From here’s we’ll change directory again to Downloads with cd Downloads. Now we’ll make a directory called projects with mkdir projects. Once more, cd projects.


To create an empty file called example.js, type touch example.js. You can open the Files app in ChromeOS and see that the file now exists.


This shows us our shell layer interfaces with the ChromeOS visually layer, namely the Downloads folder. Files you download in the Chrome Browser can be accessed by in shell. In the next part, we’re going to use nodeJS and Caret to build an web app we can access from Chrome Browser.

Part 2 – Crosh and Nano development environment
Part 4 – Creating a web app with nodeJS and Caret
Part 5 – Android Development with React Native
Part 6 – Debugging with Android Runtime for Chrome

Guide: Developing on ChromeOS (Part 2)

This is a continuation of a multi-part guide. See Part 1 to get started.

At this point, we’ve activated developer mode on our ChromeOS device and now want to get start coding. We first need to build a terminal environment that we can use to run any compilers we may want to use.

We’re going to start with Secure Shell, which is a first-party ChromeOS extension we will use to access Crosh. Secure Shell does more than your typical Crosh tab since it gives a dedicated window and allow us to use keyboards commands that won’t work in a crosh Chrome Tab (like Ctrl+W).

Setting up a shell environment

So let’s get started by downloading Secure Shell from the Chrome Web Store.

Once installed, I suggest you pin the app to the taskbar since you’ll likely be interfacing with often.

Fire up Secure Shell and we’re going to add a connection to crosh.

Call the connection anything you want and under user use run and hostname >crosh.


From here we can press ENTER to start up our Crosh shell.


Next we’ll see the crosh welcome screen and a prompt asking for input.


You don’t need Developer Mode to access crosh, but you will for the next command. Enter shell to get access to the ChromeOS shell layer. If this command doesn’t work, it means Developer Mode wasn’t enabled properly.04-SetupChromeBrew

Once you access the shell, you’ll generally want to work from the the Downloads folder, so what you do here can be seen in the Files app and all other ChromeOS apps and extensions. As in the picture above, I change directory to ~ (which is a shortcut to my user’s home directory) and Downloads.

Now we’re going to install chromebrew which is a repository of applications built and tweaked to work on your ChromeOS device. In this example I’m using jam7‘s fork which, at the time,  than the official skycocker. For the purpose of this guide, it’s a matter of preference.

To install Chromebrew, type:

wget -q -O - | bash


Once chromebrew is complete, we’re going to install nano, which is a text editor we can use in shell. Later on in the guide we’re going install a GUI based editor called Caret, but to modify files outside of Downloads, we use nano. We will install it with chromebrew by typing:

crew install nano


chromebrew will automatically know which other packages need to be installed, so we will accept the prompt by typing Y.


Once it’s done we’ll see a line saying Nano installed! Congratulations, you’ve installed your first chromebrew package. Hopefully, this will be the first of many.


Now on, you can type nano from shell and start it up. The next part of our guide will deal how to create and modify files from shell.

Note: If you get an error about loading shared libraries when running trying to run nano, perform the following command first:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

This issue may be fixed in future versions of chromebrew.

Part 3 – Creating and modifying files from shell
Part 4 – Creating a web app with nodeJS and Caret
Part 5 – Android Development with React Native
Part 6 – Debugging with Android Runtime for Chrome

Guide: Developing on ChromeOS (Part 1)

ChromeOS is becoming more and more popular every day. Apple and Microsoft are surely watching its rise closely. But what makes ChromeOS so great? In my opinion, it’s mostly due to the combination of two things: price and simplicity.

The affordability aspect means this is a low barrier entry for people who don’t have a dedicated laptop machine. Its simplicity allows for the OS to serve as a minor backplane allowing the tasks you want to run to take preference. Combined, this makes ChromeOS a great machine to develop on. In this multi-part guide, I’ll focus on how to get a basic setup started to developing full-blown Android apps from ChromeOS (if your device supports it).

Enabling Developer Mode

Before we can get to the meat of the guide, we need to enable Developer Mode on ChromeOS. This will allow us to unlock the full potential of out ChromeOS device. Note that Developer Mode is not the same thing as Developer Channel.

Every device is different, and each has it’s own method of enabling Developer Mode. You can find the official instructions at

Generally, though, you enter Recovery mode by hold ESC and Refresh (F3) while pressing the power button. If done correctly, you should see a screen with a yellow exclamation point saying:

       ChromeOS is missing or damaged.
Please insert a recovery USB stick or SD card.

At this screen press Ctrl+D to begin switching to Developer Mode.

You will receive a prompt asking to remove OS verification. This is essentially what Developer mode. It allows full access to ChromeOS system.

To turn OS verification OFF, press ENTER.
Your system will reboot and local data will be cleared.

From here we will press ENTER perform this operation.

Now the device will transition to Developer Mode. This may take a while. My Samsung  ChromeBook Pro on battery took about 15 minutes to complete, so be patient. Once it’s done, you’ll be presented with new default boot screen. This is how you device will boot from now on.

 OS verification is OFF
Press SPACE to re-enable.

DO NOT PRESS SPACE. Pressing SPACE will revert your ChromeOS device to factory default. Every time your boot your device, you must press Ctrl+D to continue or wait 30 seconds and it’ll continue automatically. You might be asking why this exists. This is to avoid users unknowingly using a compromised device. There are ways to remove this screen, but doing so would require you to modify the motherboard BIOS and would likely void your warranty.

At this point, set up your device as usual with your user and password. Ignore any other developer or debugging options since you can choose those options at a later time.

Part 2 – Crosh and Nano development environment
Part 3 – Creating and modifying files from shell
Part 4 – Creating a web app with nodeJS and Caret
Part 5 – Android Development with React Native
Part 6 – Debugging with Android Runtime for Chrome


Navigation Drawer: What would you like to see it include?

Google has made their slide out drawer available to the public. I’m wondering what you would like to see in this menu.

Since I’m working on Google Hangouts incorporation I’m thinking of a drop down list of services to pick status/availability/sign-in/sign-out.

Also, I think some quick options should be available like Auto-Open QuickReply.

From here you would be able to see and create scheduled messages.

Let me know what else you would like to see.

Dynamic Dates with Java

I made a new change for build 48 of Fusion to show the date portion based on time. The difficulty is making it all work with all the different time zones and locales. 24 hours isn’t always a day because of daylight savings time. So I have to use Calendar. Here’s the static code:

public static String stripFieldFromPattern(SimpleDateFormat sdf, Date d,
        DateFormat.Field field) {
    StringBuilder b = new StringBuilder();
    boolean isLastCharValid = true;
    boolean isNextCharValid = false;
    AttributedCharacterIterator i = sdf.formatToCharacterIterator(d);
    for (char c = i.first(); c != AttributedCharacterIterator.DONE; c = i
            .next()) {

        Map<Attribute, Object> attributes = i.getAttributes();

        if (attributes.containsKey(field)) {
            isLastCharValid = false;

        char nextChar =;
        isNextCharValid = (nextChar != AttributedCharacterIterator.DONE && i
                .getAttribute(field) == null);

        if (!attributes.isEmpty() || c == ' ') {
        } else {
            if (isLastCharValid && isNextCharValid)
        isLastCharValid = true;
    return b.toString();

This will strip any field from a date pattern. I’d strip the Year field if an event occurred in the last year. Here’s the implementation as written in Fusion:

Calendar eventDateTime = Calendar.getInstance();
Calendar yesterday = Calendar.getInstance();
Calendar lastYear = Calendar.getInstance();

yesterday.add(Calendar.DATE, -1);
lastYear.add(Calendar.YEAR, -1);

String timeString;
String providerName;
if (eventDateTime.after(yesterday)) {
    timeString = DateFormat.getTimeInstance(DateFormat.SHORT,
    providerName = IMProvider.IMServiceNames[msgItem
} else if (eventDateTime.after(lastYear)) {
    SimpleDateFormat sdfOriginal = (SimpleDateFormat) SimpleDateFormat
                    DateFormat.SHORT, Locale.getDefault());
    timeString = Utils.stripFieldFromPattern(sdfOriginal,
            eventDateTime.getTime(), DateFormat.Field.YEAR);
    providerName = IMProvider.IMServiceNames[msgItem

} else {
    timeString = DateFormat.getDateTimeInstance(DateFormat.SHORT,
            DateFormat.SHORT, Locale.getDefault()).format(
    providerName = IMProvider.IMServiceShortNames[msgItem

String format = "%1$s";
if (!this.useColoredStatus && !this.useIMServiceIcon
        && !this.useIMServiceIndicator)
    format += " via %2$s";
subText = String.format(format, timeString, providerName);

I just realized the providerName is repeated unnecessarily. Oops! Regardless, it has nothing to with the topic here.

Blog at

Up ↑