Skip to content

Commit

Permalink
Merge branch 'master' into embedded
Browse files Browse the repository at this point in the history
  • Loading branch information
Evan Greer committed Nov 16, 2023
2 parents ecc4ed2 + 46b0038 commit 0d34c39
Show file tree
Hide file tree
Showing 19 changed files with 608 additions and 109 deletions.
157 changes: 155 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,164 @@ This project adheres to [Semantic Versioning](http://semver.org/).
#### Changed
- nothing yet

## [3.4.17](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.4.17)
#### Added
- when JWT is invalid, `IterableAuthManager` is updated to fetch and store a new JWT token locally
- `IterableRequestTask` now has a retry mechanism that fetches a new JWT token and retries the request if JWT is invalid
- retries are capped at a max of 5

## [3.4.16](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.4.16)
#### Fixed
- nothing yet
- SDK now handles `null` scenarios preventing crashes when `IterableEncryptedSharedPreference` creation fails.
- Updated crypto library to version [1.1.0-alpha06](https://developer.android.com/jetpack/androidx/releases/security#1.1.0-alpha06). [1.1.0-alpha05](https://developer.android.com/jetpack/androidx/releases/security#1.1.0-alpha05) solves a race condition during creation process.

## [3.4.9](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.4.9)
## [3.4.15](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.4.15)
#### Added

This release allows you to use projects hosted on Iterable's EU data center. If your project is hosted on Iterable's [European data center (EUDC)](https://support.iterable.com/hc/articles/17572750887444), configure the SDK to use Iterable's EU-based API endpoints:

_Java_

```java
IterableConfig config = new IterableConfig.Builder()
// ... other configuration options ...
.setDataRegion(IterableDataRegion.EU)
.build();
IterableApi.initialize(context, "<YOUR_API_KEY>", config);
```

_Kotlin_

```kotlin
val configBuilder = IterableConfig.Builder()
// ... other configuration options ...
.setDataRegion(IterableDataRegion.EU)
.build();
IterableApi.initialize(context, "<YOUR_API_KEY>", config);
```

#### Fixed
- Addressed React Native SDK push notification deep linking issues where the app would restart instead of resuming the last activity upon being backgrounded.
- Resolves an additional push notification problem wherein the customActionHandler and urlHandler were not being invoked in specific scenarios, as documented in issue #470. (Credit to @tnortman-jabra for the report and the fix)

## [3.4.14](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.4.14)
#### Added
- `IterableInAppManager.setRead` now accepts `IterableHelper.FailureHandler failureHandler`

#### Fixed
- Fixes an issue where `IterableInAppManager.removeMessage` caused build failure in React Native SDK pointing to legacy method calls.
- Fixes an issue where custom action handlers were not invoked when tapping on push notification when the app is in background.

## [3.4.13](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.4.13)
#### Added
- `IterableInAppManager.setRead` now accepts `IterableHelper.SuccessHandler successHandler`.
- `IterableApi.inAppConsume` now accepts `IterableHelper.SuccessHandler successHandler` and `IterableHelper.FailureHandler failureHandler`.

## [3.4.12](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.4.12)
#### Added
- `setEmail` and `setUserId` now accepts `IterableHelper.SuccessHandler successHandler` and `IterableHelper.FailureHandler failureHandler`.

#### Changed
- OTT devices (FireTV) will now register as `OTT` device instead of `Android` under user's devices.

## [3.4.11](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.4.11)

#### Added

- Custom push notification sounds! To play a custom sound for a push notification, add a sound file to your app's `res/raw` folder and specify that same filename when setting up a template in Iterable.

Some important notes about custom sounds and notification channels:

- Android API level 26 introduced [notification channels](https://developer.android.com/develop/ui/views/notifications/channels). Every notification must be assigned to a channel.
- Each custom sound you add to an Iterable template creates a new Android notification channel. The notification channel's name matches the filename of the sound (without its extension).
- To ensure sensible notification channel names for end users, give friendly names to your sound files. For example, a custom sound file with name `Paid.mp3` creates a notification channel called `Paid`. The end user can see this notification channel name in their device's notification channel settings.
- Be sure to place the corresponding sound file in your app's `res/raw` directory.

- To help you access a user's `email` address, `userId`, and `authToken`, the SDK now provides convenience methods: `getEmail()`, `getUserId()`, and `getAuthToken()`.

#### Changed

- Updated the [Security library](https://developer.android.com/topic/security/data) and improved `EncryptedSharedPreferences` handling.

To work around a [known Android issue](https://issuetracker.google.com/issues/164901843) that can cause crashes when creating `EncryptedSharedPreferences`, we've upgraded `androidx.security.crypto` from version `1.0.0` to `1.1.0-alpha04`. When `EncryptedSharedPreferences` cannot be created, the SDK now uses `SharedPreferences` (unencrypted).

If your app requires encryption, you can prevent this fallback to `SharedPreferences` by setting the `encryptionEnforced` configuration flag to `true`. However, if you enable this flag and `EncryptedSharedPreferences` cannot be created, an exception will be thrown.

- Improved JWT token management. This change addresses an issue where `null` values could prevent the refresh of a JWT token.

#### Fixed

- Fixed an issue which could prevent in-app messages from respecting the **Position** value selected when setting up the template (top / center / bottom / full).

- Fixed crashes that sometimes happened during in-app message animations.

## [3.4.10](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.4.10)
This release includes support for encrypting some data at rest, and an option to
store in-app messages in memory.

#### Encrypted data

In Android apps with `minSdkVersion` 23 or higher ([Android 6.0](https://developer.android.com/studio/releases/platforms#6.0))
Iterable's Android SDK now encrypts the following fields when storing them at
rest:

- `email` — The user's email address.
- `userId` — The user's ID.
- `authToken` — The JWT used to authenticate the user with Iterable's API.

(Note that Iterable's Android SDK does not store the last push payload at
rest—before or after this update.)

For more information about this encryption in Android, examine the source code
for Iterable's Android SDK: [`IterableKeychain`](https://github.com/Iterable/iterable-android-sdk/blob/master/iterableapi/src/main/java/com/iterable/iterableapi/IterableKeychain.kt).

#### Storing in-app messages in memory

This release also allows you to have your Android apps (regardless of `minSdkVersion`)
store in-app messages in memory, rather than in an unencrypted local file.
However, an unencrypted local file is still the default option.

To store in-app messages in memory, set the `setUseInMemoryStorageForInApps(true)`
SDK configuration option (defaults to `false`):

_Java_

```java
IterableConfig.Builder configBuilder = new IterableConfig.Builder()
// ... other configuration options ...
.setUseInMemoryStorageForInApps(true);
IterableApi.initialize(context, "<YOUR_API_KEY>", config);
```

_Kotlin_

```kotlin
val configBuilder = IterableConfig.Builder()
// ... other configuration options ...
.setUseInMemoryStorageForInApps(true);
IterableApi.initialize(context, "<YOUR_API_KEY>", configBuilder.build());
```

When users upgrade to a version of your Android app that uses this version of
the SDK (or higher), and you've set this configuration option to `true`, the
local file used for in-app message storage (if it already exists) is deleted
However, no data is lost.

#### Android upgrade instructions

If your app targets API level 23 or higher, this is a standard SDK upgrade, with
no special instructions.

If your app targets an API level less than 23, you'll need to make the following
changes to your project (which allow your app to build, even though it won't
encrypt data):

1. In `AndroidManifest.xml`, add `<uses-sdk tools:overrideLibrary="androidx.security" />`
2. In your app's `app/build.gradle`:
- Add `multiDexEnabled true` to the `default` object, under `android`.
- Add `implementation androidx.multidex:multidex:2.0.1` to the `dependencies`.

## [3.4.9](https://github.com/Iterable/iterable-android-sdk/releases/tag/3.4.9)
#### Added
- Added new methods for `setEmail`, `setUserId` and `updateEmail` which accepts `authToken`, providing more ways to pass `authToken` to SDK
- Added two interface methods - `onTokenRegistrationSuccessful` and `onTokenRegistrationFailed`. Override these methods to see if authToken was successfully received by the SDK.
Expand Down
12 changes: 12 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,25 @@ android {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}

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

debug {
testCoverageEnabled true
}
}

testOptions.unitTests.includeAndroidResources = true

compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}

kotlinOptions {
jvmTarget = "1.8"
}
Expand Down Expand Up @@ -73,9 +77,11 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.2.0'
androidTestImplementation 'br.com.concretesolutions:kappuccino:1.2.1'
}

tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
}

task jacocoDebugTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest']) {
group = "reporting"
description = "Generate unified Jacoco code coverage report"
Expand Down Expand Up @@ -103,12 +109,14 @@ task jacocoDebugTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest'])
'**/*$ModuleAdapter.class',
'**/*$ViewInjector*.class',
]

def debugTree = fileTree(dir: "${buildDir}/intermediates/javac/debug/classes", excludes: fileFilter) //we use "debug" build type for test coverage (can be other)
def sdkTree = fileTree(dir: "${buildDir}/../../iterableapi/build/intermediates/javac/debug/classes", excludes: fileFilter)
def sdkUiTree = fileTree(dir: "${buildDir}/../../iterableapi-ui/build/intermediates/javac/debug/classes", excludes: fileFilter)
def mainSrc = "${project.projectDir}/src/main/java"
def sdkSrc = "${project.projectDir}/../iterableapi/src/main/java"
def sdkUiSrc = "${project.projectDir}/../iterableapi-ui/src/main/java"

sourceDirectories.from = files([mainSrc])
classDirectories.from = files([debugTree])
additionalSourceDirs.from = files([sdkSrc, sdkUiSrc])
Expand All @@ -121,11 +129,13 @@ task jacocoDebugTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest'])
task jacocoDebugAndroidTestReport(type: JacocoReport, dependsOn: ['connectedCheck']) {
group = "reporting"
description = "Generate Jacoco code coverage report for instumentation tests"

reports {
xml.enabled = true
html.enabled = true
csv.enabled = false
}

def fileFilter = [
'**/*Test*.*',
'**/AutoValue_*.*',
Expand All @@ -145,12 +155,14 @@ task jacocoDebugAndroidTestReport(type: JacocoReport, dependsOn: ['connectedChec
'**/*$ModuleAdapter.class',
'**/*$ViewInjector*.class',
]

def debugTree = fileTree(dir: "${buildDir}/intermediates/javac/debug/classes", excludes: fileFilter) //we use "debug" build type for test coverage (can be other)
def sdkTree = fileTree(dir: "${buildDir}/../../iterableapi/build/intermediates/javac/debug/classes", excludes: fileFilter)
def sdkUiTree = fileTree(dir: "${buildDir}/../../iterableapi-ui/build/intermediates/javac/debug/classes", excludes: fileFilter)
def mainSrc = "${project.projectDir}/src/main/java"
def sdkSrc = "${project.projectDir}/../iterableapi/src/main/java"
def sdkUiSrc = "${project.projectDir}/../iterableapi-ui/src/main/java"

sourceDirectories.from = files([mainSrc])
classDirectories.from = files([debugTree])
additionalSourceDirs.from = files([sdkSrc, sdkUiSrc])
Expand Down
5 changes: 2 additions & 3 deletions app/src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools"
package="iterable.com.iterableapi">
<uses-sdk tools:overrideLibrary="br.com.concretesolutions.kappuccino,android_libs.ub_uiautomator"/>
<manifest xmlns:tools="http://schemas.android.com/tools" package="iterable.com.iterableapi">
<uses-sdk tools:overrideLibrary="br.com.concretesolutions.kappuccino,android_libs.ub_uiautomator,androidx.security"/>
</manifest>
7 changes: 3 additions & 4 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.iterable.iterableapi.testapp">

<uses-sdk tools:overrideLibrary="androidx.security"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
Expand All @@ -14,10 +15,8 @@
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
</manifest>
5 changes: 3 additions & 2 deletions iterableapi-ui/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ ext {
siteUrl = 'https://github.com/Iterable/iterable-android-sdk'
gitUrl = 'https://github.com/Iterable/iterable-android-sdk.git'

libraryVersion = '3.4.9'
libraryVersion = '3.4.17'

developerId = 'davidtruong'
developerName = 'David Truong'
Expand All @@ -60,7 +60,8 @@ ext {
}

apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle'
if(hasProperty("mavenPublishEnabled")) {

if (hasProperty("mavenPublishEnabled")) {
apply from: '../maven-push.gradle'
}

Expand Down
2 changes: 2 additions & 0 deletions iterableapi-ui/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.iterable.iterableapi.ui">
<uses-sdk tools:overrideLibrary="androidx.security"/>
<application>
<activity
android:name=".inbox.IterableInboxActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ public void onListItemTapped(@NonNull IterableInAppMessage message) {

@Override
public void onListItemDeleted(@NonNull IterableInAppMessage message, @NonNull IterableInAppDeleteActionType source) {
IterableApi.getInstance().getInAppManager().removeMessage(message, source, IterableInAppLocation.INBOX);
IterableApi.getInstance().getInAppManager().removeMessage(message, source, IterableInAppLocation.INBOX, null, null);
}

@Override
Expand Down
17 changes: 14 additions & 3 deletions iterableapi/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,20 @@ android {
compileSdkVersion 29
buildToolsVersion '29.0.3'

compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}

defaultConfig {
minSdkVersion 16
targetSdkVersion 27

buildConfigField "String", "ITERABLE_SDK_VERSION", "\"3.4.9\""
buildConfigField "String", "ITERABLE_SDK_VERSION", "\"3.4.17\""

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled false
Expand All @@ -25,11 +31,13 @@ android {
multiDexEnabled true
}
}

testOptions.unitTests.all {
testLogging {
exceptionFormat "full"
}
}

testOptions.unitTests.includeAndroidResources = true
}

Expand All @@ -39,6 +47,7 @@ dependencies {
api 'androidx.appcompat:appcompat:1.0.0'
api 'androidx.annotation:annotation:1.0.0'
api 'com.google.firebase:firebase-messaging:20.3.0'
implementation "androidx.security:security-crypto:1.1.0-alpha06"

testImplementation 'junit:junit:4.12'
testImplementation 'androidx.test:runner:1.3.0'
Expand Down Expand Up @@ -73,7 +82,7 @@ ext {
siteUrl = 'https://github.com/Iterable/iterable-android-sdk'
gitUrl = 'https://github.com/Iterable/iterable-android-sdk.git'

libraryVersion = '3.4.9'
libraryVersion = '3.4.17'

developerId = 'davidtruong'
developerName = 'David Truong'
Expand All @@ -85,12 +94,14 @@ ext {
}

apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle'
if(hasProperty("mavenPublishEnabled")) {

if (hasProperty("mavenPublishEnabled")) {
apply from: '../maven-push.gradle'
}

task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
excludes = ['**/*.kt']
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))

exclude '**/*.kt'
Expand Down
8 changes: 3 additions & 5 deletions iterableapi/src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
package="iterable.com.iterableapi">
<uses-sdk tools:overrideLibrary="android_libs.ub_uiautomator"/>
<manifest xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" package="iterable.com.iterableapi">
<uses-sdk tools:overrideLibrary="android_libs.ub_uiautomator,androidx.security"/>
<application
android:label="IterableAPI"
android:supportsRtl="true"/>
android:supportsRtl="true" />
</manifest>
Loading

0 comments on commit 0d34c39

Please sign in to comment.