SDK para Android
Instalar
Este guia usa o Android SDK 0.2.1 com o Java SDK 2.2.4. O pacote Android é um AAR,
disponível no Maven Central.
Seu POM declara as dependências do Java SDK, do tus e do WorkManager, então o Gradle e o Maven as
adicionam automaticamente para você.
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 as interações com o SDK começam pela classe com.transloadit.android.sdk.AndroidTransloadit.
Métodos de autenticação
Mantenha o Auth Secret no seu backend, inclusive em apps distribuídos internamente. O conteúdo do APK e as configurações baixadas não conseguem mantê-lo confidencial. Exija Signature Authentication para o Workspace ou Template usado pelo app. A Auth Key pode ser fornecida ao app; o Auth Secret nunca deve ser fornecido a ele.
O construtor com chave e segredo não é adequado para um cliente Android. Aplicações de servidor confiáveis podem usar o Java SDK com credenciais mantidas no servidor.
Signature Authentication no backend
O SDK chama SignatureProvider.generateSignature de forma síncrona com o
params serializado exato que vai enviar. Ele adiciona
auth, um nonce novo e uma expiração de cinco
minutos no futuro, com o construtor usado abaixo. Seu backend precisa validar essa expiração com o
próprio relógio. Não analise e reserialize a string antes de assinar, nem reutilize uma assinatura
para params diferentes.
Antes de usar o helper abaixo, implemente a interface SigningBackend usando o
cliente HTTPS autenticado do seu app. Essa interface é uma fronteira de integração da aplicação,
não um serviço do SDK. Envie o paramsJson inalterado ao seu próprio backend e
o token de sessão do usuário atual no cabeçalho Authorization da requisição. Use
um endpoint fixo e confiável, rejeite redirecionamentos, limite o timeout da requisição e lance uma
exceção em caso de erros de transporte ou de qualquer resposta HTTP sem sucesso. Retorne a string
de params aprovada pelo backend e a assinatura como SignedParams; nunca retorne o
Auth Secret.
O backend precisa autenticar a sessão e autorizar o upload desse usuário antes de assinar. Permita
apenas a Auth Key esperada, um nonce novo, a expiração e exatamente o Step de redimensionamento
abaixo; rejeite Steps adicionais, Templates arbitrários, campos ou destinos. Aplique seus limites
de upload e sua política de cota no servidor. Para um Template controlado pelo servidor, desative
allow_steps_override e permita apenas esse Template. Estar logado não é permissão para
assinar JSON arbitrário. Assine os bytes UTF-8 originais aprovados com HMAC-SHA384 e retorne um
prefixo sha384: seguido dos 96 dígitos hexadecimais.
Criar uma Assembly
Salve este helper completo como MobileImageUpload.java. Ele vincula cada assinatura
retornada aos params exatos do SDK e recusa sessões ausentes, params divergentes e assinaturas
malformadas. O backend continua responsável pela autorização; essas verificações no cliente não
podem substituí-la.
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);
}
}
Passe sua Auth Key, o token de sessão do usuário atual e a implementação do backend para
MobileImageUpload.createClient. O token autentica a requisição ao seu próprio backend; ele não é
um Auth Secret da Transloadit nem um token da API da Transloadit. Renove uma sessão expirada antes
de criar um novo cliente. O SDK constrói auth por conta própria, então o
callback de assinatura não pode adicionar auth.max_size nem
auth.max_number_of_files. Se a sua política exigir esses limites, aplique-os em um Template
controlado pelo servidor ou use a criação de Assemblies no backend. O número de arquivos
adicionados localmente não é um limite de autorização do servidor.
Crie uma instância de AndroidAssembly com client.newAssembly(listener, context), passe
essa instância e uma imagem local legível para MobileImageUpload.addImage e depois chame
assembly.saveAsync(). Forneça um AndroidAssemblyListener que implemente
onUploadProgress, onUploadFinished,
onAssemblyFinished, onUploadFailed e onAssemblyStatusUpdateFailed. A
conclusão do upload é separada da conclusão do processamento. Verifique
status() e hasError() da resposta retornada, além de
tratar exceções; erros da API nem sempre são lançados.
A assinatura é executada de forma síncrona na thread de quem faz a chamada.
saveAsync() executa o envio da Assembly no executor do SDK, mas chamadas
síncronas diretas ao SDK precisam rodar fora da thread de UI. Os callbacks do listener usam a
thread principal por padrão. Mantenha a Assembly e o listener em um lifecycle owner adequado,
evite reter uma Activity destruída e gerencie o cancelamento e o trabalho em segundo plano no seu
app. O SDK também oferece suporte a uploads em segundo plano via WorkManager, como mostrado
abaixo. O comportamento em dispositivos e ao longo do ciclo de vida precisa ser testado na sua
aplicação Android.
Uploads em segundo plano com WorkManager
Use AndroidAssemblyWorkConfig para enfileirar uma AndroidAssemblyUploadWorker pelo
WorkManager. O worker usa tus e SharedPreferences para uploads retomáveis. Mantenha o arquivo
local disponível até a tarefa terminar.
O WorkManager persiste os cabeçalhos de assinatura nos dados da tarefa. Use um
uploadToken emitido pelo seu backend, restrito a este upload e válido durante
todo o tempo de vida agendado da tarefa. Se ele expirar ou for rejeitado, o worker faz a tarefa
falhar; enfileire uma nova requisição com credenciais novas. Renovar a sessão do app não atualiza
as credenciais de tarefas já enfileiradas.
O worker envia os params serializados do SDK como corpo UTF-8 de um POST
application/json. Configure um endpoint de assinatura HTTPS fixo que responda
diretamente, sem redirecionamentos. Aplique a política de autorização do backend descrita acima,
assine o corpo da requisição sem alterações e retorne um objeto JSON com um campo
signature.
Use um Template controlado pelo servidor que contenha os Steps de redimensionamento aprovados. Seu
backend precisa permitir exatamente esse Template e a URL de notificação. O SDK adiciona
auth quando o worker envia a Assembly.
Crie paramsJson com as opções aprovadas:
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());
Com waitForCompletion(true), a tarefa aguarda até a Assembly terminar. O SDK lê a URL de
status da Assembly diretamente, então seu backend só precisa assinar a criação da Assembly. Com
waitForCompletion(false), como neste exemplo, a tarefa termina após o upload; acompanhe o
processamento no seu backend usando Assembly Notifications com um notify_url
aprovado nos seus params.
Exemplo
Os exemplos com tag ilustram a integração com Android. Aplique os requisitos de assinatura no backend descritos acima a qualquer exemplo que você adaptar; não copie segredos do lado do app de exemplos mais antigos.
Documentação
Consulte o Javadoc para ver a documentação completa da API.