Votre app Android présente le widget DobroDesk avec un état protégé par compte et des nouvelles tentatives explicites.
Installer le bundle de release Android
Téléchargez https://github.com/comstud-io/dobrodesk-mobile-sdk/releases/download/v0.2.0/dobrodesk-mobile-sdk-0.2.0-bundle.tar.gz et extrayez-le dans un répertoire stable qui ne sera ni ajouté au code source de l'app ni téléversé publiquement. L'archive conserve le dépôt Maven local sous native/maven. Enregistrez ce répertoire dans le fichier de configuration de l'hôte afin que les projets Gradle avec FAIL_ON_PROJECT_REPOS restent valides. Cette release Mobile SDK 0.2.0 ajoute des surfaces natives inline et des corrections de wrappers. Le correctif Android du stockage protégé est également inclus. L'API publique et le contrat de l'interface native restent compatibles.
Android API 26 et les versions suivantes sont prises en charge. Les artefacts de base ne proviennent pas de Maven Central. Voice et push ont des coordonnées séparées et ne doivent être ajoutés que si l'hôte prépare aussi les permissions et les fournisseurs correspondants.
Utilisez pour l'exemple Android natif la configuration hôte Android directe testée avec Android Gradle Plugin 8.13.2, Kotlin Gradle Plugin 2.2.0, Gradle 8.14.3 et Java 17 avec compileSdk 36 et minSdk 26. Pour un autre projet Android actuel, conservez les versions générées par sa release Android ou son framework lorsqu'elles sont compatibles avec le SDK.
import org.gradle.api.initialization.resolve.RepositoriesMode
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url = uri("<extracted-bundle>/native/maven") }
}
}
// android/app/build.gradle.kts
android {
compileSdk = 36
defaultConfig { minSdk = 26 }
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}Déclarer les trois artefacts Android de base
Le dépôt local extrait contient les coordonnées du moteur, du contrôleur d'interface et des AAR d'interface. Déclarez les trois dans le module de l'application. Le wrapper n'ajoute pas de dépôt au niveau du projet et n'inclut pas silencieusement les modules optionnels voice ou push.
dependencies {
implementation("com.dobrodesk:dobrodesk-sdk:0.2.0")
implementation("com.dobrodesk:dobrodesk-ui-controller:0.2.0")
implementation("com.dobrodesk:dobrodesk-ui:0.2.0")
}Présenter depuis une Activity au premier plan
Les fonctions suivantes, gérées par l'hôte, appellent votre endpoint backend de token et renvoient l'identifiant stable du client actuel ainsi que son JWT d'identité de courte durée. Le SDK ne présente le widget que lorsque l'Activity est au premier plan.
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
import com.dobrodesk.sdk.DobroDeskConfiguration
import com.dobrodesk.sdk.ui.DobroDeskAndroidClientFactory
import com.dobrodesk.sdk.ui.DobroDeskWidgetBridgePresenter
import java.time.Duration
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
private var presenter: DobroDeskWidgetBridgePresenter? = null
private val client by lazy {
DobroDeskAndroidClientFactory.create(
context = this,
configuration = DobroDeskConfiguration(
apiOrigin = "https://dobrodesk.com",
integrationId = "wgt_0123456789abcdef0123456789abcdef",
accountScope = currentCustomerId(),
credentialProvider = { loadDobroDeskToken() },
pollInterval = Duration.ofSeconds(1),
),
)
}
override fun onCreate(state: Bundle?) {
super.onCreate(state)
lifecycleScope.launch {
presenter = DobroDeskWidgetBridgePresenter.present(
activity = this@MainActivity,
client = client,
options = mapOf("locale" to "en"),
onClosed = { presenter = null },
)
}
}
override fun onDestroy() {
presenter?.detach()
presenter = null
super.onDestroy()
}
}Utiliser un déclencheur personnalisé ou une surface intégrée
Transmettez au suspend helper une Activity visible et un FrameLayout déjà attaché à window. Le helper crée les options JsonObject requises, ajoute handle.view via Dispatchers.Main.immediate et ferme le handle si l'hôte est détaché avant ou après le montage.
Le bouton personnalisé doit rester accessible au clavier et exposer aria-controls ainsi que aria-expanded. Lors d'un nouveau montage, réutilisez le même client, la même session et le même brouillon.
Les API inline font partie des artefacts publiés de Mobile SDK 0.2.0. Utilisez la surface inline lorsque l'hôte contrôle son placement et la présentation modale lorsque l'hôte doit gérer tout l'écran.
import android.app.Activity
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import com.dobrodesk.sdk.DobroDeskClient
import com.dobrodesk.sdk.ui.DobroDeskWidgetBridgePresenter
import com.dobrodesk.sdk.ui.DobroDeskWidgetEmbeddedHandle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
suspend fun mountSupportPanel(
activity: Activity,
client: DobroDeskClient,
supportContainer: FrameLayout,
): DobroDeskWidgetEmbeddedHandle? {
check(supportContainer.isAttachedToWindow) {
"Attach the support container before mounting the widget"
}
var embeddedHandle: DobroDeskWidgetEmbeddedHandle? = null
val detachListener = object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(view: View) = Unit
override fun onViewDetachedFromWindow(view: View) {
embeddedHandle?.close()
}
}
val handle = DobroDeskWidgetBridgePresenter.createEmbedded(
activity = activity,
client = client,
options = buildJsonObject {
put("locale", "en")
put("view", "home")
},
onClosed = {
supportContainer.removeOnAttachStateChangeListener(detachListener)
embeddedHandle = null
},
)
embeddedHandle = handle
var attached = false
withContext(Dispatchers.Main.immediate) {
if (supportContainer.isAttachedToWindow && !activity.isFinishing && !activity.isDestroyed) {
supportContainer.addView(
handle.view,
ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
),
)
supportContainer.addOnAttachStateChangeListener(detachListener)
handle.setVisible(true)
attached = true
}
}
if (!attached) {
handle.close()
return null
}
return handle
}Gérer le cycle Android et l'identité
credentialProvider est une fonction suspend fournie par l'hôte qui renvoie un JWT d'identité client de courte durée. Le code natif protège l'outbox durable avec Android Keystore et la limite à accountScope. Ne stockez pas de support API token dans les préférences de l'app.
Appelez presenter.close() lorsque l'écran hôte est détruit et client.resetSession() lorsqu'une conversation est abandonnée. Le client Android direct ne possède pas logout : réinitialisez-le, détruisez-le et créez un nouveau client avant de changer accountScope. Sans override explicite, le widget suit le réglage système de réduction des mouvements.
Gérer le chargement, la visibilité et l'accessibilité
Utilisez les hooks de chargement ou les événements typés pour l'état de l'écran hôte. La surface affiche elle-même le chargement des messages, l'attente et les nouvelles tentatives afin d'éviter un second indicateur sur le champ de saisie.
Masquez ou affichez la surface lors d'une navigation temporaire en conservant le client. Le widget respecte les préférences système de réduction des mouvements. Le retrait ou la fermeture ne supprime ni la session ni le brouillon.
- Lors du nouveau montage, réutilisez le même client et des dimensions stables pour le conteneur.
- Utilisez la fonction de visibilité pour un masquage temporaire, sans réinitialiser la session.
- Terminez la session uniquement lors de la déconnexion ou d'un changement de compte volontaire.
Vérifier le flux Android
- Présentez depuis une Activity au premier plan et confirmez que des appuis répétés ne créent pas de presenters superposés.
- Envoyez un message avec un idempotency key stable, mettez l'app en arrière-plan puis rouvrez-la. Confirmez que le message en attente est réessayé avec la même clé après le retour du réseau.
- Utilisez resetSession pour un abandon volontaire. Réinitialisez et détruisez le client Android direct avant de changer de compte, créez un nouveau client et confirmez que le compte suivant commence avec une conversation vide.
