Skip to content

Commit ee5efde

Browse files
committed
Merge branch 'main' into next
Resolved Conflicts: sample/build.gradle settings.gradle urbanairship-core/src/main/java/com/urbanairship/AirshipComponentGroups.java urbanairship-core/src/main/java/com/urbanairship/UAirship.java
2 parents 5fc4ba2 + 12c009f commit ee5efde

File tree

52 files changed

+3425
-10
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+3425
-10
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ captures/
3030
.idea/misc.xml
3131
.idea/kotlinScripting.xml
3232
.idea/compiler.xml
33+
.idea/kotlinc.xml
3334

3435
# Android Studio 3 in .gitignore file.
3536
.idea/caches/build_file_checksums.ser

.idea/kotlinc.xml

-6
This file was deleted.

gradle/libs.versions.toml

+1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ androidx-preferencektx = { module = "androidx.preference:preference-ktx", versio
120120
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "androidx-recyclerview" }
121121
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "androidx-room" }
122122
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "androidx-room" }
123+
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "androidx-room" }
123124
androidx-room-testing = { module = "androidx.room:room-testing", version.ref = "androidx-room" }
124125
androidx-startup-runtime = { module = "androidx.startup:startup-runtime", version.ref = "androidx-startup" }
125126
androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version.ref = "androidx-swiperefreshlayout" }

sample/build.gradle

+3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ dependencies {
6868
// Airship Automation (In-App)
6969
implementation project(':urbanairship-automation')
7070

71+
// Airship Live Updates
72+
implementation project(':urbanairship-live-update')
73+
7174
// Airship Debug: Normally this is a debug only dependency but we embed the view in sample app
7275
implementation project(':urbanairship-debug')
7376

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.urbanairship.sample;
2+
3+
import android.content.Context;
4+
import android.util.Log;
5+
6+
import com.urbanairship.json.JsonMap;
7+
import com.urbanairship.liveupdate.LiveUpdate;
8+
import com.urbanairship.liveupdate.LiveUpdateEvent;
9+
import com.urbanairship.liveupdate.LiveUpdateCustomHandler;
10+
import com.urbanairship.liveupdate.LiveUpdateResult;
11+
12+
import org.jetbrains.annotations.NotNull;
13+
14+
import androidx.annotation.NonNull;
15+
16+
// TODO(live-update): Implement a custom live update handler to feed data to a widget.
17+
public class CustomLiveUpdate implements LiveUpdateCustomHandler {
18+
@Override
19+
@NotNull
20+
public LiveUpdateResult<Void> onUpdate(@NonNull Context context, @NonNull LiveUpdateEvent event, @NonNull LiveUpdate update) {
21+
22+
Log.d("CustomLiveUpdate", "onUpdate: action=" + event + ", update=" + update);
23+
24+
if (event == LiveUpdateEvent.END) {
25+
// Dismiss the live update on STOP. The default behavior will leave the Live Update
26+
// active until the dismissal time is reached.
27+
return LiveUpdateResult.cancel();
28+
}
29+
30+
JsonMap content = update.getContent();
31+
int teamOneScore = content.opt("team_one_score").getInt(0);
32+
int teamTwoScore = content.opt("team_two_score").getInt(0);
33+
String statusUpdate = content.opt("status_update").optString();
34+
35+
return LiveUpdateResult.ok();
36+
}
37+
}

sample/src/main/java/com/urbanairship/sample/SampleAutopilot.java

+19
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,15 @@
1010
import com.urbanairship.AirshipConfigOptions;
1111
import com.urbanairship.Autopilot;
1212
import com.urbanairship.UAirship;
13+
import com.urbanairship.liveupdate.LiveUpdateManager;
1314
import com.urbanairship.messagecenter.MessageCenter;
1415

1516
import androidx.annotation.NonNull;
1617
import androidx.annotation.Nullable;
18+
import androidx.core.app.NotificationChannelCompat;
19+
import androidx.core.app.NotificationManagerCompat;
20+
21+
import static androidx.core.app.NotificationManagerCompat.IMPORTANCE_HIGH;
1722

1823
/**
1924
* Autopilot that enables user notifications on first run.
@@ -36,6 +41,20 @@ public void onAirshipReady(@NonNull UAirship airship) {
3641
airship.getPushManager().setUserNotificationsEnabled(true);
3742
}
3843

44+
// Create notification channel for Live Updates.
45+
NotificationChannelCompat sportsChannel =
46+
new NotificationChannelCompat.Builder("sports", IMPORTANCE_HIGH)
47+
.setDescription("Live sports updates!")
48+
.setName("Sports!")
49+
.setVibrationEnabled(false)
50+
.build();
51+
52+
Context context = UAirship.getApplicationContext();
53+
NotificationManagerCompat.from(context).createNotificationChannel(sportsChannel);
54+
55+
// Register handlers for Live Updates.
56+
LiveUpdateManager.shared().register("sports", new SampleLiveUpdate());
57+
3958
MessageCenter.shared().setOnShowMessageCenterListener(messageId -> {
4059
// Use an implicit navigation deep link for now as explicit deep links are broken
4160
// with multi navigation host fragments
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.urbanairship.sample;
2+
3+
import android.app.PendingIntent;
4+
import android.content.Context;
5+
import android.content.Intent;
6+
import android.widget.RemoteViews;
7+
8+
import com.urbanairship.Logger;
9+
import com.urbanairship.json.JsonMap;
10+
import com.urbanairship.liveupdate.LiveUpdate;
11+
import com.urbanairship.liveupdate.LiveUpdateEvent;
12+
import com.urbanairship.liveupdate.LiveUpdateNotificationHandler;
13+
import com.urbanairship.liveupdate.LiveUpdateResult;
14+
import com.urbanairship.util.PendingIntentCompat;
15+
16+
import org.jetbrains.annotations.NotNull;
17+
18+
import androidx.annotation.NonNull;
19+
import androidx.core.app.NotificationCompat;
20+
21+
22+
public class SampleLiveUpdate implements LiveUpdateNotificationHandler {
23+
@Override
24+
@NotNull
25+
public LiveUpdateResult<NotificationCompat.Builder> onUpdate(@NonNull Context context, @NonNull LiveUpdateEvent event, @NonNull LiveUpdate update) {
26+
27+
Logger.debug("SampleLiveUpdate - onUpdate: action=" + event + ", update=" + update);
28+
29+
if (event == LiveUpdateEvent.END) {
30+
// Dismiss the live update on STOP. The default behavior will leave the Live Update
31+
// in the notification tray until the dismissal time is reached or the user dismisses it.
32+
return LiveUpdateResult.cancel();
33+
}
34+
35+
JsonMap content = update.getContent();
36+
int teamOneScore = content.opt("team_one_score").getInt(0);
37+
int teamTwoScore = content.opt("team_two_score").getInt(0);
38+
String statusUpdate = content.opt("status_update").optString();
39+
40+
RemoteViews bigLayout = new RemoteViews(context.getPackageName(), R.layout.live_update_notification_big);
41+
bigLayout.setTextViewText(R.id.teamOneScore, String.valueOf(teamOneScore));
42+
bigLayout.setTextViewText(R.id.teamTwoScore, String.valueOf(teamTwoScore));
43+
bigLayout.setTextViewText(R.id.statusUpdate, statusUpdate);
44+
45+
RemoteViews smallLayout = new RemoteViews(context.getPackageName(), R.layout.live_update_notification_small);
46+
smallLayout.setTextViewText(R.id.teamOneScore, String.valueOf(teamOneScore));
47+
smallLayout.setTextViewText(R.id.teamTwoScore, String.valueOf(teamTwoScore));
48+
49+
Intent launchIntent = context.getPackageManager()
50+
.getLaunchIntentForPackage(context.getPackageName())
51+
.addCategory(update.getName())
52+
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP)
53+
.setPackage(null);
54+
55+
PendingIntent contentIntent = PendingIntentCompat.getActivity(
56+
context, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE);
57+
58+
NotificationCompat.Builder builder =
59+
new NotificationCompat.Builder(context, "sports")
60+
.setSmallIcon(R.drawable.ic_notification)
61+
.setPriority(NotificationCompat.PRIORITY_MAX)
62+
.setCategory(NotificationCompat.CATEGORY_EVENT)
63+
.setStyle(new NotificationCompat.DecoratedCustomViewStyle())
64+
.setCustomContentView(smallLayout)
65+
.setCustomBigContentView(bigLayout)
66+
.setContentIntent(contentIntent);
67+
68+
return LiveUpdateResult.ok(builder);
69+
}
70+
}

sample/src/main/java/com/urbanairship/sample/home/HomeFragment.java

+70
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@
1010

1111
import com.urbanairship.actions.ActionRunRequest;
1212
import com.urbanairship.actions.ClipboardAction;
13+
import com.urbanairship.json.JsonMap;
14+
import com.urbanairship.liveupdate.LiveUpdateManager;
1315
import com.urbanairship.sample.R;
1416
import com.urbanairship.sample.databinding.FragmentHomeBinding;
1517

18+
import java.util.concurrent.atomic.AtomicInteger;
19+
1620
import androidx.annotation.NonNull;
1721
import androidx.annotation.Nullable;
1822
import androidx.appcompat.widget.Toolbar;
@@ -42,6 +46,8 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
4246
});
4347
});
4448

49+
setupLiveUpdateTestButtons(binding);
50+
4551
return binding.getRoot();
4652
}
4753

@@ -52,4 +58,68 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
5258
NavigationUI.setupWithNavController(toolbar, Navigation.findNavController(view));
5359
}
5460

61+
// TODO: Replace with something less hacky when backend is ready to send real Live Updates.
62+
// Should live update stuff even be on the home screen? Could be in settings instead...
63+
private void setupLiveUpdateTestButtons(FragmentHomeBinding binding) {
64+
AtomicInteger score1 = new AtomicInteger();
65+
AtomicInteger score2 = new AtomicInteger();
66+
67+
// Start button
68+
binding.startLiveUpdate.setOnClickListener(v -> {
69+
JsonMap content = JsonMap.newBuilder()
70+
.put("team_one_score", 0)
71+
.put("team_two_score", 0)
72+
.put("status_update", "Match start!")
73+
.build();
74+
75+
LiveUpdateManager.shared().start("foxes-tigers", "sports", content);
76+
});
77+
78+
// +1 Foxes button
79+
binding.updateLiveUpdate1.setOnClickListener(v -> {
80+
JsonMap content = JsonMap.newBuilder()
81+
.put("team_one_score", score1.getAndIncrement())
82+
.put("team_two_score", score2.get())
83+
.put("status_update", "Foxes score!")
84+
.build();
85+
86+
LiveUpdateManager.shared().update("foxes-tigers", content);
87+
});
88+
89+
// +1 Tigers button
90+
binding.updateLiveUpdate2.setOnClickListener(v -> {
91+
JsonMap content = JsonMap.newBuilder()
92+
.put("team_one_score", score1.get())
93+
.put("team_two_score", score2.getAndIncrement())
94+
.put("status_update", "Tigers score!")
95+
.build();
96+
97+
LiveUpdateManager.shared().update("foxes-tigers", content);
98+
});
99+
100+
// Stop button
101+
binding.stopLiveUpdate.setOnClickListener(v -> {
102+
int s1 = score1.get();
103+
int s2 = score2.get();
104+
String status;
105+
if (s1 == s2) {
106+
status = "It's a tie!";
107+
} else if (s1 > s2) {
108+
status = "Foxes win!";
109+
} else {
110+
status = "Tigers win!";
111+
}
112+
113+
JsonMap content = JsonMap.newBuilder()
114+
.put("teamOneScore", s1)
115+
.put("team_two_score", s2)
116+
.put("status_update", status)
117+
.build();
118+
119+
LiveUpdateManager.shared().stop("foxes-tigers", content);
120+
121+
score1.set(0);
122+
score2.set(0);
123+
});
124+
}
55125
}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="48dp"
3+
android:height="48dp"
4+
android:viewportWidth="48"
5+
android:viewportHeight="48">
6+
<path
7+
android:pathData="M41.143,29.917C41.171,29.917 41.171,29.917 41.198,29.917L44.931,30.553C42.138,27.263 41.088,25.742 37.797,23.641C37.936,23.115 38.212,22.452 38.488,21.788C41.502,14.323 39.954,11.751 37.41,7.382C35.336,10.562 34.949,11.558 29.475,14.876C27.401,16.12 25.438,17.281 24,18.995C22.562,17.281 20.599,16.092 18.553,14.848C13.134,11.585 12.747,10.618 10.618,7.355C8.074,11.724 6.525,14.295 9.539,21.76C9.816,22.452 10.092,23.088 10.23,23.613C6.94,25.714 5.889,27.235 3.097,30.525L6.829,29.889C6.857,29.889 6.857,29.889 6.885,29.889C6.359,30.664 6.083,31.134 4.617,33.401C7.134,33.318 15.29,32.378 18.608,38.848C19.714,39.207 22.866,40.23 24,40.59C25.825,40.009 28.341,39.18 29.419,38.848C32.599,32.405 41.005,33.318 43.41,33.401C41.945,31.134 41.668,30.691 41.143,29.917Z"
8+
android:fillColor="#ffffff"/>
9+
<path
10+
android:pathData="M24,20.766C23.862,20.766 23.723,20.766 23.585,20.766C20.876,16.508 14.212,15.429 10.673,10.038C6.995,16.37 11.751,21.568 11.751,24.333C10.839,24.941 8.654,26.13 6.608,28.563C7.742,28.37 9.594,28.701 9.594,28.701C9.594,28.701 8.765,29.531 7.217,31.964C16.479,31.632 19.604,37.771 19.604,37.771L24.028,39.208L28.452,37.771C28.452,37.771 31.576,31.632 40.839,31.964C39.29,29.531 38.461,28.701 38.461,28.701C38.461,28.701 40.341,28.397 41.447,28.563C39.401,26.13 37.217,24.941 36.304,24.333C36.304,21.568 41.032,16.397 37.355,10.038C33.843,15.429 27.18,16.535 24.47,20.794C24.304,20.766 24.138,20.766 24,20.766Z"
11+
android:fillColor="#E94C16"/>
12+
<path
13+
android:pathData="M19.272,34.203C15.733,30.83 10.507,29.917 10.507,29.917C10.507,29.917 11.834,28.203 12.636,27.594C12.276,28.203 12.138,29.253 12.138,29.253C12.138,29.253 16.756,30.194 20.074,33.512C19.742,33.733 19.493,33.982 19.272,34.203ZM24,37.382C24,37.382 26.599,36.332 27.18,36.028C27.18,36.028 27.594,35.005 27.235,33.76C26.571,33.622 25.991,33.622 25.521,33.65C25.604,33.76 25.631,33.843 25.631,33.954C25.631,34.562 24.415,35.115 24,35.115C23.585,35.115 22.369,34.562 22.369,33.954C22.369,33.843 22.424,33.733 22.479,33.65C22.009,33.622 21.428,33.622 20.765,33.76C20.406,34.977 20.82,36.028 20.82,36.028C21.428,36.304 24,37.382 24,37.382ZM17.779,23.945C17.779,23.889 17.779,23.862 17.779,23.806C17.17,21.263 12.193,18.525 12.193,18.525C12.193,18.525 14.378,20.378 14.627,22.369C13.631,21.152 12.663,20.903 12.663,20.903C12.663,20.903 13.493,22.313 13.852,23.641C13.852,23.641 15.65,23.53 16.673,24.028H16.645C17.005,24 17.392,23.945 17.779,23.945ZM31.355,24.028C32.35,23.53 34.175,23.641 34.175,23.641C34.535,22.286 35.364,20.903 35.364,20.903C35.364,20.903 34.396,21.152 33.401,22.369C33.65,20.378 35.834,18.525 35.834,18.525C35.834,18.525 30.885,21.263 30.277,23.806C30.277,23.862 30.277,23.889 30.277,23.945C30.663,23.972 31.051,24 31.41,24.055C31.382,24.055 31.355,24.055 31.355,24.028ZM28.728,34.203C32.267,30.83 37.493,29.917 37.493,29.917C37.493,29.917 36.166,28.203 35.364,27.594C35.723,28.203 35.862,29.253 35.862,29.253C35.862,29.253 31.244,30.194 27.926,33.512C28.258,33.733 28.535,33.982 28.728,34.203Z"
14+
android:fillColor="#ffffff"/>
15+
<path
16+
android:pathData="M22.037,29.918C22.009,29.973 21.954,30.029 21.899,30.111C21.677,30.416 21.207,31.107 20.931,31.854C20.848,31.494 20.765,31.162 20.682,30.886C19.106,31.245 17.143,30.001 17.53,27.623C18.691,28.812 21.235,27.844 22.037,29.918ZM24,33.098C23.087,33.098 22.369,33.485 22.369,33.955C22.369,34.563 23.585,35.116 24,35.116C24.415,35.116 25.631,34.563 25.631,33.955C25.659,33.485 24.912,33.098 24,33.098ZM25.991,29.918C26.018,29.973 26.074,30.029 26.129,30.111C26.35,30.416 26.82,31.135 27.097,31.854C27.18,31.494 27.263,31.162 27.346,30.886C28.922,31.245 30.885,30.001 30.498,27.623C29.309,28.812 26.765,27.844 25.991,29.918ZM40.811,31.936C31.548,31.605 28.424,37.743 28.424,37.743L24,39.181L19.576,37.743C19.576,37.743 16.452,31.605 7.189,31.936C8.737,29.503 9.567,28.674 9.567,28.674C9.567,28.674 7.687,28.37 6.581,28.535C8.654,26.13 10.811,24.913 11.751,24.333C11.751,21.568 7.023,16.397 10.7,10.038C14.212,15.429 20.876,16.535 23.585,20.794C23.723,20.794 23.862,20.794 24,20.794C24.138,20.794 24.277,20.794 24.415,20.794C27.124,16.535 33.788,15.429 37.299,10.038C40.977,16.397 36.249,21.568 36.249,24.333C37.161,24.941 39.346,26.13 41.392,28.563C40.258,28.37 38.405,28.701 38.405,28.701C38.405,28.701 39.263,29.503 40.811,31.936ZM35.392,27.623C36.415,27.402 37.576,27.485 37.576,27.485C37.576,27.485 34.977,25.107 31.355,24.056C32.35,23.559 34.175,23.669 34.175,23.669C34.535,22.314 35.364,20.932 35.364,20.932C35.364,20.932 34.396,21.181 33.401,22.397C33.65,20.406 35.834,18.554 35.834,18.554C35.834,18.554 30.857,21.291 30.277,23.835C29.585,19.273 36.829,16.84 36.691,13.605C33.373,16.591 28.645,18.194 26.323,20.904C28.23,21.844 28.507,22.674 28.507,22.674C28.479,22.674 26.931,22.093 24.028,22.093C21.124,22.093 19.576,22.674 19.548,22.674C19.548,22.674 19.825,21.844 21.733,20.904C19.41,18.194 14.682,16.563 11.364,13.577C11.226,16.812 18.47,19.245 17.779,23.807C17.198,21.264 12.193,18.526 12.193,18.526C12.193,18.526 14.378,20.379 14.627,22.37C13.631,21.153 12.664,20.904 12.664,20.904C12.664,20.904 13.493,22.314 13.852,23.642C13.852,23.642 15.65,23.531 16.673,24.029C13.051,25.107 10.424,27.457 10.424,27.457C10.424,27.457 11.613,27.374 12.636,27.623C11.834,28.204 10.507,29.918 10.507,29.918C10.507,29.918 15.733,30.83 19.272,34.204C19.687,33.761 20.267,33.291 21.069,32.987C20.184,34.508 20.793,36.029 20.793,36.029C21.401,36.333 23.972,37.383 23.972,37.383C23.972,37.383 26.571,36.333 27.152,36.029C27.152,36.029 27.76,34.508 26.876,32.987C27.677,33.319 28.258,33.761 28.673,34.204C32.212,30.83 37.438,29.918 37.438,29.918C37.438,29.918 36.166,28.204 35.392,27.623Z"
17+
android:fillColor="#181716"/>
18+
<path
19+
android:pathData="M20.489,29.862C19.548,30.83 18.774,29.723 19.078,29.309C19.161,29.613 19.687,30.166 20.489,29.862ZM27.511,29.862C28.452,30.83 29.226,29.723 28.922,29.309C28.866,29.613 28.313,30.166 27.511,29.862Z"
20+
android:fillColor="#ffffff"/>
21+
</vector>

0 commit comments

Comments
 (0)