A sua app Android apresenta o widget DobroDesk com estado protegido por conta e repetições explícitas.
Instalar o bundle de release Android
Descarregue https://github.com/comstud-io/dobrodesk-mobile-sdk/releases/download/v0.2.0/dobrodesk-mobile-sdk-0.2.0-bundle.tar.gz e extraia-o para um diretório estável que não seja incluído no código fonte da app nem num upload público. O arquivo mantém o repositório Maven local em native/maven. Registe esse diretório no ficheiro de definições do host para que projetos Gradle com FAIL_ON_PROJECT_REPOS continuem válidos. Esta release do Mobile SDK 0.2.0 adiciona superfícies nativas inline e correções dos wrappers. A correção Android para armazenamento protegido também está incluída. A API pública e o contrato da UI nativa continuam compatíveis.
Android API 26 e posteriores são suportados. Os artefactos base não são obtidos do Maven Central. Voice e push têm coordenadas separadas e não devem ser adicionados salvo se o host também preparar as permissões e fornecedores correspondentes.
Use para o exemplo Android nativo a combinação testada do host Android direto: Android Gradle Plugin 8.13.2, Kotlin Gradle Plugin 2.2.0, Gradle 8.14.3 e Java 17 com compileSdk 36 e minSdk 26. Noutro projeto Android atual, mantenha as versões geradas pela respetiva release Android ou framework quando forem compatíveis com o 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
}
}Declarar os três artefactos base Android
O repositório local extraído contém as coordenadas do motor, do controlador UI e do UI AAR. Declare os três no módulo da app. O wrapper não adiciona um repositório ao nível do projeto nem inclui silenciosamente os módulos voice e push opcionais.
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")
}Apresentar a partir de uma Activity em primeiro plano
As funções do host abaixo chamam o endpoint de token do seu backend e devolvem o ID estável do cliente atual e o JWT de identidade de curta duração. O SDK apresenta apenas enquanto a Activity está em primeiro plano.
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()
}
}Usar um acionador personalizado ou uma superfície integrada
Passe ao suspend helper uma Activity visível e um FrameLayout já ligado à window. O helper cria as opções JsonObject necessárias, adiciona handle.view através de Dispatchers.Main.immediate e fecha o handle se o host for desligado antes ou depois da montagem.
O botão personalizado deve ser acessível pelo teclado e expor aria-controls e aria-expanded. Ao montar novamente, reutilize o mesmo cliente, a mesma sessão e o mesmo rascunho.
As APIs inline fazem parte dos artefactos publicados do Mobile SDK 0.2.0. Use a superfície inline quando o host controla o posicionamento e a apresentação modal quando o host precisa de gerir o ecrã inteiro.
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
}Tratar ciclo Android e identidade
credentialProvider é uma função suspend fornecida pelo host que devolve um JWT de identidade do cliente de curta duração. O código nativo protege a outbox durável com Android Keystore e associa-a a accountScope. Não guarde um support API token nas preferências da app.
Chame presenter.close() quando o ecrã do host for eliminado e client.resetSession() quando uma conversa for descartada. O cliente Android direto não tem logout: reinicie-o, elimine-o e crie um novo cliente antes de alterar accountScope. Sem override explícito, o widget segue a definição do sistema para reduzir movimento.
Tratar carregamento, visibilidade e acessibilidade
Use hooks de carregamento ou eventos tipados para o estado da tela hospedeira. A superfície mostra o carregamento das mensagens, a espera e as tentativas novamente para evitar um segundo indicador sobre o campo de entrada.
Oculte ou mostre a superfície durante uma navegação temporária mantendo o cliente. O widget respeita as preferências do sistema para reduzir movimento. Remover ou fechar a vista não descarta a sessão nem o rascunho.
- Ao montar novamente, reutilize o mesmo cliente e dimensões estáveis do contêiner.
- Use a função de visibilidade para ocultar temporariamente, sem redefinir a sessão.
- Finalize a sessão apenas ao sair ou trocar de conta de forma intencional.
Verificar o fluxo Android
- Apresente a partir de uma Activity em primeiro plano e confirme que toques repetidos não criam presenters sobrepostos.
- Envie uma mensagem com idempotency key estável, envie a app para segundo plano e abra-a novamente. Confirme que a mensagem pendente é repetida com a mesma chave quando a rede voltar.
- Use resetSession para um descarte deliberado. Reinicie e elimine o cliente Android direto antes de mudar de conta, crie um novo cliente e confirme que a conta seguinte começa com uma conversa vazia.
