Skip to content

Commit

Permalink
feat(notifications): open app, open url, open deeplink (#128)
Browse files Browse the repository at this point in the history
* feature(notifications): open app, open url, open deeplink

* fix pinpoint unit tests (#127)

* add kotlin facade and unit tests (#126)

* chore: merge main into push-notifications (#129)

* fix(core): remove unused dynamic nav dependency (#2132)

* fix(datastore): remove typename from ModelMetadata (#2122)

* fix(datastore): remove typename from ModelMetadata

* Test a potential fix

* Test a potential fix

* fix: callbacks not invoked when attached using getTransfer api (#2111)

* fix: listener not invoked when attached using getTransfer api

* address PR comments

* default state to unknown

* add comment

* add comment

* override getRequest in storage operation & make SocketExcpetion retryable

* add nullable annotation

* address nullable request

Co-authored-by: Tyler Roach <tjroach@amazon.com>

* Prevent attempting to read backed up EncryptedSharedPreferences that are no longer readable (#2113)

* fix(auth): device metadata migration (#2114)

* Number of attributes being too high is not retryable (#2112)

* Number of attributes being too high is not retryable

* Match iOS at not retrying bad request error -- covering multiple 400 errors

* Fix lint

* Fix lint

* Update Kotlin SDK version

Co-authored-by: Thomas Leing <leint@amazon.com>

* Change errors returned on some apis while federated (#2116)

* release: Amplify Android 2.0.0 (#2115)

* release: Amplify Android 2.0.0

* add core-kotlin changelog

* add more info in changelog

* revert unintended change

* remove breaking change for analytics

* fix(datastore): remove typename from ModelMetadata

* fix(datastore): remove typename from ModelMetadata

* remove unneeded file

* small cleanup

* remove print statements

* fix comment

* force tests

* force tests

* force tests

Co-authored-by: Michael Law <1365977+lawmicha@users.noreply.github.com>
Co-authored-by: Michael Schneider <mikschn@amazon.com>
Co-authored-by: Saijad Dhuka <83975678+sdhuka@users.noreply.github.com>
Co-authored-by: Tyler Roach <tjroach@amazon.com>
Co-authored-by: Divyesh Chitroda <div5yesh@gmail.com>
Co-authored-by: Thomas Leing <bluezebragames@gmail.com>
Co-authored-by: Thomas Leing <leint@amazon.com>
Co-authored-by: Sunil Timalsina <sunil.timalsina@gmail.com>

* chore: Remove deprecated maven plugin (#2137)

* Remove deprecated maven project

* Fix task name grep

* chore: Remove Javadoc tasks (#2139)

* Remove deprecated maven project

* Fix task name grep

* Remove Javadoc tasks

* fix: Change order of updating state in local cache (#2141)

* fix: fix integration test and added logger to integration test (#2143)

* fix: Change order of updating state in local cache

* change order for updating status and add logger to integ tests

* change log level to debug

* Fix for when move to idle state is called twice (#2152)

* Update README.md (#2120)

remove dev-preview APIs note.

* Dengdan stress test (#2153)

* Initial commit

* Work in progress

* finish codes

* change build

* update build

* test excludeStressTest

* Revert "Merge branch 'main' into dengdan-stress-test"

This reverts commit b50840e, reversing
changes made to 3bacf1b.

* remove categories

* remove external changes

* remove external changes

* remove more changes

* Update copyright and refactor

* Update StorageStressTest.kt

* Update StorageStressTest.kt

* Update StorageStressTest.kt

* Update StorageStressTest.kt

* linting

* Update StorageStressTest.kt

* Delete StorageStressTest.kt

* Delete amplifyconfigurationupdated.json

* Delete amplifyconfigurationupdated.json

* Update DataStoreStressTest.kt

* Fix(Auth): Sign up if successful should return DONE instead of Confirm sign up (#2130)

* If sign up is successful in the first try return DONE

* Sign up should send DONE if it is successful

* revert jsongenerator cleandir fun

* lint fix

* Feat(Auth Test): Custom party testing for Custom Test without SRP (#2149)

* Adding custom auth test cases

* Updating test cases for Custom Auth to ensure they pass

* lint format

* Fix for phone number

* Recreate all tests

* Unignore storage and pinpoint tests (#2156)

* unignore tests

* extend timeout to 60s

Co-authored-by: Saijad Dhuka <83975678+sdhuka@users.noreply.github.com>

* feat(Geo): Add Kotlin Geo Facade (#2155)

* Add Kotlin Geo Facade

* Add return docs to the function comments

* Add tests to verify options are passed

* fix: Add missing apis in storage Kotlin & RxJava facade (#2160)

* fix: Add pause, resume api to kotlin and rxJava facade

* add unit tests

* remove irrelevant code changes

* add assertion

* Update DeviceFarm build config (#2168)

* fix: user metadata was persisted empty in the database (#2165)

* fix: usermeta was persisted as empty in the database

* fix compilation error

* fix compilation error

* avoid adding metadata if it is null

* Add Geo Rx Bindings (#2159)

* chore: Re-add storage tests (#2163)

* Readd storage tests

* rename file

* reduce stress

Co-authored-by: Saijad Dhuka <83975678+sdhuka@users.noreply.github.com>

* Add a network status listener to restart DataStore after the network … (#2148)

* Add a network status listener to restart DataStore after the network comes back online.

* Add Reachability monitor

* working pretty well

* cleanup

* update test

* fix: fix integration test and added logger to integration test (#2143)

* fix: Change order of updating state in local cache

* change order for updating status and add logger to integ tests

* change log level to debug

* Fix for when move to idle state is called twice (#2152)

* Update README.md (#2120)

remove dev-preview APIs note.

* Dengdan stress test (#2153)

* Initial commit

* Work in progress

* finish codes

* change build

* update build

* test excludeStressTest

* Revert "Merge branch 'main' into dengdan-stress-test"

This reverts commit b50840e, reversing
changes made to 3bacf1b.

* remove categories

* remove external changes

* remove external changes

* remove more changes

* Update copyright and refactor

* Update StorageStressTest.kt

* Update StorageStressTest.kt

* Update StorageStressTest.kt

* Update StorageStressTest.kt

* linting

* Update StorageStressTest.kt

* Delete StorageStressTest.kt

* Delete amplifyconfigurationupdated.json

* Delete amplifyconfigurationupdated.json

* Update DataStoreStressTest.kt

* force build

* force build

* force build

* fix typo

* Add a network status listener to restart DataStore after the network comes back online.

* Add Reachability monitor

* working pretty well

* cleanup

* update test

* force build

* force build

* force build

* fix typo

* reply to comments

* Add testImplementation lin eto compile tests correctly in intellij

* reply to comments

* make ReachabilityMonitor expose the observable

* Update datastore plugin to use the reachability monitor

* cleanup

* cleanup

* cleanup

* force tests

Co-authored-by: Michael Schneider <mikschn@amazon.com>
Co-authored-by: Saijad Dhuka <83975678+sdhuka@users.noreply.github.com>
Co-authored-by: gpanshu <91897496+gpanshu@users.noreply.github.com>
Co-authored-by: Divyesh Chitroda <div5yesh@gmail.com>
Co-authored-by: dengdan154 <85711456+dengdan154@users.noreply.github.com>

* chore: Upgrade Gradle, AGP, and KtLint (#2172)

* Remove deprecated maven project

* Fix task name grep

* Upgrade Gradle to 7.5.1

* Upgrade AGP

* Add VERSION_NAME back to BuildConfig

This was removed for library projects in AGP 4.1. We may consider renaming this in the future to disambiguate the Amplify version and the application version.

* Update KtLint and fix all new lint errors

* Use JDK11 on codebuild

* Use JDK11 in workflows

* Upgrade compileSdkVersion to 31

* Try using custom commands to install Android SDK 31

* Update device farm buildspec with manual Android SDK install

* Fix additional ktlint errors

* Upgrade Desugar to JDK11-compatible version

* Upgrade Robolectric

* Set locale explicitly to match expectation

* fix(geo): Increase Geo timeout so that it runs successfully on a Pixel 3a XL (#2177)

* Increase Geo timeout so that it runs successfully on a Pixel 3a XL

* Fix lint

Co-authored-by: Thomas Leing <leint@amazon.com>

* Add a buildspec file for nightly tests (#2180)

* Chore(Auth): Implementation of the custom auth with SRP parity testing use case (#2167)

* Added the test case for custom auth with SRP

* ktlint

* release: Amplify Android 2.1.0 (manually created) (#2185)

Co-authored-by: Thomas Leing <leint@amazon.com>

* chore: Add PR checker workflow (#2188)

* fix(Auth): Fix for when loading credentials the success/error is fired twice (#2184)

* chore: update changelog for Amplify Android 2.1.0 (#2193)

* feat(Auth): Overriding sign in when the State machine is already in the signing in state (#2187)

* chore: fix inconsistency with endpointWithAttributes test (#2196)

* chore: update changelog for v2.1.0 (#2198)

* chore: replace md5 with sha-256 for file data validation (#2199)

* chore: Remove unused version and group properties (#2186)

* chore: Add a label that will disable the PR title check (#2195)

Co-authored-by: gpanshu <91897496+gpanshu@users.noreply.github.com>

* chore: add release tag to PR title checker config (#2194)

Co-authored-by: Matt Creaser <mattwcc@amazon.com>

* fix(datastore): Fix lock contention issue when running DataStore.start() from the callback of DataStore.stop() (#2208)

Co-authored-by: Michael Schneider <mikschn@amazon.com>

* chore: Add group and version back to all subprojects (#2213)

Co-authored-by: Erica Eaton <67125657+eeatonaws@users.noreply.github.com>
Co-authored-by: Michael Schneider <mikepschneider@users.noreply.github.com>
Co-authored-by: Michael Law <1365977+lawmicha@users.noreply.github.com>
Co-authored-by: Michael Schneider <mikschn@amazon.com>
Co-authored-by: Saijad Dhuka <83975678+sdhuka@users.noreply.github.com>
Co-authored-by: Tyler Roach <tjroach@amazon.com>
Co-authored-by: Thomas Leing <bluezebragames@gmail.com>
Co-authored-by: Thomas Leing <leint@amazon.com>
Co-authored-by: Sunil Timalsina <sunil.timalsina@gmail.com>
Co-authored-by: Matt Creaser <mattwcc@amazon.com>
Co-authored-by: gpanshu <91897496+gpanshu@users.noreply.github.com>
Co-authored-by: dengdan154 <85711456+dengdan154@users.noreply.github.com>

* Remove duplicate definition of isReleaseBuild from a merge error

* Finish open app/url/deeplink

* Update PushNotificationsUtils.kt

* Update build.gradle

* Added style for activity and misc fixes

* Update styles.xml

Co-authored-by: Divyesh Chitroda <div5yesh@gmail.com>
Co-authored-by: Erica Eaton <67125657+eeatonaws@users.noreply.github.com>
Co-authored-by: Michael Schneider <mikepschneider@users.noreply.github.com>
Co-authored-by: Michael Law <1365977+lawmicha@users.noreply.github.com>
Co-authored-by: Michael Schneider <mikschn@amazon.com>
Co-authored-by: Saijad Dhuka <83975678+sdhuka@users.noreply.github.com>
Co-authored-by: Tyler Roach <tjroach@amazon.com>
Co-authored-by: Thomas Leing <bluezebragames@gmail.com>
Co-authored-by: Thomas Leing <leint@amazon.com>
Co-authored-by: Sunil Timalsina <sunil.timalsina@gmail.com>
Co-authored-by: Matt Creaser <mattwcc@amazon.com>
Co-authored-by: gpanshu <91897496+gpanshu@users.noreply.github.com>
  • Loading branch information
13 people committed Jan 24, 2023
1 parent e116fd2 commit 33a5470
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 24 deletions.
1 change: 1 addition & 0 deletions aws-analytics-pinpoint-targeting/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ plugins {
}
apply plugin: 'com.android.library'
apply from: rootProject.file("configuration/checkstyle.gradle")
apply from: rootProject.file("configuration/publishing.gradle")
apply plugin: 'kotlin-android'
apply plugin: 'org.jlleitschuh.gradle.ktlint'

Expand Down
4 changes: 4 additions & 0 deletions aws-analytics-pinpoint-targeting/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
POM_ARTIFACT_ID=aws-analytics-pinpoint-targeting
POM_NAME=Amplify Framework for Android - Analytics
POM_DESCRIPTION=Amplify Framework for Android - Analytics Plugin for Amazon Pinpoint
POM_PACKAGING=aar
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package com.amplifyframework.pushnotifications.pinpoint.utils

import android.os.Bundle
import java.util.UUID
import kotlin.collections.HashMap
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
Expand All @@ -27,13 +28,15 @@ data class NotificationPayload internal constructor(
val notificationId: Int,
val title: String?,
val body: String?,
val imageUrl: String?
val action: HashMap<String, String>?,
val imageUrl: String?,
) {

constructor(title: String?, body: String?, imageUrl: String?) : this(
constructor(title: String?, body: String?, action: HashMap<String, String>?, imageUrl: String?) : this(
UUID.randomUUID().hashCode(),
title,
body,
action,
imageUrl
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ class PushNotificationsConstants {
companion object {
const val AWS_PINPOINT_NOTIFICATION_CHANNEL = "pinpoint.notification.channel"

const val AWS_PINPOINT_OPENAPP = "pinpoint.openApp"
const val AWS_PINPOINT_URL = "pinpoint.url"
const val AWS_PINPOINT_DEEPLINK = "pinpoint.deeplink"
const val AWS_PINPOINT_NOTIFICATION_TITLE = "pinpoint.notification.title"
const val AWS_PINPOINT_NOTIFICATION_BODY = "pinpoint.notification.body"
const val AWS_PINPOINT_NOTIFICATION_IMAGE = "pinpoint.notification.imageUrl"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,25 @@ abstract class PushNotificationsService : FirebaseMessagingService() {

open fun processRemoteMessage(remoteMessage: RemoteMessage): NotificationPayload {
val data = remoteMessage.data
val action: HashMap<String, String> = HashMap()
data[PushNotificationsConstants.AWS_PINPOINT_OPENAPP]?.let {
action.put(PushNotificationsConstants.AWS_PINPOINT_OPENAPP, it)
}
data[PushNotificationsConstants.AWS_PINPOINT_URL]?.let {
action.put(PushNotificationsConstants.AWS_PINPOINT_URL, it)
}
data[PushNotificationsConstants.AWS_PINPOINT_DEEPLINK]?.let {
action.put(PushNotificationsConstants.AWS_PINPOINT_DEEPLINK, it)
}
val title = data[PushNotificationsConstants.AWS_PINPOINT_NOTIFICATION_TITLE]
val body = data[PushNotificationsConstants.AWS_PINPOINT_NOTIFICATION_BODY]
val imageUrl = data[PushNotificationsConstants.AWS_PINPOINT_NOTIFICATION_IMAGE]
return NotificationPayload(title, body, imageUrl)
return NotificationPayload(title, body, action, imageUrl)
}

override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
Log.d("TAG", "Message: " + remoteMessage.data + "," + remoteMessage.notification)

// handle payload and show notification
val payload = processRemoteMessage(remoteMessage).bundle()
Amplify.Notifications.Push.handleNotificationReceived(payload, { }, { })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import android.app.ActivityManager
import android.app.ActivityManager.RunningAppProcessInfo
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Build
Expand Down Expand Up @@ -92,19 +94,17 @@ class PushNotificationsUtils(
}

@SuppressLint("NewApi")
fun showNotification(details: NotificationPayload) {
fun showNotification(details: NotificationPayload, targetClass: Class<*>?) {
val requestCode = 0
val largeImageIcon = details.imageUrl?.let { downloadImage(it) }

// val notificationIntent = Intent(context, com.amplifyframework.pushnotifications.pinpoint.PushNotificationsApplication::class.java).apply {
// flags = (Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
// }
// val intent = PendingIntent.getActivity(
// context,
// 0,
// notificationIntent,
// PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
// )

val notificationIntent = Intent(context, targetClass)
notificationIntent.putExtra("action", details.action)
val pendingIntent = PendingIntent.getActivity(
context,
requestCode,
notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val notificationChannel = retrieveNotificationChannel(channelId)
val builder = if (isNotificationChannelSupported() && notificationChannel != null) {
NotificationCompat.Builder(context, notificationChannel.id)
Expand All @@ -116,7 +116,7 @@ class PushNotificationsUtils(
setContentTitle(details.title)
setContentText(details.body)
setSmallIcon(R.drawable.ic_launcher_foreground)
// setContentIntent(intent)
setContentIntent(pendingIntent)
setPriority(NotificationCompat.PRIORITY_DEFAULT)
setLargeIcon(largeImageIcon)
}
Expand Down
9 changes: 5 additions & 4 deletions aws-push-notifications-pinpoint/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

<application>
<!-- <activity-->
<!-- android:name="com.amplifyframework.pushnotifications.pinpoint.AWSPinpointPushNotificationsActivity"-->
<!-- android:launchMode="singleInstance"-->
<!-- android:exported="false" />-->
<activity
android:name="com.amplifyframework.pushnotifications.pinpoint.AWSPinpointPushNotificationsActivity"
android:theme="@style/PinpointNotificationActivityTheme"
android:launchMode="singleInstance"
android:exported="false" />
<service
android:name="com.amplifyframework.pushnotifications.pinpoint.AWSPinpointPushNotificationsPlugin$ServiceExtension"
android:exported="false">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,48 @@
package com.amplifyframework.pushnotifications.pinpoint

import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import com.amplifyframework.core.Amplify
import com.amplifyframework.pushnotifications.pinpoint.utils.PushNotificationsConstants

class AWSPinpointPushNotificationsActivity : Activity()
class AWSPinpointPushNotificationsActivity : Activity() {

@Override
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Amplify.Notifications.Push.recordNotificationOpened(emptyMap(), { }, { })
val resultIntent = intent.extras
@Suppress("UNCHECKED_CAST")
val action = resultIntent?.get("action") as HashMap<String, String>
val intent = processIntent(action)
try {
startActivity(intent)
} catch (e: ActivityNotFoundException) {
Log.e("TAG", "Couldn't launch intent.", e)
}
finish()
}

private fun processIntent(action: HashMap<String, String>): Intent {
// Action is open url
val notificationIntent: Intent = if (action.containsKey(PushNotificationsConstants.AWS_PINPOINT_URL)) {
val url = action[PushNotificationsConstants.AWS_PINPOINT_URL]
Intent(Intent.ACTION_VIEW, Uri.parse(url))
}
// Action is open deeplink
else if (action.containsKey(PushNotificationsConstants.AWS_PINPOINT_DEEPLINK)) {
val deepLink = action[PushNotificationsConstants.AWS_PINPOINT_DEEPLINK]
Intent(Intent.ACTION_VIEW, Uri.parse(deepLink))
}
// Default action is open app
else {
val packageName = applicationContext.packageName
applicationContext.packageManager.getLaunchIntentForPackage(packageName)!!
}
return notificationIntent
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ class AWSPinpointPushNotificationsPlugin : PushNotificationsPlugin<PinpointClien
onSuccess: Action,
onError: Consumer<PushNotificationsException>
) {
TODO("Not yet implemented")
tryAnalyticsRecordEvent("notification_opened")
PushNotificationResult.NotificationOpened()
onSuccess.call()
}

override fun handleNotificationReceived(
Expand All @@ -161,7 +163,7 @@ class AWSPinpointPushNotificationsPlugin : PushNotificationsPlugin<PinpointClien
tryAnalyticsRecordEvent("foreground_event")
PushNotificationResult.AppInForeground()
} else {
pushNotificationsUtils.showNotification(payload)
pushNotificationsUtils.showNotification(payload, AWSPinpointPushNotificationsActivity::class.java)
tryAnalyticsRecordEvent("background_event")
PushNotificationResult.NotificationPosted()
}
Expand Down
29 changes: 29 additions & 0 deletions aws-push-notifications-pinpoint/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License.
A copy of the License is located at
http://aws.amazon.com/apache2.0
or in the "license" file accompanying this file. This file 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.
-->

<resources>

<!--This theme ensures the Headless PinpointNotificationActivity is completely hidden-->
<style name="PinpointNotificationActivityTheme" parent="android:Theme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>

</resources>

0 comments on commit 33a5470

Please sign in to comment.