Skip to content

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:

kotlin
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)
java
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:

kotlin
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())
java
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ámetroTipoValor predeterminadoDescripción
enableDelayedSendingBooleantrueHabilita o deshabilita la cola de solicitudes cuando la red no está disponible. Si es false, las solicitudes fallidas se descartan inmediatamente.
maxPendingTimeMillisLong600000 (10 min)Tiempo máximo durante el que se conservan las solicitudes pendientes antes de descartarlas.
autoRetryOnNetworkRecoveryBooleantrueReintenta 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 enableDelayedSending es true.

Resumen del comportamiento

Estado de la redenableDelayedSendingComportamiento
Disponibletrue o falseLa solicitud se envía inmediatamente.
No disponibletrueLa solicitud se guarda para entregarla después.
No disponiblefalseLa 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:

kotlin
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:

kotlin
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:

kotlin
override fun onRequestQueued(materialId: String, queueCount: Int) {
    if (queueCount > 5) {
        // Many requests are pending, consider notifying the user
        showPendingRequestsNotification(queueCount)
    }
}

Cómo funciona

  1. Fase de detección: cuando se reconoce audio, el SDK intenta publicar la actividad en el servidor.
  2. Comprobación de la red: antes de enviar, el SDK comprueba la disponibilidad de la red.
  3. Puesta en cola si falla: si la red no está disponible, la solicitud se añade a una cola en memoria.
  4. Supervisión de la red: el SDK supervisa los cambios del estado de la red mediante ConnectivityManager de Android.
  5. Reintento automático: cuando la red vuelve a estar disponible, las solicitudes en cola se procesan automáticamente.
  6. 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:

xml
<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:

kotlin
val config = SORIConfig(enableDelayedSending = true)
sori.setConfig(config)

Las solicitudes en cola no se envían

  1. Verifique que autoRetryOnNetworkRecovery esté habilitado.
  2. Compruebe que su aplicación tenga el permiso ACCESS_NETWORK_STATE.
  3. 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:

kotlin
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
            }
        }
    }
}
java
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);
            }
        });
    }
}