Skip to content

Commit 3e7b7e8

Browse files
committed
Added Android Auto notification support.
Signed-off-by: Jens Zalzala <jens@shakingearthdigital.com>
1 parent d01e2ce commit 3e7b7e8

4 files changed

Lines changed: 72 additions & 14 deletions

File tree

SETUP.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,19 @@ This requires a working Internet connection.
106106

107107
The generated APK file is saved in ```app/build/outputs/apk``` as ```app-generic-debug.apk```.
108108

109+
### Working with Android Auto
110+
111+
To test [notification extension to Android Auto](https://developer.android.com/training/cars/communication/notification-messaging), Developer settings and Unknown sources need to be enabled in
112+
the Android Auto settings:
113+
114+
1. Open the Settings app on your device
115+
2. Search for Android Auto, or click on Connected Devices > Android Auto
116+
3. Scroll all the way down to Version, and click it 10 times to enable Developer settings
117+
4. Click the 3 dots in the top right and select Developer settings
118+
5. Enable Unknown sources
119+
120+
You can now receive notifications on Android Auto from a Nextcloud Talk development build.
121+
109122
### App flavours
110123

111124
The app is currently equipped to be built with three flavours:

app/src/main/AndroidManifest.xml

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,11 @@
9999

100100
<meta-data
101101
android:name="android.max_aspect"
102-
android:value="10" />
102+
android:value="10"/>
103+
104+
<meta-data
105+
android:name="com.google.android.gms.car.application"
106+
android:resource="@xml/automotive_app_desc"/>
103107

104108
<activity
105109
android:name=".activities.MainActivity"
@@ -299,11 +303,21 @@
299303
</intent-filter>
300304
</receiver>
301305

302-
<receiver android:name=".receivers.DirectReplyReceiver" />
303-
<receiver android:name=".receivers.MarkAsReadReceiver" />
304-
<receiver android:name=".receivers.DeclineCallReceiver" android:exported="false" />
305-
<receiver android:name=".receivers.DismissRecordingAvailableReceiver" />
306-
<receiver android:name=".receivers.ShareRecordingToChatReceiver" />
306+
<receiver
307+
android:name=".receivers.DirectReplyReceiver"
308+
android:exported="false" />
309+
<receiver
310+
android:name=".receivers.MarkAsReadReceiver"
311+
android:exported="false" />
312+
<receiver
313+
android:name=".receivers.DismissRecordingAvailableReceiver"
314+
android:exported="false" />
315+
<receiver
316+
android:name=".receivers.ShareRecordingToChatReceiver"
317+
android:exported="false" />
318+
<receiver
319+
android:name=".receivers.DeclineCallReceiver"
320+
android:exported="false" />
307321

308322
<service
309323
android:name=".utils.SyncService"

app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.kt

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,10 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
762762
}
763763

764764
private fun styleImageNotification(notificationBuilder: NotificationCompat.Builder) {
765+
val notificationUser = pushMessage.notificationUser
766+
val senderName = notificationUser?.name ?: ""
767+
val conversationTitle = pushMessage.subject.ifEmpty { senderName }
768+
765769
val bitmap = loadImageBitmapSync(imagePreviewUrl!!)
766770
if (bitmap != null) {
767771
notificationBuilder
@@ -770,6 +774,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
770774
NotificationCompat.BigPictureStyle()
771775
.bigPicture(bitmap)
772776
.bigLargeIcon(null as Bitmap?)
777+
.setBigContentTitle(conversationTitle)
773778
)
774779
}
775780
}
@@ -821,10 +826,19 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
821826
}
822827
person.setIcon(loadAvatarSync(avatarUrl, context!!))
823828
}
824-
notificationBuilder.setStyle(getStyle(person.build(), style))
829+
val deviceUser = Person.Builder()
830+
.setKey(signatureVerification.user!!.id.toString() + "@" + signatureVerification.user!!.userId)
831+
.setName(signatureVerification.user!!.displayName ?: signatureVerification.user!!.userId ?: "You")
832+
.build()
833+
notificationBuilder.setStyle(getStyle(deviceUser, person.build(), style))
825834
}
826835

827-
private fun buildIntentForAction(cls: Class<*>, systemNotificationId: Int, messageId: Int): PendingIntent {
836+
private fun buildIntentForAction(
837+
cls: Class<*>,
838+
systemNotificationId: Int,
839+
messageId: Int,
840+
mutable: Boolean = true
841+
): PendingIntent {
828842
val actualIntent = Intent(context, cls)
829843

830844
// NOTE - systemNotificationId is an internal ID used on the device only.
@@ -835,7 +849,8 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
835849
actualIntent.putExtra(KEY_MESSAGE_ID, messageId)
836850

837851
val intentFlag: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
838-
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
852+
val mutabilityFlag = if (mutable) PendingIntent.FLAG_MUTABLE else PendingIntent.FLAG_IMMUTABLE
853+
mutabilityFlag or PendingIntent.FLAG_UPDATE_CURRENT
839854
} else {
840855
PendingIntent.FLAG_UPDATE_CURRENT
841856
}
@@ -854,7 +869,8 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
854869
val pendingIntent = buildIntentForAction(
855870
MarkAsReadReceiver::class.java,
856871
systemNotificationId,
857-
messageId
872+
messageId,
873+
mutable = false
858874
)
859875
val markAsReadAction = NotificationCompat.Action.Builder(
860876
R.drawable.ic_mark_chat_read_24px,
@@ -964,9 +980,13 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
964980
notificationBuilder.addAction(shareRecordingAction)
965981
}
966982

967-
private fun getStyle(person: Person, style: NotificationCompat.MessagingStyle?): NotificationCompat.MessagingStyle {
968-
val newStyle = NotificationCompat.MessagingStyle(person)
969-
newStyle.conversationTitle = pushMessage.subject
983+
private fun getStyle(
984+
deviceUser: Person,
985+
sender: Person,
986+
style: NotificationCompat.MessagingStyle?
987+
): NotificationCompat.MessagingStyle {
988+
val newStyle = NotificationCompat.MessagingStyle(deviceUser)
989+
newStyle.conversationTitle = pushMessage.subject.ifEmpty { sender.name }
970990
newStyle.isGroupConversation = "one2one" != conversationType
971991
style?.messages?.forEach(
972992
Consumer { message: NotificationCompat.MessagingStyle.Message ->
@@ -979,7 +999,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
979999
)
9801000
}
9811001
)
982-
newStyle.addMessage(pushMessage.text, pushMessage.timestamp, person)
1002+
newStyle.addMessage(pushMessage.text, pushMessage.timestamp, sender)
9831003
return newStyle
9841004
}
9851005

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="utf-8"?><!--
2+
~ Nextcloud Talk - Android Client
3+
~
4+
~ SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
5+
~ SPDX-License-Identifier: GPL-3.0-or-later
6+
~ SPDX-FileCopyrightText: 2026 Jens Zalzala <jens@shakingearth.digital>
7+
-->
8+
9+
<automotiveApp>
10+
<uses name="notification" />
11+
</automotiveApp>

0 commit comments

Comments
 (0)