Skip to content
This repository was archived by the owner on Jul 28, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ dependencies {
implementation "com.google.firebase:firebase-messaging:17.3.4"
...
}

apply plugin: 'com.google.gms.google-services'
```

#### b. Add your Batch key
Expand Down Expand Up @@ -115,23 +117,25 @@ BatchPush.registerForRemoteNotifications();

### Small push notification icon

It is recommended to provide a small notification icon in your `MainActivity.java`:

```java
// push_icon.png in your res/drawable-{dpi} folder
import com.batch.android.Batch;
import android.os.Bundle;
import android.graphics.Color;

...
For better results on Android 5.0 and higher, it is recommended to add a Small Icon and Notification Color.
An icon can be generated using Android Studio's asset generator: as it will be tinted and masked by the system, only the alpha channel matters and will define the shape displayed. It should be of 24x24dp size.
If your notifications shows up in the system statusbar in a white shape, this is what you need to configure.

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
This can be configured in the manifest as metadata in the application tag:

Batch.Push.setSmallIconResourceId(R.drawable.push_icon);
Batch.Push.setNotificationsColor(Color.parseColor(getResources().getString(R.color.pushIconBackground)));
}
```xml
<!-- Assuming there is a push_icon.png in your res/drawable-{dpi} folder -->

<manifest ...>
<application ...>
<meta-data
android:name="com.batch.android.push.smallicon"
android:resource="@drawable/push_icon" />

<!-- Notification color. ARGB but the alpha value can only be FF -->
<meta-data
android:name="com.batch.android.push.color"
android:value="#FF00FF00" />
```

### Mobile landings and in-app messaging
Expand Down
29 changes: 29 additions & 0 deletions android/src/main/java/tech/bam/RNBatchPush/RNBatchModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.app.Activity;
import android.content.res.Resources;
import android.location.Location;
import android.support.annotation.Nullable;
import android.util.Log;

Expand All @@ -12,6 +13,7 @@
import com.batch.android.BatchMessage;
import com.batch.android.BatchUserDataEditor;
import com.batch.android.Config;
import com.batch.android.json.JSONObject;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
Expand Down Expand Up @@ -287,6 +289,33 @@ public void userData_save(ReadableArray actions) {
editor.save();
}

@ReactMethod
public void userData_trackEvent(String name, String label, ReadableMap serializedEventData) {
Batch.User.trackEvent(name, label, RNUtils.convertSerializedEventDataToEventData(serializedEventData));
}

@ReactMethod
public void userData_trackTransaction(double amount, ReadableMap data) {
Batch.User.trackTransaction(amount, new JSONObject(data.toHashMap()));
}

@ReactMethod
public void userData_trackLocation(ReadableMap serializedLocation) {
Location nativeLocation = new Location("tech.bam.RNBatchPush");
nativeLocation.setLatitude(serializedLocation.getDouble("latitude"));
nativeLocation.setLongitude(serializedLocation.getDouble("longitude"));

if (serializedLocation.hasKey("precision")) {
nativeLocation.setAccuracy((float) serializedLocation.getDouble("precision"));
}

if (serializedLocation.hasKey("date")) {
nativeLocation.setTime((long) serializedLocation.getDouble("date"));
}

Batch.User.trackLocation(nativeLocation);
}

// EVENT LISTENERS

@Override
Expand Down
41 changes: 41 additions & 0 deletions android/src/main/java/tech/bam/RNBatchPush/RNUtils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package tech.bam.RNBatchPush;

import android.support.annotation.Nullable;
import android.util.Log;

import com.batch.android.BatchEventData;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
Expand Down Expand Up @@ -65,4 +69,41 @@ public static WritableArray convertArrayToWritableArray(Object[] input) {
}
return output;
}

@Nullable
public static BatchEventData convertSerializedEventDataToEventData(@Nullable ReadableMap serializedEventData) {
if (serializedEventData == null) {
return null;
}

BatchEventData batchEventData = new BatchEventData();
ReadableArray tags = serializedEventData.getArray("tags");

for (int i = 0; i < tags.size(); i++) {
batchEventData.addTag(tags.getString(i));
}

ReadableMap attributes = serializedEventData.getMap("attributes");
ReadableMapKeySetIterator iterator = attributes.keySetIterator();

while (iterator.hasNextKey()) {
String key = iterator.nextKey();
ReadableMap valueMap = attributes.getMap(key);

String type = valueMap.getString("type");
if ("string".equals(type)) {
batchEventData.put(key, valueMap.getString("value"));
} else if ("boolean".equals(type)) {
batchEventData.put(key, valueMap.getBoolean("value"));
} else if ("integer".equals(type)) {
batchEventData.put(key, valueMap.getDouble("value"));
} else if ("float".equals(type)) {
batchEventData.put(key, valueMap.getDouble("value"));
} else {
Log.e("RNBatchPush", "Invalid parameter : Unknown event_data.attributes type (" + type + ")");
}
}

return batchEventData;
}
}
160 changes: 160 additions & 0 deletions ios/RNBatch.m
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,166 @@ - (id)init {
[editor save];
}

// Event tracking

RCT_EXPORT_METHOD(userData_trackEvent:(NSString*)name label:(NSString*)label data:(NSDictionary*)serializedEventData)
{
BatchEventData *batchEventData = nil;

if ([serializedEventData isKindOfClass:[NSDictionary class]])
{
batchEventData = [BatchEventData new];

if (![serializedEventData isKindOfClass:[NSDictionary class]])
{
NSLog(@"RNBatch: Error while tracking event data: event data should be an object or null");
return;
}

NSArray<NSString*>* tags = serializedEventData[@"tags"];
NSDictionary<NSString*, NSDictionary*>* attributes = serializedEventData[@"attributes"];

if (![tags isKindOfClass:[NSArray class]])
{
NSLog(@"RNBatch: Error while tracking event data: event data.tags should be an array");
return;
}
if (![attributes isKindOfClass:[NSDictionary class]])
{
NSLog(@"RNBatch: Error while tracking event data: event data.attributes should be a dictionnary");
return;
}

for (NSString *tag in tags)
{
if (![tag isKindOfClass:[NSString class]])
{
NSLog(@"RNBatch: Error while tracking event data: event data.tag childrens should all be strings");
return;
}
[batchEventData addTag:tag];
}

for (NSString *key in attributes.allKeys)
{
NSDictionary *typedAttribute = attributes[key];
if (![typedAttribute isKindOfClass:[NSDictionary class]])
{
NSLog(@"RNBatch: Error while tracking event data: event data.attributes childrens should all be String/Dictionary tuples");
return;
}

NSString *type = typedAttribute[@"type"];
NSObject *value = typedAttribute[@"value"];

if ([@"string" isEqualToString:type]) {
if (![value isKindOfClass:[NSString class]])
{
NSLog(@"RNBatch: Error while tracking event data: event data.attributes: expected string value, got something else");
return;
}
[batchEventData putString:(NSString*)value forKey:key];
} else if ([@"boolean" isEqualToString:type]) {
if (![value isKindOfClass:[NSNumber class]])
{
NSLog(@"RNBatch: Error while tracking event data: event data.attributes: expected number (boolean) value, got something else");
return;
}
[batchEventData putBool:[(NSNumber*)value boolValue] forKey:key];
} else if ([@"integer" isEqualToString:type]) {
if (![value isKindOfClass:[NSNumber class]])
{
NSLog(@"RNBatch: Error while tracking event data: event data.attributes: expected number (integer) value, got something else");
return;
}
[batchEventData putInteger:[(NSNumber*)value integerValue] forKey:key];
} else if ([@"float" isEqualToString:type]) {
if (![value isKindOfClass:[NSNumber class]])
{
NSLog(@"RNBatch: Error while tracking event data: event data.attributes: expected number (float) value, got something else");
return;
}
[batchEventData putDouble:[(NSNumber*)value doubleValue] forKey:key];
} else {
NSLog(@"RNBatch: Error while tracking event data: Unknown event data.attributes type");
return;
}
}
}

[BatchUser trackEvent:name withLabel:label associatedData:batchEventData];
}

RCT_EXPORT_METHOD(userData_trackTransaction:(double)amount data:(NSDictionary*)rawData)
{
if (rawData && ![rawData isKindOfClass:[NSDictionary class]])
{
NSLog(@"RNBatch: trackTransaction data should be an dictionary or nil");
return;
}

[BatchUser trackTransactionWithAmount:amount data:rawData];
}

RCT_EXPORT_METHOD(userData_trackLocation:(NSDictionary*)serializedLocation)
{
if (![serializedLocation isKindOfClass:[NSDictionary class]] || [serializedLocation count]==0)
{
NSLog(@"RNBatch: Empty or null parameters for trackLocation");
return;
}

NSNumber *latitude = serializedLocation[@"latitude"];
NSNumber *longitude = serializedLocation[@"longitude"];
NSNumber *date = serializedLocation[@"date"]; // MS
NSNumber *precision = serializedLocation[@"precision"];

if (![latitude isKindOfClass:[NSNumber class]])
{
NSLog(@"RNBatch: latitude should be a string");
return;
}

if (![longitude isKindOfClass:[NSNumber class]])
{
NSLog(@"RNBatch: longitude should be a string");
return;
}

NSTimeInterval ts = 0;

if (date)
{
if ([date isKindOfClass:[NSNumber class]]) {
ts = [date doubleValue] / 1000.0;
} else {
NSLog(@"RNBatch: date should be an object or undefined");
return;
}
}

NSDate *parsedDate = ts != 0 ? [NSDate dateWithTimeIntervalSince1970:ts] : [NSDate date];

NSInteger parsedPrecision = 0;
if (precision)
{
if ([precision isKindOfClass:[NSNumber class]]) {
parsedPrecision = [precision integerValue];
} else {
NSLog(@"RNBatch: precision should be an object or undefined");
return;
}
}

[BatchUser trackLocation:[[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake([latitude doubleValue], [longitude doubleValue])
altitude:0
horizontalAccuracy:parsedPrecision
verticalAccuracy:-1
course:0
speed:0
timestamp:parsedDate]];
}

// Inbox module

RCT_EXPORT_METHOD(inbox_fetchNotifications:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"doc:deploy": "yarn doc:generate && yarn doc:publish"
},
"peerDependencies": {
"react-native": "*"
"react-native": "*",
"@types/react-native": "*"
},
"dependencies": {
"jest": "^24.1.0"
Expand Down
13 changes: 8 additions & 5 deletions readme/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
- Create a `mkdir @bam.tech`
- Go into the folder `cd @bam.tech`
- Add `local-modules` to your _.gitignore_
- Clone the batch-push repository `git clone git@github.com:bamlab/react-native-batch-push.git`
- Clone the react-native-batch-push repository `git clone git@github.com:bamlab/react-native-batch-push.git`
- Rename `react-native-batch-push` to `react-native-batch`
- Checkout the required branch or a new branch
- Run `yarn` to install dependencies

## 3. Run build for development

- Open `@bam.tech/react-native-batch` within VSCode
- Open `local-modules/@bam.tech/react-native-batch` within VSCode
- Run the `Task run build task >> tsc: watch`

## 4. Install the plugin on Android
Expand All @@ -30,7 +31,7 @@
// android/settings.gradle

include ':@bam.tech_react-native-batch'
project(':@bam.tech_react-native-batch').projectDir = new File(rootProject.projectDir, '../local-modules/@bam.tech/react-native-batch-push/android')
project(':@bam.tech_react-native-batch').projectDir = new File(rootProject.projectDir, '../local-modules/@bam.tech/react-native-batch/android')
```

```groovy
Expand Down Expand Up @@ -82,6 +83,8 @@ dependencies {
implementation "com.google.firebase:firebase-messaging:17.3.4"
...
}

apply plugin: 'com.google.gms.google-services'
```

### c. Add your Batch key
Expand All @@ -104,7 +107,7 @@ defaultConfig {
- Open the `/android` folder with _Android studio_
- Connect your phone to your computer
- Run `adb reverse tcp:8081 tcp:8081`
- Tun `yarn start`
- Run `yarn start`
- Run the project in debug mode

## 5. Install the plugin on iOS
Expand All @@ -121,7 +124,7 @@ defaultConfig {
- Open `/ios/<ProjectName>.xcworkspace`
- Select _<ProjectName>_ in XCode
- Right click on _Librairies_ > _Add files to <Project Name>_
- Select `/local-modules/@bam.tech/react-native-batch-push/ios/RNBatchPush.xcodeproj`
- Select `/local-modules/@bam.tech/react-native-batch/ios/RNBatchPush.xcodeproj`
- In the project window select
- _Build Phases_
- _Link Binary With Librairies_
Expand Down
1 change: 1 addition & 0 deletions src/Batch.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NativeModules } from 'react-native';
export * from './BatchEventData';
export * from './BatchInbox';
export * from './BatchMessaging';
export * from './BatchPush';
Expand Down
Loading