Building a Kentico News Android app with the Kentico Cloud Delivery JavaRX SDK

By Bryan Soltis in Kentico
·8 min read

Our Community team is hard at work, producing new SDKs for Kentico Cloud for all types of platforms. Recently, we launched our new Kentico Cloud Delivery JavaRx SDK, enabling Java and Android developers to easily integrate Kentico Cloud into their apps. In this article, I’ll take a closer look at the SDK and sample projects to help you get started with these new GitHub projects.

One of the best parts of development is the ever-changing landscape of technology. Sure, you may be an expert in a library or framework, but there’s about 50 new ones just waiting to be released. It keeps things very exciting and there’s always something new to learn. When it comes to mobile, this is especially true as the major providers look to stake their claim as the go-to platform for developers.

It’s no secret there are plenty of Android devices floating around. With the most diversified and distributed ecosystem, the Android OS is one of the first frameworks that developers look to when creating their mobile apps. To keep up with demand, we recently announced our new Kentico Cloud Delivery JavaRx SDK. 

This new SDK is designed to simplify integrating Kentico Cloud into your Java or Android apps by providing built in support for multiple programming styles while giving you built in support for ReactiveX observables. With support for multiple content types, query parameters, and nearly every other Kentico Cloud feature, the SDK should be your one-stop shop for all things Android.

In this article, I want to let you know a little more about the SDK, the sample apps included, and walk you through developing a custom mobile app. Recently, I took the new sample app and updated it to display the always exciting Kentico Cloud News feed. KenticoCloud.com is completely powered by our Kentico Cloud service, so it makes for a great demo of the capabilities. 

Be sure to read up on the Kentico Cloud Delivery API to understand the concepts and terms in this article. Also, check out the SDK and it’s included Readme for in-depth info. Alright, let’s get to it!

The Setup

Before I could get going, I needed to make sure my environment was set up for development. Because I’m using Windows 10, this meant getting the Android Studio IDE on my machine. Now, this is a pretty big install, so plan on it taking a bit to complete.

Download Android Studio

The Android Studio IDE provides a decent interface for development, with code completion, formatting, and coloring options. It’s not Visual Studio 2017, but does have some familiar features. The emulators are baked right in, so no need to download extra components to debug your app. Also, any change to your app can kick off a build process, including tests, ensuring that the code you just wrote will compile. 

If you’re just getting started with the IDE, I recommend firing up a sample app and testing it out to get the hang of things. 

Kentico Cloud Delivery Java RX SDK

With Android Studio in place, I was ready to get going with the Kentico Cloud Delivery Android SDK. A combination of both the Java and Android platforms, this SDK is designed to bring you all the great functionality of the Kentico Cloud Delivery API to your projects. 

Kentico Cloud Delivery Java RX SDK

Built to support ReactiveX projects, the SDK supports the latest trends in Android development, while also maintaining support for traditional programming styles through standard, synchronous, web requests. We also provide two libraries that present different observables, one for standard JavaRx (delivery-rx) and one for Android-specific RX observables using Rx2Android requests (delivery-android). Of course, if you are not using ReactiveX, we also have an adapter for standard http web requests.  This makes the SDK a very powerful tool in your arsenal, regardless of your development style.

NOTE

When developing a new application that will utilize our SDK, you should create a new project and follow the GitHub documentation to get started. In my case, I downloaded the entire GitHub project to my local machine to share the sample along that I had access to the entire SDK to show.

Starting with the sample project

The GitHub project contains a lot of code, from the SDK itself to sample projects for Java and Android. Following the pattern for other Kentico Cloud demos, these applications demonstrate how to use the SDK to display sample content from the Dancing Goat site. It’s great way to see how the SDK works with “real” data, however this full project should not be the starting point for your project as it includes the entire SDK rather than including it through Gradle. Let’s check out the sample project structure.

NOTE

You can also start with a blank project. Just follow the GitHub project documentation to see how to create your Kentico Cloud Delivery client and access your content. 

SDK Project Structure

The SDK contains several projects, including the delivery-core (the bulk of the SDK), delivery-rx and delivery-android (ReactiveX components), testing projects, and the sample applications for Java and Android. The main area we will take a look at is the sample-android-app and its underlying structure as this the type of project we will be creating in our separate project.

java

In the sample-android-app project, you can see that the code is separated into logical sections, depending on the purpose.

app
This folder contains the logic for each area of the application. This includes core functionality for the base app, as well as content type-specific code. 

data
This folder contains the models for the Kentico Cloud content types. It also contains the CloudSource, DataSource, and Repository classes for the content types. This is where the DeliveryClient is used to retrieve the content. 

injection
This folder contains classes related to how injection is handled within the app. In the case of the sample project, this is where the different content repositories are loaded.

util
This folder contains several helper classes used within the application. This includes a NetworkHelperSyncHelper, and ActivityUtils class for working with the data. 

res

For the layouts, the sample app contains multiple files for each content type, allowing the display to be customized for each one. Each content type has a unique look and feel.

Here is what the sample app looks like on a device. 

 

The Android Sample app contains a lot of functionality out the box. I would recommend you run the app locally to familiarize yourself with all the components. For the rest of this article, I’ll be creating my own app using a lot of the code from the sample project to model my project around. 

Content Type Models

To start my custom development, I needed to define my new content type models. Because my app would be using the Kentico Cloud blog posts, this meant defining my Author and BlogPost models. I also cleared out the existing models, to keep things clean. Because the SDK encompasses the entire Delivery API, we can use strongly-type classes and objects to retrieve content type elements and data.

Author

The Author content type is a pretty basic model, consisting of only a name. The important aspect of this model is it will be used for modular content in my BlogPost model. Other than that, it extends the ContentItem class and has one function for returning the name.

public final class Author extends ContentItem { public static final String TYPE = "author"; @ElementMapping("name") public TextElement name; public String getName() { return name.getValue(); } }

BlogPost

The BlogPost is the more complex of the two, with several fields for the different content elements. This includes an AssetElement (header image), DateTimeElement (post date), MultipleChoiceElement (topic), and ModularContentElement (author). The SDKs can support several types of elements, so be sure to map yours correctly for your Kentico Cloud content types.

@ElementMapping("title") public TextElement title; @ElementMapping("header_image") public AssetsElement headerImage; @ElementMapping("perex") public RichTextElement perex; @ElementMapping("body") public RichTextElement body; @ElementMapping("date") public DateTimeElement postDate; @ElementMapping("topic") public MultipleChoiceElement topic; @ElementMapping("author") public ModularContentElement<Author> author;

The BlogPost model contains several functions to return the data. Because AssetElement fields may have multiple values, the class contains a function to return the first item in the collection.

public String getTeaserImageUrl(){ AssetModel[] assets = this.headerImage.getValue(); if (assets == null){ return null; } if (assets.length == 0){ return null; } return assets[0].url; }

The same concept is applied to the MultipleChoice element for the topic.

public String getTopic(){ if(topic.getValue().length > 0) { MultipleChoiceOption option = topic.getValue()[0]; return option.name; } else { return "General"; } }

Lastly, blog posts use modular content for the author. The class contains a function to return the author name, using the SDK to retrieve the modular content.

public String getAuthor(){ String strAuthor = ""; if(!author.getValue().isEmpty()) { for(Author auth : author.getValue()) { if(strAuthor.length() > 0) { strAuthor += ", "; } strAuthor += auth.getSystem().getName(); } return "by " + strAuthor; } else { return "by General"; } }

For the layout folder, I created new files for my content types, leveraging the existing pattern.

TypeResolver

Next, I updated the TypeResolver to handle my new models. In the /app/config/AppConfig class, I added my new content types. I also updated my project id to the Kentico Cloud website.

public final static String KENTICO_CLOUD_PROJECT_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; public static List<TypeResolver<?>> getTypeResolvers(){ // Type resolvers are responsible for creating the strongly typed object out of type List<TypeResolver<?>> typeResolvers = new ArrayList<>(); /// BlogPost resolver typeResolvers.add(new TypeResolver<>(BlogPost.TYPE, new Function<Void, BlogPost>() { @Nullable @Override public BlogPost apply(@Nullable Void input) { return new BlogPost(); } })); /// Author resolver typeResolvers.add(new TypeResolver<>(Author.TYPE, new Function<Void, Author>() { @Nullable @Override public Author apply(@Nullable Void input) { return new Author(); } })); return typeResolvers; }

Retrieve the content

The next step was to create my repository for the content. Following the sample app pattern, I created the BlogPostsCloudSource, BlogPostsDataSource, and BlogPostsRepository classes in the  /data/source/blogposts folder. The only real modification from the sample app was to update the BlogPostsRepository class to retrieve blogpost content items, sorted by the post date.

@Override public void getBlogPosts(@NonNull final LoadBlogPostsCallback callback) { this.deliveryService.<BlogPost>items() .type(BlogPost.TYPE) .orderParameter("elements.date", OrderType.Desc) .limitParameter(10) .getObservable() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<DeliveryItemListingResponse<BlogPost>>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(DeliveryItemListingResponse<BlogPost> response) { List<BlogPost> items = (response.getItems()); if (items == null || items.size() == 0){ callback.onDataNotAvailable(); return; } callback.onItemsLoaded(items); } @Override public void onError(Throwable e) { callback.onError(e); } @Override public void onComplete() { } }); }

This code leverages the Delivery Filter Parameters in the call to retrieve only the first 10 items, sorted by the post date.

Inline Assets

By using the sample app and its patterns, my app was already close to being done. The main outstanding issue was displaying inline images. By default, Android Studio will replace an <img> tags with placeholder images. Because Kentico Cloud can support super cool inline images, I wanted to make sure those displayed properly. This meant implementing a custom ImageGetter into my project.

PicassoImageGetter

In my /util folder, I created a new class called PicassoImageGetter. This class contains the logic needed to parse HTML and create a Drawing object for any images. The idea is that when the HTML content is retrieved from Kentico Cloud, the custom ImageGetter will parse it and create the image objects for each asset it finds.

package com.kenticocloud.delivery.sample.androidapp.util; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.text.Html; import com.kenticocloud.delivery.sample.androidapp.R; import com.squareup.picasso.Picasso; import com.squareup.picasso.Target; public class PicassoImageGetter implements Html.ImageGetter { private Context mContext; public PicassoImageGetter(Context context) { mContext = context; } @Override public Drawable getDrawable(String source) { BitmapDrawablePlaceHolder drawable = new BitmapDrawablePlaceHolder(); Picasso.with(mContext) .load(source) .placeholder(R.drawable.ic_image_placeholder) .into(drawable); return drawable; } private class BitmapDrawablePlaceHolder extends BitmapDrawable implements Target { protected Drawable drawable; @Override public void draw(final Canvas canvas) { if (drawable != null) { drawable.draw(canvas); } } public void setDrawable(Drawable drawable) { this.drawable = drawable; int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); drawable.setBounds(0, 0, width, height); setBounds(0, 0, width, height); } @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { setDrawable(new BitmapDrawable(mContext.getResources(), bitmap)); } @Override public void onBitmapFailed(Drawable errorDrawable) { //handle later } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { //handle later } } }

With the ImageGetter created, I updated my /app/blogpost_detail/BlogPostDetailFragment class to utilize the new class. This meant creating a new PicassoImageGetter object and passing it to the Html.fromHtml function. 

// body PicassoImageGetter imageGetter = new PicassoImageGetter(view.getContext()); TextView bodyCopyTV = (TextView) view.findViewById(R.id.blogpostDetailBodyCopyTV); bodyCopyTV.setText(Html.fromHtml(blogpost.getBody(), imageGetter, null));

Note that the sample app already utilizes the Picasso library, so adding this was pretty simple.

Other stuff

For my demo, I modified a number of other areas of the sample app.

Colors

The sample app contains a helpful /res/values/colors.xml file for the primary app colors. I updated this with my custom colors.

<resources> <color name="colorPrimary">#1e88e5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorPrimaryLight">#FFFFFF</color> <color name="colorAccent">#2196f3</color> </resources>

Strings

The app uses several strings to set labels for titles, menus, and other areas. I updated the /res/values/strings.xml file with my custom values.

<!-- global items --> <string name="app_name">Kentico Cloud News</string> <string name="app_main_activity_title">Kentico Cloud News</string> <string name="action_settings">Settings</string> <string name="error_network_failure_msg">Network connection failed</string> <string name="error_msg">Error occurred</string> <string name="error_network_not_available">Network not available</string> <string name="error_loading_data">Error loading data</string> <string name="error_problem_fetching_data">There was a problem fetching data</string> <string name="try_again">TRY AGAIN</string> <!-- navigation drawer --> <string name="navigation_drawer_open">Open navigation drawer</string> <string name="navigation_drawer_close">Close navigation drawer</string> <string name="navigation_drawer_title">Kentico Cloud News</string> <string name="navigation_drawer_subtitle">cloud@kentico.com</string> <!-- main menu items --> <string name="main_menu_home">Kentico Cloud News</string> <string name="main_menu_blogposts">Blog Posts</string> <string name="hello_blank_fragment">Hello blank fragment</string> <string name="teaser_image">Teaser image</string> <string name="no_data">There is no data</string>

Menus

Because the sample app has a flyout menu, these values needed to be updated to match my structure. In the /res/menu/drawer_menu.xml, I updated the code with my single menu item.

<group android:checkableBehavior="single"> <item android:id="@+id/blogposts" android:icon="@drawable/ic_list" android:title="@string/main_menu_blogposts" /> </group>

Testing

Once all the code was complete, I was ready to test. I built the app, then fired up the emulator. I confirmed the app launched properly. I also confirmed my blog posts were being displayed correctly.

I selected an item and confirmed the details properly.

Lastly, I confirmed the inline images properly displayed.

Moving forward

In this blog, I took a closer look at the new Kentico Cloud Delivery JavaRx SDK. This project is packed full of great examples and code, to help jump start your Android or Java development. By leveraging the built-in architecture, you can quickly create your Android apps and get up and running quickly. Now, go and make some awesome Kentico Cloud-powered mobile apps!

Download the full source code

By Bryan Soltis in Kentico
search
Gartner report
We're named a Challenger in the 2018
Gartner Magic Quadrant for WCM!
×