Node v6
Starting with v0.19 Astro must be used with Node v6+!
Menu

Android Tutorial

This tutorial is very similar to the iOS tutorial but with specific changes for Android. In this tutorial you will build a simple mobile shopping app for Android called Velo. By the end you will have added a few features and have a better understanding of how Astro works. Before you start, make sure you've installed all the prerequisites by following the quick start guide.

1. Install and Run the Sample Site

Run the following commands:

git clone --branch 1.0 https://github.com/mobify/astro-tutorial.git
cd astro-tutorial
npm run deps
cd site
npm install

Great, you should now have everything ready to get started. We wrote a sample website for you to experiment with. To run the server, run:

node index.js

Go to the demo site at http://localhost:5000 to check it out. Leave Node running - you'll need the site running in the steps ahead.

(If you get stuck, you can checkout the final code sample at the end of this tutorial).

2. Open and Run the App

Next, open app/app.js in your favourite text editor. We're going to point the app to the sample site you have running. Change the baseUrl to your IP address.

// Enter your site url here
const baseUrl = 'http://<Your IP Address>:5000/'

Now build and run the app on Android Studio to check it out (ideally, you want to run it on a physical Android device because the emulator can be very buggy and slow). You should see your website running in the app.

3. Add the Header Bar

In app.js, add the HeaderBarPlugin:

import HeaderBarPlugin from 'astro/plugins/headerBarPlugin'

Now you're ready to use the HeaderBarPlugin. Your next step is to initialize the plugin. Initializing a plugin returns a promise.

// Initialize plugins
...
const headerPromise = HeaderBarPlugin.init()

Put the following code snippet under the promise block that calls layout.setContentView. This will create a basic (but blank) header bar.

// Add the header bar once `layoutPromise` and `headerPromise` are fulfilled.
const layout = await layoutPromise
const headerBar = await headerPromise
// Set up the header bar
headerBar.setBackgroundColor("#FFFFFF")
headerBar.setTextColor("#333333")

layout.addTopView(headerBar)

What we've done is added a basic header bar to the layout of our app. Because the header bar and main navigation view depend on each other for various things, we need to do a little more work to hook the two together. Below, you'll see that we're able to assign icons to the header bar when we navigate in our main view. We also ensure that when the back button is pressed we navigate the main view backwards. Finally, we hook up the 'hardware' back button of the device to navigate the main navigation view back also (same as tapping the back button on the header bar).

// Delete this code
const mainNavigationView = await NavigationPlugin.init()
mainNavigationView.navigate(baseUrl)

// Replace it with this code
const mainNavigationView = await NavigationPlugin.init()
const navigationHeaderBar = await headerPromise

// Now, let's hook up the main navigation to the header bar
mainNavigationView.setHeaderBar(navigationHeaderBar)

// Navigate to the base url and set the icons
mainNavigationView.navigate(baseUrl, {
    header: {
        leftIcon: {
            id: 'account',
            imageUrl: 'file:///account.png'
        },
        centerIcon: {
            id: 'logo',
            imageUrl: 'file:///velo.png'
        },
        rightIcon: {
            id: 'cart',
            imageUrl: 'file:///cart.png'
        }
    }
})

// When the back button is pressed navigate back
navigationHeaderBar.on('click:back', () => {
    mainNavigationView.back()
})


// When the (Android hardware) back button is pressed navigate backwards
Application.on('backButtonPressed', () => {
    mainNavigationView.back()
})

Now re-run the app in Android Studio to check out your new header bar.

4. Add a Flyout Drawer

Again, in app.js, let's include the DrawerPlugin.

import DrawerPlugin from 'astro/plugins/drawerPlugin'

Now that you have the DrawerPlugin, let's initialize it below the HeaderBarPlugin from before.

// Initialize plugins
...
const headerPromise = HeaderBarPlugin.init()
const drawerPromise = DrawerPlugin.init()

Under the Promise statement that adds the header bar to the layout, set the main content area of our DrawerPlugin to the AnchoredLayoutPlugin instance with the following code snippet

// Set the drawer's content area once `drawerPromise` and `layoutPromise` are fulfilled.
const drawer = await drawerPromise
const layout = await layoutPromise
drawer.setContentView(layout)

At the bottom of the file, delete the Promise which sets the layout as the application's main view. In its place, tell the Application to use the DrawerPlugin instance as its main view with the following code snippet:

// Delete this code
const layout = await AnchoredLayoutPlugin.init()
Application.setMainViewPlugin(layout)

// Replace it with this code
Application.setMainViewPlugin(drawer)

Now you have a DrawerPlugin instance, but it does not yet have any drawers. The DrawerPlugin plugin exposes three content areas: the left drawer, the right drawer and the main content area. Let's create a WebViewPlugin that we'll add to one of the drawer's content areas.

First, let's import WebViewPlugin at the top of app.js.

import WebViewPlugin from 'astro/plugins/webViewPlugin';

Initialize the WebViewPlugin below where we initialized the DrawerPlugin:

// Initialize plugins
...
const headerPromise = HeaderBarPlugin.init()
const drawerPromise = DrawerPlugin.init()
const cartWebViewPromise = WebViewPlugin.init()

At the bottom of the file, underneath the last Promise to set the DrawerPlugin instance to the main view, add code to navigate the webview to the cart and assign the view to the right drawer:

// Navigate the web view to the cart
const cartWebView = await cartWebViewPromise
cartWebView.navigate(`${baseUrl}/cart`);
cartWebView.setBackgroundColor("#FFFFFF")
// Don't navigate when links are pressed
cartWebView.disableDefaultNavigationHandler()

// Set the right drawer view to the cart web view instance once the promises have been fulfilled.
const drawer = await drawerPromise
const rightDrawer = drawer.initRightMenu(cartWebView)

Now if you run the app in Android Studio you'll have a right drawer! To check out your right drawer, swipe left from the right-hand side of screenm. Not ideal, but don't worry, next we're going to show the right right drawer by tapping on the 'cart' icon.

5. Show and Hide the Drawer

Now, let's hook up the 'cart' button in the header bar to open and close the right drawer.

The HeaderBarPlugin instance emits events when buttons are pressed. The event name has a format of click:<id>. If you remember from when we created the HeaderBar we assigned ids to the buttons. We gave the cart an id of cart, so we have to listen for the click:cart event.

We'll need a refererence to the right drawer from above so let's capture that in a variable:

const cartWebView = await cartWebViewPromise
const drawer = await drawerPromise
const rightDrawerPromise = drawer.initRightMenu(cartWebView)

Then, add this code at the bottom:

// Bind the `rightIconClick` event once the promises have been fulfilled.
const rightDrawer = await rightDrawerPromise
const header = await headerPromise
header.on('click:cart', () => {
        rightDrawer.toggle()
})

Save the app.js file and re-run the app in Android Studio. Tap the bag icon in the header bar to open and close the right drawer.

6. Add Cart Interaction

In this section we're going to make the right drawer open when a user adds an item to their cart. First, include the Astro JavaScript library in the demo site.

In your editor of choice, open the HandleBars partial site/views/partials/scripts.hbs. This file gets included on every page of the sample site. Include the script:

<script src="http://assets.mobify.com/astro/astro-client-1.0.0-rc2.min.js"></script>

You can now access the Astro JavaScript API on the window.Astro object. Next you will add some code to the site/public/js/cart-add.js file that will trigger an event when a user adds an item to their cart. Attach a handler to the cart button click event with the code below:

$(".js-add").click(() => {
    Astro.trigger('addToCartClicked')
})

This handler triggers a custom addToCartClicked event through Astro. By binding addToCartClicked through Astro, we are now able to listen for this event in our app.js file. At the bottom of the app.js file, after the last Promise to toggle the right drawer, listen for the addToCartClicked event and open the drawer with the code below:

// Add a handler on the main web view to open drawer when 'addToCartClicked' event happens.
const mainNavigationView = await mainNavigationPromise
const rightDrawer = await rightDrawerPromise
const cartWebView = await cartWebViewPromise
mainNavigationView.on('addToCartClicked', () => {
    // Open the right drawer
    rightDrawer.open()
    // Let the cart view know that something has been added
    cartWebView.trigger('cartUpdated')
})

Save the app.js file and re-run the app in Android Studio. Congrats on finishing the tutorial! You can checkout the final tutorial code to see how your code compares.