This version of Astro is only compatible with Xcode 7.3
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 0.14.0 https://github.com/mobify/astro-tutorial.git
cd astro-tutorial
npm install
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
var 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. Make sure you add a comma after the second last plugin.

require([
    .
    .,
    'plugins/headerBarPlugin'
],
function(
    .
    .,
    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
...
var 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.
Promise.join(layoutPromise, headerPromise, function(layout, headerBar) {
    // 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
mainNavigationPromise.then(function(mainNavigationView){
    mainNavigationView.navigate(baseUrl)
});

// Replace it with this code
Promise.join(mainNavigationPromise, headerPromise, function(mainNavigationView, headerBar) {
    // Now, let's hook up the main navigation to the header bar
    mainNavigationView.setHeaderBar(headerBar);

    // 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
    headerBar.on('click:back', function() {
        mainNavigationView.back();
    });

    // When the back button is pressed navigate backwards
    Application.on('onKeyDown', function(params) {
        if (params.keyCode == 4) {
            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.

require([
    .
    .,
    'plugins/drawerPlugin'
],
function(
    .
    .,
    DrawerPlugin
) {

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

// Initialize plugins
...
var headerPromise = HeaderBarPlugin.init();
var 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.
Promise.join(drawerPromise, layoutPromise, function(drawer, layout) {
    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
layoutPromise.then(function(layout) {
    Application.setMainViewPlugin(layout);
});

// Replace it with this code
drawerPromise.then(function(drawer) {
    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.

// Initialize plugins
...
var headerPromise = HeaderBarPlugin.init();
var drawerPromise = DrawerPlugin.init();
var 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
cartWebViewPromise.then(function(webView) {
    webView.navigate(baseUrl + "/cart");
    webView.setBackgroundColor("#FFFFFF");
    // Don't navigate when links are pressed
    webView.disableDefaultNavigationHandler();
});

// Set the right drawer view to the cart web view instance once the promises have been fulfilled.
var rightDrawerPromise = Promise.join(cartWebViewPromise, drawerPromise, function(cartWebView, drawer) {
    var rightDrawer = drawer.initRightMenu(cartWebView);
    // We want the right drawer later, so we will return it
    return rightDrawer;
});

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 is 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. Add this code at the bottom.

// Bind the `rightIconClick` event once the promises have been fulfilled.
Promise.join(rightDrawerPromise, headerPromise, function(rightDrawer, header) {
    header.on('click:cart', function() {
        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-0.14.0.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(function() {
    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.
Promise.join(mainNavigationPromise,
                rightDrawerPromise,
                cartWebViewPromise,
                function(mainNavigationView, rightDrawer, cartWebView) {
    mainNavigationView.on('addToCartClicked', function() {
        // 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.