Gestión de red y compatibilidad sin conexión
Descripción general
SORI SDK procesa el reconocimiento de audio en el dispositivo. Sin embargo, necesita una conexión a Internet para recibir las campañas asociadas, cargar los recursos de imagen relacionados y retransmitir webhooks. Cuando el reconocimiento de audio se completa correctamente, pero la red no está disponible durante el procesamiento, el SDK proporciona varios métodos para gestionar esta situación.
Funciones
- Detección automática de la red: el SDK supervisa en tiempo real los cambios de conectividad de red.
- Cola de solicitudes: las solicitudes que fallan por problemas de red se guardan en una cola en memoria.
- Reintento automático: las solicitudes en cola se procesan automáticamente cuando la red vuelve a estar disponible.
- Comportamiento configurable: puede personalizar la forma en que el SDK gestiona los fallos de red.
- Caducidad temporal: las solicitudes con más de 10 minutos de antigüedad se descartan automáticamente.
Configuración
Puede configurar la gestión de red mediante la clase SORIConfig:
import com.iplateia.sorisdk.SORIConfig
import com.iplateia.sorisdk.SORIAudioRecognizer
// Create a custom configuration
val config = SORIConfig(
enableDelayedSending = true, // Enable request queuing
maxPendingTimeMillis = 600000L, // 10 minutes (default)
autoRetryOnNetworkRecovery = true // Auto-retry when network returns
)
// Apply configuration to the recognizer
val sori = SORIAudioRecognizer(
"YOUR_SORI_API_KEY",
"YOUR_SORI_SECRET_KEY"
)
sori.setConfig(config)import com.iplateia.sorisdk.SORIConfig;
import com.iplateia.sorisdk.SORIAudioRecognizer;
// Create a custom configuration
SORIConfig config = new SORIConfig(
true, // enableDelayedSending
600000L, // maxPendingTimeMillis (10 minutes)
true // autoRetryOnNetworkRecovery
);
// Apply configuration to the recognizer
SORIAudioRecognizer sori = new SORIAudioRecognizer(
"YOUR_SORI_API_KEY",
"YOUR_SORI_SECRET_KEY"
);
sori.setConfig(config);Gestionar eventos de red
El SDK proporciona callbacks para notificar a su aplicación los eventos relacionados con la red mediante la interfaz ISORIListener:
import com.iplateia.sorisdk.ISORIListener
import com.iplateia.sorisdk.SORICampaign
class MyListener : ISORIListener {
override fun onReady() {
// SDK is ready
}
override fun onStateChanged(state: String) {
// Service state changed
}
override fun onError(error: String) {
// An error occurred
}
override fun onCampaignFound(campaign: SORICampaign) {
// Campaign detected successfully
}
override fun onNetworkError(materialId: String, error: String) {
// Network error occurred while posting activity
Log.w("SORI", "Network error for material $materialId: $error")
// You can show a user-friendly message here
}
override fun onRequestQueued(materialId: String, queueCount: Int) {
// Request has been queued for later delivery
Log.i("SORI", "Request queued for material $materialId. Queue size: $queueCount")
// You can notify the user that the request will be sent later
}
}
// Set the listener
sori.setListener(context, MyListener())import com.iplateia.sorisdk.ISORIListener;
import com.iplateia.sorisdk.SORICampaign;
import android.util.Log;
public class MyListener implements ISORIListener {
@Override
public void onReady() {
// SDK is ready
}
@Override
public void onStateChanged(String state) {
// Service state changed
}
@Override
public void onError(String error) {
// An error occurred
}
@Override
public void onCampaignFound(SORICampaign campaign) {
// Campaign detected successfully
}
@Override
public void onNetworkError(String materialId, String error) {
// Network error occurred while posting activity
Log.w("SORI", "Network error for material " + materialId + ": " + error);
// You can show a user-friendly message here
}
@Override
public void onRequestQueued(String materialId, int queueCount) {
// Request has been queued for later delivery
Log.i("SORI", "Request queued for material " + materialId +
". Queue size: " + queueCount);
// You can notify the user that the request will be sent later
}
}
// Set the listener
sori.setListener(context, new MyListener());Opciones de configuración
Parámetros de SORIConfig
| Parámetro | Tipo | Valor predeterminado | Descripción |
|---|---|---|---|
enableDelayedSending | Boolean | true | Habilita o deshabilita la cola de solicitudes cuando la red no está disponible. Si es false, las solicitudes fallidas se descartan inmediatamente. |
maxPendingTimeMillis | Long | 600000 (10 min) | Tiempo máximo durante el que se conservan las solicitudes pendientes antes de descartarlas. |
autoRetryOnNetworkRecovery | Boolean | true | Reintenta automáticamente las solicitudes en cola cuando la red vuelve a estar disponible. Si es false, las solicitudes permanecen en memoria, pero deben procesarse manualmente. Solo tiene efecto si enableDelayedSending es true. |
Comprender las opciones de configuración
Las dos opciones booleanas tienen propósitos diferentes:
enableDelayedSending: controla si se guardan las solicitudes fallidas en una cola cuando la red no está disponible.true: guarda las solicitudes fallidas para enviarlas más tarde cuando la red no está disponible.false: descarta inmediatamente las solicitudes fallidas cuando la red no está disponible.- Nota: cuando la red está disponible, las solicitudes siempre se envían inmediatamente, independientemente de este ajuste.
autoRetryOnNetworkRecovery: controla qué ocurre cuando se restablece la red.true: procesa automáticamente las solicitudes en cola cuando vuelve la red.false: mantiene las solicitudes en la cola, pero no las procesa automáticamente (requiere intervención manual).- Nota: este ajuste solo tiene efecto cuando
enableDelayedSendingestrue.
Resumen del comportamiento
| Estado de la red | enableDelayedSending | Comportamiento |
|---|---|---|
| Disponible | true o false | La solicitud se envía inmediatamente. |
| No disponible | true | La solicitud se guarda para entregarla después. |
| No disponible | false | La solicitud se descarta. |
La mayoría de las aplicaciones utilizarán ambos ajustes con el mismo valor (true para un comportamiento resistente y false para gestionar los fallos inmediatamente).
Prácticas recomendadas
1. Informar al usuario
Informe siempre a los usuarios cuando se produzcan problemas de red:
override fun onNetworkError(materialId: String, error: String) {
runOnUiThread {
Toast.makeText(
context,
"Network unavailable. Will retry when connection is restored.",
Toast.LENGTH_SHORT
).show()
}
}2. Deshabilitar la cola para operaciones urgentes
Si su caso de uso requiere una entrega inmediata, puede deshabilitar la cola:
val config = SORIConfig(
enableDelayedSending = false // Disable queuing
)3. Supervisar el estado de la cola
Lleve un seguimiento de las solicitudes pendientes para informar a los usuarios:
override fun onRequestQueued(materialId: String, queueCount: Int) {
if (queueCount > 5) {
// Many requests are pending, consider notifying the user
showPendingRequestsNotification(queueCount)
}
}Cómo funciona
- Fase de detección: cuando se reconoce audio, el SDK intenta publicar la actividad en el servidor.
- Comprobación de la red: antes de enviar, el SDK comprueba la disponibilidad de la red.
- Puesta en cola si falla: si la red no está disponible, la solicitud se añade a una cola en memoria.
- Supervisión de la red: el SDK supervisa los cambios del estado de la red mediante
ConnectivityManagerde Android. - Reintento automático: cuando la red vuelve a estar disponible, las solicitudes en cola se procesan automáticamente.
- Comprobación de caducidad: se descartan las solicitudes que superan el tiempo de espera configurado.
Permisos necesarios
El SDK necesita los siguientes permisos para gestionar la red:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />Estos permisos ya se incluyen en el manifiesto del SDK y se combinarán automáticamente con su aplicación.
Solución de problemas
Las solicitudes no se añaden a la cola
Asegúrese de que el envío diferido esté habilitado:
val config = SORIConfig(enableDelayedSending = true)
sori.setConfig(config)Las solicitudes en cola no se envían
- Verifique que
autoRetryOnNetworkRecoveryesté habilitado. - Compruebe que su aplicación tenga el permiso
ACCESS_NETWORK_STATE. - Asegúrese de que las solicitudes no hayan caducado (de forma predeterminada, después de 10 minutos).
Consideraciones sobre la memoria
La cola de solicitudes se conserva en memoria. Si el sistema cierra su aplicación, se perderán las solicitudes en cola. Para operaciones críticas, considere implementar su propio mecanismo de almacenamiento persistente.
Ejemplo: implementación completa
Este es un ejemplo completo que muestra cómo implementar la gestión de red:
class MainActivity : AppCompatActivity() {
private lateinit var sori: SORIAudioRecognizer
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Initialize SORI with custom configuration
initializeSori()
}
private fun initializeSori() {
// Create configuration
val config = SORIConfig(
enableDelayedSending = true,
maxPendingTimeMillis = 600000L, // 10 minutes
autoRetryOnNetworkRecovery = true
)
// Create recognizer
sori = SORIAudioRecognizer(
BuildConfig.SORI_API_KEY,
BuildConfig.SORI_SECRET_KEY
)
// Apply configuration
sori.setConfig(config)
// Set listener
sori.setListener(this, object : ISORIListener {
override fun onReady() {
Log.d("SORI", "SDK is ready")
}
override fun onStateChanged(state: String) {
Log.d("SORI", "State changed: $state")
}
override fun onError(error: String) {
Log.e("SORI", "Error: $error")
}
override fun onCampaignFound(campaign: SORICampaign) {
Log.i("SORI", "Campaign found: ${campaign.name}")
// Handle the campaign
handleCampaign(campaign)
}
override fun onNetworkError(materialId: String, error: String) {
Log.w("SORI", "Network error: $error")
// Show user-friendly message
showNetworkErrorMessage()
}
override fun onRequestQueued(materialId: String, queueCount: Int) {
Log.i("SORI", "Request queued. Total pending: $queueCount")
// Update UI to show pending status
updatePendingRequestsUI(queueCount)
}
})
// Start recognition
sori.startRecognition(this)
}
private fun handleCampaign(campaign: SORICampaign) {
// Your campaign handling logic
}
private fun showNetworkErrorMessage() {
runOnUiThread {
Toast.makeText(
this,
"Network unavailable. Campaign will be processed when connection is restored.",
Toast.LENGTH_LONG
).show()
}
}
private fun updatePendingRequestsUI(count: Int) {
runOnUiThread {
// Update your UI to show pending requests
val pendingIndicator = findViewById<TextView>(R.id.pendingIndicator)
if (count > 0) {
pendingIndicator.visibility = View.VISIBLE
pendingIndicator.text = "$count pending"
} else {
pendingIndicator.visibility = View.GONE
}
}
}
}public class MainActivity extends AppCompatActivity {
private SORIAudioRecognizer sori;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initialize SORI with custom configuration
initializeSori();
}
private void initializeSori() {
// Create configuration
SORIConfig config = new SORIConfig(
true, // enableDelayedSending
600000L, // maxPendingTimeMillis (10 minutes)
true // autoRetryOnNetworkRecovery
);
// Create recognizer
sori = new SORIAudioRecognizer(
BuildConfig.SORI_API_KEY,
BuildConfig.SORI_SECRET_KEY
);
// Apply configuration
sori.setConfig(config);
// Set listener
sori.setListener(this, new ISORIListener() {
@Override
public void onReady() {
Log.d("SORI", "SDK is ready");
}
@Override
public void onStateChanged(String state) {
Log.d("SORI", "State changed: " + state);
}
@Override
public void onError(String error) {
Log.e("SORI", "Error: " + error);
}
@Override
public void onCampaignFound(SORICampaign campaign) {
Log.i("SORI", "Campaign found: " + campaign.getName());
// Handle the campaign
handleCampaign(campaign);
}
@Override
public void onNetworkError(String materialId, String error) {
Log.w("SORI", "Network error: " + error);
// Show user-friendly message
showNetworkErrorMessage();
}
@Override
public void onRequestQueued(String materialId, int queueCount) {
Log.i("SORI", "Request queued. Total pending: " + queueCount);
// Update UI to show pending status
updatePendingRequestsUI(queueCount);
}
});
// Start recognition
sori.startRecognition(this);
}
private void handleCampaign(SORICampaign campaign) {
// Your campaign handling logic
}
private void showNetworkErrorMessage() {
runOnUiThread(() -> {
Toast.makeText(
this,
"Network unavailable. Campaign will be processed when connection is restored.",
Toast.LENGTH_LONG
).show();
});
}
private void updatePendingRequestsUI(int count) {
runOnUiThread(() -> {
// Update your UI to show pending requests
TextView pendingIndicator = findViewById(R.id.pendingIndicator);
if (count > 0) {
pendingIndicator.setVisibility(View.VISIBLE);
pendingIndicator.setText(count + " pending");
} else {
pendingIndicator.setVisibility(View.GONE);
}
});
}
}