News Feed

The News Feed is a fully customizable in-app content feed for your users. Our targeting and segmentation allows you to create a stream of content that is individually catered to the interests of each user. Depending on their position in the user life cycle and the nature of your app, this could be an on-boarding content server, an advertisement center, an achievement center, or a generic news center.

Example News Feed

Sample News Feed

News Feed Integration Overview

In Android, the News Feed and feedback form are implemented as Fragments that are available in the Braze Android UI project. View Google’s documentation on Fragments for information on how to add a Fragment to an Activity.

The Android UI Fragments do not automatically track session analytics. To ensure that sessions are tracked correctly, you should call IAppboy.openSession() when your app is opened (learn more about tracking user sessions).

The AppboyFeedFragment class will automatically refresh and display the contents of the News Feed and log usage analytics. The cards that can appear in a user’s News Feed are set on the Braze dashboard.

Linking to the News Feed from an in-app message must be enabled by registering the AppboyFeedActivity within your AndroidManifest.xml file.

Implementation Example

See DroidBoyActivity.java in the Droidboy sample app.

News Feed Customization

Default Styling

The Braze UI elements (the feedback form and News Feed) come with a default look and feel that matches the Android standard UI guidelines and provides a seamless experience. You can see these default styles in the res/values/style.xml file in the Braze SDK distribution.

1
2
3
4
5
6
7
8
9
10
11
12
13
  <style name="Appboy"/>
  <!-- Feedback -->
  <style name="Appboy.Feedback"/>
  <style name="Appboy.Feedback.Layout"/>
  <style name="Appboy.Feedback.NavigationBar">
    <item name="android:padding">4dp</item>
    <item name="android:background">@color/com_appboy_feedback_form_navigation_bar_background</item>
  </style>
  <style name="Appboy.Feedback.NavigationBarCancelButton">
    <item name="android:layout_marginRight">2dp</item>
    <item name="android:text">@string/com_appboy_feedback_form_cancel</item>
    <item name="android:textStyle">bold</item>
  </style>

Overriding Styles

If you would prefer, you can override these styles to create a look and feel that better suits your app. To override a style, copy it in its entirety to the styles.xml file in your own project and make modifications. The whole style must be copied over to your local styles.xml file in order for all of the attributes to be correctly set.

Correct Style Override

1
2
3
4
5
6
7
8
9
<style name="Appboy.Feed.List">
  <item name="android:background">@color/mint</item>
  <item name="android:cacheColorHint">@color/mint</item>
  <item name="android:divider">@android:color/transparent</item>
  <item name="android:dividerHeight">16.0dp</item>
  <item name="android:paddingLeft">12.5dp</item>
  <item name="android:paddingRight">5.0dp</item>
  <item name="android:scrollbarStyle">outsideInset</item>
</style>

Incorrect Style Override

1
2
3
4
<style name="Appboy.Feed.List">
  <item name="android:background">@color/mint</item>
  <item name="android:cacheColorHint">@color/mint</item>
</style>

Feed Style Elements

Below is a description of the themable Braze UI elements and their names for styling purposes:

Android Feed Android Cards Android Empty Android Network Error

Setting A Custom Font

Braze allows for setting a custom font using the font family guide. To use it, override a style for cards and use the fontFamily attribute to instruct Braze to use your custom font family.

For example, to update the font on all titles for Short News Cards, override the Appboy.Cards.ShortNews.Title style and reference your custom font family. The attribute value should point to a font family in your res/font directory.

Here is a truncated example with a custom font family, my_custom_font_family, referenced on the last line:

1
2
3
4
5
6
  <style name="Appboy.Cards.ShortNews.Title">
    <item name="android:layout_height">wrap_content</item>
    ...
    <item name="android:fontFamily">@font/my_custom_font_family</item>
    <item name="fontFamily">@font/my_custom_font_family</item>
  </style>

Setting a Custom News Feed Click Listener

As of Android SDK v.1.14.0, you can handle News Feed clicks manually by setting a custom News Feed click listener. This enables use cases such as selectively using the native web browser to open web links.

Step 1: Implement a News Feed Click Listener

Create a class that implements IFeedClickActionListener. Implement the onFeedCardClicked() method, which will be called when the user clicks a News Feed card.

See CustomFeedClickActionListener.java in our Droidboy sample application for an example implementation.

Step 2: Instruct Braze to Use Your News Feed Click Listener

Once your IFeedClickActionListener is created, call AppboyFeedManager.getInstance().setFeedCardClickActionListener() to instruct AppboyFeedManager to use your custom IFeedClickActionListener.

See PreferencesActivity.java in our Droidboy sample application for an example implementation.

Fully Custom Feed Display

If you would like to display the feed in a completely custom manner, it is possible to do so by using your own views populated with data from our models. To obtain Braze’s News Feed models, you will need to subscribe for News Feed updates and use the resulting model data to populate your views. You will also need to log analytics on the model objects as users interact with your views.

Part 1: Subscribing to Feed Updates

First, declare a private variable in your custom feed class to hold your subscriber:

1
2
// subscriber variable
private IEventSubscriber<FeedUpdatedEvent> mFeedUpdatedSubscriber;

Next, add the following code to subscribe to feed updates from Braze, typically inside of your custom feed activity’s Activity.onCreate():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Remove the old subscription first
Appboy.getInstance(this).removeSingleSubscription(mFeedUpdatedSubscriber, FeedUpdatedEvent.class);
mFeedUpdatedSubscriber = new IEventSubscriber<FeedUpdatedEvent>() {
  @Override
  public void trigger(final FeedUpdatedEvent event) {
    // This list of Card objects included in the FeedUpdatedEvent should be used to populate your News Feed views.
    List<Card> cards = event.getFeedCards();
    // your logic here
  }
};
Appboy.getInstance(this).subscribeToFeedUpdates(mFeedUpdatedSubscriber);

// Request a refresh of feed data
Appboy.getInstance(this).requestFeedRefresh();

We also recommend unsubscribing when your custom feed activity moves out of view. Add the following code to your activity’s onDestroy() lifecycle method:

1
Appboy.getInstance(this).removeSingleSubscription(mFeedUpdatedSubscriber, FeedUpdatedEvent.class);

Part 2: Logging Analytics

When using custom views, you will need to log analytics manually as well, since analytics are only handled automatically when using Braze views.

To log a display of the feed, call Appboy.logFeedDisplayed().

To log an impression or click on a Card, call Card.logClick() and Card.logImpression() respectively.

Categories

Defining a News Feed Category

Instances of the Braze News Feed can be configured to only receive cards from a certain “category”. This allows for effective integration of multiple News Feed streams within a single application. For more information on this feature see Braze Academy

News Feed Categories can be defined by calling the following methods as you load the News Feed:

1
2
3
4
5
6
newsFeed.setCategories(CardCategory.ALL_CATEGORIES);
newsFeed.setCategories(CardCategory.ADVERTISING);
newsFeed.setCategories(CardCategory.ANNOUNCEMENTS);
newsFeed.setCategories(CardCategory.NEWS);
newsFeed.setCategories(CardCategory.SOCIAL);
newsFeed.setCategories(CardCategory.NO_CATEGORY);

You can also populate a feed with a combination of categories as in the following example:

1
newsFeed.setCategories:EnumSet.of(CardCategory.ANNOUNCEMENTS, CardCategory.NEWS);

Read/Unread Indicators

Braze allows you to optionally toggle on an Unread/Read indicator on News Feed cards as pictured below:

UnreadvsRead

Enabling the Indicators

In order to enable this functionality add the following line to your appboy.xml file:

1
<bool name="com_appboy_newsfeed_unread_visual_indicator_on">true</bool>

Customizing the Indicators

These indicators can be customized by altering the values in android-sdk-ui/src/main/res/drawable-hdpi/icon_unread.png and android-sdk-ui/src/main/res/drawable-hdpi/icon_read.png.

Card Types

Braze has 5 unique News Feed card types which share a base model. Each card type also has additional card-specific properties which are listed below.

Base Card

The Base Card model provides foundational behavior for all cards.

  • getId() - returns the card’s ID set by Braze
  • getViewed() - returns a boolean reflects if the card is read or unread by the user
  • getExtras() - returns a map of key-value extras for this card
  • setViewed(boolean) - sets a card’s viewed field
  • getCreated() - returns the unix timestamp of the card’s creation time from Braze dashboard
  • getUpdated() - returns the unix timestamp of the card’s latest update time from Braze dashboard
  • getCategories() - returns the list of categories assigned to the card, cards without a category will be assigned ABKCardCategoryNoCategory
  • isInCategorySet(EnumSet) - returns true if the card belongs to the given category set

Banner Image Cards are clickable full-sized images. In addition to the base card properties:

  • getImageUrl() - returns the URL of the card’s image
  • getUrl() - returns the URL that will be opened after the card is clicked on. It can be a http(s) URL or a protocol URL
  • getDomain() - returns link text for the property url.

Captioned Image Card

Captioned Image Cards are clickable full-sized images with accompanying descriptive text. In addition to the base card properties:

  • getImageUrl() - returns the URL of the card’s image
  • getTitle() - returns the title text for the card
  • getDescription() - returns the body text for the card
  • getUrl() - returns the URL that will be opened after the card is clicked on. It can be a http(s) URL or a protocol URL
  • getDomain() - returns the link text for the property url.

Text Announcement Card (Captioned Image without Image)

Text Announcement Cards are clickable cards containing descriptive text. In addition to the base card properties:

  • getTitle() - returns the title text for the card
  • getDescription() - returns the body text for the card
  • getUrl() - returns the URL that will be opened after the card is clicked on. It can be a http(s) URL or a protocol URL
  • getDomain() - returns the link text for the property url.

Short News Card

Short News Cards are clickable cards with images and accompanying descriptive text. In addition to the base card properties:

  • getImageUrl() - returns the URL of the card’s image
  • getTitle() - returns the title text for the card
  • getDescription() - returns the body text for the card
  • getUrl() - returns the URL that will be opened after the card is clicked on. It can be a http(s) URL or a protocol URL
  • getDomain() - returns the link text for the property url.

Cross Promotion Small Card

Cross-Promotion Small Cards link to items in the Google Play Store or Kindle Store. In addition to the base card properties:

  • getTitle() - returns the title text for the card. This will be the promoted item’s name.
  • getSubtitle() - returns the text of the category of the promoted item
  • getImageUrl() - returns property is the URL of the card’s image.
  • getPackage() - reutrns the package name of the promoted item.
  • getRating() - returns the rating of the promoted app. This property will be 0.0 unless the promoted item is an app, in which case the rating will be in the range of [0.0, 5.0];
  • getPrice() - returns the price of the promoted app.
  • getReviewCount() - returns the number of reviews of the promoted app. This property will be 0 unless the promoted item is an app.
  • getCaption() - returns the text that will be displayed in the tag on the top of the small cross promotion card.
  • getUrl() - returns the url of the promoted item which leads to the item’s App Store page.

Adding a Badge

You can request the number of unread cards at any time by calling:

1
getUnreadCardCount()

See the Javadoc for more information.

Refreshing the Feed

You can queue a manual refresh of the Braze News Feed at any time by calling:

1
Appboy.requestFeedRefresh()

See the Javadoc for more information.

Key-Value Pairs

Card objects may optionally carry key-value pairs as extras. These can be used to send data down along with a Card for further handling by the application.

Call the following on a Card object to retrieve its extras:

1
Map<String, String> getExtras()

See the Javadoc for more information.

GIFs

Braze requires an external image library to display animated GIFs with the News Feed.

Custom Image Library Integration

Braze offers the ability to use a custom image library to display animated GIFs with the News Feed.

Note: Although the example below uses Glide, any image library that supports GIFs is compatible.

Step 1: Creating the Image Loader Delegate

The Image Loader delegate must implement the following methods:

The integration example below is taken from the Glide Integration Sample App included with the Braze Android SDK.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class GlideAppboyImageLoader implements IAppboyImageLoader {
  private static final String TAG = GlideAppboyImageLoader.class.getName();
  private RequestOptions mRequestOptions = new RequestOptions();

  @Override
  public void renderUrlIntoView(Context context, String imageUrl, ImageView imageView, AppboyViewBounds viewBounds) {
    Glide.with(context)
        .load(imageUrl)
        .apply(mRequestOptions)
        .into(imageView);
  }

  @Override
  public Bitmap getBitmapFromUrl(Context context, String imageUrl, AppboyViewBounds viewBounds) {
    try {
      return Glide.with(context)
          .asBitmap()
          .apply(mRequestOptions)
          .load(imageUrl).submit().get();
    } catch (Exception e) {
      AppboyLogger.e(TAG, "Failed to retrieve bitmap at url: " + imageUrl, e);
    }
    return null;
  }

  @Override
  public void setOffline(boolean isOffline) {
    // If the loader is offline, then we should only be retrieving from the cache
    mRequestOptions = mRequestOptions.onlyRetrieveFromCache(isOffline);
  }
}

Step 2: Setting the Image Loader Delegate

The Braze SDK will use any custom image loader set with setAppboyImageLoader. Note that we recommend setting the custom image loader in a custom application subclass.

1
2
3
4
5
6
7
public class GlideIntegrationApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    Appboy.getInstance(this).setAppboyImageLoader(new GlideAppboyImageLoader());
  }
}

Fresco Migration

Fresco is no longer supported as a GIF loading library in version 3.0.0 of the Braze Android SDK. A custom image loader, such as Glide, must be used in order to display GIFs.

The usage of Fresco with IAppboyImageLoader is not supported since Fresco requires Drawee views to work.

WAS THIS PAGE HELPFUL?