Skip to content

Commit

Permalink
Merge pull request #1 from saasquatch/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
slisaasquatch authored Feb 17, 2021
2 parents 18d05cb + c18850d commit de6dd5c
Show file tree
Hide file tree
Showing 19 changed files with 901 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ captures/

# IntelliJ
*.iml
.idea
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
Expand Down
140 changes: 140 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,142 @@
# SquatchAndroid

[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![](https://jitpack.io/v/saasquatch/squatch-android.svg)](https://jitpack.io/#saasquatch/squatch-android)

Helper library for loading SaaSquatch widgets in Android WebView

## Adding SaaSquatch Java SDK to your project

SaaSquatch Java SDK is hosted on JitPack.

Add JitPack repository:

```gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
```

Add the dependency:

```gradle
dependencies {
implementation 'com.github.saasquatch:squatch-android:0.0.1'
}
```

For more information and other built tools, [please refer to the JitPack page](https://jitpack.io/#saasquatch/squatch-android).

This library relies on [SaaSquatch Java SDK](https://github.com/saasquatch/saasquatch-java-sdk), which has transitive dependencies including [RxJava 3](https://github.com/ReactiveX/RxJava), [Gson](https://github.com/google/gson), and [Apache HttpClient 5](https://hc.apache.org/httpcomponents-client-5.0.x/index.html). This library also has [RxAndroid](https://github.com/ReactiveX/RxAndroid) as a transitive dependency. **It is recommended that you explicitly import the transitive dependencies if you intend to use them**, since we may upgrade or switch to other libraries in the future. You do NOT, however, need to explicitly include [SaaSquatch Java SDK](https://github.com/saasquatch/saasquatch-java-sdk), as it is exposed in public interfaces in this library.

## Using the SDK

This library is a wrapper of [SaaSquatch Java SDK](https://github.com/saasquatch/saasquatch-java-sdk) with Android specific features, specifically loading widgets into a WebView. In fact, The `SquatchAndroid` interface has a method called `getSaaSquatchClient()`, which you can use to retrieve the underlying `SaaSquatchClient`. Depending on your use case, [SaaSquatch Java SDK](https://github.com/saasquatch/saasquatch-java-sdk) may be what you need.

The entry point of the SDK is `SquatchAndroid`. To create a `SquatchAndroid` for your tenant with default options, use:

```java
SquatchAndroid.createForTenant("yourTenantAlias");
```

It is recommended that you keep a singleton `SquatchAndroid` for all your requests instead of creating a new `SquatchAndroid` for every request. `SquatchAndroid` implements `Closeable`, and it's a good idea to call `close()` to release resources when you are done with it.

`SquatchAndroid` returns [Reactive Streams](https://www.reactive-streams.org/) interfaces. Assuming you are using RxJava, then a typical API call made with this SDK would look something like this:

```java
Flowable.fromPublisher(squatchAndroid.widgetUpsert(
WidgetUpsertInput.newBuilder()
.setUserInputWithUserJwt(userJwt)
.setWidgetType(WidgetType.ofProgramWidget("referral-program", "referrerWidget"))
.build(),
null, AndroidRenderWidgetOptions.ofWebView(webView)))
.onErrorComplete() // or provide your own error handling
.subscribe();
```

In the code above, a widget upsert is performed asynchronously with the given `userJwt`, and the resulting widget is loaded into the given `webView` with the Android main thread.

## More Code Samples

Widget upsert while setting a user's `customFields`

```java
final Map<String, Object> userInput = new HashMap<>();
userInput.put("id", "a");
userInput.put("accountId", "a");
final Map<String, Object> customFields = new HashMap<>();
customFields.put("birthday", "--12-25");
userInput.put("customFields", customFields);
Flowable.fromPublisher(squatchAndroid.widgetUpsert(
WidgetUpsertInput.newBuilder()
.setUserInput(userInput)
.build(),
RequestOptions.newBuilder()
.setAuthMethod(AuthMethod.ofJwt(userJwt))
.build(),
AndroidRenderWidgetOptions.ofWebView(webView)))
.onErrorComplete() // or provide your own error handling
.subscribe();
```

Rendering a widget for a user

```java
Flowable.fromPublisher(squatchAndroid.renderWidget(
RenderWidgetInput.newBuilder()
.setUserWithUserJwt(userJwt)
.setWidgetType(WidgetType.ofProgramWidget("referral-program", "referrerWidget"))
.build(),
null, AndroidRenderWidgetOptions.ofWebView(webView)))
.onErrorComplete() // or provide your own error handling
.subscribe();
```

Logging an event for a user (using the underlying `SaaSquatchClient`)

```java
final Map<String, Object> fields = new HashMap<>();
fields.put("currency", "CAD");
Flowable.fromPublisher(squatchAndroid.getSaaSquatchClient().logUserEvent(
UserEventInput.newBuilder()
.setAccountId("a")
.setUserId("a")
.addEvents(UserEventDataInput.newBuilder()
.setKey("purchase")
.setFields(fields)
.build())
.build(),
RequestOptions.newBuilder()
.setAuthMethod(AuthMethod.ofJwt(userJwt))
.build()))
// This is necessary so the main thread does not start the IO operation
.subscribeOn(Schedulers.io())
.onErrorComplete() // or provide your own error handling
.subscribe();
```

## License

Unless explicitly stated otherwise all files in this repository are licensed under the Apache
License 2.0.

License boilerplate:

```
Copyright 2021 ReferralSaaSquatch.com Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
1 change: 1 addition & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
37 changes: 37 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
apply plugin: 'com.android.library'

android {
compileSdkVersion 30
buildToolsVersion "30.0.3"

defaultConfig {
minSdkVersion 19
targetSdkVersion 30
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
api 'com.github.saasquatch:saasquatch-java-sdk:0.0.1'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
}
21 changes: 21 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.saasquatch.android;

import static org.junit.Assert.assertEquals;

import android.content.Context;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {

@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.saasquatch.android", appContext.getPackageName());
}

}
8 changes: 8 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.saasquatch.android">

<application
android:allowBackup="true"
android:supportsRtl="true"/>

</manifest>
60 changes: 60 additions & 0 deletions app/src/main/java/com/saasquatch/android/SquatchAndroid.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.saasquatch.android;

import android.webkit.WebView;
import com.saasquatch.android.input.AndroidRenderWidgetOptions;
import com.saasquatch.sdk.RequestOptions;
import com.saasquatch.sdk.SaaSquatchClient;
import com.saasquatch.sdk.input.RenderWidgetInput;
import com.saasquatch.sdk.input.WidgetUpsertInput;
import com.saasquatch.sdk.output.JsonObjectApiResponse;
import com.saasquatch.sdk.output.TextApiResponse;
import java.io.Closeable;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.reactivestreams.Publisher;

/**
* Wrapper for {@link SaaSquatchClient} that contains Android specific features.
*
* @author sli
*/
public interface SquatchAndroid extends Closeable {

/**
* @return A {@link SquatchAndroid} instance that wraps the given {@link SaaSquatchClient}.
*/
static SquatchAndroid create(@Nonnull SaaSquatchClient saasquatchClient) {
return new SquatchAndroidImpl(Objects.requireNonNull(saasquatchClient));
}

/**
* @return A {@link SquatchAndroid} instance using the given tenant alias with default options.
*/
static SquatchAndroid createForTenant(@Nonnull String tenantAlias) {
return create(SaaSquatchClient.createForTenant(tenantAlias));
}

/**
* @return The underlying {@link SaaSquatchClient}.
*/
@Nonnull
SaaSquatchClient getSaaSquatchClient();

/**
* Wrapper for {@link SaaSquatchClient#renderWidget(RenderWidgetInput, RequestOptions)} that loads
* the result widget HTML into a {@link WebView}.
*/
Publisher<TextApiResponse> renderWidget(@Nonnull RenderWidgetInput renderWidgetInput,
@Nullable RequestOptions requestOptions,
@Nonnull AndroidRenderWidgetOptions androidRenderWidgetOptions);

/**
* Wrapper for {@link SaaSquatchClient#widgetUpsert(WidgetUpsertInput, RequestOptions)} that loads
* the result widget HTML into a {@link WebView}.
*/
Publisher<JsonObjectApiResponse> widgetUpsert(@Nonnull WidgetUpsertInput widgetUpsertInput,
@Nullable RequestOptions requestOptions,
@Nonnull AndroidRenderWidgetOptions androidRenderWidgetOptions);

}
Loading

0 comments on commit de6dd5c

Please sign in to comment.