Skip to content

Commit f9bb561

Browse files
committed
Merge branch 'master' into inbox
# Conflicts: # README.md
2 parents 2cb73bf + 28eb838 commit f9bb561

File tree

5 files changed

+101
-49
lines changed

5 files changed

+101
-49
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1515
#### Fixed
1616
- nothing yet
1717

18+
## [3.1.4](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.1.4)
19+
#### Added
20+
- Push notifications now also display image thumbnails when collapsed
21+
22+
#### Changed
23+
- Connection timeout for GET requests is now 3 seconds, to match other request timeouts
24+
- `Api-Key` header is now also used for GET requests
25+
26+
#### Fixed
27+
- Fixed possible exceptions when an in-app message is not on the screen when it's being resized
28+
1829
## [3.1.3](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.1.3)
1930
#### Fixed
2031
- Fixed a NullPointerException that could occur in some cases when trying to get Advertising ID

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,13 @@ Note that `FirebaseInstanceIdService` is deprecated and replaced with `onNewToke
121121
> ⚠ Don't specify both email and userId in the same session, as they will be treated as different users by the SDK. Only use one type of identifier, email or userId, to identify the user.
122122

123123
3. Register for remote notifications
124-
125-
On application launch (or whenever you want to register the token), call `registerForPush`:
124+
125+
Iterable SDK automatically registers the push token with Iterable whenever `setEmail` or `setUserId` is called.
126+
> ⚠ This default behavior is the preferred way of handling token registrations.
127+
128+
If you want to trigger token registration manually, first disable automatic registration by calling `setAutoPushRegistration(false)` on `IterableConfig.Builder` when initializing the SDK.
129+
130+
Than call `registerForPush` whenever you want to register the token:
126131

127132
```
128133
IterableApi.getInstance().registerForPush();

iterableapi/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ android {
99
minSdkVersion 15
1010
targetSdkVersion 27
1111

12-
buildConfigField "String", "ITERABLE_SDK_VERSION", "\"3.1.3\""
12+
buildConfigField "String", "ITERABLE_SDK_VERSION", "\"3.1.4\""
1313

1414
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1515
}
@@ -71,7 +71,7 @@ ext {
7171
siteUrl = 'https://github.com/Iterable/iterable-android-sdk'
7272
gitUrl = 'https://github.com/Iterable/iterable-android-sdk.git'
7373

74-
libraryVersion = '3.1.3'
74+
libraryVersion = '3.1.4'
7575

7676
developerId = 'davidtruong'
7777
developerName = 'David Truong'

iterableapi/src/main/java/com/iterable/iterableapi/IterableInAppHTMLNotification.java

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class IterableInAppHTMLNotification extends Dialog {
3030

3131
static final String BACK_BUTTON = "itbl://backButton";
3232
static final String JAVASCRIPT_INTERFACE = "ITBL";
33+
private static final String TAG = "IterableInAppHTMLNotification";
3334

3435
static IterableInAppHTMLNotification notification;
3536

@@ -189,54 +190,58 @@ public void resize(final float height) {
189190
activity.runOnUiThread(new Runnable() {
190191
@Override
191192
public void run() {
192-
// Since this is run asynchronously, notification might've been dismissed already
193-
if (notification == null || notification.getWindow() == null) {
194-
return;
195-
}
193+
try {
194+
// Since this is run asynchronously, notification might've been dismissed already
195+
if (notification == null || notification.getWindow() == null || !notification.isShowing()) {
196+
return;
197+
}
196198

197-
DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics();
198-
Window window = notification.getWindow();
199-
Rect insetPadding = notification.insetPadding;
199+
DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics();
200+
Window window = notification.getWindow();
201+
Rect insetPadding = notification.insetPadding;
200202

201-
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
202-
Display display = wm.getDefaultDisplay();
203-
Point size = new Point();
203+
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
204+
Display display = wm.getDefaultDisplay();
205+
Point size = new Point();
204206

205-
// Get the correct screen size based on api level
206-
// https://stackoverflow.com/questions/35780980/getting-the-actual-screen-height-android
207-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
208-
display.getRealSize(size);
209-
} else {
210-
display.getSize(size);
211-
}
212-
int webViewWidth = size.x;
213-
int webViewHeight = size.y;
214-
215-
//Check if the dialog is full screen
216-
if (insetPadding.bottom == 0 && insetPadding.top == 0) {
217-
//Handle full screen
218-
window.setLayout(webViewWidth, webViewHeight);
219-
220-
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
221-
} else {
222-
// Calculates the dialog size
223-
double notificationWidth = 100-(insetPadding.left +insetPadding.right);
224-
float widthPercentage = (float) notificationWidth/100;
225-
int maxHeight = Math.min((int) (height * displayMetrics.scaledDensity), webViewHeight);
226-
int maxWidth = Math.min(webViewWidth, (int) (webViewWidth * widthPercentage));
227-
window.setLayout(maxWidth, maxHeight);
228-
229-
//Calculates the horizontal position based on the dialog size
230-
double center = (insetPadding.left + notificationWidth/2f);
231-
int offset = (int) ((center - 50)/100f * webViewWidth);
232-
233-
//Set the window properties
234-
WindowManager.LayoutParams wlp = window.getAttributes();
235-
wlp.x = offset;
236-
wlp.gravity = getVerticalLocation(insetPadding);
237-
wlp.dimAmount = (float) notification.backgroundAlpha;
238-
wlp.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
239-
window.setAttributes(wlp);
207+
// Get the correct screen size based on api level
208+
// https://stackoverflow.com/questions/35780980/getting-the-actual-screen-height-android
209+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
210+
display.getRealSize(size);
211+
} else {
212+
display.getSize(size);
213+
}
214+
int webViewWidth = size.x;
215+
int webViewHeight = size.y;
216+
217+
//Check if the dialog is full screen
218+
if (insetPadding.bottom == 0 && insetPadding.top == 0) {
219+
//Handle full screen
220+
window.setLayout(webViewWidth, webViewHeight);
221+
222+
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
223+
} else {
224+
// Calculates the dialog size
225+
double notificationWidth = 100 - (insetPadding.left + insetPadding.right);
226+
float widthPercentage = (float) notificationWidth / 100;
227+
int maxHeight = Math.min((int) (height * displayMetrics.scaledDensity), webViewHeight);
228+
int maxWidth = Math.min(webViewWidth, (int) (webViewWidth * widthPercentage));
229+
window.setLayout(maxWidth, maxHeight);
230+
231+
//Calculates the horizontal position based on the dialog size
232+
double center = (insetPadding.left + notificationWidth / 2f);
233+
int offset = (int) ((center - 50) / 100f * webViewWidth);
234+
235+
//Set the window properties
236+
WindowManager.LayoutParams wlp = window.getAttributes();
237+
wlp.x = offset;
238+
wlp.gravity = getVerticalLocation(insetPadding);
239+
wlp.dimAmount = (float) notification.backgroundAlpha;
240+
wlp.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
241+
window.setAttributes(wlp);
242+
}
243+
} catch (IllegalArgumentException e) {
244+
IterableLogger.e(TAG, "Exception while trying to resize an in-app message", e);
240245
}
241246
}
242247
});

iterableapi/src/test/java/com/iterable/iterableapi/IterablePushActionReceiverTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package com.iterable.iterableapi;
22

3+
import android.content.ClipData;
34
import android.content.Context;
45
import android.content.Intent;
6+
import android.os.Bundle;
7+
import android.support.v4.app.RemoteInput;
58

69
import org.json.JSONObject;
710
import org.junit.After;
@@ -17,6 +20,7 @@
1720
import okhttp3.mockwebserver.MockWebServer;
1821
import okhttp3.mockwebserver.RecordedRequest;
1922

23+
import static android.support.v4.app.RemoteInput.RESULTS_CLIP_LABEL;
2024
import static com.iterable.iterableapi.IterableTestUtils.stubAnyRequestReturningStatusCode;
2125
import static junit.framework.Assert.assertEquals;
2226
import static junit.framework.Assert.assertNotNull;
@@ -107,6 +111,33 @@ public void testPushActionWithSilentAction() throws Exception {
107111
assertNull(activityIntent);
108112
}
109113

114+
@Test
115+
public void testPushActionWithTextInput() throws Exception {
116+
IterablePushActionReceiver iterablePushActionReceiver = new IterablePushActionReceiver();
117+
Intent intent = new Intent(IterableConstants.ACTION_PUSH_ACTION);
118+
intent.putExtra(IterableConstants.ITERABLE_DATA_ACTION_IDENTIFIER, "textInputButton");
119+
intent.putExtra(IterableConstants.ITERABLE_DATA_KEY, IterableTestUtils.getResourceString("push_payload_action_buttons.json"));
120+
121+
// Inject input text
122+
Bundle resultsBundle = new Bundle();
123+
Intent clipDataIntent = new Intent();
124+
resultsBundle.putString(IterableConstants.USER_INPUT, "input text");
125+
clipDataIntent.putExtra(RemoteInput.EXTRA_RESULTS_DATA, resultsBundle);
126+
intent.setClipData(ClipData.newIntent(RESULTS_CLIP_LABEL, clipDataIntent));
127+
128+
PowerMockito.mockStatic(IterableActionRunner.class);
129+
130+
iterablePushActionReceiver.onReceive(RuntimeEnvironment.application, intent);
131+
132+
// Verify that IterableActionRunner was called with the proper action
133+
PowerMockito.verifyStatic(IterableActionRunner.class);
134+
ArgumentCaptor<IterableAction> actionCaptor = ArgumentCaptor.forClass(IterableAction.class);
135+
IterableActionRunner.executeAction(any(Context.class), actionCaptor.capture(), eq(IterableActionSource.PUSH));
136+
IterableAction capturedAction = actionCaptor.getValue();
137+
assertEquals("handleTextInput", capturedAction.getType());
138+
assertEquals("input text", capturedAction.userInput);
139+
}
140+
110141
@Test
111142
public void testLegacyDeepLinkPayload() throws Exception {
112143
stubAnyRequestReturningStatusCode(server, 200, "{}");

0 commit comments

Comments
 (0)