SDK para Android
Instalación
Esta guía usa el Android SDK 0.2.1 con el Java SDK 2.2.4. El paquete de Android es un AAR,
disponible en Maven Central.
Su POM declara las dependencias del Java SDK, tus y WorkManager, así que Gradle y Maven las
agregan automáticamente.
Gradle:
implementation 'com.transloadit.android.sdk:transloadit-android:0.2.1'
Maven:
<dependency>
<groupId>com.transloadit.android.sdk</groupId>
<artifactId>transloadit-android</artifactId>
<version>0.2.1</version>
<type>aar</type>
</dependency>
Uso
Todas las interacciones con el SDK comienzan con la clase com.transloadit.android.sdk.AndroidTransloadit.
Métodos de autenticación
Mantén el Auth Secret en tu backend, incluso en apps de distribución interna. Ni el contenido del APK ni la configuración descargada pueden mantenerlo confidencial. Exige Signature Authentication para el Workspace o el Template que usa la app. La Auth Key puede proporcionarse a la app; el Auth Secret nunca debe proporcionarse a ella.
El constructor con clave y secreto no es adecuado para un cliente Android. Las aplicaciones de servidor de confianza pueden usar el Java SDK con credenciales guardadas en el servidor.
Signature Authentication en el backend
El SDK llama a SignatureProvider.generateSignature de forma síncrona con el
params serializado exacto que enviará. Con el constructor que se usa a
continuación, agrega auth, un nonce nuevo y una
expiración de cinco minutos en el futuro. Tu backend debe validar esa expiración con su propio reloj.
No analices ni vuelvas a serializar la cadena antes de firmarla, ni reutilices una firma para params
diferentes.
Antes de usar el helper siguiente, implementa su interfaz SigningBackend con el
cliente HTTPS autenticado de tu app. Esta interfaz es un límite de integración de la aplicación, no
un servicio del SDK. Envía el paramsJson sin cambios a tu propio backend y el
token de sesión del usuario actual en el encabezado Authorization de la solicitud.
Usa un endpoint fijo y de confianza, rechaza las redirecciones, limita el tiempo de espera de la
solicitud y lanza una excepción ante errores de transporte o ante cualquier respuesta HTTP no
exitosa. Devuelve la cadena de params y la firma aprobadas por el backend como
SignedParams; nunca devuelvas el Auth Secret.
El backend debe autenticar la sesión y autorizar la subida de este usuario antes de firmar. Permite
solo la Auth Key esperada, un nonce nuevo, la expiración y el Step de redimensionamiento exacto que
aparece a continuación; rechaza Steps adicionales, Templates arbitrarios, campos o destinos. Aplica
tus límites de subida y tu política de cuotas en el servidor. Para un Template propiedad del
servidor, desactiva allow_steps_override y permite solo ese Template. Haber iniciado
sesión no otorga permiso para firmar JSON arbitrario. Firma los bytes UTF-8 originales aprobados con
HMAC-SHA384 y devuelve un prefijo sha384: seguido de los 96 dígitos
hexadecimales.
Crear una Assembly
Guarda este helper completo como MobileImageUpload.java. Vincula cada firma devuelta a los
params exactos del SDK y rechaza sesiones ausentes, params que no coinciden y firmas mal formadas.
La autorización sigue correspondiendo al backend; estas comprobaciones del cliente no pueden
reemplazarla.
import com.transloadit.android.sdk.AndroidTransloadit;
import com.transloadit.sdk.Assembly;
import com.transloadit.sdk.SignatureProvider;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public final class MobileImageUpload {
private MobileImageUpload() {}
public static final class SignedParams {
public final String params;
public final String signature;
public SignedParams(String params, String signature) {
this.params = params;
this.signature = signature;
}
}
@FunctionalInterface
public interface SigningBackend {
SignedParams approve(String paramsJson, String userSessionToken) throws Exception;
}
public static AndroidTransloadit createClient(
String authKey, String userSessionToken, SigningBackend backend) {
Objects.requireNonNull(backend, "A signing backend is required");
if (userSessionToken == null || userSessionToken.trim().isEmpty()) {
throw new IllegalArgumentException("An authenticated user session is required");
}
SignatureProvider signatures = paramsJson -> {
SignedParams approved = backend.approve(paramsJson, userSessionToken);
if (approved == null || !paramsJson.equals(approved.params)
|| approved.signature == null
|| !approved.signature.matches("sha384:[0-9a-f]{96}")) {
throw new IllegalStateException("Signing was not approved for these parameters");
}
return approved.signature;
};
return new AndroidTransloadit(authKey, signatures);
}
public static void addImage(Assembly assembly, File image) {
assembly.addFile(image, "image");
Map<String, Object> stepOptions = new HashMap<>();
stepOptions.put("width", 75);
stepOptions.put("height", 75);
stepOptions.put("resize_strategy", "pad");
assembly.addStep("resize", "/image/resize", stepOptions);
}
}
Pasa tu Auth Key, el token de sesión del usuario actual y la implementación del backend a
MobileImageUpload.createClient. El token autentica la solicitud a tu propio backend; no es un Auth
Secret de Transloadit ni un token de la API de Transloadit. Renueva una sesión expirada antes de
crear un nuevo cliente. El SDK construye auth por sí mismo, por lo que el
callback de firma no puede agregar auth.max_size ni
auth.max_number_of_files. Si tu política exige esos límites, aplícalos en un Template
propiedad del servidor o crea la Assembly desde el backend. La cantidad de archivos agregados
localmente no es un límite de autorización del servidor.
Crea un AndroidAssembly con client.newAssembly(listener, context), pásalo junto con una
imagen local legible a MobileImageUpload.addImage y luego llama a
assembly.saveAsync(). Proporciona un AndroidAssemblyListener que implemente
onUploadProgress, onUploadFinished, onAssemblyFinished,
onUploadFailed y onAssemblyStatusUpdateFailed. La finalización de la subida es
independiente de la finalización del procesamiento. Además de manejar las excepciones, revisa
status() y hasError() en la respuesta devuelta; los
errores de la API no siempre se lanzan como excepciones.
La firma realiza trabajo síncrono en el hilo del llamador. saveAsync() ejecuta
el envío de la Assembly en el executor del SDK, pero las llamadas síncronas directas al SDK deben
ejecutarse fuera del hilo de la UI. Los callbacks del listener usan el hilo principal de forma
predeterminada. Mantén la Assembly y el listener en un propietario de ciclo de vida adecuado, evita
retener una Activity destruida y gestiona la cancelación y el trabajo en segundo plano en tu app. El
SDK también admite subidas en segundo plano mediante WorkManager, como se muestra a continuación. El
comportamiento según el dispositivo y el ciclo de vida debe probarse en tu aplicación Android.
Subidas en segundo plano con WorkManager
Usa AndroidAssemblyWorkConfig para poner en cola un AndroidAssemblyUploadWorker mediante
WorkManager. El worker usa el protocolo tus y SharedPreferences para las subidas reanudables.
Mantén el archivo local disponible hasta que termine el trabajo.
WorkManager almacena de forma persistente los encabezados de firma en los datos del trabajo. Usa un
uploadToken emitido por tu backend, limitado a esta subida y válido durante toda
la vida programada del trabajo. Si expira o se rechaza, el worker hace fallar el trabajo; pon en
cola una nueva solicitud con credenciales nuevas. Renovar la sesión de la app no actualiza las
credenciales de los trabajos en cola.
El worker envía los params serializados del SDK como cuerpo UTF-8 de una solicitud POST
application/json. Configura un endpoint de firma HTTPS fijo que responda directamente
sin redirecciones. Aplica la política de autorización del backend descrita arriba, firma el cuerpo
de la solicitud sin cambios y devuelve un objeto JSON con un campo signature.
Usa un Template propiedad del servidor que contenga los Steps de redimensionamiento aprobados. Tu
backend debe permitir exactamente ese Template y esa URL de notificación. El SDK agrega
auth cuando el worker envía la Assembly.
Crea paramsJson con las opciones aprobadas:
import androidx.work.WorkManager;
import com.transloadit.android.sdk.AndroidAssemblyWorkConfig;
String paramsJson = "{\"template_id\":\"YOUR_APPROVED_TEMPLATE_ID\","
+ "\"notify_url\":\"https://your-backend.example/transloadit-notify\"}";
AndroidAssemblyWorkConfig config = AndroidAssemblyWorkConfig
.newBuilder(authKey)
.signatureProvider("https://your-backend.example/sign")
.addSignatureProviderHeader("Authorization", "Bearer " + uploadToken)
.paramsJson(paramsJson)
.preferenceName("image_uploads")
.addFile(image, "image")
.waitForCompletion(false)
.build();
WorkManager.getInstance(context).enqueue(config.toWorkRequest());
Con waitForCompletion(true), el trabajo espera hasta que la Assembly finalice. El SDK lee
directamente la URL de estado de la Assembly, por lo que tu backend solo necesita firmar la
creación de la Assembly. Con waitForCompletion(false), como en este ejemplo, el trabajo
finaliza después de la subida; haz el seguimiento del procesamiento en tu backend mediante Assembly
Notifications con un notify_url aprobado en tus params.
Ejemplo
Los ejemplos etiquetados ilustran la integración con Android. Aplica los requisitos de firma en el backend descritos arriba a cualquier ejemplo que adaptes; no copies secretos del lado de la app de ejemplos anteriores.
Documentación
Consulta el Javadoc para ver la documentación completa de la API.