Skip to content

Commit

Permalink
feat: support init SDK with custom configuration (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhu-xiaowei authored Mar 22, 2024
1 parent eff7fe2 commit 4dbefaf
Show file tree
Hide file tree
Showing 23 changed files with 566 additions and 487 deletions.
44 changes: 36 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Clickstream Android SDK supports Android 4.1 (API level 16) and later.

## Integrate SDK

**1.Include SDK**
### 1. Include SDK

Add the following dependency to your `app` module's `build.gradle` file.

Expand All @@ -28,7 +28,7 @@ dependencies {

then sync your project, if you have problem to build your app, please check [troubleshooting](#Troubleshooting)

**2.Parameter configuration**
### 2. Parameter configuration

Find the res directory under your `project/app/src/main` , and manually create a raw folder in the res directory.

Expand All @@ -41,7 +41,7 @@ Download your `amplifyconfiguration.json` file from your clickstream control pla
"analytics": {
"plugins": {
"awsClickstreamPlugin": {
"appId": "appId",
"appId": "your appId",
"endpoint": "https://example.com/collect",
"isCompressEvents": true,
"autoFlushEventsInterval": 10000,
Expand All @@ -60,16 +60,16 @@ Your `appId` and `endpoint` are already set up in it, here's an explanation of e
- **autoFlushEventsInterval**: event sending interval, the default is `10s`
- **isTrackAppExceptionEvents**: whether auto track exception event in app, default is `false`

**3.Initialize the SDK**
### 3. Initialize the SDK

It is recommended that you initialize the SDK in the Application `onCreate()` method. Please note that the initialization code needs to run in the main thread.
It is recommended that you initialize the SDK in your application's `onCreate()` method. Please note that the initialization code needs to run in the main thread.

#### 3.1 Initialize the SDK with default configuration
```java
import software.aws.solution.clickstream.ClickstreamAnalytics;

public void onCreate() {
super.onCreate();

try{
ClickstreamAnalytics.init(getApplicationContext());
Log.i("MyApp", "Initialized ClickstreamAnalytics");
Expand All @@ -78,10 +78,36 @@ public void onCreate() {
}
}
```
#### 3.2 Initialize the SDK with global attributes and custom configuration
```java
import software.aws.solution.clickstream.ClickstreamAnalytics;

public void onCreate() {
super.onCreate();
try{
ClickstreamAttribute globalAttributes = ClickstreamAttribute.builder()
.add("_traffic_source_name", "Summer promotion")
.add("_traffic_source_medium", "Search engine")
.build();
ClickstreamConfiguration configuration = new ClickstreamConfiguration()
.withAppId("your appId")
.withEndpoint("http://example.com/collect")
.withLogEvents(true)
.withInitialGlobalAttributes(globalAttributes);
ClickstreamAnalytics.init(getApplicationContext(), configuration);
Log.i("MyApp", "Initialized ClickstreamAnalytics");
} catch (AmplifyException error){
Log.e("MyApp", "Could not initialize ClickstreamAnalytics", error);
}
}
```
By default, we will use the configurations in `amplifyconfiguration.json` file. If you add a custom configuration, the added configuration items will override the default values.

**4.Config the SDK**
You can also add all the configuration parameters you need in the `init` method without using the `amplifyconfiguration.json` file.

After initial the SDK we can use the following code to custom configure it.
### 4. Update Configuration

After initial the SDK we can use the following code to up configure it.

```java
import software.aws.solution.clickstream.ClickstreamAnalytics;
Expand Down Expand Up @@ -146,6 +172,8 @@ ClickstreamAnalytics.addGlobalAttributes(globalAttribute);
ClickstreamAnalytics.deleteGlobalAttributes("level");
```

It is recommended to set global attributes when initializing the SDK, global attributes will be included in all events that occur after it is set.

#### Login and logout

```java
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ ext {
okhttp: 'com.squareup.okhttp3:okhttp:4.9.1',
junit: 'junit:junit:4.13.2',
mockito: 'org.mockito:mockito-core:4.11.0',
mockitoinline: 'org.mockito:mockito-inline:4.11.0',
moco: 'com.github.dreamhead:moco-core:1.4.0',
robolectric: 'org.robolectric:robolectric:4.9.2',
]
Expand Down
1 change: 1 addition & 0 deletions clickstream/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ dependencies {

testImplementation dependency.junit
testImplementation dependency.mockito
testImplementation dependency.mockitoinline
testImplementation dependency.robolectric
testImplementation dependency.androidx.test
testImplementation dependency.moco
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@
import software.aws.solution.clickstream.client.Event;

import java.util.Map;
import java.util.Objects;

/**
* The plugin implementation for Clickstream in Analytics category.
*/
public final class AWSClickstreamPlugin extends AnalyticsPlugin<Object> {

static final String PLUGIN_KEY = "awsClickstreamPlugin";
private static final Log LOG = LogFactory.getLog(AWSClickstreamPlugin.class);
private final Context context;
private AnalyticsClient analyticsClient;
Expand All @@ -63,12 +64,10 @@ public AWSClickstreamPlugin(final Context context) {
@Override
public void identifyUser(@NonNull String userId, @Nullable UserProfile profile) {
if (userId.equals(Event.ReservedAttribute.USER_ID_UNSET)) {
if (profile instanceof ClickstreamUserAttribute) {
for (Map.Entry<String, AnalyticsPropertyBehavior<?>> entry :
((ClickstreamUserAttribute) profile).getUserAttributes()) {
AnalyticsPropertyBehavior<?> property = entry.getValue();
analyticsClient.addUserAttribute(entry.getKey(), property.getValue());
}
for (Map.Entry<String, AnalyticsPropertyBehavior<?>> entry :
((ClickstreamUserAttribute) Objects.requireNonNull(profile)).getUserAttributes()) {
AnalyticsPropertyBehavior<?> property = entry.getValue();
analyticsClient.addUserAttribute(entry.getKey(), property.getValue());
}
} else {
analyticsClient.updateUserId(userId);
Expand Down Expand Up @@ -114,11 +113,9 @@ public void recordEvent(@NonNull AnalyticsEventBehavior analyticsEvent) {
analyticsClient.createEvent(event.getName());

if (clickstreamEvent != null) {
if (analyticsEvent.getProperties() != null) {
for (Map.Entry<String, AnalyticsPropertyBehavior<?>> entry : analyticsEvent.getProperties()) {
AnalyticsPropertyBehavior<?> property = entry.getValue();
clickstreamEvent.addAttribute(entry.getKey(), property.getValue());
}
for (Map.Entry<String, AnalyticsPropertyBehavior<?>> entry : analyticsEvent.getProperties()) {
AnalyticsPropertyBehavior<?> property = entry.getValue();
clickstreamEvent.addAttribute(entry.getKey(), property.getValue());
}
clickstreamEvent.addItems(event.getItems());
recordAnalyticsEvent(clickstreamEvent);
Expand Down Expand Up @@ -156,7 +153,7 @@ public void flushEvents() {
@NonNull
@Override
public String getPluginKey() {
return "awsClickstreamPlugin";
return PLUGIN_KEY;
}

@Override
Expand All @@ -171,31 +168,46 @@ public void configure(
getPluginKey() + " under the analytics category."
);
}

AWSClickstreamPluginConfiguration.Builder configurationBuilder =
AWSClickstreamPluginConfiguration.builder();

ClickstreamConfiguration configuration = ClickstreamConfiguration.getDefaultConfiguration();
// Read all the data from the configuration object to be used for record event
try {
configurationBuilder.withAppId(pluginConfiguration
.getString(ConfigurationKey.APP_ID.getConfigurationKey()));
configuration.withAppId(pluginConfiguration.getString(ConfigurationKey.APP_ID));
configuration.withEndpoint(pluginConfiguration
.getString(ConfigurationKey.ENDPOINT));

configurationBuilder.withEndpoint(pluginConfiguration
.getString(ConfigurationKey.ENDPOINT.getConfigurationKey()));

if (pluginConfiguration.has(ConfigurationKey.SEND_EVENTS_INTERVAL.getConfigurationKey())) {
configurationBuilder.withSendEventsInterval(pluginConfiguration
.getLong(ConfigurationKey.SEND_EVENTS_INTERVAL.getConfigurationKey()));
if (pluginConfiguration.has(ConfigurationKey.SEND_EVENTS_INTERVAL)) {
configuration.withSendEventsInterval(pluginConfiguration
.getLong(ConfigurationKey.SEND_EVENTS_INTERVAL));
}

if (pluginConfiguration.has(ConfigurationKey.COMPRESS_EVENTS.getConfigurationKey())) {
configurationBuilder.withCompressEvents(
pluginConfiguration.getBoolean(ConfigurationKey.COMPRESS_EVENTS.getConfigurationKey()));
if (pluginConfiguration.has(ConfigurationKey.IS_COMPRESS_EVENTS)) {
configuration.withCompressEvents(
pluginConfiguration.getBoolean(ConfigurationKey.IS_COMPRESS_EVENTS));
}

if (pluginConfiguration.has(ConfigurationKey.TRACK_APP_EXCEPTION_EVENTS.getConfigurationKey())) {
configurationBuilder.withTrackAppExceptionEvents(pluginConfiguration
.getBoolean(ConfigurationKey.TRACK_APP_EXCEPTION_EVENTS.getConfigurationKey()));
if (pluginConfiguration.has(ConfigurationKey.IS_TRACK_APP_EXCEPTION_EVENTS)) {
configuration.withTrackAppExceptionEvents(pluginConfiguration
.getBoolean(ConfigurationKey.IS_TRACK_APP_EXCEPTION_EVENTS));
}
if (pluginConfiguration.has(ConfigurationKey.IS_LOG_EVENTS)) {
configuration.withLogEvents(pluginConfiguration.getBoolean(ConfigurationKey.IS_LOG_EVENTS));
}
if (pluginConfiguration.has(ConfigurationKey.IS_TRACK_SCREEN_VIEW_EVENTS)) {
configuration.withTrackScreenViewEvents(
pluginConfiguration.getBoolean(ConfigurationKey.IS_TRACK_SCREEN_VIEW_EVENTS));
}
if (pluginConfiguration.has(ConfigurationKey.IS_TRACK_USER_ENGAGEMENT_EVENTS)) {
configuration.withTrackUserEngagementEvents(
pluginConfiguration.getBoolean(ConfigurationKey.IS_TRACK_USER_ENGAGEMENT_EVENTS));
}
if (pluginConfiguration.has(ConfigurationKey.SESSION_TIMEOUT_DURATION)) {
configuration.withSessionTimeoutDuration(
pluginConfiguration.getLong(ConfigurationKey.SESSION_TIMEOUT_DURATION));
}
if (pluginConfiguration.has(ConfigurationKey.AUTH_COOKIE)) {
configuration.withAuthCookie(pluginConfiguration.getString(ConfigurationKey.AUTH_COOKIE));
}
if (pluginConfiguration.has(ConfigurationKey.GLOBAL_ATTRIBUTES)) {
configuration.withInitialGlobalAttributes(
(ClickstreamAttribute) pluginConfiguration.get(ConfigurationKey.GLOBAL_ATTRIBUTES));
}
} catch (JSONException exception) {
throw new AnalyticsException(
Expand All @@ -204,16 +216,10 @@ public void configure(
"Please take a look at the documentation for expected format of amplifyconfiguration.json."
);
}

AWSClickstreamPluginConfiguration clickstreamPluginConfiguration = configurationBuilder.build();
clickstreamManager = ClickstreamManagerFactory.create(
context,
clickstreamPluginConfiguration
);
clickstreamManager = new ClickstreamManager(context, configuration);
this.analyticsClient = clickstreamManager.getAnalyticsClient();

LOG.debug("AWSClickstreamPlugin create AutoEventSubmitter.");
autoEventSubmitter = new AutoEventSubmitter(clickstreamPluginConfiguration.getSendEventsInterval());
autoEventSubmitter = new AutoEventSubmitter(configuration.getSendEventsInterval());
autoEventSubmitter.start();

activityLifecycleManager = new ActivityLifecycleManager(clickstreamManager);
Expand All @@ -232,57 +238,20 @@ public String getVersion() {
}

/**
* Clickstream configuration in amplifyconfiguration.json contains following values.
* The Clickstream configuration keys.
*/
public enum ConfigurationKey {

/**
* The Clickstream appId.
*/
APP_ID("appId"),

/**
* the Clickstream Endpoint.
*/
ENDPOINT("endpoint"),

/**
* Time interval after which the events are automatically submitted to server.
*/
SEND_EVENTS_INTERVAL("sendEventsInterval"),

/**
* Whether to compress events.
*/
COMPRESS_EVENTS("isCompressEvents"),

/**
* Whether to track app exception events automatically.
*/
TRACK_APP_EXCEPTION_EVENTS("isTrackAppExceptionEvents");

/**
* The key this property is listed under in the config JSON.
*/
private final String configurationKey;

/**
* Construct the enum with the config key.
*
* @param configurationKey The key this property is listed under in the config JSON.
*/
ConfigurationKey(final String configurationKey) {
this.configurationKey = configurationKey;
}

/**
* Returns the key this property is listed under in the config JSON.
*
* @return The key as a string
*/
public String getConfigurationKey() {
return configurationKey;
}
static class ConfigurationKey {
static final String APP_ID = "appId";
static final String ENDPOINT = "endpoint";
static final String SEND_EVENTS_INTERVAL = "autoFlushEventsInterval";
static final String IS_COMPRESS_EVENTS = "isCompressEvents";
static final String IS_LOG_EVENTS = "isLogEvents";
static final String AUTH_COOKIE = "authCookie";
static final String SESSION_TIMEOUT_DURATION = "sessionTimeoutDuration";
static final String IS_TRACK_APP_EXCEPTION_EVENTS = "isTrackAppExceptionEvents";
static final String IS_TRACK_SCREEN_VIEW_EVENTS = "isTrackScreenViewEvents";
static final String IS_TRACK_USER_ENGAGEMENT_EVENTS = "isTrackUserEngagementEvents";
static final String GLOBAL_ATTRIBUTES = "globalAttributes";
}
}

Loading

0 comments on commit 4dbefaf

Please sign in to comment.