Developing Android Apps for the HD4000 | Part 2 - Displaying Content

This is part 2 of the blog series - Developing Android Apps for the HD4000 - if you missed part 1, you can check it out here!

Introduction

There are multiple ways of displaying data on the HUD, depending on what that data is. For example, if we want to display an image, we can call the showImage(); method. If we want to display a message, we can use the showMessage(); method. If we wanted to display something a little more complicated, we can use the showView() method. This blog post will elaborate on each of these APIs and walk you through implementing them into your application.

Before we get into the specific APIs, there is a key thing to remember: You will only be able to interact with the HUD when it is connected – whilst this seems obvious, I just wanted to highlight this to remind you to make sure you’re performing these actions in the context of a connected HUD. To ensure this, simply wrap your API calls in an if block to check isConnected() returns true, otherwise handle your use case appropriately by, for example, informing the user that the device needs to be connected. Now we have that out of the way, let's get into the specifics.  

Displaying Messages

So, the first API we will cover is the showMessage() function. This is by far the simplest way to start interacting with the HUD, and as you will see in a moment, is extremely straightforward.

All we need to do is take our instance of the ZebraHud class and call the showMessage() API, passing through two String parameters: Title & Message. The example below demonstrates this:

// Init Title & Message Strings
String title = "Your Custom Title";
String message = "Your Custom Message";

// Perform Connection Check
if (mZebraHud.isConnected()) {
    // Show Message
    mZebraHud.showMessage(title, message);
    } else {
    // TODO: Handle disconnected HUD
    Log.i(TAG, "No HUD Found!");
}
show message screenshot.png
show message screenshot.png, by JS6845

Displaying Images

The second API we will cover in this part of the blog is the showImage() function. This API takes one parameter: A Bitmap image. I’m sure most Android developers are more than comfortable with creating Bitmaps, but for those who aren’t I would suggest leveraging a mature library such as Glide or Picasso to create your Bitmaps – this is a memory-intensive operation and should be performed on a background thread. Both Picasso and Glide can take care of all of this for you and will make sure your application runs smoothly. The example below demonstrates using the showImage() API, using Glide to create our bitmap:

// Init Image File Path (This can be anything that Glide supports: URL, file path etc...)
String imageFilePath = "/huddemo/images/demoimage.png";
        
// Perform Connection Check
if (mZebraHud.isConnected()) {
    // Call Glide to Build Bitmap on Background thread from image path
    Glide.with(this) // Context
        .asBitmap() // Set Image Type
        .load(imageFilePath) // File Path
        .into(new CustomTarget<Bitmap>() {
            @Override
            public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                // This is a Glide Callback when Bitmap has been created
                // Call showImage() & pass through the generated bitmap
                mZebraHud.showImage(resource);
            }

            @Override
            public void onLoadCleared(@Nullable Drawable placeholder) {
                // Empty Calllback
            }
    });
}

Displaying Views

The third & final API we will cover in this blog post is showView(). Call this API actually involves using another API: createView(), to transform standard android Layout files to HUD compatible views. There are a few steps to this process, so let's go through them one by one.

The first thing we’re going to need to do is to create the Layout. This is the bread & butter of any android developer, so I won't go through the details. Below is a very simple layout using an ImageView & TextView to display an image & some text respectively. Bear in mind that whilst this is a very simple example, the layouts can be as complex as your use-vase requires – I’m keeping things simple for the sake of brevity in this tutorial – on the left-hand side of the screenshot we have the XML definition of the layout, and on the right, we have a visual representation of the layout – i.e. what it will look like on the HUD:

hud_layout_screenshot.png
hud_layout_screenshot.png, by JS6845

Now that we’ve created our layout, we can begin to leverage the HUD APIs to create & display this layout. The first thing we’re going to need to do is to call the createView() API, passing through one parameter: the layout file we just created. Again, remember to perform an isConnected check, as we won't be able to create the view otherwise. Once called, this method will return an instance of a View object, containing the views (ImageView & TextView) included in the layout file:

// Perform Connection Check
if (mZebraHud.isConnected()) {
    // Create View from Layout
    View customView = mZebraHud.createHudView(R.layout.layout_hud_text);
}

Now we have an instance of the View object, we can use the standard findViewById API from android to obtain an instance of our ImageView & TextView:

// Get Views from View
ImageView customImageView = customView.findViewById(R.id.custom_image_view);
TextView customTextView = customView.findViewById(R.id.custom_text_view);

Having obtained these instances, we can then perform whatever action we require. In this case, I’m going to set the image resource to an “X” drawable SVG asset included in my project, and set the text to say “There was an error”. Again, remember for your use case, this layout can be as complex as required, and you will be able to modify the layout at this point to match whatever your use case may be. The example below shows how to update these views to match our requirements:

// Set Resources 
customImageView.setImageResource(R.drawable.ic_cross);
customTextView.setText("There was an error");

That’s the designing portion out of the way, all that’s left to do is send the view to the HUD. To do this, simply call the showView() method, and pass through a single parameter: the View we just created:

// Show View on HUD
mZebraHud.showHudView(customView);

And that’s it! Just like that we have created a custom layout, modified it to meet our use-case, and sent it to the HUD to be displayed, the complete code snippet is below:

// Perform Connection Check
if (mZebraHud.isConnected()) {
    // Create View from Layout
    View customView = mZebraHud.createHudView(R.layout.layout_hud_text);

    // Get Views from View
    ImageView customImageView = customView.findViewById(R.id.custom_image_view);
    TextView customTextView = customView.findViewById(R.id.custom_text_view);

    // Set Resources
    customImageView.setImageResource(R.drawable.ic_cross);
    customTextView.setText("There was an error");

    // Show View on HUD
    mZebraHud.showHudView(customView);
}

And with that, we come to the end of Part 2 of our blog series on interacting with the HD4000. In Part 3 we will discuss using a Json Image Model (JIM), to create HUD layouts using JSON files, which requires very little coding, meaning anyone who is familiar with JSON can create custom layouts for the HD4000.