Skip to content

Commit 33a5470

Browse files
dengdan154div5yesheeatonawsmikepschneiderlawmicha
authored
feat(notifications): open app, open url, open deeplink (#128)
* 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 <[email protected]> * 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 <[email protected]> * 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 <[email protected]> Co-authored-by: Michael Schneider <[email protected]> Co-authored-by: Saijad Dhuka <[email protected]> Co-authored-by: Tyler Roach <[email protected]> Co-authored-by: Divyesh Chitroda <[email protected]> Co-authored-by: Thomas Leing <[email protected]> Co-authored-by: Thomas Leing <[email protected]> Co-authored-by: Sunil Timalsina <[email protected]> * 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 <[email protected]> * 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 <[email protected]> * 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 <[email protected]> Co-authored-by: Saijad Dhuka <[email protected]> Co-authored-by: gpanshu <[email protected]> Co-authored-by: Divyesh Chitroda <[email protected]> Co-authored-by: dengdan154 <[email protected]> * 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 <[email protected]> * 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 <[email protected]> * 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 <[email protected]> * chore: add release tag to PR title checker config (#2194) Co-authored-by: Matt Creaser <[email protected]> * fix(datastore): Fix lock contention issue when running DataStore.start() from the callback of DataStore.stop() (#2208) Co-authored-by: Michael Schneider <[email protected]> * chore: Add group and version back to all subprojects (#2213) Co-authored-by: Erica Eaton <[email protected]> Co-authored-by: Michael Schneider <[email protected]> Co-authored-by: Michael Law <[email protected]> Co-authored-by: Michael Schneider <[email protected]> Co-authored-by: Saijad Dhuka <[email protected]> Co-authored-by: Tyler Roach <[email protected]> Co-authored-by: Thomas Leing <[email protected]> Co-authored-by: Thomas Leing <[email protected]> Co-authored-by: Sunil Timalsina <[email protected]> Co-authored-by: Matt Creaser <[email protected]> Co-authored-by: gpanshu <[email protected]> Co-authored-by: dengdan154 <[email protected]> * 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 <[email protected]> Co-authored-by: Erica Eaton <[email protected]> Co-authored-by: Michael Schneider <[email protected]> Co-authored-by: Michael Law <[email protected]> Co-authored-by: Michael Schneider <[email protected]> Co-authored-by: Saijad Dhuka <[email protected]> Co-authored-by: Tyler Roach <[email protected]> Co-authored-by: Thomas Leing <[email protected]> Co-authored-by: Thomas Leing <[email protected]> Co-authored-by: Sunil Timalsina <[email protected]> Co-authored-by: Matt Creaser <[email protected]> Co-authored-by: gpanshu <[email protected]>
1 parent e116fd2 commit 33a5470

File tree

10 files changed

+119
-24
lines changed

10 files changed

+119
-24
lines changed

aws-analytics-pinpoint-targeting/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ plugins {
1818
}
1919
apply plugin: 'com.android.library'
2020
apply from: rootProject.file("configuration/checkstyle.gradle")
21+
apply from: rootProject.file("configuration/publishing.gradle")
2122
apply plugin: 'kotlin-android'
2223
apply plugin: 'org.jlleitschuh.gradle.ktlint'
2324

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
POM_ARTIFACT_ID=aws-analytics-pinpoint-targeting
2+
POM_NAME=Amplify Framework for Android - Analytics
3+
POM_DESCRIPTION=Amplify Framework for Android - Analytics Plugin for Amazon Pinpoint
4+
POM_PACKAGING=aar

aws-push-notifications-pinpoint-utils/src/main/java/com/amplifyframework/pushnotifications/pinpoint/utils/NotificationPayload.kt

+5-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package com.amplifyframework.pushnotifications.pinpoint.utils
1717

1818
import android.os.Bundle
1919
import java.util.UUID
20+
import kotlin.collections.HashMap
2021
import kotlinx.serialization.Serializable
2122
import kotlinx.serialization.decodeFromString
2223
import kotlinx.serialization.encodeToString
@@ -27,13 +28,15 @@ data class NotificationPayload internal constructor(
2728
val notificationId: Int,
2829
val title: String?,
2930
val body: String?,
30-
val imageUrl: String?
31+
val action: HashMap<String, String>?,
32+
val imageUrl: String?,
3133
) {
3234

33-
constructor(title: String?, body: String?, imageUrl: String?) : this(
35+
constructor(title: String?, body: String?, action: HashMap<String, String>?, imageUrl: String?) : this(
3436
UUID.randomUUID().hashCode(),
3537
title,
3638
body,
39+
action,
3740
imageUrl
3841
)
3942

aws-push-notifications-pinpoint-utils/src/main/java/com/amplifyframework/pushnotifications/pinpoint/utils/PushNotificationsConstants.kt

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ class PushNotificationsConstants {
1919
companion object {
2020
const val AWS_PINPOINT_NOTIFICATION_CHANNEL = "pinpoint.notification.channel"
2121

22+
const val AWS_PINPOINT_OPENAPP = "pinpoint.openApp"
23+
const val AWS_PINPOINT_URL = "pinpoint.url"
24+
const val AWS_PINPOINT_DEEPLINK = "pinpoint.deeplink"
2225
const val AWS_PINPOINT_NOTIFICATION_TITLE = "pinpoint.notification.title"
2326
const val AWS_PINPOINT_NOTIFICATION_BODY = "pinpoint.notification.body"
2427
const val AWS_PINPOINT_NOTIFICATION_IMAGE = "pinpoint.notification.imageUrl"

aws-push-notifications-pinpoint-utils/src/main/java/com/amplifyframework/pushnotifications/pinpoint/utils/PushNotificationsService.kt

+11-2
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,25 @@ abstract class PushNotificationsService : FirebaseMessagingService() {
4545

4646
open fun processRemoteMessage(remoteMessage: RemoteMessage): NotificationPayload {
4747
val data = remoteMessage.data
48+
val action: HashMap<String, String> = HashMap()
49+
data[PushNotificationsConstants.AWS_PINPOINT_OPENAPP]?.let {
50+
action.put(PushNotificationsConstants.AWS_PINPOINT_OPENAPP, it)
51+
}
52+
data[PushNotificationsConstants.AWS_PINPOINT_URL]?.let {
53+
action.put(PushNotificationsConstants.AWS_PINPOINT_URL, it)
54+
}
55+
data[PushNotificationsConstants.AWS_PINPOINT_DEEPLINK]?.let {
56+
action.put(PushNotificationsConstants.AWS_PINPOINT_DEEPLINK, it)
57+
}
4858
val title = data[PushNotificationsConstants.AWS_PINPOINT_NOTIFICATION_TITLE]
4959
val body = data[PushNotificationsConstants.AWS_PINPOINT_NOTIFICATION_BODY]
5060
val imageUrl = data[PushNotificationsConstants.AWS_PINPOINT_NOTIFICATION_IMAGE]
51-
return NotificationPayload(title, body, imageUrl)
61+
return NotificationPayload(title, body, action, imageUrl)
5262
}
5363

5464
override fun onMessageReceived(remoteMessage: RemoteMessage) {
5565
super.onMessageReceived(remoteMessage)
5666
Log.d("TAG", "Message: " + remoteMessage.data + "," + remoteMessage.notification)
57-
5867
// handle payload and show notification
5968
val payload = processRemoteMessage(remoteMessage).bundle()
6069
Amplify.Notifications.Push.handleNotificationReceived(payload, { }, { })

aws-push-notifications-pinpoint-utils/src/main/java/com/amplifyframework/pushnotifications/pinpoint/utils/PushNotificationsUtils.kt

+13-13
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import android.app.ActivityManager
2020
import android.app.ActivityManager.RunningAppProcessInfo
2121
import android.app.NotificationChannel
2222
import android.app.NotificationManager
23+
import android.app.PendingIntent
2324
import android.content.Context
25+
import android.content.Intent
2426
import android.graphics.Bitmap
2527
import android.graphics.BitmapFactory
2628
import android.os.Build
@@ -92,19 +94,17 @@ class PushNotificationsUtils(
9294
}
9395

9496
@SuppressLint("NewApi")
95-
fun showNotification(details: NotificationPayload) {
97+
fun showNotification(details: NotificationPayload, targetClass: Class<*>?) {
98+
val requestCode = 0
9699
val largeImageIcon = details.imageUrl?.let { downloadImage(it) }
97-
98-
// val notificationIntent = Intent(context, com.amplifyframework.pushnotifications.pinpoint.PushNotificationsApplication::class.java).apply {
99-
// flags = (Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
100-
// }
101-
// val intent = PendingIntent.getActivity(
102-
// context,
103-
// 0,
104-
// notificationIntent,
105-
// PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
106-
// )
107-
100+
val notificationIntent = Intent(context, targetClass)
101+
notificationIntent.putExtra("action", details.action)
102+
val pendingIntent = PendingIntent.getActivity(
103+
context,
104+
requestCode,
105+
notificationIntent,
106+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
107+
)
108108
val notificationChannel = retrieveNotificationChannel(channelId)
109109
val builder = if (isNotificationChannelSupported() && notificationChannel != null) {
110110
NotificationCompat.Builder(context, notificationChannel.id)
@@ -116,7 +116,7 @@ class PushNotificationsUtils(
116116
setContentTitle(details.title)
117117
setContentText(details.body)
118118
setSmallIcon(R.drawable.ic_launcher_foreground)
119-
// setContentIntent(intent)
119+
setContentIntent(pendingIntent)
120120
setPriority(NotificationCompat.PRIORITY_DEFAULT)
121121
setLargeIcon(largeImageIcon)
122122
}

aws-push-notifications-pinpoint/src/main/AndroidManifest.xml

+5-4
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@
1919
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
2020

2121
<application>
22-
<!-- <activity-->
23-
<!-- android:name="com.amplifyframework.pushnotifications.pinpoint.AWSPinpointPushNotificationsActivity"-->
24-
<!-- android:launchMode="singleInstance"-->
25-
<!-- android:exported="false" />-->
22+
<activity
23+
android:name="com.amplifyframework.pushnotifications.pinpoint.AWSPinpointPushNotificationsActivity"
24+
android:theme="@style/PinpointNotificationActivityTheme"
25+
android:launchMode="singleInstance"
26+
android:exported="false" />
2627
<service
2728
android:name="com.amplifyframework.pushnotifications.pinpoint.AWSPinpointPushNotificationsPlugin$ServiceExtension"
2829
android:exported="false">

aws-push-notifications-pinpoint/src/main/java/com/amplifyframework/pushnotifications/pinpoint/AWSPinpointPushNotificationsActivity.kt

+44-1
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,48 @@
1616
package com.amplifyframework.pushnotifications.pinpoint
1717

1818
import android.app.Activity
19+
import android.content.ActivityNotFoundException
20+
import android.content.Intent
21+
import android.net.Uri
22+
import android.os.Bundle
23+
import android.util.Log
24+
import com.amplifyframework.core.Amplify
25+
import com.amplifyframework.pushnotifications.pinpoint.utils.PushNotificationsConstants
1926

20-
class AWSPinpointPushNotificationsActivity : Activity()
27+
class AWSPinpointPushNotificationsActivity : Activity() {
28+
29+
@Override
30+
override fun onCreate(savedInstanceState: Bundle?) {
31+
super.onCreate(savedInstanceState)
32+
Amplify.Notifications.Push.recordNotificationOpened(emptyMap(), { }, { })
33+
val resultIntent = intent.extras
34+
@Suppress("UNCHECKED_CAST")
35+
val action = resultIntent?.get("action") as HashMap<String, String>
36+
val intent = processIntent(action)
37+
try {
38+
startActivity(intent)
39+
} catch (e: ActivityNotFoundException) {
40+
Log.e("TAG", "Couldn't launch intent.", e)
41+
}
42+
finish()
43+
}
44+
45+
private fun processIntent(action: HashMap<String, String>): Intent {
46+
// Action is open url
47+
val notificationIntent: Intent = if (action.containsKey(PushNotificationsConstants.AWS_PINPOINT_URL)) {
48+
val url = action[PushNotificationsConstants.AWS_PINPOINT_URL]
49+
Intent(Intent.ACTION_VIEW, Uri.parse(url))
50+
}
51+
// Action is open deeplink
52+
else if (action.containsKey(PushNotificationsConstants.AWS_PINPOINT_DEEPLINK)) {
53+
val deepLink = action[PushNotificationsConstants.AWS_PINPOINT_DEEPLINK]
54+
Intent(Intent.ACTION_VIEW, Uri.parse(deepLink))
55+
}
56+
// Default action is open app
57+
else {
58+
val packageName = applicationContext.packageName
59+
applicationContext.packageManager.getLaunchIntentForPackage(packageName)!!
60+
}
61+
return notificationIntent
62+
}
63+
}

aws-push-notifications-pinpoint/src/main/java/com/amplifyframework/pushnotifications/pinpoint/AWSPinpointPushNotificationsPlugin.kt

+4-2
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,9 @@ class AWSPinpointPushNotificationsPlugin : PushNotificationsPlugin<PinpointClien
147147
onSuccess: Action,
148148
onError: Consumer<PushNotificationsException>
149149
) {
150-
TODO("Not yet implemented")
150+
tryAnalyticsRecordEvent("notification_opened")
151+
PushNotificationResult.NotificationOpened()
152+
onSuccess.call()
151153
}
152154

153155
override fun handleNotificationReceived(
@@ -161,7 +163,7 @@ class AWSPinpointPushNotificationsPlugin : PushNotificationsPlugin<PinpointClien
161163
tryAnalyticsRecordEvent("foreground_event")
162164
PushNotificationResult.AppInForeground()
163165
} else {
164-
pushNotificationsUtils.showNotification(payload)
166+
pushNotificationsUtils.showNotification(payload, AWSPinpointPushNotificationsActivity::class.java)
165167
tryAnalyticsRecordEvent("background_event")
166168
PushNotificationResult.NotificationPosted()
167169
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License").
6+
You may not use this file except in compliance with the License.
7+
A copy of the License is located at
8+
9+
http://aws.amazon.com/apache2.0
10+
11+
or in the "license" file accompanying this file. This file is distributed
12+
on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13+
express or implied. See the License for the specific language governing
14+
permissions and limitations under the License.
15+
-->
16+
17+
<resources>
18+
19+
<!--This theme ensures the Headless PinpointNotificationActivity is completely hidden-->
20+
<style name="PinpointNotificationActivityTheme" parent="android:Theme">
21+
<item name="android:windowIsTranslucent">true</item>
22+
<item name="android:windowBackground">@android:color/transparent</item>
23+
<item name="android:windowContentOverlay">@null</item>
24+
<item name="android:windowNoTitle">true</item>
25+
<item name="android:windowIsFloating">true</item>
26+
<item name="android:backgroundDimEnabled">false</item>
27+
</style>
28+
29+
</resources>

0 commit comments

Comments
 (0)