Skip to content

Showing & Using Offers

The Loop Media Android SDK provides a number of pre-built components to load and display offers in a variety of ways. It also provides consistent interfaces for loading offer and business related data.

Basics

Data Providers

The DataProvider interface is the core mechanism used to query paginated data (collections, businesses, locations) via the SDK. It handles responses, error, and request details like pagination in a consistent manner.

In order to get results from a DataProvider callbacks can be added to any number of the following methods:

Method Description
onFetchSuccess Invoked when the first page of results loads. This is triggered on first loads and when a force refresh is made.
onNextPageSuccess Invoked when a non-first page of results has loaded with the array of results from that page
onDataChanged Invoked when any change (load or next page) occurs and re-emits the entire list of data
onError Invoked when any exception occurs loading the data

The DataProvider has several methods for fetching data

Method Description
fetch(Boolean forceRefresh) Performs a fetch with the current params set on the DataProvider. Passing true to forceRefresh will ensure that the data is fetched from the network instead of a cached version
refresh() Equivalent to calling fetch(true)
fetch(P params, Boolean forceRefresh) Performs a fetch with the given params. Setting forceRefresh to true will ensure fresh data is fetched from the api instead of using the cache
loadNextPage() Performs a next page fetch with the previously set params
cancel() Cancels any in-progress data fetching
dispose() Removes all callbacks provided to the DataProvider and cancels any ongoing requests

Warning

It is vital to call dispose() on the DataProvider when the containing Activity or Fragment is destroyed so that all calls are canceled and the callbacks are freed. Failing to call dispose() will result in memory leaks.

Data providers react to changes to global content filters, and reload automatically as soon as filter changes or gets removed.

Collections

Searching Collections by Tag

Lists of collections can be retrieved with the following code:

import com.loopmediagroup.LoopMediaGroup;
import com.loopmediagroup.domain.data.Collection;
import com.loopmediagroup.domain.data.params.CollectionListRequestParams;
import com.loopmediagroup.provider.DataProvider;

DataProvider<Collection, CollectionListRequestParams> provider = LoopMediaGroup.client().collections();

provider.onFetchSuccess(collections -> {
    // Handle collection first page fetched
    return Unit.INSTANCE;
});

provider.onDataChanged(collections -> {
    // Handle the full list of collections when changed
    return Unit.INSTANCE;
});

provider.onError(throwable -> {
// Handle exceptions
    return Unit.INSTANCE;
});

provider.onNextPageSuccess(collections -> {
// Handle additional page loads
    return Unit.INSTANCE;
});

List<String> tags = new ArrayList<>();
tags.add("Food");
tags.add("Drink");

provider.fetch(
        new CollectionListRequestParams.Builder()
                .tags(tags)
                .useDeviceLocation(true)
                .build(),
        false
);

// Loads the next page after a successful load.
provider.loadNextPage();

// Refreshes from the api with the current params
provider.refresh();
import com.loopmediagroup.LoopMediaGroup
import com.loopmediagroup.domain.data.Collection
import com.loopmediagroup.domain.data.params.CollectionListRequestParams
import com.loopmediagroup.provider.DataProvider

val provider = LoopMediaGroup.client().collections()

// The data provider has 4 methods available to 
provider.onFetchSuccess { collections ->
    // Emits the first page of items on every successful fetch.
}

provider.onNextPageSuccess { collections ->
    // Emits a page of items on every successful next page fetch
}

provider.onDataChanged { collections ->
    // Emits the entire new list on every successful fetch or next page fetch
}

provider.onError {throwable -> 
    // Emits exceptions that occur during a fetch        
}

val params = CollectionListRequestParams.Builder()
            .useDeviceLocation(true)
            .tags(listOf("food", "drink"))
            .build()

// Load the collections for the given parameters
provider.fetch(
    params = params,
    forceRefresh = false // Change to true to force skipping the cache
)

// Loads the next page after a successful load.
provider.loadNextPage()

// Refreshes from the api with the current params
provider.refresh()

Showing Collections

Collection details and contents can be displayed as either a fragment or an activity.

Standard SDK CollectionFragment
CollectionFragment from GetintheLoop
CollectionActivity

Collections displayed with the CollectionActivity contain a collapsing header, collection details, and nested lists of businesses with their offers.

From an Activity
import com.loopmediagroup.ui.collections.CollectionActivity;
startActivity(CollectionActivity.createIntent(this, "collectionId"));
import com.loopmediagroup.ui.collections.CollectionActivity
startActivity(CollectionActivity.createIntent(this, "collectionId"))
From a Fragment
import com.loopmediagroup.ui.collections.CollectionActivity;
startActivity(CollectionActivity.createIntent(getContext(), "collectionId"));
import com.loopmediagroup.ui.collections.CollectionActivity
startActivity(CollectionActivity.createIntent(context!!, "collectionId"))
CollectionFragment

Collections displayed with the CollectionFragment contain only the nested lists of businesses with their offers.

From an Activity
import com.loopmediagroup.ui.collection.CollectionActivity;
getSupportFragmentManager().beginTransaction()
        .add(com.loopmediagroup.client.demo.R.id.container, CollectionFragment.newInstance("collectionId"))
        .commit();
import com.loopmediagroup.ui.collection.CollectionActivity
supportFragmentManager.beginTransaction()
    .add(R.id.container, CollectionFragment.newInstance("collectionId"))
    .commit()

Using Offers

Although showing Offer Details, Business Details, and Redeeming offers can be done through methods on the SDK, there is generally no need to manually handle these functions. Redemption views and UI flow are all handled automatically by the SDK.

Advanced Views

Offers Map

Location Map View

The Offers Map loads and displays locations and businesses in a GoogleMap. This LocationMapBrowserFragment handles clustering, loading and map view events.

Initialization

A LocationMapBrowserFragment can be initialized and added to any activity with the following code.

<fragment
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.loopmediagroup.ui.location.browser.LocationMapBrowserFragment"
/>
import com.loopmediagroup.ui.location.browser.LocationMapBrowserFragment;
getSupportFragmentManager().beginTransaction()
.add(R.id.container, LocationMapBrowserFragment.newInstance())
.commit();
import com.loopmediagroup.ui.location.browser.LocationMapBrowserFragment
supportFragmentManager.beginTransaction()
.add(R.id.container, LocationMapBrowserFragment.newInstance())
.commit();

When the map is first displayed it will try to get the current device location and centre on that location.

If a geographic Content Filter has been set, the map will show that area by default. If the users currently location can be determined, and is inside the content filter area, then it will be shown and the map will be centred on the user location.

If there is no location, or the location is outside of the current content filter, the filter area will be shown centred on the content filter area centre.

Offers are first loaded automatically based on the initial map location. Additional loading is manually triggered by a Search for offers button that shows on the map.

Optional Map Configuration

The initial location of the map can be manually set when the fragment is instantiated.

LocationMapBrowserFragment.newInstance(
  Options(
    defaultLocation = LatLng(55.585901, -105.750596),
    defaultZoom = 5f
  )
)

Customization

Map pin colours can be customized via the lmgColorBrand and lmgColorBrandVarient theme colors.

Offer searching is provided by the SearchFragment. This fragment must hosted by an activity that contains an android.support.v7.app.ActionBar in order to display the search widget in the app bar. The fragment will automatically add the search widget icons and text entry into the app bar menu.

The fragment handles all searching, text entry and filtering as required.

import com.loopmediagroup.ui.search.SearchFragment;

getSupportFragmentManager().beginTransaction()
    .add(R.id.container, SearchFragment.newInstance())
    .commit()
import com.loopmediagroup.ui.search.SearchFragment

supportFragmentManager.beginTransaction()
    .add(R.id.container, SearchFragment.newInstance())
    .commit()

Additional Features

Bookmarked Offers

Warning

Bookmarked offers are available ONLY to identified users. See Tracking Audience for more detail on identifying your users.

Content Area

Use ignoreContentArea to filter or not results depending of Content Area

Bookmarked Offers View

Enable Bookmarking

Bookmarking is disabled by default. To enable the bookmarking action, create a config.xml under main\res\values and add the following line.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="lmg_showBookmarkAction">true</bool>
</resources>

Showing Bookmarked Offers

supportFragmentManager.beginTransaction()
    .add(R.id.container, BusinessListFragment.newInstance(
        BusinessListFragment.Options.Builder()
            .contentType(BusinessListFragment.ContentType.Bookmarks)
            .build()
    )
    .commit()

Punch Card & Reward Offers

Warning

Rewards offers are available ONLY to identified users. See Tracking Audience for more detail on identifying your users.

Content Area

Use ignoreContentArea to filter or not results depending of Content Area

Showing In Progress Offers

supportFragmentManager.beginTransaction()
    .add(R.id.container, BusinessListFragment.newInstance(
        BusinessListFragment.Options.Builder()
            .contentType(BusinessListFragment.ContentType.InProgress)
            .build()
    )
    .commit()

Showing Earned Offers

supportFragmentManager.beginTransaction()
    .add(R.id.container, BusinessListFragment.newInstance(
        BusinessListFragment.Options.Builder()
            .contentType(BusinessListFragment.ContentType.Earned)
            .build()
    )
    .commit()

Sharing

The Loop Media SDK allows you to share links to offers and businesses available inside your integration. Links point to your Public Offer Viewer by default.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="lmg_enableShareAction">true</bool>
</resources>