Skip to content

Commit 3e07b5b

Browse files
zhu-xiaoweixiaoweii
andauthored
feat: support enable and disable SDK (#46)
Co-authored-by: xiaoweii <xiaoweii@amazom.com>
1 parent effe568 commit 3e07b5b

File tree

11 files changed

+318
-72
lines changed

11 files changed

+318
-72
lines changed

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ Your `appId` and `endpoint` are already set up in it, here's an explanation of e
6060

6161
**3.Initialize the SDK**
6262

63-
Please Initialize the SDK in the Application `onCreate()` method.
63+
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.
6464

6565
```java
6666
import software.aws.solution.clickstream.ClickstreamAnalytics;
@@ -200,10 +200,26 @@ If you want to use custom DNS for network request, you can create your `CustomOk
200200
#### Send event immediately
201201

202202
```java
203+
import software.aws.solution.clickstream.ClickstreamAnalytics;
204+
203205
// for send event immediately.
204206
ClickstreamAnalytics.flushEvent();
205207
```
206208

209+
#### Disable SDK
210+
You can disable the SDK in the scenario you need. After disabling the SDK, the SDK will not handle the logging and sending of any events. Of course you can enable the SDK when you need to continue logging events.
211+
212+
Please note that the disable and enable code needs to be run in the main thread.
213+
```java
214+
import software.aws.solution.clickstream.ClickstreamAnalytics;
215+
216+
// disable SDK
217+
ClickstreamAnalytics.disable();
218+
219+
// enable SDK
220+
ClickstreamAnalytics.enable();
221+
```
222+
207223
## How to build locally
208224

209225
open an terminal window, at the root project folder to execute:

clickstream/src/main/java/software/aws/solution/clickstream/AWSClickstreamPlugin.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ public final class AWSClickstreamPlugin extends AnalyticsPlugin<Object> {
4848
private AnalyticsClient analyticsClient;
4949
private AutoEventSubmitter autoEventSubmitter;
5050
private ActivityLifecycleManager activityLifecycleManager;
51+
private ClickstreamManager clickstreamManager;
52+
private boolean isEnable = true;
5153

5254
/**
5355
* Constructs a new {@link AWSClickstreamPlugin}.
@@ -76,15 +78,25 @@ public void identifyUser(@NonNull String userId, @Nullable UserProfile profile)
7678
}
7779

7880
@Override
79-
public void disable() {
80-
autoEventSubmitter.stop();
81-
activityLifecycleManager.stopLifecycleTracking(context);
81+
public synchronized void disable() {
82+
if (isEnable) {
83+
autoEventSubmitter.stop();
84+
activityLifecycleManager.stopLifecycleTracking(context, ProcessLifecycleOwner.get().getLifecycle());
85+
clickstreamManager.disableTrackAppException();
86+
isEnable = false;
87+
LOG.info("Clickstream SDK disabled");
88+
}
8289
}
8390

8491
@Override
85-
public void enable() {
86-
autoEventSubmitter.start();
87-
activityLifecycleManager.startLifecycleTracking(context, ProcessLifecycleOwner.get().getLifecycle());
92+
public synchronized void enable() {
93+
if (!isEnable) {
94+
autoEventSubmitter.start();
95+
activityLifecycleManager.startLifecycleTracking(context, ProcessLifecycleOwner.get().getLifecycle());
96+
clickstreamManager.enableTrackAppException();
97+
isEnable = true;
98+
LOG.info("Clickstream SDK enabled");
99+
}
88100
}
89101

90102
@Override
@@ -182,7 +194,7 @@ public void configure(
182194
}
183195

184196
AWSClickstreamPluginConfiguration clickstreamPluginConfiguration = configurationBuilder.build();
185-
ClickstreamManager clickstreamManager = ClickstreamManagerFactory.create(
197+
clickstreamManager = ClickstreamManagerFactory.create(
186198
context,
187199
clickstreamPluginConfiguration
188200
);

clickstream/src/main/java/software/aws/solution/clickstream/ActivityLifecycleManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ void startLifecycleTracking(final Context context, Lifecycle lifecycle) {
6060
}
6161
}
6262

63-
void stopLifecycleTracking(final Context context) {
63+
void stopLifecycleTracking(final Context context, Lifecycle lifecycle) {
6464
if (context instanceof Application) {
6565
((Application) context).unregisterActivityLifecycleCallbacks(this);
66+
lifecycle.removeObserver(this);
6667
}
6768
}
6869

clickstream/src/main/java/software/aws/solution/clickstream/ClickstreamAnalytics.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,18 @@
2121
import com.amplifyframework.AmplifyException;
2222
import com.amplifyframework.core.Amplify;
2323

24+
import com.amazonaws.logging.Log;
25+
import com.amazonaws.logging.LogFactory;
2426
import software.aws.solution.clickstream.client.AnalyticsClient;
2527
import software.aws.solution.clickstream.client.ClickstreamConfiguration;
2628
import software.aws.solution.clickstream.client.Event;
29+
import software.aws.solution.clickstream.client.util.ThreadUtil;
2730

2831
/**
2932
* This is the top-level customer-facing interface to The ClickstreamAnalytics.
3033
*/
3134
public final class ClickstreamAnalytics {
35+
private static final Log LOG = LogFactory.getLog(ClickstreamAnalytics.class);
3236

3337
private ClickstreamAnalytics() {
3438
throw new UnsupportedOperationException("No instances allowed.");
@@ -41,6 +45,9 @@ private ClickstreamAnalytics() {
4145
* @throws AmplifyException Exception of init.
4246
*/
4347
public static void init(@NonNull Context context) throws AmplifyException {
48+
if (ThreadUtil.notInMainThread()) {
49+
throw new AmplifyException("Clickstream SDK initialization failed", "Please initialize in the main thread");
50+
}
4451
Amplify.addPlugin(new AWSClickstreamPlugin(context));
4552
Amplify.configure(context);
4653
}
@@ -71,7 +78,7 @@ public static void flushEvents() {
7178
}
7279

7380
/**
74-
* add user clickstreamAttribute.
81+
* Add user clickstreamAttribute.
7582
*
7683
* @param clickstreamAttribute the global clickstreamAttribute.
7784
*/
@@ -80,7 +87,7 @@ public static void addGlobalAttributes(ClickstreamAttribute clickstreamAttribute
8087
}
8188

8289
/**
83-
* delete global attributes.
90+
* Delete global attributes.
8491
*
8592
* @param attributeName the attribute name to delete.
8693
*/
@@ -89,7 +96,7 @@ public static void deleteGlobalAttributes(@NonNull String... attributeName) {
8996
}
9097

9198
/**
92-
* add user attributes.
99+
* Add user attributes.
93100
*
94101
* @param userProfile user
95102
*/
@@ -98,7 +105,7 @@ public static void addUserAttributes(ClickstreamUserAttribute userProfile) {
98105
}
99106

100107
/**
101-
* set user id.
108+
* Set user id.
102109
*
103110
* @param userId user
104111
*/
@@ -111,7 +118,29 @@ public static void setUserId(String userId) {
111118
}
112119

113120
/**
114-
* get clickstream configuration
121+
* Enable clickstream SDK.
122+
*/
123+
public static void enable() {
124+
if (ThreadUtil.notInMainThread()) {
125+
LOG.error("Clickstream SDK enabled failed, please execute in the main thread");
126+
return;
127+
}
128+
Amplify.Analytics.enable();
129+
}
130+
131+
/**
132+
* Disable clickstream SDK.
133+
*/
134+
public static void disable() {
135+
if (ThreadUtil.notInMainThread()) {
136+
LOG.error("Clickstream SDK disabled failed, please execute in the main thread");
137+
return;
138+
}
139+
Amplify.Analytics.disable();
140+
}
141+
142+
/**
143+
* Get clickstream configuration
115144
* please config it after initialize.
116145
*
117146
* @return ClickstreamConfiguration configurationF

clickstream/src/main/java/software/aws/solution/clickstream/client/ClickstreamExceptionHandler.java

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -31,35 +31,41 @@ public final class ClickstreamExceptionHandler implements Thread.UncaughtExcepti
3131
private static final Log LOG = LogFactory.getLog(ClickstreamExceptionHandler.class);
3232
private static ClickstreamExceptionHandler handlerInstance;
3333
private static final int SLEEP_TIMEOUT_MS = 500;
34-
private final Thread.UncaughtExceptionHandler defaultExceptionHandler;
35-
private ClickstreamContext clickstreamContext;
34+
private Thread.UncaughtExceptionHandler defaultExceptionHandler;
35+
private final ClickstreamContext clickstreamContext;
3636

37-
private ClickstreamExceptionHandler() {
37+
private ClickstreamExceptionHandler(ClickstreamContext context) {
38+
this.clickstreamContext = context;
39+
}
40+
41+
/**
42+
* start listening the exception events.
43+
*/
44+
public void startTrackException() {
3845
defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
3946
Thread.setDefaultUncaughtExceptionHandler(this);
4047
}
4148

49+
/**
50+
* stop listening the exception events.
51+
*/
52+
public void stopTackException() {
53+
Thread.setDefaultUncaughtExceptionHandler(null);
54+
}
55+
4256
/**
4357
* init static method for ClickstreamExceptionHandler.
4458
*
59+
* @param context the clickstream context for initial the ClickstreamExceptionHandler
4560
* @return ClickstreamExceptionHandler the instance.
4661
*/
47-
public static synchronized ClickstreamExceptionHandler init() {
62+
public static synchronized ClickstreamExceptionHandler init(ClickstreamContext context) {
4863
if (handlerInstance == null) {
49-
handlerInstance = new ClickstreamExceptionHandler();
64+
handlerInstance = new ClickstreamExceptionHandler(context);
5065
}
5166
return handlerInstance;
5267
}
5368

54-
/**
55-
* setter for clickstreamContext.
56-
*
57-
* @param context ClickstreamContext
58-
*/
59-
public void setClickstreamContext(ClickstreamContext context) {
60-
this.clickstreamContext = context;
61-
}
62-
6369
/**
6470
* fetch uncaught exception and record crash event.
6571
*
@@ -69,32 +75,35 @@ public void setClickstreamContext(ClickstreamContext context) {
6975
@Override
7076
public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
7177
try {
72-
String exceptionMessage = "";
73-
String exceptionStack = "";
74-
try {
75-
if (throwable.getMessage() != null) {
76-
exceptionMessage = throwable.getMessage();
77-
}
78-
final Writer writer = new StringWriter();
79-
PrintWriter printWriter = new PrintWriter(writer);
80-
throwable.printStackTrace(printWriter);
81-
Throwable cause = throwable.getCause();
82-
while (cause != null) {
83-
cause.printStackTrace(printWriter);
84-
cause = cause.getCause();
78+
if (clickstreamContext.getClickstreamConfiguration().isTrackAppExceptionEvents()) {
79+
String exceptionMessage = "";
80+
String exceptionStack = "";
81+
try {
82+
if (throwable.getMessage() != null) {
83+
exceptionMessage = throwable.getMessage();
84+
}
85+
final Writer writer = new StringWriter();
86+
PrintWriter printWriter = new PrintWriter(writer);
87+
throwable.printStackTrace(printWriter);
88+
Throwable cause = throwable.getCause();
89+
while (cause != null) {
90+
cause.printStackTrace(printWriter);
91+
cause = cause.getCause();
92+
}
93+
printWriter.close();
94+
exceptionStack = writer.toString();
95+
} catch (Exception exception) {
96+
LOG.error("exception for get exception stack:", exception);
8597
}
86-
printWriter.close();
87-
exceptionStack = writer.toString();
88-
} catch (Exception exception) {
89-
LOG.error("exception for get exception stack:", exception);
90-
}
9198

92-
final AnalyticsEvent event =
93-
this.clickstreamContext.getAnalyticsClient().createEvent(Event.PresetEvent.APP_EXCEPTION);
94-
event.addInternalAttribute("exception_message", exceptionMessage);
95-
event.addInternalAttribute("exception_stack", exceptionStack);
96-
this.clickstreamContext.getAnalyticsClient().recordEvent(event);
99+
final AnalyticsEvent event =
100+
this.clickstreamContext.getAnalyticsClient().createEvent(Event.PresetEvent.APP_EXCEPTION);
101+
event.addInternalAttribute("exception_message", exceptionMessage);
102+
event.addInternalAttribute("exception_stack", exceptionStack);
103+
this.clickstreamContext.getAnalyticsClient().recordEvent(event);
104+
}
97105

106+
this.clickstreamContext.getAnalyticsClient().submitEvents();
98107
try {
99108
Thread.sleep(SLEEP_TIMEOUT_MS);
100109
} catch (InterruptedException exception) {

clickstream/src/main/java/software/aws/solution/clickstream/client/ClickstreamManager.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class ClickstreamManager {
3939
private final AnalyticsClient analyticsClient;
4040
private final SessionClient sessionClient;
4141
private final AutoRecordEventClient autoRecordEventClient;
42+
private ClickstreamExceptionHandler exceptionHandler;
4243

4344
/**
4445
* Constructor.
@@ -57,6 +58,7 @@ public ClickstreamManager(@NonNull final ClickstreamConfiguration config) {
5758
this.autoRecordEventClient = new AutoRecordEventClient(this.clickstreamContext);
5859
this.clickstreamContext.setSessionClient(this.sessionClient);
5960
if (config.isTrackAppExceptionEvents()) {
61+
exceptionHandler = ClickstreamExceptionHandler.init(this.clickstreamContext);
6062
enableTrackAppException();
6163
}
6264
LOG.debug(String.format(Locale.US,
@@ -68,9 +70,22 @@ public ClickstreamManager(@NonNull final ClickstreamConfiguration config) {
6870
}
6971
}
7072

71-
private void enableTrackAppException() {
72-
ClickstreamExceptionHandler handler = ClickstreamExceptionHandler.init();
73-
handler.setClickstreamContext(this.clickstreamContext);
73+
/**
74+
* Enable track app exception.
75+
*/
76+
public void enableTrackAppException() {
77+
if (exceptionHandler != null) {
78+
exceptionHandler.startTrackException();
79+
}
80+
}
81+
82+
/**
83+
* Disable track app exception.
84+
*/
85+
public void disableTrackAppException() {
86+
if (exceptionHandler != null) {
87+
exceptionHandler.stopTackException();
88+
}
7489
}
7590

7691
/**
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.aws.solution.clickstream.client.util;
17+
18+
import android.os.Looper;
19+
20+
/**
21+
* Thread utility methods.
22+
*/
23+
public final class ThreadUtil {
24+
25+
/**
26+
* Default constructor.
27+
*/
28+
private ThreadUtil() {
29+
}
30+
31+
/**
32+
* method for return current thread whether not in main thread.
33+
*
34+
* @return boolean value notInMainThread.
35+
*/
36+
public static boolean notInMainThread() {
37+
return Looper.getMainLooper() != Looper.myLooper();
38+
}
39+
40+
}
41+

0 commit comments

Comments
 (0)