From 12c112fa399ebe5ed369fcda2286161dc8f58b0f Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 12 Aug 2024 13:30:58 +0200 Subject: [PATCH] Added favorites contacts grid in Android Auto UI --- app/src/main/AndroidManifest.xml | 7 +- .../org/linphone/telecom/auto/AAScreen.kt | 128 ++++++++++++++++++ .../AAService.kt} | 12 +- .../org/linphone/telecom/auto/AASession.kt | 36 +++++ app/src/main/res/values-fr/strings.xml | 4 + app/src/main/res/values/strings.xml | 4 + 6 files changed, 186 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/org/linphone/telecom/auto/AAScreen.kt rename app/src/main/java/org/linphone/telecom/{TelecomAndroidAutoService.kt => auto/AAService.kt} (86%) create mode 100644 app/src/main/java/org/linphone/telecom/auto/AASession.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 69399d84c..e72dd1667 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -55,10 +55,13 @@ android:theme="@style/Theme.Linphone" tools:targetApi="35"> - + + diff --git a/app/src/main/java/org/linphone/telecom/auto/AAScreen.kt b/app/src/main/java/org/linphone/telecom/auto/AAScreen.kt new file mode 100644 index 000000000..20340f6c3 --- /dev/null +++ b/app/src/main/java/org/linphone/telecom/auto/AAScreen.kt @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2010-2024 Belledonne Communications SARL. + * + * This file is part of linphone-android + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.linphone.telecom.auto + +import androidx.car.app.CarContext +import androidx.car.app.Screen +import androidx.car.app.model.Action +import androidx.car.app.model.CarIcon +import androidx.car.app.model.GridItem +import androidx.car.app.model.GridTemplate +import androidx.car.app.model.Header +import androidx.car.app.model.ItemList +import androidx.car.app.model.Template +import androidx.core.graphics.drawable.IconCompat +import org.linphone.LinphoneApplication.Companion.coreContext +import org.linphone.R +import org.linphone.contacts.getNativeContactPictureUri +import org.linphone.core.MagicSearch +import org.linphone.core.tools.Log +import org.linphone.utils.LinphoneUtils + +class AAScreen(context: CarContext) : Screen(context) { + companion object { + private const val TAG = "[Android Auto Screen]" + } + + private val favoritesList = arrayListOf() + + private var loading = true + + init { + Log.i( + "$TAG Creating favorites contacts list template for host with API level [${carContext.carAppApiLevel}]" + ) + coreContext.postOnCoreThread { core -> + val magicSearch = core.createMagicSearch() + val results = magicSearch.getContactsList( + "", + LinphoneUtils.getDefaultAccount()?.params?.domain.orEmpty(), + MagicSearch.Source.FavoriteFriends.toInt(), + MagicSearch.Aggregation.Friend + ) + val favorites = arrayListOf() + for (result in results) { + val builder = GridItem.Builder() + val friend = result.friend ?: continue + + builder.setTitle(friend.name) + val pictureUri = friend.getNativeContactPictureUri() + if (pictureUri != null) { + Log.i( + "$TAG Creating car icon for friend [${friend.name}] with URI [$pictureUri]" + ) + try { + builder.setImage( + CarIcon.Builder(IconCompat.createWithContentUri(pictureUri)) + .build(), + GridItem.IMAGE_TYPE_LARGE + ) + } catch (e: Exception) { + Log.e("$TAG Exception trying to create CarIcon: $e") + } + } + + builder.setOnClickListener { + val address = friend.address ?: friend.addresses.firstOrNull() + if (address != null) { + Log.i("$TAG Starting audio call to [${address.asStringUriOnly()}]") + coreContext.startAudioCall(address) + } + } + val item = builder.build() + favorites.add(item) + } + loading = false + Log.i("$TAG Processed [${favorites.size}] favorites") + + coreContext.postOnMainThread { + favoritesList.addAll(favorites) + invalidate() + } + } + } + + override fun onGetTemplate(): Template { + Log.i("$TAG onGetTemplate called, favorites are [${if (loading) "loading" else "loaded"}]") + + val listBuilder = ItemList.Builder() + listBuilder.setNoItemsMessage( + carContext.getString(R.string.car_favorites_contacts_list_empty) + ) + for (favorite in favoritesList) { + listBuilder.addItem(favorite) + } + val list = listBuilder.build() + + val header = Header.Builder() + .setTitle(carContext.getString(R.string.car_favorites_contacts_title)) + .setStartHeaderAction(Action.APP_ICON) + .build() + + val gridBuilder = GridTemplate.Builder() + gridBuilder.setHeader(header) + gridBuilder.setLoading(loading) + if (!loading) { + Log.i("$TAG Added [${favoritesList.size}] favorites items to grid") + gridBuilder.setSingleList(list) + } + return gridBuilder.build() + } +} diff --git a/app/src/main/java/org/linphone/telecom/TelecomAndroidAutoService.kt b/app/src/main/java/org/linphone/telecom/auto/AAService.kt similarity index 86% rename from app/src/main/java/org/linphone/telecom/TelecomAndroidAutoService.kt rename to app/src/main/java/org/linphone/telecom/auto/AAService.kt index b75b13b59..81ffc6de9 100644 --- a/app/src/main/java/org/linphone/telecom/TelecomAndroidAutoService.kt +++ b/app/src/main/java/org/linphone/telecom/auto/AAService.kt @@ -17,17 +17,18 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.linphone.telecom +package org.linphone.telecom.auto import android.content.pm.ApplicationInfo import androidx.car.app.CarAppService +import androidx.car.app.Session import androidx.car.app.validation.HostValidator import org.linphone.R import org.linphone.core.tools.Log -class TelecomAndroidAutoService : CarAppService() { +class AAService : CarAppService() { companion object { - private const val TAG = "[Telecom Android Auto Service]" + private const val TAG = "[Android Auto Service]" } override fun createHostValidator(): HostValidator { @@ -51,4 +52,9 @@ class TelecomAndroidAutoService : CarAppService() { validator } } + + override fun onCreateSession(): Session { + Log.i("$TAG Creating Session object") + return AASession() + } } diff --git a/app/src/main/java/org/linphone/telecom/auto/AASession.kt b/app/src/main/java/org/linphone/telecom/auto/AASession.kt new file mode 100644 index 000000000..cc3515617 --- /dev/null +++ b/app/src/main/java/org/linphone/telecom/auto/AASession.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2010-2024 Belledonne Communications SARL. + * + * This file is part of linphone-android + * (see https://www.linphone.org). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.linphone.telecom.auto + +import android.content.Intent +import androidx.car.app.Screen +import androidx.car.app.Session +import org.linphone.core.tools.Log + +class AASession : Session() { + companion object { + private const val TAG = "[Android Auto Session]" + } + + override fun onCreateScreen(intent: Intent): Screen { + Log.i("$TAG Creating Screen object for host with API level [${carContext.carAppApiLevel}]") + return AAScreen(carContext) + } +} diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 5250c2bb1..c02ab9fba 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -678,6 +678,10 @@ Enregistrements Aucun appel enregistré… + + Favoris + Aucun contact dans la liste des favoris + Ajouter aux contacts Voir le contact diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 58aba061e..1d9154ece 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -716,6 +716,10 @@ Recordings No recording for the moment… + + Favorites + No favorite contact yet + Add to contacts See contact