Skip to content
This repository has been archived by the owner on Sep 3, 2021. It is now read-only.

Commit

Permalink
Merge branch 'release/2.2.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
catt-stefano committed Oct 4, 2017
2 parents 4bb5319 + c4c8343 commit 54a353f
Show file tree
Hide file tree
Showing 12 changed files with 269 additions and 63 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ To start using the SDK, include this in your app *build.gradle*

```java
dependencies {
compile 'it.near.sdk:nearit:2.2.5'
compile 'it.near.sdk:nearit:2.2.6'
}
```

Expand Down
80 changes: 38 additions & 42 deletions docs/in-app-content.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
# Handle In-app Content

NearIT takes care of delivering content at the right time, you will just need to handle content presentation.

## Foreground vs Background

Recipes either deliver content in background or in foreground but not both. Check this table to see how you will be notified.
After an user **taps on a notification**, you will receive content through an intent to your app launcher activity.
If you want to just check if the intent carries NearIT content use this method:
```java
boolean hasNearItContent = NearUtils.carriesNearItContent(intent);
```
To extract the content from an intent use the utility method:
```java
NearUtils.parseCoreContents(intent, coreContentListener);
```

| Type of trigger | Delivery |
|----------------------------------|--------------------|
| Push (immediate or scheduled) | Background intent |
| Enter and Exit on geofences | Background intent |
| Enter and Exit on beacon regions | Background intent |
| Enter in a specific beacon range | Proximity listener (foreground) |

## Foreground Content
If you want to customize the behavior of background notification see [this page](custom-bkg-notification.md).

To receive foreground content (e.g. ranging recipes) set a proximity listener with the method
## Beacon Interaction Content
Beacon interaction (beacon ranging) is a peculiar trigger that works only when your app is in the foreground.<br>
To receive this kind of content set a **proximity listener** with the method:
```java
{
...
Expand All @@ -32,33 +32,31 @@ public void foregroundEvent(Parcelable content, TrackingInfo trackingInfo) {
NearUtils.parseCoreContents(content, trackingInfo, coreContentListener);
}
```
**Warning:** For this kind of content you will need to write the code for **Trackings** and to eventually show an **In-app notification**.

## Background Content

Once you have added at least one of the receivers for any background working trigger you will be delivered the actual content through an intent that will call your app launcher activity and carry some extras.
To extract the content from an intent use the utility method:
```java
NearUtils.parseCoreContents(intent, coreContentListener);
```
If you want to just check if the intent carries NearIT content, without having to eventually handle the actual content, use this method
```java
boolean hasNearContent = NearUtils.carriesNearItContent(intent);
```

If you want to customize the behavior of background notification see [this page](custom-bkg-notification.md)

## Trackings
NearIT allows to track user engagement events on recipes. Any recipe has at least two default events:

- **Notified**: the user *received* a notification
- **Engaged**: the user *tapped* on the notification

Usually the SDK tracks those events automatically, but if you write custom code to show notification or content (i.e. to receive Beacon interaction content) please make sure that at least the "**notified**" event is tracked.
<br>**Warning:** Failing in tracking this event cause some NearIT features to not work.

NearIT analytics on recipes are built from trackings describing the status of user engagement with a recipe. The two recipe states are "Notified" and "Engaged" to represent a recipe delivered to the user and a recipe that the user responded to.
Built-in background recipes track themselves as notified and engaged.

Foreground recipes don't have automatic tracking. You need to track both the "Notified" and the "Engaged" statuses when it's the best appropriate for you scenario.
You can track **default or custom events** using the "**sendTracking**" method:

```java
// notified - notification received
NearItManager.getInstance().sendTracking(trackingInfo, Recipe.NOTIFIED_STATUS);
// and

// engaged - notification tapped
NearItManager.getInstance().sendTracking(trackingInfo, Recipe.ENGAGED_STATUS);

// custom recipe event
NearItManager.getInstance().sendTracking(trackingInfo, "my awesome custom event");
```
The recipe cooldown feature uses tracking calls to hook its functionality, so failing to properly track user interactions will result in the cooldown not being applied.

## Content Objects

Expand All @@ -70,11 +68,9 @@ Here are the public fields for every other one:
- `message` returns the notification message (it is the same as `notificationMessage`)

- `Content` for the notification with content, with the following getters and fields:
- `title` returns the content title
- `contentString` returns the text content
- `video_link` returns the video link string
- `getImages_links()` returns a list of *ImageSet* object containing the source links for the images
- `upload` returns an Upload object containing a link to a file uploaded on NearIT if any
- `audio` returns an Audio object containing a link to an audio file uploaded on NearIT if any
- `getImageLink()` returns an *ImageSet* object containing the links for the image

- `Feedback` with the following getters and fields:
- `question` returns the feedback request string
Expand Down Expand Up @@ -111,16 +107,16 @@ We handle the complete emission and redemption coupon cycle in our platform, and
You can ask the library to fetch the list of all the user current coupons with the method:
```java
NearItManager.getInstance().getCoupons(new CouponListener() {
@Override
public void onCouponsDownloaded(List<Coupon> list) {
@Override
public void onCouponsDownloaded(List<Coupon> list) {

}
}

@Override
public void onCouponDownloadError(String s) {
@Override
public void onCouponDownloadError(String s) {

}
});
}
});
```
The method will also return already redeemed coupons so you get to decide to filter them if necessary.

Expand Down
2 changes: 1 addition & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ To start using the SDK, include this in your app *build.gradle*

```java
dependencies {
compile 'it.near.sdk:nearit:2.2.5'
compile 'it.near.sdk:nearit:2.2.6'
}
```

Expand Down
14 changes: 7 additions & 7 deletions docs/location-based-notifications.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Location Based Notifications

The SDK automatically includes the permission for location access in its manifest (necessary for beacon and geofence monitoring). When targeting API level 23+, please ask for and verify the presence of ACCESS_FINE_LOCATION permissions at runtime.
If you are also manually including ACCESS_COARSE_LOCATION in your manifest please be sure to specify a `maxSdkVersion` of _22_.
```java
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"
android:maxSdkVersion="22"/>
```

When you want to start the radar for **geofences and beacons** call this method:

```java
Expand All @@ -8,13 +15,6 @@ NearItManager.getInstance().startRadar()
// to stop the radar call the method nearItManager.stopRadar()
```

The SDK automatically includes the permission for location access in its manifest (necessary for beacon and geofence monitoring). When targeting API level 23+, please ask for and verify the presence of ACCESS_FINE_LOCATION permissions at runtime.
If you are also manually including ACCESS_COARSE_LOCATION in your manifest please be sure to specify a `maxSdkVersion` of _22_.
```java
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"
android:maxSdkVersion="22"/>
```

The SDK creates a system notification for every background recipe. On the notification tap, your launcher activity will start.
To learn how to deal with in-app content once the user taps on the notification, see this [section](in-app-content.md).

Expand Down
16 changes: 8 additions & 8 deletions docs/user-profiling.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ userDataMap.put("name", "John");
userDataMap.put("age", "23"); // set everything as String
userDataMap.put("saw_tutorial", "true") // even booleans, the server has all the right logic
NearItManager.getInstance().setBatchUserData(userDataMap, new UserDataNotifier() {
@Override
public void onDataCreated() {
// data was set/created
}
@Override
public void onDataCreated() {
// data was set/created
}

@Override
public void onDataNotSetError(String error) {
@Override
public void onDataNotSetError(String error) {

}
});
}
});
```
If you try to set user data before creating a profile the error callback will be called.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import it.near.sdk.reactions.contentplugin.model.Audio;
import it.near.sdk.reactions.contentplugin.model.Content;
import it.near.sdk.reactions.contentplugin.model.ContentLink;
import it.near.sdk.reactions.contentplugin.model.ImageSet;
import it.near.sdk.reactions.contentplugin.model.Upload;

Expand All @@ -35,6 +36,7 @@ public void contentIsParcelable() {
content.video_link = "video_link";
content.setId("content_id");
content.updated_at = "updated@whatever";
content.title = "title";
Audio audio = new Audio();
HashMap<String, Object> audioMap = Maps.newHashMap();
audioMap.put("url", "a.mp3");
Expand All @@ -46,6 +48,8 @@ public void contentIsParcelable() {
upload.uploadMap = uploadMap;
content.upload = upload;
content.notificationMessage = "fejrf";
ContentLink contentLink = new ContentLink("a", "b");
content.setCta(contentLink);

Parcel parcel = Parcel.obtain();
content.writeToParcel(parcel, 0);
Expand All @@ -59,6 +63,9 @@ public void contentIsParcelable() {
assertThat(content.audio.audioMap, is(actual.audio.audioMap));
assertThat(content.upload.uploadMap, is(actual.upload.uploadMap));
assertThat(content.notificationMessage, is(actual.notificationMessage));
assertThat(content.title, is(actual.title));
assertThat(content.getCta(), is(actual.getCta()));
assertThat(content.getImageLink(), is(actual.getImageLink()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package it.near.sdk.reactions.contentplugin.model;

import android.os.Parcel;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static junit.framework.Assert.assertNotNull;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

@RunWith(AndroidJUnit4.class)
public class ContentLinkTest {

@Test
public void isParcelable() {
ContentLink contentLink = new ContentLink("a", "b");
Parcel parcel = Parcel.obtain();
contentLink.writeToParcel(parcel, 0);
parcel.setDataPosition(0);

ContentLink actual = ContentLink.CREATOR.createFromParcel(parcel);
assertNotNull(actual);
assertThat(actual.label, is(contentLink.label));
assertThat(actual.url, is(contentLink.url));
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@
import it.near.sdk.reactions.CoreReaction;
import it.near.sdk.reactions.contentplugin.model.Audio;
import it.near.sdk.reactions.contentplugin.model.Content;
import it.near.sdk.reactions.contentplugin.model.ContentLink;
import it.near.sdk.reactions.contentplugin.model.Image;
import it.near.sdk.reactions.contentplugin.model.ImageSet;
import it.near.sdk.reactions.contentplugin.model.Upload;
import it.near.sdk.recipes.NearNotifier;

import static it.near.sdk.reactions.contentplugin.model.ContentLink.CTA_LABEL_KEY;
import static it.near.sdk.reactions.contentplugin.model.ContentLink.CTA_URL_KEY;
import static it.near.sdk.utils.NearUtils.safe;

public class ContentReaction extends CoreReaction<Content> {
// ---------- content notification plugin ----------
public static final String PLUGIN_NAME = "content-notification";
Expand All @@ -34,6 +39,7 @@ public class ContentReaction extends CoreReaction<Content> {
public static final String RES_AUDIOS = "audios";
public static final String RES_UPLOADS = "uploads";


ContentReaction(Cacher<Content> cacher, NearAsyncHttpClient httpClient, NearNotifier nearNotifier, Type cacheType) {
super(cacher, httpClient, nearNotifier, Content.class, cacheType);
}
Expand Down Expand Up @@ -76,14 +82,27 @@ protected void injectRecipeId(Content element, String recipeId) {
protected void normalizeElement(Content element) {
List<Image> images = element.images;
List<ImageSet> imageSets = new ArrayList<>();
for (Image image : images) {
for (Image image : safe(images)) {
try {
imageSets.add(image.toImageSet());
} catch (Image.MissingImageException ignored) {

}
}
element.setImages_links(imageSets);

try {
if (element.link != null &&
element.link.containsKey(CTA_LABEL_KEY) &&
element.link.containsKey(CTA_URL_KEY)) {
String label = (String) element.link.get(CTA_LABEL_KEY);
String url = (String) element.link.get(CTA_URL_KEY);

ContentLink contentLink = new ContentLink(label, url);
element.setCta(contentLink);
}
} catch (Throwable ignored) {}

}

@Override
Expand Down
Loading

0 comments on commit 54a353f

Please sign in to comment.