Pitch: PhotoCleaner+ — esconder dados pessoais em fotos e PDFs sem enviar nada para servidor (Android)
Desenvolvo sozinho apps utilitários para Android e Windows (CodeDAC). Aqui vai como fiz o PhotoCleaner+, um app que encontra dados pessoais em fotos e PDFs — rostos, QR codes, telefones, e-mails, números de cartão — e cobre tudo com caixas. Divido em quatro partes: detecção sem servidor, evitar que o que foi coberto possa ser recuperado, as armadilhas do PDF e os padrões de texto.
1. A imagem não sai do aparelho
Se o objetivo é esconder dados pessoais, mandar a foto para um servidor para encontrá-los não faz sentido. Toda a detecção usa os modelos embutidos (bundled) do ML Kit:
- Reconhecimento de texto (latino, coreano, japonês, chinês), detecção de rostos e leitura de códigos de barras/QR rodam em paralelo, e os resultados são unidos no final. Se um falhar, os outros continuam valendo.
- Os modelos vêm dentro do app, então não há download na primeira execução.
- A classificação do texto (o que é telefone, e-mail etc.) é feita com expressões regulares, sem rede.
- O app não pede permissão de acesso às fotos. O arquivo chega pelo menu de compartilhar ou pelo seletor de arquivos do sistema (SAF), só o arquivo que o usuário escolheu.
Usei OpenDocument do SAF em vez do Photo Picker por um motivo simples: o Photo Picker não deixa escolher PDF.
2. Evitar o "cobri, mas dá para recuperar"
O pior que um app desses pode fazer é parecer que escondeu algo e deixar o original no arquivo.
- A cobertura é sempre um retângulo de cor sólida e opaca. Não há opção de mosaico nem de desfoque. A cor pode ser trocada (Pro), mas o alfa é forçado para
0xFFao salvar, então nunca fica semitransparente. - Não é uma camada por cima: o bitmap é copiado, os pixels são sobrescritos com
drawRecte o resultado é codificado de novo em JPEG. Os pixels originais da área coberta não existem no arquivo salvo. - As caixas detectadas ganham uma margem para cobrir as bordas das letras (texto 15%, rostos 8%, códigos 6%).
- Como a imagem é recodificada do zero, o EXIF não vai junto: localização GPS, data e modelo da câmera ficam fora do arquivo salvo. Se a foto original tiver localização, o editor avisa.
3. Armadilhas do PDF
O PDF é renderizado página a página com PdfRenderer, coberto e montado de novo com PdfDocument. Três problemas:
- Fundo transparente vira preto. O
PdfRendererdesenha sobre fundo transparente; salvando direto em JPEG, o transparente fica preto. A página é pintada de branco antes de renderizar. - Camada de texto. Se você só desenha a caixa sobre o PDF original, o texto embaixo continua selecionável e pesquisável. O PDF de saída é feito de imagens das páginas, então a camada de texto original não sobrevive. Em troca, não dá para pesquisar texto no PDF gerado.
- Páginas que o usuário não abriu. Num PDF de várias páginas, se a pessoa olhou só até a página 3 e salvou, as seguintes ainda não foram analisadas. Na hora de salvar, as páginas pendentes são analisadas na hora; se alguma não ficar pronta, o salvamento é cancelado inteiro, para nunca sair uma página sem cobertura.
O PdfRenderer não é thread-safe e só permite uma página aberta por vez, por isso todo trabalho pesado passa por um único executor de uma thread. Como uma gravação travada no armazenamento deixava o indicador de carregamento girando para sempre, a exportação tem um watchdog de 20 segundos que troca o executor travado por um novo.
4. Padrões de texto
- Cartão só conta se passar no Luhn; IBAN, no mod-97. Dezesseis dígitos não bastam.
- Conta bancária só perto de uma palavra-chave (hoje: "account", "bank", "IBAN" e equivalentes em coreano, japonês e chinês). No começo, bastava a palavra-chave aparecer uma vez na página para todo número virar conta bancária — num extrato, tudo ficava coberto. Hoje só contam números até cerca de duas linhas de distância da palavra-chave. Código de rastreio funciona igual.
- A comparação de palavras-chave usa
Locale.ROOT: com o locale do aparelho, a comparação sem maiúsculas/minúsculas quebra no turco (i/İ). - Tudo que é detectado já vem marcado; o usuário toca para desmarcar ou arrasta para desenhar uma caixa. Ao detectar de novo, as caixas desmarcadas e as desenhadas à mão são mantidas.
Grátis e Pro
Detecção, edição, cobrir com caixa preta e salvar/compartilhar imagens são grátis, sem marca d'água. No grátis são 3 salvamentos por dia (salvar de novo o mesmo documento não conta). O Pro libera salvar e imprimir PDF, salvamentos ilimitados, cor da caixa, lista de termos para sempre esconder e tira os anúncios. Salvar PDF e salvamentos ilimitados também podem ser liberados por 24 horas assistindo a um anúncio.
Feedback é bem-vindo, principalmente:
- formatos de dados pessoais brasileiros que deveriam ser detectados (CPF e palavras-chave em português como "conta" e "agência" ainda não têm regra própria)
- o que faria você confiar que um app desses realmente não envia nada
Google Play: https://play.google.com/store/apps/details?id=com.codedac.photocleaner