The payload feature in the beacon management frontend enables you to implement virtually unlimited use-case posibilities with beacons. We will highlight one use case in this post:
We would like to show a notification when the application is in the background with a message. Upon tapping the notification, the app should be opened and a new Activity (screen) should be shown with a QR code and some text. This can be used to deliver a coupon code when entering a shop.
I´ve setup my campaign as an in-app campaign with some custom payload. The payload contains the actual content that will be rendered when you tap the notification, or when you´re using the app:
{
"title": "Save 17%",
"couponCode": "3A2601DD-C508-4AB5-9FD4-201B3A5361E3",
"message": "Show this QR code at the cashier."
}
The Subject and Body will be used to construct the Notification. I use the URL coupon://redeem to identify this use-case.
Here is how it looks when the app is in the foreground and background:
The most complicated part propably is the notification:
case MESSAGE_IN_APP:
InAppAction inAppAction = (InAppAction) action;
if (inAppAction.getUri().getScheme().equalsIgnoreCase("coupon") && inAppAction.getUri().getHost().equalsIgnoreCase("redeem")) {
try {
JSONObject p = action.getPayloadJSONObject();
PendingIntent pendingIntent =
TaskStackBuilder.create(context)
.addNextIntentWithParentStack(new Intent(context, ShowcaseFragmentActivity.class))
.addNextIntentWithParentStack(CouponActivity.getIntent(context, p.getString("couponCode"), p.getString("title"), p.getString("message") ))
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setContentTitle(inAppAction.getSubject())
.setContentText(inAppAction.getBody())
.setAutoCancel(true)
.setShowWhen(true);
if (icon != null){
builder.setLargeIcon(icon);
} else {
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher));
}
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(action.getUuid().hashCode(), builder.build());
return;
} catch (JSONException e) {
e.printStackTrace();
}
}
Here is the Activity:
public class CouponActivity extends Activity {
public static final String EXTRA_BARCODE = "com.sensorberg.android.showcaseutils.Activities.CouponActivity.barcode";
public static final String EXTRA_TITLE = "com.sensorberg.android.showcaseutils.Activities.CouponActivity.title";
public static final String EXTRA_MESSAGE = "com.sensorberg.android.showcaseutils.Activities.CouponActivity.message";
private String barcode;
private String title;
private String message;
private TextView titleTextView;
private TextView messageTextView;
private ImageView barcodeTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.coupon_activity);
titleTextView = (TextView) findViewById(R.id.title_textView);
messageTextView = (TextView) findViewById(R.id.message_textView);
barcodeTextView = (ImageView) findViewById(R.id.barcode_imageView);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
barcode = intent.getStringExtra(EXTRA_BARCODE);
title = intent.getStringExtra(EXTRA_TITLE);
message = intent.getStringExtra(EXTRA_MESSAGE);
updateViews();
}
@Override
protected void onResume() {
super.onResume();
Intent intent = getIntent();
barcode = intent.getStringExtra(EXTRA_BARCODE);
title = intent.getStringExtra(EXTRA_TITLE);
message = intent.getStringExtra(EXTRA_MESSAGE);
updateViews();
getActionBar().setDisplayHomeAsUpEnabled(true);
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
this.finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void updateViews() {
if (barcode != null) {
QRCodeWriter writer = new QRCodeWriter();
try {
Map<EncodeHintType, Object> options = new HashMap<>();
options.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
BitMatrix bitMatrix = writer.encode(barcode, BarcodeFormat.QR_CODE, 768, 768, options);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
bmp.setPixel(x, y, bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE);
}
}
barcodeTextView.setImageBitmap(bmp);
} catch (WriterException e) {
e.printStackTrace();
}
} else{
barcodeTextView.setImageBitmap(null);
}
titleTextView.setText(title);
messageTextView.setText(message);
}
public static Intent getIntent(Context context, String couponCode, String title, String message) {
Intent intent = new Intent(context, CouponActivity.class);
intent.putExtra(EXTRA_BARCODE, couponCode);
intent.putExtra(EXTRA_TITLE, title);
intent.putExtra(EXTRA_MESSAGE, message);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return intent;
}
}
And the layout for this Activity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"
android:weightSum="1">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
tools:text="Redeem this coupon"
android:id="@+id/title_textView" />
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/barcode_imageView"
android:layout_gravity="center_horizontal"
android:layout_weight="0.55" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:text="30€"
android:id="@+id/message_textView"
android:layout_gravity="center_horizontal" />
</LinearLayout>